Preventing entry to sleep when using tickless idle

Hello Community, I have a question about preventing (“turning off”) entry to sleep during specific idle periods. For example, suppose I am performing a network provisioning task which involves a lot of waiting during which the MCU could go to sleep. But, for simplicity and to prevent continuous sleep-wake cycles, I wish to have the idle task run (skipping entry to sleep mode) until the network provisioning completes or timesout. Essentially I would like to control (select) either entry to low-power sleep, or simply remain idling. Here is a little background on my project: I am using Keil uVision v5.20 for development with FreeRTOS v9.0.0 on STM32L471 ARM Cortex M4 MCU. My RTOS project defines 5 tasks, 4 of which use a Queue and wait for events to process, and the fifth uses Task Notifications to block until something happens. Some relevant configuration: ~~~

define configOVERRIDEDEFAULTTICK_CONFIGURTION 1

define configUSETICKLESSIDLE 2

define configUSEIDLEHOOK 0

~~~ I use 32.768kHz oscillator to drive low-power timer and generate the RTOS tick. I have the RTOS tick independent of the MCU SYSCLK so I can achieve longer sleep periods, and also I need to keep SYSCLK running at a low frequency while in SLEEP. To do all this I had to implemented my own portSUPPRESSTICKSAND_SLEEP() for tickless idle. Back to the question of selecting either idle or sleep: I am thinking of introducing a simple global variable into the idle task which will determine whether the tickless idle code is skipped or run. I think it’s pretty simple but wouldn’t mind a little feedback about this approach or more generally how to control entry to sleep mode. (For example, if portSUPPRESSTICKSAND_SLEEP() is to be skipped, perhaps I should call vApplicationIdleHook() to increment an idle time counter that could be cleared when any task wakes. It could be used to ensure a “minimum idle time” before allowing entry to sleep in general circumstances.) Thanks for any suggestions! Bryce

Preventing entry to sleep when using tickless idle

The expected way would be to define a portPRESLEEPPROCESSING( x ) macro in FreeRTOSConfig.h. If sleep should not be entered set x to 0 in the macro. What does setting configUSETICKLESSIDLE to 2 do?

Preventing entry to sleep when using tickless idle

Thanks for the reply! Ah, yes, now I see that option to set x = 0 and cause the sleep to be skipped. I think that could work — though the code will run right “up to” the sleep instruction and skip at the last possible chance. I think I’m looking for something a bit more “coarse” — i.e. not stop the scheduler at all. I will keep this in mind and trying some other options. Thanks for reminding me of this possibility. The #define configUSETICKLESSIDLE 2 setting doesn’t add anything — from what I saw looking at the code it just ensures the default vPortSetupTimerInterrupt() and portSUPPRESSTICKSANDSLEEP() and anything related to the default configUSETICKLESSIDLE == 1 setting (which assumes that SysTick is the source for RTOS tick) isn’t compiled. According to website notes it appropriate when defining your own clock other than SysTick to generate the RTOS tick interrupt. There’s some notes about it here and here.

Preventing entry to sleep when using tickless idle

To be more clear, I’m thinking more of an higher “application level” approach to preventing the idle task from entering into sleep, rather than lower “RTOS level”. For example, during configuration of peripherals or devices there might be periods of idle (e.g. waiting for sensor to initialize), during which the application can be considered “busy waiting”. Is it possible (safe?) to suspend the idle task using vTaskSuspend()? Any special considerations for doing that?

Preventing entry to sleep when using tickless idle

You must always have a task to run, so if you suspend the idle task you must have an application task that can run. If all the tasks are blocked or suspended it will crash. This will help http://www.freertos.org/a00021.html#xTaskGetCurrentTaskHandle

Preventing entry to sleep when using tickless idle

Correct link is http://www.freertos.org/a00021.html#xTaskGetIdleTaskHandle

Preventing entry to sleep when using tickless idle

Hi, I asked few weeks ago maybe the same question. You can look : https://sourceforge.net/p/freertos/discussion/382005/thread/063d54e8/ The conclusion was that you can move the responsibily to sleep_sleep which is EnergyMicro library function in our case. The usage of macros in FreeRTOS give you very strong possibilities. Thank’s to FreeRTOS developers. Zdenek

Preventing entry to sleep when using tickless idle

Thanks for the info on what can happen if Idle task is suspended and there’s nothing to run! I’ll keep this information in mind!

Preventing entry to sleep when using tickless idle

Hello and thanks for the pointer to your thread! Definitely it’s a question on the same topic. I’ve had a read from your thread and got further ideas! Plenty to work with now 🙂

Preventing entry to sleep when using tickless idle

Hi Bryce, I had the problem that I need to prevent entering low power or tickless idle mode in case there is some communication pending (e.g. UART). For this I have extended FreeRTOS with two defines: ~~~

define configUSETICKLESSIDLEDECISIONHOOK 1 /* set to 1 to enable application hook, zero otherwise */

define configUSETICKLESSIDLEDECISIONHOOK_NAME xEnterTicklessIdle /* function name of decision hook */

~~~ The first one turns on an extra hook, and the second one provides the name. You can find an implementation on GitHub here: https://github.com/ErichStyger/Hexiwearv2/tree/master/KDS/HexiwearSDKv2/freertos/Source The extension is in task.c https://github.com/ErichStyger/Hexiwearv2/blob/master/KDS/HexiwearSDKv2/freertos/Source/tasks.c around line 3336: ~~~ /* This conditional compilation should use inequality to 0, not equality to 1. This is to ensure portSUPPRESSTICKSANDSLEEP() is called when user defined low power mode implementations require configUSETICKLESSIDLE to be set to a value other than 1. */ #if ( configUSETICKLESSIDLE != 0 ) #if configUSETICKLESSIDLEDECISIONHOOK /* << EST */ if (configUSETICKLESSIDLEDECISIONHOOKNAME()) /* ask application if it shall enter tickless idle mode */ #endif { TickType_t xExpectedIdleTime;
        /* It is not desirable to suspend then resume the scheduler on
        each iteration of the idle task.  Therefore, a preliminary
        test of the expected idle time is performed without the
        scheduler suspended.  The result here is not necessarily
        valid. */
xExpectedIdleTime = prvGetExpectedIdleTime(); ~~~ Basically this extra hook allows the application to decide if the idle (and low power) mode really shall be entered. That approach worked really well for me. See as well https://mcuoneclipse.com/2014/02/09/iot-freertos-down-to-the-micro-amps/ and https://mcuoneclipse.com/2013/07/06/low-power-with-freertos-tickless-idle-mode/ I hope this helps, Erich

Preventing entry to sleep when using tickless idle

I think there might be an easier way because portSUPPRESSTICKSAND_SLEEP() is declared in a way that allows the user to override its default implementation by providing their own. The default definition is as follows:
#ifndef portSUPPRESS_TICKS_AND_SLEEP
     extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
     #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) 
vPortSuppressTicksAndSleep( xExpectedIdleTime )
#endif
To override the definition you can add your own implementation of portSUPPRESSTICKSAND_SLEEP into FreeRTOSConfig.h, and can use that definition to decide if you want to go into sleep mode or not. Something like the following to be added to FreeRTOSConfig.h:
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) 
     if( AppWantsToEnterSleepMode() == pdTRUE )            
     {                                                     
         vPortSuppressTicksAndSleep( xExpectedIdleTime );  
     }