Skip to main content
Graduate II
August 29, 2024
Question

Writing a program that updates itself at runtime

  • August 29, 2024
  • 3 replies
  • 3355 views

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.

    This topic has been closed for replies.

    3 replies

    Graduate II
    August 29, 2024

    Well generally you don't want to erase / overwrite the existing firmware as the window for failure and bricking is exceedingly high.

    Configuration type stuff, you separate the pieces so the configuration has it's own entity, and perhaps if corrupted gets written with some default.

    You could move enough code to RAM to erase flash, and update via say X-MODEM, but you're not really going to be able to do things concurrently, ie run your app whilst updating.

    If you have enough RAM to stage the entire firmware, then just do that, and reflash when you have a complete and valid image. Shrinks the window for failure significantly.

    If you have MicroSD or SPI FLASH, you can stage there too.

     

    Graduate II
    August 29, 2024

    I forgot to say that my current setup uses a bootloader for USB DFU updates, and all updates to the firmware should be done over USB DFU. Do you think this is still possible?

    Graduate II
    August 29, 2024

    Not clear on the benefits of running a DFU update from RAM, vs just using the ROM

    Graduate II
    August 29, 2024

    Questions to ask yourself.

    How large is the firmware you're running?

    Will the firmware run in RAM based on it's size of code/data foot print?

    Does your HID firmware implement a Compound USB Device with HID + DFU ?

     

    Graduate II
    August 29, 2024

    @Tesla DeLorean wrote:

    Questions to ask yourself.

    How large is the firmware you're running?

    Will the firmware run in RAM based on it's size of code/data foot print?

    Does your HID firmware implement a Compound USB Device with HID + DFU ?

     


    - Assume the firmware does fit in RAM.

    - One current version isn't DFU + HID: the bootloader is DFU and the program after that is HID.

    Another version is HID + HID: the bootloader is HID and the program is also HID.

    The "self-update" version I'm talking about would be (I guess) DFU + HID or just HID, since doing the updates over HID is also okay.

    Graduate II
    August 29, 2024

    Well should definitely be possible to migrate the firmware into RAM, I'd approach via 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.

    Graduate II
    August 30, 2024

    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.