2024-06-11 1:21 AM
Dear all,
I'm working on a project based on STM32F479 and FreeRTOS. In this project the microcontroller is connected via I2C and SPI bus to other devices, such as switch ethernet and spi-uart converter. I run the initialization of these devices before the start of the FreeRTOS scheduler. Startup procedure requires switching some GPIOs and waiting a few milliseconds as described in the devices datasheet. I've manged the waiting part of the initialization using the HAL_Delay function. This project has been generated in 2019 with STM32F4 fw package 1.24.0 and an old version of STM32CubeMX.
Recently I've created a new project for the same hardware using fw package 1.28.0 and STM32CubeMX 6.11.1. I noticed that the initialization of TIM6 in stm32f4xx_hal_timebase_tim.c has been updated and HAL_InitTick function is changed (which you can find in the attachment). Now I'm experiencing a strange behaviour. During devices initialization the program remains stuck in the HAL_Delay function. Apparently TIM6 interrupt is not running before the start of the scheduler, so the global variable uwTick is not incremented and as a result HAL_Delay waits forever. I had to move the initialization of the devices after the start of the FreeRTOS scheduler to solve the issue.
Can anyone help me figure out what I'm missing?
Best regards.
Massimo G.
2025-11-02 1:42 AM
Sorry, I cannot see your point. Both SysTicks are non time-critical. RTOS SysTick interrupt does not trigger other interrupts (other than PendSV of the same priority as SysTick). All the other IRQs are more critical. In a properly designed system the CPU will never be saturated. With a classic, event loop approach and with RTOS-based approach, SysTicks should have the lowest priority. In some cases higher SysTick priority may be desirable in purely interrupt-driven firmware design, where the lowest priority, software-triggered interrupts logically replace the event loops for time-consuming tasks (so they may require timekeeping services).
2025-11-02 2:38 PM - edited 2025-11-02 2:38 PM
The point is it changed. You may like it better that way, but that is beside the point.
You continue to make an argument about what it should be. That's beside the point. The point is it changed.
I hope that makes it a bit clearer.
2025-11-02 10:52 PM
OK. When you use FreeRTOS with CubeMX, it automatically adjusts interrupt priorities to make your life easier. So it sets both SysTicks and PendSV to the lowest priority and it sets all the other peripherals' IRQs to RTOS Syscall priority (5 by default, unless you chage it). That's actually quite good as a starting point. You may still change the priorities manually in NVIC settings.
2026-03-24 10:15 AM
Hi @MGall.11
I experienced the same issue when migrated from FreeRTOS 1.0.1 to 1.5.0 (CubeMX 6.17 example STM32U5G9J-DK2-3.0.7.tpa).
CubeMX changed priority of TIM6 to 15 and my previously working Gfx demo stopped working. After i changed TIM6 prio to 0 the demo worked again.
This made me think what is TIM6 used for ? Is it 1ms time base for HAL delay ? Or tick for FreeRTOS ? I think FreeRTOS tick is coming from Cortex SysTick timer. Very confusing.
2026-03-24 8:35 PM
Yes it is confusing. Changing things without providing a rationale compounds the confusion, as you can see from this thread. Let me try to clear things up:
So in your case, TIM6 is doing whatever you configured it to do, which make take some poking around to figure out. On STM32 it's highly likely it is not providing the RTOS Tick (because SysTick does that), and given that the priority changed, it's likely it is the "timebase source" for the HAL. But there's nothing stopping you using it for other purposes too.
2026-03-25 12:56 AM
Hi ferro,
As explained by LiteYear, it depends on how the system is configured with STM32CubeMX. In my case, I have the TIM6 timer interrupt set to 1 ms, which increments the HAL tick, and the FreeRTOS tick interrupt is handled by the SysTick_Handler IRQ (xPortSysTickHandler) with priority set by configKERNEL_INTERRUPT_PRIORITY. The number of ticks per second is defined by configTICK_RATE_HZ. All of this is configured in xPortStartScheduler.
2026-03-27 4:40 AM
>> "But wanted to confirm my understanding: in the old HAL implementation the systick priority was 0 and in the new implementation the priority is set to 15 which is not working, and setting it to 0 works again?"
Exaclety. TIM6 prio has changed to 15 (was 0) and with that change, HAL_IncTick() is not called.
As soon as i set TIM6 priority to number 4 or less, the system works. So it seems it has sth to do with that number 5 that sets boundary between "RTOS aware IRQs" and the "rest". I am trying to understand what is masking the TIM6 IRQ. The RTOS initialisation is executed only after HAL modules initialisation so it is not RTOS, I think.
With TIM6 IRQ priority set to 5(or higher), my program waits at delay and HAL_GetTick() returns always 0.
2026-03-27 2:03 PM
Uf, really nice write-up, @liteyear - thank you. There’s a lot of material to go through; I’m only just starting with FreeRTOS.
I found that my application (based on STM32U5G9J-DK2-3.0.14.tpa) uses TIM6 for the STM HAL tick and the Cortex SysTick for the FreeRTOS tick.
You mentioned, “All ARM devices have a SysTick.” . Not all, but Cortex-M devices do.
2026-03-30 3:41 AM
In you main(), before anything else, try to call __set_BASEPRI(0)
int main(void)
{
/* USER CODE BEGIN 1 */
__set_BASEPRI(0);
/* USER CODE END 1 */
2026-03-30 4:22 AM
> I am trying to understand what is masking the TIM6 IRQ. The RTOS initialisation is executed only after HAL modules initialisation so it is not RTOS, I think.
Something can call a function that internally uses a RTOS lock (for example, malloc) while the scheduler is not started yet. For FreeRTOS, in some configuration, these locks raise BASEPRI.