Trying to implement Tickless Idle sleeping on STM32L476 using STM32CubeMx

mattster5 wrote on Friday, May 06, 2016:

Trying to get the Tickless Idle working on my project. Using a Nucleo64 l476 board, used STMCubeMx to set the project up and had it install FreeRTOS.

Turned to Tickless Idle in the config.

First problem/question: How to get the code to start. Finally decided to suspend my two tasks, then put code in the interrupt to resume the tasks. That did not work and when I stepped through the freertos.c code I discovered that it did not work because it was determining that it could only sleep for 1 tick. Why 1 tick, because of the default idle task created by Cube:


So I decided to also suspend the idle task - don’t know if that’s a good idea, but it works.

I have a break point in PreSleepProcessing, and I’m finding that it is always called with ulExpectedIdleTime set to 209. I don’t understand why, all the tasks are suspended, shouldn’t it be infinate?

Also: I want to eventually put in code to change the CPU clock so I can enter stop mode. But I’m unsure how FreeRTOS is waking itself up and how changing the CPU clock would affect that.

So, how do I figure out why it is sleeping for 209 ticks? should I change the default idle task? is it ok to suspend the default idle task? could I use a vTaskSuspendAll? will changing the CPU clock mess things up?

Thanks so much - first time posting to this board!

rtel wrote on Saturday, May 07, 2016:

I would suggest the following steps:

  1. Create just one task that does nothing but sleep for a fixed period, then toggle an LED (just to give visual feedback).
void vATask( void *pvParameters )
const TickType_t x100ms = pdMS_TO_TICKS( 100UL );

    for( ;; )
        vTaskDelay( x100ms );
        /* You will have to provide the ToggleLED() function. */

Compile and run this with configUSE_TICKLESS_IDLE set to 0 as a sanity check that everything is as expected, and the LED does indeed toggle at the expected rate.

  1. Set configUSE_TICKLESS_IDLE to 1, and configUSE_TIMERS to 0 (so the timer task is not interfering with anything) and build and run the code again. You should not see any difference in behaviour, but now the system should be turning the tick interrupt off in between LED toggles.

  2. Record the expected idle time value as before - do this by just saving it into a variable, or array of variables, rather than printing it out of any other slow mechanism - as anything slow (writing to a UART or whatever) would adversely effect the operation at that point.

  3. Halve the time passed to vTaskDelay() and record the expected idle time value again.

Does the expected Idle time halve when the block time is halved?

If not, look at the value of xMaximumPossibleSuppressedTicks in FreeRTOS/Source/portable/[compiler]/ARM_CM4F/port.c, because the expected idle time is capped to that value, and if you have a fast clock speed you may find the value is quite short as the SysTick timer is only 24-bits.

This is why, if you can’t slow the clock that feeds the SysTick timer (which some microcontrollers can, but most can’t) and you want ultra low power, then you need to implement a chip specific version. Links to some chip specific versions are found at the top of this page: but I expect you have seen those already. Note the STM32L version might not be optimal. The CEC1032 and EFM32 examples are the newest and known to be extremely robust for slow clock speeds.

With regards to indefinite sleeps - I’m not sure if the generic tickless idle will ever sleep indefinitely, but some of the chip specific examples will. If all the tasks are blocked indefinitely or suspended and it is ok to only keep relative time, rather than absolute time, then eTaskConfirmSleepModeStatus() will return eNoTasksWaitingTimeout and you can sleep indefinitely - in which case only an interrupt other than the clock/timer interrupt will bring you out of sleep mode.

mattster5 wrote on Monday, May 09, 2016:

Thanks very much for the suggestions. What do you suggest I do about the default task? Remove it?

Also, xMaximumPossibleSuppressedTicks is… 209. (80 MHz clock, 1ms tick).


rtel wrote on Monday, May 09, 2016:

I’m not sure what the default task is doing, but if it is nothing more
than shown in your previous post I would guess it was meant to be a
template that you could then add your own code into. If you have
created your own tasks already then there would seem to be no reason to
keep the default task that was generated for you.

mattster5 wrote on Tuesday, May 10, 2016:

Ah, I see. I assumed it was the idle task - it’s not. It’s a template ‘default’.

I changed the system clock to 4Mhz, and now the system sleeps for a little over 2 minutes at a time.

I have decided to change the clock FreeRTOS uses from the SysTick to LPTIM2. This way I can configure LPTIM2 to have the LSE clock (~32K). The clock will continue to run while asleep, and run at low power. I’ll change the ticks per second to a lower number, which will give me more flexability to have long sleep times. It also means I can change the system clock to what ever speed I want and it won’t affect FreeRTOS.

I think this is a very good solution and will be writting a paper on it for the rest of the company.

Also, is it possible to use vTaskSuspendAll instead of suspending each task indivdually? (just asking, I don’t plan on doing it in the product).


rtel wrote on Tuesday, May 10, 2016:

No - vTaskSuspendAll() is perhaps not the best named function as it
actually suspends the scheduler, not the tasks. It is not the same as
suspending each task and when the “suppress ticks and sleep” function is
called the scheduler is actually already suspended (to prevent race

mattster5 wrote on Tuesday, May 10, 2016:

One more thing - if I’m implementing a clock other than SysTick, do I need to set the alternate clock interrupt time inside configPRE_SLEEP_PROCESSING? Or is there a routine other than vPortSetupTimerInterrupt that I need to create?

Thanks for your replies!

rtel wrote on Wednesday, May 11, 2016:

If you are using your own clock then it would be best to provide your own version of vPortSuppressTicksAndSleep().

Here are few examples you can use as templates. Note the one to use depends on whether your clock is an up counter or a down counter. You also have to take into account when the counter is cleared - some counters will be cleared by updating a compare match value, others won’t:

Up counter example:

Down counter example: