What I learned about STM32 HAL STOP mode and crash in FreeRTOS

Hi community. I struggled a few good days with this. I did not find an exactly related topic, so I thought about posting my experience. Maybe someone will save a couple of days after reading this.

I use STM32F302 (Cortex-M4F) with STM32 HAL and FreeRTOS 10.2.1. I use STOP mode to save power only after certain events. For this purpose I have a custom sleeping function, inspired by port.c vPortSuppressTicksAndSleep().

When returning from STOP mode I call STM32CubeIDE autogenerated SystemClock_Config() to restore system clocks etc. This calls HAL_RCC_ClockConfig() and further HAL_InitTick(TICK_INT_PRIORITY) inside the lib, which sets Systick priority to HAL’s default, which is 0.

This allows Systick interrupts running inside FreeRTOS critical sections, corrupting pxCurrentTCB->xStateListItem->pxContainer.

Browsing through the topics in the forums helped me get ideas where to look. I humbly tip my hat to those who have struggled with this before me.


Thanks for sharing your experience.

My basic theory with the ST HAL code is to avoid using it. It makes a lot of assumptions about how you want to do things that don’t match my preferences. I will look at their code and adapt it, but as a unit, it doesn’t work well with other systems.

+1 on the comment from @richard-damon regarding the ST HAL. It can be useful as a reference, but look out.

It sounds like in your case you are using SysTick for both the HAL and for FreeRTOS. ST has moved away from that approach (eg, in projects currently generated by CubeIDE) because the SysTick IRQ priority cannot satisfy all parties. For example, I think HAL code uses delays and timeouts inside ISRs, which means the SysTick priority must be higher than any ISR that uses HAL code. However, for FreeRTOS, SysTick priority must not be higher than configMAX_SYSCALL_INTERRUPT_PRIORITY. It’s a no-win situation for some applications.

Thank you for sharing the information. Just want to add that CubeMX and STM32CubeIDE allow to change the ST HAL to use any other timer than SysTick:


1 Like

Thanks for all the input, people.

I changed HAL default Systick priority to match FreeRTOS’ and I currently believe (emphasis on believe, I still need to prove this) that it’s not in conflict with my design, because I only use HAL calls from thread context, not from interrupts handlers. Also going to look into Gaurav’s suggestion, nice tip.

For the next projects I’ll definitely look for other options to replace HAL. Maybe ST LL-only, or 3rd party libs.

The issue isn’t you calling in an interrupt context, but that some of their ISR used to handle device drivers have timeout delays in them that use their systick.

One solution is that the Cube can configure the HAL to use one of the timers for the HAL systick that can be a different resource than what the FreeRTOS systick is. This does basically disable any option to use tickless idle without a LOT of work, as the processor will always get an interrupt every millisecond.

Based on the warning dialog from CubeMX, it seems a recommendation from ST to use any timer other than SysTick for HAL tick when using FreeRTOS.


You can use the SysTick for HAL if you move the FreeRTOS tick to another timer. For other STM32 parts, I have put the FreeRTOS tick on a low power timer that runs even in stop mode to make a cleaner implementation of Tickless Idle. But, if you want to use tickless idle, you are going to need to turn off the HAL tick for the duration of the idle, but that is generally safe side you shouldn’t try to enter that mode if you have active I/O that needs the HAL tick.