Switching between tickless mode and normal idling mode

amichalec wrote on Tuesday, January 21, 2014:

I have created porting for Atmega128 with tickless low-power support, and it works fine. I am struggling however combining low-power mode and some low speed I/O (USART) that does not wake MCU when necessary.

Interrupt-driven USART works fine in full active mode. In low-power mode scheduler will put MCU to sleep between idling tasks but when data is sent back to MCU it will not wake it up. Trying to use external interrupt on RX pin is tempting but MCU may be too slow waking up and will loose initial bits of start sequence making whole communication out-of sync. The other option is to use active poll (waiting for data in a loop) instead of interrupts; all this to not let scheduler go sleep: this works but does not looks elegant. I could create separate task with such active poll and connect them with queue (more resource consuming) or to implement blocking functions with such looping and use them locally right time in task flow.

More transparent and more flexible option would be to switch scheduler into regular tick mode for the time of using USART and interrupts (let say for “session time” when MCU sends requests and collects responses from other module); later after completing this part of job and turning USART off, I could switch back scheduler to tickless low-power mode.

Problem is RTOS support for tickless mode in compile-time, not run-time. Porting layer cannot switch back to ticking idle and I do not think that emulating ticking inside portSUPPRESS_TICKS_AND_SLEEP is good idea. Is there a way to instruct FreeRTOS scheduler in runtime to use active idle even if tickless mode is configured in compilation? Or maybe there is proven pattern to combine sleeping with USART in FreeRTOS?


davedoors wrote on Tuesday, January 21, 2014:

You could edit the code to make configEXPECTED_IDLE_TIME_BEFORE_SLEEP a variable instead of a constant, then set the variable to 0xffffffff when you don’t want to stop the tick. Preferably because it does not involve editing the kernel you can use the PRE_SLEEP_PROCESSING macro to return ‘don’t sleep’ when the UART is being used.

amichalec wrote on Tuesday, January 21, 2014:

Dave, thanks for quick reply. I will use configEXPECTED_IDLE_TIME_BEFORE_SLEEP to keep scheduler active. It is clean approach as I can redefine it as macro in custom FreeRTOSConfig.h and since this header is picked up first (in FreeRTOS.h) it works without modifying FreeRTOS source code.

I do not see using PRE_SLEEP_PROCESSING similarly clean. On porting sample I found comment next to it saying “configPRE_SLEEP_PROCESSING() can set its parameter to 0 to indicate that its implementation contains its own wait for interrupt or wait for event instruction”. So PRE_SLEEP_PROCESSING has to implement waiting given number of ticks on its own, unnecessary extra code. Also scheduler is suspended meantime so it is not true “tick idling” and if external interrupt would happen, and if this ISR sends a message to task, this had to wait until scheduler is resumed again.

Anyway, the first approach is for me a way to go.