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 portSUPPRESSTICKSAND_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?
You could edit the code to make configEXPECTEDIDLETIMEBEFORESLEEP 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 PRESLEEPPROCESSING macro to return 'don't sleep' when the UART is being used.
Dave, thanks for quick reply. I will use configEXPECTEDIDLETIMEBEFORESLEEP 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 PRESLEEPPROCESSING similarly clean. On porting sample I found comment next to it saying "configPRESLEEPPROCESSING() can set its parameter to 0 to indicate that its implementation contains its own wait for interrupt or wait for event instruction". So PRESLEEPPROCESSING 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.
Copyright (C) Amazon Web Services, Inc. or its affiliates. All rights reserved.