cancel
Showing results for 
Search instead for 
Did you mean: 

Vector table and flash origin addresses when using a bootloader to redirect to one of two apps

LKett.1
Associate II

I am trying to allow an STM32G070x MCU I'm using in a project to be (OTA) updatable by a second MCU. To that end, I followed Viktor Vano's instructions, here and here.

As described there, there is a (secondary) bootloader programmed at flash address 0x8000000 ("partition 1") and two versions of firmware for the MCU to run, at later flash addresses, in my case at 0x08003000 and 0x08011000 ("partition 2" and "partition 3"). The bootloader makes a decision of which firmware version to jump to, then jumps there using an assembly instruction, as also noted in the code here.

That works fine when the two versions of the MCU firmware are programmed to the MCU using the STM32CubeIDE, or similar, and each version has the FLASH  (rx)  : ORIGIN value set to 0x08003000 or 0x08011000 in the STM32G070CBTX_FLASH.ld file, and the VECT_TAB_OFFSET value set to 0x00003000U or 0x00011000U in the system_stm32g0xx.c file. That writes them to the correct place, and the bootloader can jump to one of the two partitions and run the appropriate firmware version.

The problem comes when I get the second MCU to send a new version of the firmware to the STM32 MCU. I want to write this firmware to either "partition 2" or "partition 3", depending on which one has the "oldest" firmware in. For that to be possible, the firmware needs to be writable to either partition (when an update arrives), so that the bootloader can run the new code, to test it works, before marking that firmware version as the "current" one to run on future reboots.

But, since the values for the FLASH  (rx)  : ORIGIN and VECT_TAB_OFFSET are essentially hard-coded into the firmware, if I write firmware that was destined for "partition 2" to "partition 3", the bootloader jumps there, but those FLASH  (rx)  : ORIGIN and VECT_TAB_OFFSET values seem to redirect code execution back to "partition 2".

That means that I'd have to have two versions of the firmware available each time the STM32 MCU needed to have an update, one that works in "partition 2" and one that works in "partition 3", and the second MCU would need to know which one was about to be written (when the update is sent to the STM32 MCU), so it could send the appropriate version for the "partition" (flash location) it would be written into.

I've read a few posts that say that STM's approach with this is "broken", and doesn't really allow for any flexibility where code is written to/run from, without the hard-coding of these addresses, but I'm not sure what would be a better approach.

Does anyone have any suggestions for a way to tackle this, that wouldn't require needing two versions of the firmware sent to the second MCU each time the STM32 MCU needs an update?

Thank you for any help you can give.

15 REPLIES 15

>>(as that's the minimum page erase that allows me to modify something, in a fixed position)

This is how i do it:

Copy the 2KB page from FLASH to RAM, modify the 2KB page in RAM (even if its only 1 byte), erase FLASH, copy the modified 2KB back from RAM to FLASH.

>>and I'm at about the limit of flash usage with all of the things that are going on in the bootloader and firmware partitions.

I see.

>>Maybe something in RAM is the way to go...

maybe, just add a variable to your linker script for the RAM space so its usage is reserved.

we dont need to firmware by ourselves, lets talk

@MM.1​ Yep this is simple when the developer owns the update process as well. But harder to explain the need for two variants to management and escape the Murphy laws (if something can be done wrongly, someone will always do so).

Pavel A.
Evangelist III

@gbm​ 

>  the easiest way of dealing with Bootloader or mutiple apps is to leave the VTOR seting to the bootloaer,

But this makes debugging harder in some IDEs. When you debug the app this requires that bootloader always runs and does its work before entering the app.

The ST debugger seems to do this by default (starts from target reset, this goes to the bootloader) but IAR by default intercepts reset and immediately moves to the app reset vector, bypassing the bootloader. It requires a custom script to run thru the bootloader (I could not find a simpler way).

Maybe , but only bootloader have info about partition with inactive boot, and code request proper variant or dont use it if is bad. I dont see place for murphy.

In IAR you can add the additional bootloader image and set the vector table address for debugging in

Project > Options > Debugger > Extra Options

 --drv_vector_table_base=0x08000000

 (Source: https://www.iar.com/knowledge/support/technical-notes/general/creating-a-bootloader-for-cortex-m/)

Thank you @spoorcc