I’m using FreerTOS 8.0.0 on a PIC24 and am attempting to use the tickless idle mode. It works fine except for one thing I don’t quite understand.
FreeRTOS is used for a simple data logger which is in sleep mode most of the time. It wakes up on an RTCC alarm every 10 seconds and takes a measurement which should take around 200ms. There are multiple UART interfaces used for communication during the measurement phase using queues to report their status to the main task. In the main task I’m using xQueueReceive timeouts to block until data has been sent or received by the UART drivers. Once the measurement is done, the main task blocks indefinitely on a semaphore given by the RTCC alarm ISR.
What I see happen is that the system does not call portSUPPRESS_TICKS_AND_SLEEP() immediately after the main task blocks, but stays awake for the last used timeout time that was unequal to portMAX_DELAY.
When stepping through the code with the debugger I can see that the main task is placed in the overflow list when calling xSemaphoreTake( interval_timer, portMAX_DELAY ). In this case NextTaskUnblockTime is not changed and still holds the timeout time from the last xQueueReceive call from one of the UART drivers. When moving on to portTASK_FUNCTION(), the tickless idle feature checks xExpectedIdleTime
which is equal to xNextTaskUnblockTime and still holds the previous timeout time instead of portMAX_DELAY. Once the system was idle for xNextTaskUnblockTime, its value gets updated and the system finally enters sleep mode.
To me it seems to be a problem with blocking on portMAX_DELAY and xNextTaskUnblockTime not getting updated in that case. Is there something I’m missing?
As workaround I could set configEXPECTED_IDLE_TIME_BEFORE_SLEEP lower than my last timeout time or insert a vTaskDelay(0) before my infinite block to force-update xNextTaskUnblockTime, but those aren’t solutions I’m keen to use.