cancel
Showing results for 
Search instead for 
Did you mean: 

STM32L4 bootloader on internal flash jumping to application on external flash

jacob2
Associate II
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
7 REPLIES 7
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
Up vote any posts that you find helpful, it shows what's working..
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?

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
Up vote any posts that you find helpful, it shows what's working..
Posted on March 16, 2017 at 23:01

Thinking more on what you've said, I was sure to disable everything that wouldn't be configured the same in the main application and have been running through tests, my main concern is keeping the external memory alive for the code to be running out of. It appears I go through the jump, make it through SystemInit() (vector table gets set to where I expect it to) and then I run into problems and I think eventually hit some fault that forces an infinite loop with an offset of 0x282 from the base of where I'm setting my code.

I tried modifying my code to toggle the LED after initializing all the GPIOs in main and I don't seem to make it that far so I seem to be hitting something either after SystemInit and before Main or before this GPIO initialize. Would extra precautions need to be taken for the GPIO pin configurations and the FMC configuration for the external flash to be able to execute code on it? Basically, I'm working on the case you mentioned later on where I simply want to hand over my functioning FMC config to the main application to keep external flash alive. I don't seem to be making it to the FMC init in the main application before my problems though, so would there be something in the GPIO init that could cause me problems? For instance, if it is initialized in the bootloader, would it need to be un-initialized before the main application or should the main application not initialize the pins again?

Posted on March 17, 2017 at 17:23

If you are executing code from the FMC, one would assume you've already initialized the pins, bus and peripheral to achieve that, tearing it down mid execution is probably inadvisable.

On the App side SystemInit() likely needs to do nothing, beyond setting SCB->VTOR, which you are doing already.

The code in __main (KEIL), called prior to your main() function is trying to clear/unpack the statics into RAM

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on March 17, 2017 at 18:19

I seem to be running into an issue when application code calls SystemClock_Config() that is throwing me into an infinite loop (probably through some fault) but unfortunately, I can't run through it with my debugger because it is not supported on the external flash so I am simply toggling LEDs to check progress.

Would it be bad to call a SystemClock_Config() in the main application if it was already called in the bootloader? I set it to shut off systick before I make the jump to application code, this function is just to reconfigure it and tunes down the HCLK from bootloader and initializes other peripheral clocks that were not ever enabled in the bootloader. In other projects, I've never been working with external flash or with a clock change between bootloader and application, here the only change is adding in some clocks to be configured and a slower HCLK but the APB clocks remain the same.
Posted on March 17, 2017 at 20:32

It is important to consider what it is doing, and if that is necessary. Changing the APB/AHB clocks probably isn't something you'd want to do if the FMC and the external bus timings are dependent on those things.

You can have the loader bring the system up in a viable state, the application doesn't have to change things, just enable the peripherals, clocks and pins it uses.

A lot of the stock ST code is going to assume reset conditions, adjust the application code to understand it isn't and tread more carefully. ie Test if the PLL is running before configuring it, make sure the HSI is functional before selecting it, chose not to repeat steps/processes you have made the loader responsible for.

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