Low Power Modes: When Should vPortSuppressTicksAndSleep (or other) Be Called?

groger57 wrote on Friday, April 05, 2019:

I am really trying to understand the implementation of the low power modes in FreeeRTOS, trying some things, and would very much appreciate some help, or suggested reading.

Since I am using a Cortex-M4, I am trying the default implementation of “vPortSuppressTicksAndSleep”, as in port.c
In my FreeRTOSConfig.h file, I have the required defines:
//#define configUSE_TICKLESS_IDLE 1
//#define portSUPPRESS_TICKS_AND_SLEEP vPortSuppressTicksAndSleep

When the code executes, it never hits the breakpoint in port.c (as I have read in another post) as it should. I have also tried a different example, with a user defined call:
For this, in FreeRTOSConfig.h, I have
//define portSUPPRESS_TICKS_AND_SLEEP( xIdleTime ) vApplicationSleep( xIdleTime )
whose definition is in my freertos.c file. It is never executed either.

Any help would be appreciated to further my understanding of this!


rtel wrote on Friday, April 05, 2019:

What is configIDLE_TIME_BEFORE_SLEEP set to? That defines how long the
system expects there to be idle time before it enters low power mode.
See the second post in this thread:

groger57 wrote on Saturday, April 06, 2019:

I read those references, and although they are helpful (thank you) the poroblem still persists.
To take another try, I regenrated my code base, using TIM17 on the L476VG as a system timer. I also have in my FreeRTOSconfig:
//#define configUSE_TICKLESS_IDLE 1
//#define portSUPPRESS_TICKS_AND_SLEEP vPortSuppressTicksAndSleep
Further down:
//#if defined…
//void PreSleepProcessing(uint32_t *ulExpectedIdleTime);
//void PostSleepProcessing(uint32_t *ulExpectedIdleTime);

So that seems to be correct according to what I have read. In the function PreSleepProcessing, I have the call:

I have one task running, and it executes every 1000ms. No matter what I set EXPECTED_IDLE_TIME_BEFORE_SLEEP to, the code never breakpoints at the system call in in PreSleepProcessing!

I also tried to breakpoint in port.c, and it never executes code in vPortSuppressTicksAndSleep either.
To be clear, I did not write a separate “vPortSuppressTicksAndSleep” function, so the port.c should be executing.
Why would the function PreSleepProcessing never get executed? I believe everything is set up correctly.

groger57 wrote on Sunday, April 07, 2019:

Hi Richard
I have also checked the L152 demo. The thing I see different is that you have implemented your own call to “vPortSuppressTicksAndSleep” because your notes indicate TIM2 needs to be managed. In my case I use TIM17. So none of this explains why the vPortSuppressTicksAndSleep in port.c never gets executed in my code. What is “stopping it” from executing maybe is the question?

Can you please advise on this issue? I am sure everything has been done correctly according to what I have read on the posts. Some help would be very appreciated.

richarddamon wrote on Sunday, April 07, 2019:

One thing that I notice as that all your defines are preceeded by \ which makes them a comment, and not a define, is that how they actually are in FreeRTOSConfig.h ?

Second, you show the configEXPECTED_IDLE_TIME_BEFORE_SLEEP 500, but don’t show your tick rate. If it is less than 1000 Hz, then 500 tick might be longer than 1 Second.

You could put a breakpoint at the test for configEXPECTED_IDLE_TIME_BEFORE_SLEEP and see if there is something else running that has a shorted timeout, and that is keeping you from going to tickless idle.

groger57 wrote on Sunday, April 07, 2019:

Hi, thank you for responding Richard.
Your suggestion of puting the breakpoint in file tasks.c, on configEXPECTED_IDLE_TIME_BEFORE_SLEEP, has helped. It is now working as it should and more importantly, I understand what had happened. In my test application CubeMX put an osDelay(1), in the default task. Grrr…little wonder it did not reach there! I changed it to 100 (it will be taken out when I add tasks) and using a configEXPECTED_IDLE_TIME_BEFORE_SLEEP value of 5, power dropped to 50%, without doing anything else other than calling HAL_PWR_EnterSLEEPMode(PWR_LOWPOWERREGULATOR_ON, PWR_SLEEPENTRY_WFI); in
PreSleepProcessing. Once I add GPIO and peripheral clocks that should improve.

So just one further question - how can the value of configEXPECTED_IDLE_TIME_BEFORE_SLEEP be optimized? I understand how it works, that is now clear, but what are the negatives of having it that low to enable LPM so quickly?

richarddamon wrote on Sunday, April 07, 2019:

Generally entering (or leaving) low power mode has an energy cost, and you need to expect to sleep long enough that the low power mode will save enough energy to pay for the transistion.

Note, that the time isn’t how long you wait before going into low power mode, but how long you expect that you will be waiting before going into low power mode (so if you know you are going to be interrupted soon, even though the timeouts are long, you may want to have to pre-check callback prevent the entry to low power mode in that condition.

groger57 wrote on Sunday, April 07, 2019:

Got it, thanks then!