cancel
Showing results for 
Search instead for 
Did you mean: 

Jumping to bootloader from user code in STM32L476

Aaron McNeil
Associate III

I am trying to implement a procedure to update firmware in a STM32L476 by jumping to the bootloader from user code. I am able to connect Boot0 to 3,3V and enter the bootloader just fine. But trying to jump there from user code seems to be giving some problems.

It seems that when I execute my code, the device does a soft reset, and just restarts the application. I believe it may have something to do with the dual bank management. Even when I jump to the bootloader, I think it is checking both ram locations and finding valid code, thus not staying in the bootloader. Here is my code:

void JumpToBootloader(void)

{

  void (*SysMemBootJump)(void);

  // Step: Set system memory address

  //    See AN2606 rev 38, Table 118

  volatile uint32_t addr = 0x1FFF0000;

  // Step: Disable RCC, set it to default (after reset) settings

  //    Internal clock, no PLL, etc.

  HAL_RCC_DeInit();

  // Step: Disable systick timer and reset it to default values

  SysTick->CTRL = 0;

  SysTick->LOAD = 0;

  SysTick->VAL = 0;

  // Step: Disable all interrupts

  __disable_irq();

  // Step: ARM Cortex-M Programming Guide to Memory Barrier Instructions

  __DSB();

  // Step: Remap system memory to address 0x0000 0000 in address space

  __HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH();  // Call HAL macro to do this for you

  // Step: Remap is not visible at once. Execute some unrelated command! */

  __DSB();

  __ISB();

  // Step: Set jump memory location for system memory

  //    Use address with 4 bytes offset which specifies jump location where program starts

  uint32_t a = 0x1FFF0000 + 4;

  SysMemBootJump = (void (*)(void)) (*((uint32_t *)(a)));

  // Step: Set main stack pointer.

  //    This step must be done last otherwise local variables in this function

  //    don't have proper value since stack pointer is located on different position

  //;

  //    Set direct address location which specifies stack pointer in SRAM location

  uint32_t p = *(uint32_t *)0x1FFF0000;

  __set_MSP(p);

  // Step: Actually call our function to jump to set location

  //    This will start system memory execution

  SysMemBootJump();

   

  while(1);

  // Step: Use STM32CubeProgrammer or custom application to update firmware.

}

For testing purposes, I am just calling this function right after main() starts. One other thing I will need to be able to do is activate a GPIO to enable my RS232 chip that is connected to USART2. So I need that G?PIO to stay in the state I put it in instead of the reset state, is this possible

4 REPLIES 4

I seem to have to repeat this a lot, but this is like throwing your keys in the lake when you've asked the mechanic to work on the car, its unhelpful.

 // Step: Disable all interrupts

  __disable_irq();

You need to disable the sources, not the processor. The loader will not re-enable this.

The L4 loader may also quite likely bounce back if it finds executable code in FLASH.

No, you're not going to be able to fiddle with GPIO or clocks and expect the loader to honour them.

If you have custom hardware that needs special conditions you will either need to write your own loader, or find a way to leverage entry points into the ROM.

 

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

I understand that disabling the interrupts this way isn't the cleanest, but I am just using this procedure as a test to try to see if I can jump to the bootloader successfully. I am calling this function before I've even enabled any interrupts. When I get to where I can enter the bootloader, I will do this procedure more elegantly and disable all individual interrupts.

So, to the real problem, is it not possible to use the bootloader on the L4 from code since it just bounces back if there is already code in FLASH?

Lastly, if I configure the GPIO before jumping to the bootloader, will it lose its state upon entering it? I dont need to change them while in the bootloader, just need to make sure my RS232 chip stays enabled in order to communicate to the USART2 peripheral.

Piranha
Chief II

> The L4 loader may also quite likely bounce back if it finds executable code in FLASH.

At least STM32L432KB starts the system bootloader after reset under these conditions:

  1. FLASH is empty. BOOT0 state doesn't matter.
  2. BOOT0 is high. FLASH state doesn't matter.

> just need to make sure my RS232 chip stays enabled in order to communicate to the USART2 peripheral

Reverse the hardware logic - make that chip enabled by default (with MCU pin at reset state) and disable it in your firmware.

Johnny1
Associate III

In my code, it was also required to suspend the HAL Tick after HAL_RCC_DeInit() and HAL_DeInit() to make it working:

HAL_SuspendTick();