cancel
Showing results for 
Search instead for 
Did you mean: 

HAL_Delay hangs after jumping from bootloader to FreeRTOS app (using TIM14 as tick source)

SaiKumar1
Associate II

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:

  1. 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?

  2. Should I override HAL_InitTick/HAL_GetTick in the application so that HAL_Delay() works with FreeRTOS (using TIMx ticks)?

  3. If HAL_Delay() must work before FreeRTOS scheduler starts, should I explicitly reconfigure SysTick in the application even though FreeRTOS uses TIM14?

  4. 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.

4 REPLIES 4
NicRoberts
Senior II

Isn't it recommended that you leave SysTick to FreeRTOS & designate a separate TIM for HAL use?

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.

TDK
Super User

> 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.

If you feel a post has answered your question, please click "Accept as Solution".
I am working with a custom bootloader on STM32F446RE.
The bootloader successfully jumps to my application at 0x0800C000.
The application runs, prints "Application Running", but as soon as it calls HAL_Delay(), the code stops executing.
 
If I flash the application directly (without bootloader), it runs completely fine.
 
In my jump code, I de-initialize peripherals, disable SysTick, clear pending interrupts, reset NVIC, and then relocate the vector table before jumping. Example:
 
void jump_to_application(void)
{
    uint32_t appStack        = *(volatile uint32_t*)APP_START_ADDR;
    uint32_t appResetHandler = *(volatile uint32_t*)(APP_START_ADDR + 4);
    typedef void (*pFunction)(void);
    pFunction JumpToApp = (pFunction)appResetHandler;
 
    __disable_irq();
 
    SysTick->CTRL = 0;
    SysTick->LOAD = 0;
    SysTick->VAL  = 0;
  
    for (uint32_t i = 0; i < 8; i++) {
        NVIC->ICER[i] = 0xFFFFFFFF;
        NVIC->ICPR[i] = 0xFFFFFFFF;
    }
 
    HAL_UART_DeInit(&huart2);
    HAL_DeInit();
    HAL_RCC_DeInit();
 
    SCB->VTOR = APP_START_ADDR;
    __set_MSP(appStack);
    __enable_irq();
    JumpToApp();
}
 
The code will jump from bootloader to app on pressing the button PC13 configured as EXTI 
 
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if(GPIO_Pin==KEY_Pin)
{
jump_to_application();
}
}
and my app code is very simple just to print a small text on uart2,
  while (1)
  {
  Log_Msg("Application Running\r\n");
  HAL_Delay(1000);
    /* USER CODE END WHILE */
 
    /* USER CODE BEGIN 3 */
  }