-
Notifications
You must be signed in to change notification settings - Fork 7.6k
micros() returning inconsistent values when call from different tasks #1165
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
The cycle count that micros() is using to report timing is a PER Task value. When micros() or delayMicroseconds() is called from different Tasks, the lastCycleCount value may have no relationship to the current Task specific cycleCount. If the current cycleCount is less than the saved lastCycleCount a rollover condition is assumed. This erroneous conditions results in incorrect delays and reported microseconds. This fix creates thread local storage so that each Task will have accurate microsecond reporting and delays. The reported microseconds are not real time, they are microseconds of the current Task execution.
Very nice, Chuck! I have looked at that code several times and thought it just was not enough in an RTOS environment. Also, is special register %0 a per core entity? And maybe you can also enlighten me as to what other process/event/hardware manipulate this register. The Tensilica LX6 documentation is a pretty heavy read. I assume it's okay to do a malloc() inside an ISR, although I've never written code that did so. Not sure how you can avoid it here. But you should at least make sure the return value is not NULL or ptr[0] and ptr[1] will surely lead to doom. |
@tferrin I have no Idea how to decode the This code has nothing to do with an interrupt, except that it has been declared If the I have never found any reliable documentation, the Espressif hardware docs on readthedocs are almost useless. My reading through the hal layers has been the most beneficial. But, they are so sparse on comments that guesses must fill in for facts. Chuck. |
very very nice :) |
FYI: There is a function which returns consistent time since startup, in microseconds — |
@igrr, if you stall the cores by calling esp_light_sleep_start(), does esp_timer_get_time() still accurately keep track of time since startup? |
@tferrin, it does not do that yet (in the same way that However we will roll out support for automatic light sleep into IDF soon, where RTOS will be able to put the system into light sleep when no tasks are expected to run for a few ticks. As part of that work, we are also fixing the interaction between light sleep and esp_timer timekeeping. |
Will the roll out of automatic low power sleep still work if the WiFi is enabled and disabled periodically? Currently, I find that low power sleep can only be used after:
If WiFi is enabled, delay() or vTaskDelay() or delayMicroseconds() work ok, but not low power sleep. I assume WiFi stack requires CPU running continuously. As per espressif/esp-idf#1864 , esp_light_sleep_start() is enabling and disabling the hardware WDT, which means that any code which requires HW WDT can end up with WDT disabled after light sleep. The automatic light sleep mode will need to preserve the state of the HW WDT so that any application out in the field (i.e. at remote location) is not left unprotected from any FreeRTOS stall/blocking states. |
@Electrozest automatic light sleep (while keeping WiFi connection) is now supported in ESP-IDF (master branch). Please check the updated wifi/power_save example. @tferrin The changes also affect esp_timer_get_time — now the time is correctly updated after light sleep (subject to RTC timer accuracy). |
…espressif#1165) The cycle count that micros() is using to report timing is a PER Task value. When micros() or delayMicroseconds() is called from different Tasks, the lastCycleCount value may have no relationship to the current Task specific cycleCount. If the current cycleCount is less than the saved lastCycleCount a rollover condition is assumed. This erroneous conditions results in incorrect delays and reported microseconds. This fix creates thread local storage so that each Task will have accurate microsecond reporting and delays. The reported microseconds are not real time, they are microseconds of the current Task execution.
The cycle count that micros() is using to report timing is a PER Task value. When micros() or delayMicroseconds() is called from different Tasks, the lastCycleCount value may have no relationship to the current Task specific cycleCount. If the current cycleCount is less than the saved lastCycleCount a rollover condition is assumed. This erroneous conditions results in incorrect delays and reported microseconds. This fix creates thread local storage so that each Task will have accurate microsecond reporting and delays. The reported microseconds are not real time, they are microseconds of the current Task execution.