cancel
Showing results for 
Search instead for 
Did you mean: 

Jump to sysmem bootloader on STM32L476. How to perform correctly?

JNord
Associate II

I need to jump to DFU from software (BOOT0 pin not available in board design) on STM32L476RG. I'm following the process outlined in https://stm32f4-discovery.net/2017/04/tutorial-jump-system-memory-software-stm32/ - but added the memory barriers that seems to be critical for STM32L4 - from https://community.st.com/s/question/0D50X00009XkeeWSAR/stm32l476rg-jump-to-bootloader-from-software

Two people seemed to have success with that receipe on STM32L476, but I don't end up in the sysmem DFU bootloader - just get thrown back into my application.

Here is the code that I got:

#define SYSMEM_START 0x1FFF0000
 
void check_jump_bootloader(void)
{
  // Define our function pointer
  volatile void (*SysMemBootJump)(void);
 
  if (bootloader_flag == BOOTLOADER_FLAG_SET) {
     bootloader_flag = BOOTLOADER_FLAG_RESET;
 
#if 1
    SysTick->CTRL = 0;
    SysTick->LOAD = 0;
    SysTick->VAL = 0;
#endif
#if 1
    __disable_irq();
#endif
#if 1
    __DSB();
    __HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH();
    /* Remap is not visible at once. */
    __DSB();
    __ISB();
#endif
      //  System Memory reset vector is one word after SYSMEM_START
      SysMemBootJump = (void (*)(void)) ((uint32_t *)(SYSMEM_START + 4));
 
      // Set stack pointer value
      //__IO uint32_t sp = *(__IO uint32_t*)SYSMEM_START;
      __set_MSP(*(__IO uint32_t*)SYSMEM_START);
      // jump
      SysMemBootJump();
      while (1);
  }
}

This function is called as the first thing in SystemInit. I am testing this on a Nucleo-L476 development board for now.

Using gdb to break in check_jump_bootloader() , using "monitor rest halt" to reset the CPU, and then setting the bootloader flag at breakpoint before stepping through the jump code.

Then I can see that the microcontroller seems to reset instantly upon hitting the SysMemBootJump(), and goes back to the start of my application.

If I remove the __HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH() call then I instead get a hardfault.

I can also see this reset loop behavior when triggering bootloader from a GPIO pin, without gdb connected.

What am I doing wrong?

I tried removing the interrupt disabling and the systick reset (should not be needed as I'm coming through a reset?) - but no change.

Compiler is GCC 9.1.0. Using a Makefile generated by STM32CubeMx on a simple project (only GPIO pheripherals, LSE clock). Using STM32Cube_FW_L4_V1.13.0

3 REPLIES 3

If there is valid code in Flash, the ROM will likely transfer control back. Instrument the Reset_Handler to output to a UART or GPIO to confirm.​

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
JNord
Associate II

Ah, that could fit what I am seeing. My reset handler is being called immediately. How do I prevent ROM from transferring control back? (until a new firmware has been flashed, or device has been powered on/off)? My intention is to use this as an in-field update mechanism. So there will usually be a valid code in there already.

I read chapter 4.1 in AN2606 "Bootloader activation", but my understanding that when jumping from application code, a "boot pattern" is not required? Is that wrong? If so which one is recommended for my usecase?

Panometric
Associate III

@jnord Did you ever figure out of this will work? I'm wanting to do the same thing. Even if this part you are fighting here works, it seems it may not work without an HSE crystal also.