Skip to main content
Graduate II
February 22, 2024
Question

Jump to System bootloader: does not stay inside

  • February 22, 2024
  • 4 replies
  • 6307 views

It has been asked several times, however I can not find a working solution for me.

With STM32L486RGT6 I achieved to implement jump to bootloader, entering DFU mode successfully. All fine!

Doing it similar for STM32L071CZY6TR and STM32F469VE it does not remain in bootloader, but starts the application from flash.

 

Environment: Boot0 = 0 fixed. Application is stored in Bank1.

Debugging STM32L071 I see the jump to 0x1ff0’0510. Stepping forward ends up in a small loop. Disconnecting the debugger, the application starts from flash. I don’t see any Hardfault message.

 

Do I miss something to reset or should this anyway not be used to update the FW in Flash?
Below the code I use.

 

 

void Jump2StInternalBootloader(void)
{
 volatile uint32_t addr = 0x1FF00000;

 HAL_UART_DeInit(&huart1);
 HAL_UART_DeInit(&huart5);
 HAL_ADC_DeInit(&hadc);
 HAL_I2C_DeInit(&hi2c1);
 HAL_TIM_Base_DeInit(&htim2);
 HAL_LPTIM_DeInit(&hlptim1);

 HAL_StatusTypeDef s = HAL_RCC_DeInit();
 if (s != HAL_OK){
 while(1){;}
 }
 HAL_SuspendTick();

 SysTick->CTRL = 0;
 SysTick->LOAD = 0;
 SysTick->VAL = 0;

 HAL_DeInit();
 __disable_irq();

 HAL_RCCEx_DisableLSECSS();

 __HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH();

 /* Clear Interrupt Enable Register & Interrupt Pending Register. TODO check code */
 for (uint8_t i = 0; i < (MCU_IRQS + 31u) / 32; i++) {
 NVIC->ICER[i] = 0xFFFFFFFF;
 NVIC->ICPR[i] = 0xFFFFFFFF;
 }
 for (IRQn_Type i = WWDG_IRQn; i <= LPUART1_IRQn; i++) {
 HAL_NVIC_DisableIRQ(i);
 }

 void (*jumpFuncPtr)(void);
 jumpFuncPtr = (void (*)(void))(*((uint32_t *)(addr + 4)));
 __set_MSP(*(uint32_t *)addr);
 jumpFuncPtr();
}

 

Thanks in advance.
Led

    This topic has been closed for replies.

    4 replies

    Graduate II
    February 22, 2024

    I think, the best way is to set some magic in RAM, do a system reset, in the startup process check for that magic and either jump to the application or the bootloader. But maybe in your case it can help to disable all IRQs at startup and double check the bootloader address.

    LedAuthor
    Graduate II
    February 22, 2024

    Assuming I want to implement this solution, using the magic in the RAM, then I could call the function shown in my first post as the very first thing in the main(). Expecting, that the application would always to go bootloader immediately.

     

     

    void main(void)
    {
     Jump2StInternalBootloader();

     

     

    I gave it a short try (commenting out the *_DeInit() function). Unfortunately it does not stop in bootloader, as I cannot connect via Uart and the debugging shows that the application is started again.

    As bootloader address I use the system memory address according datasheet.

    By the way: I can successfully enter bootloader by erasing the chip and set BFB2 Option Byte Flag.

    Graduate II
    February 22, 2024

    main() is too late. A lot of initialization has already been done on system initialization. You must put it in the startup code.

    Super User
    February 22, 2024

    Is a watchdog running?

    Disconnecting debugger shouldn't have an effect on code being ran if you're not debugging.

    Interrupts need enabled for the DFU bootloader. You're not enabling them. General working jump to bootloader code can be seen here:

    https://community.st.com/t5/stm32-mcus/how-to-jump-to-system-bootloader-from-application-code-on-stm32/ta-p/49424

     

    LedAuthor
    Graduate II
    February 23, 2024

    Thank you TDK for the proposal. Watchdog is not running. I've tried with interrupts enabled according the link you added. But did not make any difference.
    (Actually I based my code on the first reply in this chat. But as the first reply states 'is full of errors and unnecessary actions' and later I read from the author 'I will update', but nothing has changed, ... I don't put confidence into it. )

    Super User
    February 23, 2024

    Can you show the full code you're using for the STM32F4? Not sure what "first reply in this chat" refers to.

    Graduate II
    February 22, 2024

    You can't disable IRQ's at a system level, nothing reenables them, that's not how the processor starts.

    You're expected to stop / teardown whatever your app has running, cause that's not going to be running any more.

    Some of the newer System Loaders may try and check if your firmware is present and jump to it. It may look at the mapping based on the BOOTx pins, and these may be sticky. This was done to limit several vectors of attack on design.

    The ROM can be patched on CM3,CM4 and CM7, and I've demonstrated this previously, if it doesn't do what you want out-of-the-box.

    Disassemble and Debug if you're not getting the behaviour you want.

    It will really help to have a solid understanding of the Cortex-Mx MCU's and debugging / tracing code

    Check Zero Memory Mapping, and setting SCB->VTOR to the Vectors that will be in use.

    For updating your OWN application, implement your OWN boot loader. The System Boot Loader is primarily for initial programming or unbricking, not for your best end-user experience.

    Graduate II
    February 22, 2024

    Even if you implement your own bootloader, having the system bootloader switch  in the startup code  and triggering a software reset is easier. No need to tear down anything. Only gracefull application shutdwon is needed.

    Explorer II
    February 23, 2024

    Hello,

    Is the address right? You can get the address at AN2606.

    Elatewendy_0-1708675458794.png

    I did the same function at STM32F429 with the stdlib.It works sucessfully.

    #define BootloaderAddress 0x1FFF0000
    void JumptoBoot(void)
    {
     unsigned char i;
    
     /* Test if user code is programmed starting from address "BootloaderAddress" */
     if (((*(__IO uint32_t*)BootloaderAddress) & 0x2FFE0000 ) == 0x20000000)
     { 
     #if defined(STM32F429_439xx)
     SYSCFG_MemoryRemapConfig(SYSCFG_MemoryRemap_SystemFlash);
     #endif
     GPIO_DeInit(GPIOF);
     GPIO_DeInit(GPIOE);
     GPIO_DeInit(GPIOD);
     GPIO_DeInit(GPIOC);
     GPIO_DeInit(GPIOB);
     GPIO_DeInit(GPIOA);
    
     TIM_DeInit(TIM4);
     USART_DeInit(USART1);
     INTX_DISABLE();
    
     SysTick->CTRL = 0;
     SysTick->LOAD = 0;
     SysTick->VAL = 0;
     RCC_DeInit();
     for (i = 0; i < 8; i++)
     {
     NVIC->ICER[i]=0xFFFFFFFF;
     NVIC->ICPR[i]=0xFFFFFFFF;
     } 
     //INTX_ENABLE();
     INTX_DISABLE();
    
     /* Jump to user application */
     JumpAddress = *(__IO uint32_t*) (BootloaderAddress + 4);
     Jump_To_Application = (pFunction) JumpAddress;
     /* Initialize user application's Stack Pointer */
     __set_MSP(*(__IO uint32_t*) BootloaderAddress);
     Jump_To_Application();
     }
    }