FreeRTOS with STM32 and going into STOP mode

Hello,
In the past I had lots of issues with FreeRTOS and anyhow sleeping the MCU. There are a lot of topics regarding using a different timer than SysTick for the HAL base, tickles idle features and so on… It never really gave me the functionality I was looking for.

Based on that experience, whenever I am facing a new project, I am reluctant to use FreeRTOS whenever there is a feature request for power optimization and any soft of MCU sleeping. In this one however the functionality request is quite simple: I don’t need to periodically sleep and wake up, or anything. After some time I only need to go to STOP mode and wake up from it if an external interrupt or comparator interrupt is detected. I don’t see any value from running the scheduler during sleep, so I guess its ok for it to be stopped and just continue wherever it finished before going to sleep. It could even be ok to reset the MCU once it wakes up from sleep.

Given these features/ requirements, would you say there are any pitfalls for using FreeRTOS as a base for such an application?

I would appreciate all feedback!

That approach sounds okay. If you do not want to reset on waking up, you can use tickless idle feature as well.

What functionality were you not able to achieve?

I will be more than happy to help if you face any issue with FreeRTOS. Which STM32 MCU do you plan to use?

Thanks.

Hi @aggarg , thank you for the reply.

That approach sounds okay. If you do not want to reset on waking up, you can use tickless idle feature as well.

Please tell me if I understand this correctly for STOP mode:

  1. I run the FreeRTOS application normally.
  2. I decide to go to STOP mode, so I call the right HAL API function.
  3. The MCU is in STOP mode, all peripherals are off.
  4. I wake up the MCU via one of the supported WKUP pins,
  5. The MCU resets and everything as if it was caused by the #RESET line, apart from that one bit in the registers that allow you to check that it was actually a WKUP action (PWR_FLAG_SB).

What functionality were you not able to achieve?

What was beneficial for the application at the time was to go to STOP mode with RTC and RAM retention. So in practice the Scheduler would go to sleep after entering the right code part in one of the threads and then wake up in the exact same position without loosing any context. The timers and peripherals should be off at the time.

I am not familiar with the STOP mode exactly but from the FreeRTOS prescriptive, you are essentially stopping everything and then doing a reset which will start everything fresh, right? If so, it should work - just remember to mask all other interrupts including the tick interrupt so that the MCU does not wake up unnecessarily.

This should be achievable with tickless idle.

I am not familiar with the STOP mode exactly but from the FreeRTOS prescriptive, you are essentially stopping everything and then doing a reset which will start everything fresh, right? If so, it should work - just remember to mask all other interrupts including the tick interrupt so that the MCU does not wake up unnecessarily.

Noted, thanks

This should be achievable with tickless idle.

Issue is here that tickless idle limits you with time, that is derived from the used clock and prescallers. For example, with the MCU I was using I managed to slow down the clock enough for the tickless idle to beat every ~0.8 s. The interval I would be normally interested in is expressed in seconds, minutes or even hours. Is there a way for the scheduler to not need to do ticks and still be ok after it is put back to life?

If the stop mode stops the clock that the wakeup timer uses, then the timer just will not wake up the processor, since it never reaches its expiration time.

The key thing to remember in this case is that time literally stopped while in stop mode, so periodic actions don’t all happen as soon as you wake up for being “past due”.

Yes - you can use a low frequency timer which remains active when the core is in sleep (and the tick interrupts are suppressed) and use vTaskSteptick to adjust the tick count when you wake up. This page provides more details - Tickless Low power features in FreeRTOS

aggarg, I think bremenpl’s question is about cases where the application doesn’t actually need “time” to be kept when going into deep sleep. If it is true that the application really doesn’t care how long the system was asleep, then there is no need for the “Low Power Timer” to catch up the system tick.

The are basically 3 classes of “Stop Mode” that processors have, with different effects on the system.

The lowest impact mode stops the system clock, and thus most of the peripherals, but everything keeps its configuration. For this type of stop mode, if you don’t care how long it was in, you can almost just enter it and then resume when done. Maybe some periodic tasks might want to be kicked, but that is application specific. In this mode, some “Low Power” peripheral might be able to continue running, particularly timers, so you might be able to know how long the system slept if you have things that need that.

The next mode in addition to stopping the main system clock, also powers done much of th core, and on wake up you need to reinitialize most of the peripherals. Because memory is retained, you can often just resume the application where it was. You likely need to save some context before entering this mode, and restore that (and reconfigure the peripherals) before resuming.

The lowest power stop mode shuts off power to much of the system ram, so it loses contents. There may be some limited memory that retains contents. Generally, for a FreeRTOS-based system, this type of mode requires a complete system restart, but maybe some information can be passed in the memory that retains its context.

Agree - if that is the case, vTaskSteptick is not needed.

Hi @aggarg and @richard-damon , thank you for the further answers.

In my current application it is true that I don’t need to care for the passing time while the MCU is asleep. The limiting factors are the hardware:

  • Standby mode is best from the current consumption point of view, especially when considering a product being on a shelf for say half year. But the drawbacks are: The MCU will reset + wakeup can be done only with 3 dedicated pins
  • Stop mode gives more flexibility to waking up the device and Stop mode with RTC and RAM seems to be the most feasible software wise, as the MCU does not need to reset and the overall runtime time value can be preserved.

But for the latter, many inits/ deinits need to be perform and so many things can go wrong in there. A fair balance between consumption and functionality could be to simply lower the CPU clock and adjust the sysTick timer so it still has 1 kHz frequency…

You may not get good results with this strategy. You could end up stuck with 100+ uA just to allow the system to run the tick handler every millisecond. That’s a big difference compared to 1 uA.

Using stop/standby modes is a huge help to reduce power consumption. And if you combine it with tickless idle, you can have lots of flexibility too, for when feature creep comes.

Which specific STM32 are you using? And which on-chip peripherals do you expect to use? You should find enough help here on the forum to be successful.

Hi @jefftenney , thanks for the feedback.

For this one I am using an STM32L071 series MCU. The peripherals I need are:

  • I2Cs,
  • UART,
  • SysTick timer,
  • Clock/ crystals subsystem,
  • RTC,
  • ADCs
  • Comparator.
  • GPIO’s with EXTI support.

Like I initially stated, I think the standby mode would work, since its OK for me to go to sleep and reset when wake up. But like you mentioned, there might come the need for some functionalities, that do not fit into this picture…

And from your list of peripherals, you need only GPIO and comparator to wake you from stop/standby I think you said.

Just my own 2 cents: you won’t regret using stop mode and tickless idle. That combination gives you the best flexibility. The burden of init/de-init is smaller than you might think. There are some design ideas that really help:

  • Implement a low-power driver that knows which peripherals are currently in use at all times
  • Design all application code to register peripheral use with low-power driver.
  • Low-power driver also implements the configPRE_SLEEP_PROCESSING() and configPOST_SLEEP_PROCESSING() macros to use stop mode instead of sleep mode when appropriate
  • Move the tick to LPTIM (not systick) if you want to use stop mode while delays, timeouts, or FreeRTOS timers are active. (You may not need this, not at first anyway.)

These ideas are demonstrated in GitHub - jefftenney/LPTIM-Tick: FreeRTOS Tick/Tickless via LPTIM in case it helps. Note it is written for the 'L4 so watch out for 'L0 differences.

1 Like