nodemcu / nodemcu-firmware

Lua based interactive firmware for ESP8266, ESP8285 and ESP32
https://nodemcu.readthedocs.io
MIT License
7.64k stars 3.12k forks source link

ESP32: timer module #1619

Closed jmattsson closed 7 years ago

jmattsson commented 7 years ago

Rationale: Everybody loves timing things, and we get 64bits of timing goodness on the ESP32.

I'd like to see a cleaned up timer interface for this module, object-based only. Ideally we'd have no pesky .delay() this time around - hopefully @TerryE could provide some notes on how to achieve delays properly using co-routines? If we really have to have one, it MUST be implemented using vTaskDelay() to avoid hard-blocking everything (which will lead to crashes and reboots), and it MUST be strictly limited in the delay length, since it would be blocking all other Lua processing and might be filling up RAM with packets, GPIO events and heaven knows what else. Really, .delay() is evil. We should avoid it at all cost. We just need to provide our users with a viable alternative.

Priority: High

Dependencies:

Note: Wall-clock time should not be dealt with in this module. This module is to be only for relative-time alarms.


Object-oriented API from esp8266 FW. Omissions:

tmr.create()

tmr.obj:alarm()

tmr.obj:interval()

tmr.obj:register()

tmr.obj:start()

tmr.obj:state()

tmr.obj:stop()

tmr.obj:unregister()

LDmitryL commented 7 years ago

And there are predictions when it will be ready TMR module?

devsaurus commented 7 years ago

I've sketched the resulting API functions in the original post to get the ball rolling here. Implementing them with FreeRTOS timers appears to be straight forward.

@jmattsson what's the background of the alternative to craft an own timer system based on the HW timer(s)? Precision in the sub-ms range could be on the pro side, while cons are that some (future) modules would really benefit from bare-metal HW timers.

jmattsson commented 7 years ago

@devsaurus Largely that wrap-arounds wouldn't be something we'd have to consider at all, I believe, but it's been a while since I had a chance to look at this area. It's entirely possible that RTOS timers are the right way to go for the tmr module - there's a reason I only wrote "evaluate" after all :) And if it's really easy to get it going with RTOS timers, we probably should do it just to get a tmr module available.

devsaurus commented 7 years ago

Ok, sounds good. There's a draft tmr module in my repo based on RTOS timers. Needs some more testing, but the FreeRTOS stuff was an easy thing. More challenging was to remove things I don't need anymore from the original code.

As a side note: the FreeRTOS callbacks seem to be very restrictive when it comes to time spent there (at least for the timers here). Got watchdogs yelling at me when I had log prints in there.

djphoenix commented 7 years ago

the FreeRTOS callbacks seem to be very restrictive

RTOS (and more, e.g. LWIP) callbacks, at most, called in "idle" thread that have very small stack size. In my RTOS-based FW I use "callback queue" and polling task with medium priority.

devsaurus commented 7 years ago

In my RTOS-based FW I use "callback queue" and polling task with medium priority.

Hm, I just post to the NodeMCU task queue from the FreeRTOS timer callback. That seems to be ok in terms of stack usage and for safe communication between the FreeRTOS tasks.

djphoenix commented 7 years ago

@devsaurus yep, nodemcu have "NodeMCU task queue", but my firmware project haven't :) </offtop> This is what I was mean: use another task and never call heavy code from callbacks directly.

LDmitryL commented 7 years ago

downloaded the dev branch-esp32_tmr with https://github.com/devsaurus/nodemcu-firmware.git the module timer is running. Thank you. But for some reason the module does not work sigma_delta. in make menuconfig [*] Sigma-Delta module.

sigma_delta.setup(1, 2) stdin:1: attempt to index global 'sigma_delta' (a nil value)

what's wrong?

devsaurus commented 7 years ago

the module timer is running.

Thanks for testing! It's now in dev-esp branch here for a broader audience,

But for some reason the module does not work sigma_delta.

Finally figured that the Kconfig name has to match the file name, otherwise the module is silently skipped from linking.

config LUA_MODULE_SIGMA_DELTA
sigma_delta.c

Fixed now, please re-generate your sdkconfig from scratch and it should be included.

LDmitryL commented 7 years ago

@jmattsson You can comment to the example of the application of tmr.obj:alarm() (example from the documentation file to the module tmr) tmr.create():alarm(5000, tmr.ALARM_AUTO, function() print("hey there") end) How to stop it, if no object name? How to remove it if it is not needed already? How many of these timers so I can run simultaneously?

marcelstoer commented 7 years ago

The timer itself is passed to the callback function for tmr.alarm. See here for an example: http://nodemcu.readthedocs.io/en/latest/en/upload/#initlua

jmattsson commented 7 years ago

@LDmitryL There's nothing stopping you from grabbing a reference to it, e.g.

local t = tmr.create()
t:alarm(5000, tmr.ALARM_AUTO, function() print("hey there") end)

Garbage collection will take care of used timers, just like other Lua objects. With the object-based tmr API there's no predefined limit to the number of timers you can run.

devsaurus commented 7 years ago

Note about default resolution added to docs.