2024-08-29 12:28 PM
How can you write a program that updates itself for an STM32, eg. for an STM32F103C8?
I'm not talking about a bootloader, since (as far as I know), a bootloader lives from (say) 0x08000000 to 0x08001000 in Flash and then updates another program (another part of flash), in this case, eg., starting at 0x08001000.
One option I thought of would be to run the code not from flash but from RAM/SRAM, like in this question and then update the flash memory, reset, and boot from flash. However, the answers there involve booting from SRAM, which I think I may not want to do. (One of the reasons being that this must run in production, without a debugger.)
Rather, what makes more sense to me is to flash the program to the STM32 flash, as usual, at 0x08000000, run the code from flash, and then, at runtime, upon receiving the update command from the user, move the entire program (or perhaps just the strictly necessary parts) to RAM/SRAM, continue execution from SRAM, and then update the entire flash memory and reset the MCU and boot from flash, again, as usual. (In particular, you never boot from SRAM, and you only run code from SRAM when you want to update.)
So, can this (or something logically similar) be done, in order to have a program that updates itself completely?
Now, I know this is possible if you only want to update a subset of flash memory (eg. I think VIA does a partial update of flash memory at runtime in order to update keyboard mappings without reflashing the keyboard and without as much as reconnecting your keyboard), but I wonder how it can be done if you want to update the entire contents of flash memory.
2024-08-29 01:44 PM
@Tesla DeLorean wrote:Well should definitely be possible to migrate the firmware into RAM, I'd approach vis code in Reset Handler, and immediately after the Vector Table.
As there's no DFU in ROM, overwriting the FLASH gets to be a proposition with a lot of risk, and very few avenues for recovery.
- Yes, that sounds like something I could use. Could you please give more detail about doing this using a Reset Handler and the Vector Table?
- About recovery: is the STM32 device gets bricked, is it possible to recover by reflashing the keyboard using an ST-LINK programmer?
2024-08-29 02:04 PM
Build for 0x20000000 base address, with whatever split for data, rebase the Reset_Handler entry point, copy the entire FLASH image to RAM, set SCB->VTOR to 0x20000000 per SystemInit() and fork.
You could use ST-LINK with SWD/JTAG for recovery.
2024-08-29 05:52 PM
Thank you very much.
Can you elaborate more on the first part of the answer, please?
"Build for 0x20000000 base address, with whatever split for data, rebase the Reset_Handler entry point, copy the entire FLASH image to RAM, set SCB->VTOR to 0x20000000 per SystemInit() and fork."
Eg. when you say "Build for 0x20000000 base address" do you mean to change the base flash address in the .ld linker script from 0x08000000 to 0x20000000?
What do the other things mean?
I'm still in the process of learning STM32 programming in general, and STM32F103 programming in particular.
2024-08-30 10:20 AM
At some point I'm doing the actual work of making this happen..
You're making an image designed to run in RAM, and staged in FLASH, and enough startup code to move it and transfer control.
Pretend it's not an STM32, and that it's an MCU and tool-chain you have familiarity with, the mechanics of code execution
2024-08-30 10:30 AM - edited 2024-08-30 10:33 AM
You completely dont say how new fw load into MCU... For more about ROM read AN2606 and F103 is little obsolete..
And subject of thread sounds more as try AI coding ... static update is many years standart
2024-08-30 11:44 AM - edited 2024-09-04 07:37 PM
> I wonder how it can be done if you want to update the entire contents of flash memory.
a lot of missing details here about what's driving your requirements (i.e XY problem).
> Rather, what makes more sense to me is to [...], at runtime, upon receiving the update command
> from the user, move the entire > program (or perhaps just the strictly necessary parts) to RAM/SRAM,
Generally, STM32 chips have far more flash than RAM (this is certainly true for the older STM32F103). If, as your description implies, your program is small enough to fit in RAM, then you're probably not constrained by flash space. So you can implement a dual-copies/active-partition scheme for your firmware, jumping to it after boot. Or sacrifice one sector of flash for use as an "immutable" update routine, and then use that to update the mutable portion of your firmware.
You are deliberately creating a potential bricking scenario If you design your update process such that a failed update can leave the system in a "non-bootable" state. If you want the ability to easily recover from a failed update, your update must not tamper with the code implementing the update process itself. Then, you can simply recharge the battery or put your cat outside, and try again.
That's why ST (or perhaps this is baked in by ARM?) places their bootloader in a separate section of memory, independent of user applications. When something goes wrong with your user application (because of a failed update, or user error), you have a chance to recover by activating a known-good piece of code that's still available on the device.