Skip to main content
jacob2
Associate III
March 16, 2017
Question

STM32L4 bootloader on internal flash jumping to application on external flash

  • March 16, 2017
  • 7 replies
  • 2369 views
Posted on March 16, 2017 at 16:09

I'm working with an STM32L476ZG with an external flash connected through the FMC interface set up as NOR Flash memory starting at address 0x64000000. I wrote a custom bootloader to write code to this external flash address and I am now working to jump to application but am running into problems. I currently have the bootloader and main application built so before the jump the bootloader will set the vector table to the base of the external flash and the main application agrees in the System_Init. My jump procedure is as follows:

JumpAddress = *(__IO uint32_t*) (EXT_FLASH_START_ADDRESS+4);

Jump_To_Application = (pFunction) JumpAddress;

SCB->VTOR = EXT_FLASH_START_ADDRESS | (APP_OFFSET & (uint32_t)0x1FFFFF80);

__disable_irq();

//Initialize user application's Stack Pointer

__set_MSP(*(__IO uint32_t*) (EXT_FLASH_START_ADDRESS));

Jump_To_Application();

where EXT_FLASH_START_ADDRESS is 0x64000000, APP_OFFSET is 0x00000000, JumpAddress is a uint32_t, and Jump_To_Application is defined as pFunction.

I have __enable_irq(); as the first thing that gets done in main on the actual application code.

I was wondering if there were additional steps I would need to take for trying to run in external flash? I have this bootloader set up similar to another project I've worked on in the past but that was using exclusively the internal flash. From debugging, it looks like I manage to set the new stack pointer correctly and I jump to what I believe is the right address to start execution. It manages to go a few steps further and then sits in one spot which I believe is an infinite loop.

#stm32l4 #stm32l4-bootloader #stm32l4-external-flash #stm32l4-flash
This topic has been closed for replies.

7 replies

Tesla DeLorean
Guru
March 16, 2017
Posted on March 16, 2017 at 16:23

SCB->VTOR = EXT_FLASH_START_ADDRESS; // Should suffice, it is a register expecting the low 8-9 bits to be zero

Disabling interrupts in this fashion is a cop out. Turn off the sources for the interrupts so you have a clean slate. Turn off SysTick, etc.

When you simply __enable_irq() on the other side of the wormhole it is just going to jump immediately to vector table entries where you've done no initialization or preparation. Most probably Default_Handler

Look at the infinite loop address in the .MAP file. It shouldn't be that hard to determine what source line in your app code this is. The entry point is Reset_Handler, in startup.s, walk the code execution.

Consider a Hard Fault Handler on the boot loader side, and not reconfiguring SCB->VTOR until you get to SystemInit() or main() on the App side.

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
jacob2
jacob2Author
Associate III
March 16, 2017
Posted on March 16, 2017 at 16:34

By 'Turn off SysTick' are you referring to just going through and calling HAL_NVIC_DisableIRQ() on all possible interrupts I have enabled? or should I call DeInits for everything that might be initialized?

Tesla DeLorean
Guru
March 16, 2017
Posted on March 16, 2017 at 19:59

My philosophy would be to leave the kitchen tidy, don't leave everything a mess, leave it as you would like to find it.

My approach would be to turn things off, getting them into a non-triggering state

SysTick->CTRL &= ~(SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk);

USART_ITConfig(USART1, USART_IT_RXNE, DISABLE);

Now contractually, your boot loader could hand specific things over to your application working, but in those case you clearly need to identify what those are, and what buffers and memory, and interrupts need to get handled. It is one thing to hand over a system with the PLL functioning and a USART ready to go, it is another to get a fire hose of data streaming in when you enable the interrupts. Where is that supposed to go when the C runtime hasn't initialized the statics, or you don't have a handler on the application side.

If you hand over a functioning PLL, you'd generally not want to stop and tear it down and then immediately restart it, but that is what most code in SystemInit() will do if you don't manage it properly. Most of the example code expects to be handed a system in near reset conditions, you should pay close attention to things when that's not the case.

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..