2025-08-22 3:44 AM
Hello,
I am working on an STM32F446RE with a custom bootloader and FreeRTOS application.
Bootloader address: 0x08000000
Application address: 0x0800C000
The bootloader successfully jumps to the application by setting MSP, PC, and SCB->VTOR.
In my application, I configured FreeRTOS to use a hardware timer (TIM14) instead of SysTick as the OS tick source.
Problem:
When I flash the application directly, it runs fine.
But when I run through the bootloader, the application stops working as soon as it calls HAL_Delay(). If I comment out HAL_Delay(), the app continues normally. After the RTOS kernel starts, I get a HardFault on the first interrupt.
I suspect this is related to SysTick still being dirty from the bootloader, while my application is configured to use TIMx as the tick source.
My questions:
What is the recommended way to cleanly reinitialize the HAL tick and interrupt system after jumping from a bootloader to an application that uses TIMx instead of SysTick?
Should I override HAL_InitTick/HAL_GetTick in the application so that HAL_Delay() works with FreeRTOS (using TIMx ticks)?
If HAL_Delay() must work before FreeRTOS scheduler starts, should I explicitly reconfigure SysTick in the application even though FreeRTOS uses TIM14?
Is there a recommended sequence of peripheral deinitialization in the bootloader to avoid SysTick/interrupt leftovers?
Extra info:
Toolchain: GCC (CubeIDE, no optimizations)
Bootloader disables SysTick (SysTick->CTRL=0; SysTick->LOAD=0; SysTick->VAL=0;) before jump.
Application runs fine standalone, fails only after bootloader jump when HAL_Delay() is called.
Thanks in advance for guidance.
Solved! Go to Solution.
2025-09-15 10:28 PM - edited 2025-09-15 10:33 PM
enabling the interrupts in application after HAL_Init in application solved the problem
2025-08-22 4:01 AM
Isn't it recommended that you leave SysTick to FreeRTOS & designate a separate TIM for HAL use?
2025-08-22 4:07 AM
Yes, I am aware that FreeRTOS normally takes over SysTick, and the recommendation is to keep SysTick for FreeRTOS while designating a separate hardware timer for HAL timebase.In my case, I configured FreeRTOS to use a hardware TIM (not SysTick) for the RTOS tick source. That’s why HAL_Delay() is failing after bootloader jump — because Cube HAL by default still expects SysTick to be running for delays, unless HAL_InitTick is overridden.
2025-08-22 6:11 AM
> When I flash the application directly, it runs fine.
> But when I run through the bootloader, the application stops working as soon as it calls HAL_Delay().
Ensure SCB->VTOR is being set correctly by the application. When it hard fault, see what interrupt it thinks it's in (VECTACTIVE bits in SCB) and address the problem appropriately.
2025-09-05 3:15 AM
2025-09-14 11:27 PM
I used FreeRTOS in bootloader and after jump first hal_delay / systick interrupt caused hard fault. Problem was that the bootloader thread mode uses PSP. After jump to simple led blink application PSP is still used. MSP points to start of RAM. Now when interrupt occurs, registers are pushed where MSP points. This causes stack corruption?
__set_CONTROL(__get_CONTROL() & ~0x2); // clear SPSEL → use MSP __ISB();
Before jump we need to set thread mode to use MSP. This worked for me.
I think you also need to use inline asm to jump to the app, so compiler don`t make anything extra stuff.
__asm__ volatile( "bx %0 \n" : : "r"(appResetHandler) : );
Hope this helps you.
2025-09-15 5:22 AM
Don't jump to the bootloader within an interrupt context (HAL_GPIO_EXTI_Callback).
Set a flag and make the jump within the main thread.
2025-09-15 10:28 PM - edited 2025-09-15 10:33 PM
enabling the interrupts in application after HAL_Init in application solved the problem