cancel
Showing results for 
Search instead for 
Did you mean: 

Custom "thick" bootloader to boot identical application binary from either address A or B?

Code257
Associate III

Hello. I have run into a problem in a MCU project I have. I'll explain the situation.

We have a STM32F072RB -based product where we are implementing firmware update functionality. There would be 3 binaries in the MCU:

  1. Custom "thick" bootloader selecting application binary 1 or application binary 2 and jumping to run it
  2. Application binary 1 beginning at address A
  3. Application binary 2 beginning at address B

Our initial plan was to build different application binaries with explicitly different locations, but my customer is kind of wishing to use only one application binary. Therefore binary 1 would have exactly the same contents as binary 2.

Some experts say the way my customer wants the functionality is almost impossible to make. What do you say?

If anyone has any pointers what to google, what documents to read, etc, I'm all ears.

(My current, possibly stupid, idea is to make the single application binary to contain some kind of functionality to determine where it is run from and if it is run from binary 2 beginning from address B, then maybe perform some kind of elegant function/resource remapping so that when the image 2 runs, it does not use image 1 addresses for stuff, but locations in image 2 address space. Is this totally dumb?)

1 ACCEPTED SOLUTION
23 REPLIES 23

>>Some experts say the way my customer wants the functionality is almost impossible to make. What do you say?

Address/position Independent code, relocatable vector table, sure.

Thick loader defines the ground rules

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

Thanks, I'll get googling with this.

I cannot understand how compiling in position Independent mode alone can be enough.

The code must be written in a specific way, to avoid for example this:

void foo() {.... }
 
const void (*funcptr)() = foo;

as the const data is placed in the flash. Even if not, the image needs to contain relocations.

-- pa

Can't the address of a symbol be computed in a PC relative manner?

The real singular problem is absolute addresses within the executable region that might move. The linker should be able to identify these, and the libraries would need to be built with the same options/expectations.

Some testing and validation would be in order, one could start by having the linker build the images for two different base locations, and then comparing and identifying areas where the build changed.

The loader in this case would need to set aside some RAM to relocate the vector table into,and create an environment where either image code run successfully.

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

Here is a pretty dumb idea - pack both binaries in a single file. There you go. It's a "single binary" now.

Seriously... Compile and run firmware only at address A and use the address B as a backup storage. Before update a bootloader can copy the old firmware to it and in case of necessity copy it back to the address A.

More seriously... The "two applications" approach seems easy only for customer, marketing people and other non-engineers. And the gain is also pretty minor. Compared to other more typical approaches, you only gain one feature - in case of a failed update, a user doesn't have to repeat it until it is successful for the device to be fully usable again. But for most use cases there is no such requirement and the only real requirement is for the device to be able to recover. That means the bootloader must be smart enough to always be able to update the main firmware regardless of the main firmware's current state. With such an approach you also don't need to waste a half of the FLASH memory.

Yeah I think least hassle for us with most of the customer constraints honored would be if we had permission to have "regular", different binary for bank 1 and bank 2. And off course the bootloader. And yeah I have thought about bundling both application binaries together. I don't understand what's customer's endgame with single binary, but I promised some research.

Code257
Associate III

Ok I started to experiment a bit. I had NUCLEO-F070RB evaluation board and I followed this https://archive.is/GZubE : What I did:

  1. Created 2 example projects, 1 x Bootloader and 1 x Application (application blinks LEDs)
  2. For linker scripts, defined sections RAM, BOOTLOADER and FIRMWARE, removed FLASH sections, made ROM alias of BOOTLOADER or FIRMWARE and chanced FLASH references to ROM. I also added firmware start address symbol of firmware at 0x08004000
  3. For Bootloader main.c I added the extern to the firmware start address symbol, then added the jump command (needed to change CPU_NVIC_DisableIRQ => HAL_NVIC_DisableIRQ )
  4. For Application main.c I added the extern to the firmware start address symbol and in main() I made it call the added Remap_Table() function the first thing. I also added simple LED state changer for loop
  5. I opened STM32CubeProgrammer, did mass erase, then flashed the Bootloader to 0x08000000 and Application to 0x08004000.

To my utmost surprise the thing worked on the first try.

Of course this does not solve the original problem, but now I can experimentally poke the Application with compile and link options and try to arbitrarily locate it, put stuff to r9, etc. I need of course update the position to Bootloader, but only there if everything goes right. What an exciting endeavor so far!

Code257
Associate III

Ok, this is too complicated to gather info about. I'm giving up regarding the project (STM32F072RB).

But I'm still interested to get it working as a hobby (NUCLEO-F070RB).

Remember, there are 2 IDE projects, Bootloader and Application. Keeping this in mind, how should I change linker scripts? Should I add got and or plt sections? Where? Bootloader? Application? Both?

 (I tried to follow this partially: https://github.com/rgujju/STM32-projects/tree/master/got_plt but I have a bit different scenario I think and I'm failing)

In this case you only want position independent code, executing in place.. Every image will use the same stack, data & bss addresses.

So tinkering with GOT looks like overkill.

--pa