2025-07-25 2:36 AM
Hello,
I wrote a custom bootloader (that loads firmware image from an external flash) for a device that was using an STM32WL55CCU6. Now I want to use the same bootloader on a device with a similar uC, the STM32WL5MOCH6TR.
The bootloader works correctly up and until the point where it needs to jump to the main application. The code that I am using is this:
static void jump_to_user_app(void)
{
typedef void (*FUNC_PTR_T)(void);
FUNC_PTR_T jumpTo = (FUNC_PTR_T)(*(__IO uint32_t *)(FLASH_INT_APP_START + 4U));
// de-initialize the used peripherals
HAL_SPI_MspDeInit(SPI_BUS);
// disable interrupts, set the stack pointer and ... fingers crossed
__disable_irq();
__set_MSP(*((__IO uint32_t *)FLASH_INT_APP_START));
jumpTo();
}
I checked the registers at the moment of the jump, and they are correct. My application was compiled with the correct vector table offset, and it runs correctly otherwise.
But when the bootloader jumps to the application, it crashes. And looking at the stack, it seems that it crashed after calling HAL_GetTick(). It might be just a coincidence or there might be something wrong with the HAL initialization.
But I have tried calling HAL_DeInit() before jumping, and also feeding the hardware watchdog before the jump. None this worked.
As far as I can tell, the jump from the bootloader to the application is successfull. But I don't understand why it fails to run.
Are there any special init/deinit calls that need to be made ?
The only peripherals used by the bootloader and the aplication are SPI bus and the hardware watchdog. Everything else should be exactly the same, including the clock settings.
What am I missing ?
2025-07-25 7:16 AM
HAL_GetTick() doesn't contain anything that would cause a crash. You should in general revert the state of the chip to an as-reset state before making the jump.
It sounds like an interrupt from the bootloader may be getting triggered but the relevant code is no longer there.
2025-07-25 8:37 AM
__disable_irq(); ??
Make sure you re-enable on the other side. My preference is to set the SP in the Reset_Handler rather than transition mid-subroutine. Check you are adapting SCB->VTOR to the new location, typically in SystemInit()
It is better to disable the *source* of the interrupt(s) you have running in the loader, and their dependencies on RAM and instance structures, than disable everything on the MCU side.
Have a working HardFault_Handler so crashes to there have some detail.