Difference between HAL tick and FreeRTOS tick

we are using a STM32H7with FreeRTOS. Code was generated using the ST CubeIDE and therefore the ST HAL is implemented as well.

We have FreeRTOS running preemption mode and several task / peripherals. As our overall system was designed to rely on the systick and/or the accuracy of the FreeRTOS wait/delay features we run into problems if anything corrupts the system time.

The HAL uses a timer as time base generating a tick every ms. Same for FreeRTOS - we expect the systick to increase by 1 each ms.

I tried comparing both the HAL tick and the freeRTOS tick and i see a huge difference between the two ( around 10ms statically so 50ms rtos tick is actually 60ms HAL tick ). I believe this to come from the different priorities of freeRTOS tick and HAL tick, but wasn’t able to resolve this.

Since RTOS tick should run at the lowest priority I’m not quite sure how to solve this issue as making the rtos tick a higher priority is not possible. Do I have to live with this loss of accuracy or is there some other way around this? I’m quite new to freeRTOS and micro controller in general, so I might be missing some things here.

If someone has experienced something similar and could point me in the right direction, it would be much appreciated.

Best regards

Are you masking interrupts for too long in your application?

You do not have to use SysTick - you can use any other timer. Override the weak function vPortSetupTimerInterrupt to initialize your timer and call xTaskIncrementTick from the timer ISR. Note that the timer ISR cannot have a priority higher than configMAX_SYSCALL_INTERRUPT_PRIORITY as it needs to call FreeRTOS API xTaskIncrementTick.

From looking at pieces of the ST HAL code, I am not impressed, or surprised at strange results. Some of there drivers will spin wait inside ISRs waiting for time to expire, blocking other interupts, so that could easily make FreeRTOS lose ticks.

My solution has been to look at the HAL code as hints about how the hardware works, and write my own drivers.

This sort of problem is not exclusive to ST, a lot of vendor supplied drivers are of fairly low quality and not well done, and are often something quickly thrown together to build some quick demos for their processors.


Thank you for your replies so far! It helps me a lot with understanding this!

I already moved away from the systick and I’m using a timer instead. (which I will just call systick for the sake of convenience)

Just to make sure that I understood everything correctly:

  1. The systick should have the lowest urgency in my NVIC priorities, is this correct?
  2. Is it alright to set its priority to configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY or are there problems with this since this is a rather high priority?

right now when i assign the lowest NVIC priority to the systick, freeRTOS thinks that a timer is running at 50ms while in truth it is running at 80ms. It seems quite unrealistic to me that interrupts are responsible for a delay of about 60%. Also even though I’m using the HAL Drivers, I use dma whenever it is possible (havent checked those functions yet, going to do that now to see if there is some waiting hidden there.)

The FreeRTOS tick should be the LOWEST priority (highest number).

A hardware timer not used to call the FreeRTOS tick routine, can use any priority you want, (within the requirements if it calls FreeRTOS functions).

Note, to be clear, “SYSTIC” is to me, the name of a physical timer implemented in the core of Arm Cortex processors, which is used, by default, for the FreeRTOS tick, but doesn’t need to be.

Depending on your system requirements, changing the timer source for FreeRTOS can make a lot of sense. I often used one of the Low Power Timers that can run when the CPU is totally stopped and the main high frequency clock turned off.

In the FreeRTOS STM32U5 Reference Integration, I approached this problem by:

  1. Overriding the HAL_InitTick function to do initialize SysTick if HAL_Delay is needed before the FreeRTOS scheduler is started.
  2. Overriding the HAL_Delay function to use vTaskDelay when the FreeRTOS scheduler is running
  3. Redefining the SysTick interrupt handler in startup_stm32u585aiixq.s
  4. Wrapping the FreeRTOS provided SysTick_Handler function in interrupt_handlers.c