cancel
Showing results for 
Search instead for 
Did you mean: 

STM32L0x3 Bootloader + Application without Compiling for Flash Offset

CWadd
Associate

Hi there,

I am developing a bootloader + application architecture for both serial and OTA programming. 

I have managed to get this working, the bootloader is able to program the application into flash, check the CRC, set the VTOR, etc. and then jump into it (this process is well documented and I think I understand this part quite well).

Currently there are two methods of shifting the application code to the memory address where it will run. I have successfully used both of these:

1) The bootloader is located starting at 0x0800000. The application is starting at a predetermined fixed location, say for example 0x0800A000. The flash offset in the app linker script is changed so that the binary file is compiled for this memory location:

/* Specify the memory areas */
MEMORY
{
RAM (xrw)      : ORIGIN = 0x20000000, LENGTH = 20K
FLASH (rx)      : ORIGIN = 0x800A000, LENGTH = 192K
}

The bootloader then takes this bin file, programs it at 0x0800A000, jumps to it. No worries, works well.

2) The bootloader is located starting at 0x0800000. The application is starting at a variable location determined by the bootloader at runtime. The bootloader figures out what the end of it's own program space is, and then sets the application start address just after that.

The application is then compiled with no offset in the linker script (the VTOR is set by the bootloader, so the only change is that line is commented out in the app). This un-shifted binary is then sent to the bootloader (either over serial or OTA). The bootloader then shifts the binary to the correct offset and places it in flash.

The bootloader shifts this by adding the offset to any word which falls within the flash range, i.e. between 0x08000000 and 0x0802FFFF. So the bin file looks something like this after (left) and before (right) the shift:

0690X000008BUhzQAG.png

You can see that, for example, 0x0800D89D has been shifted to 0x0801529D by adding on the offset of 0x7A00. What you end up with is identical to the binary compiled with the flash offset as in 1).

The downside to method 1) is that you have to make sure you have compiled the firmware with the correct offset before sending it with to the bootloader. This is not great if there are different sized versions of the bootloader, or multiple possible app slots.

The problem with 2) is that it is possible the the shifting algorithm may not work for every bin file. For example, if you had a constant string (stored in flash) which happened to be stored in memory such that it looked like an address which should be shifted. Your binary data would then get corrupted, and break the application.

So after all that, my question is:

Is there another method or architecture of having a bootloader + application which doesn't require the application to be compiled with an offset?

As far as I'm aware the bootloader must start at the flash base (0x08000000), as this is what is run first when the devices powers up, but maybe there is a way around this (i.e. bootload at a different location, then jump into the app at 0x08000000)?

Memory remapping sounds like a good way to get around this problem:

https://www.sciencedirect.com/topics/engineering/boot-loader

but this doesn't seem possible on STMs?

Thanks in advance for any insight or suggestions.

1 REPLY 1
turboscrew
Senior III

You can try with PIC (position independent code) and convert the program to bin (just binary, no loader headers).

There should be compiler setting for generating PIC, but the binary may become somewhat bigger.