1
\$\begingroup\$

I have a custom board with an STM32F407 on it. As SWD is not available, I have to program the microcontroller through the UART bootloader.

Imagine that the folllowing sequence of events takes place. I pull the BOOT0 pin high and after reset the microcontroller enters the bootloader. At my request, the bootloader erases the flash of the microcontroller. I assume that now all words in memory are 0xffffffff. Then I send a sequence of write commands to write the flash, starting at the first byte of my fimware image and continuing to the last.

If power fails or communication is lost somewhere in this process, I have a microcontroller that has an invalid program image in flash. When the microcontroller is subsequently powered on again, with BOOT0 so as to run the application, it runs what is essentially a corrupted firmware. Depending on the program behavior and attached hardware, the results could be catastrophic.

I cannot find any kind of support to inhibit firmware startup when a corrupt image is present in the STM32F407. Workable mechanisms could be a CRC check before the CPU jumps to the firmware or an "inhibit firmware startup" bit in flash that is set (erased) first during erase and cleared (written 0) last in the update process. However, I find no such provisions in the hardware.

  • Write a custom bootloader into Flash that has to be programmed one time. The reset vectors are set to always jump to the custom bootloader. That one checks for the presence and verifies the integrity of the firmware. To that end, the firmware has to include size and checksum information at a place known to the custom bootloader. This solution has the obvious downside of requiring me to get hold of this custom bootloader - writing it myself or adapting something that exists - and that the custom bootloader needs to be loaded first during production.
  • Assume that an erased flash leads to a lock up of the processor. I am not yet this convinced that booting into an erased flash leads to lockup quickly. Even if the processor locks up when booting firmware, I can still activate the bootloader by pulling /RST low, BOOT0 high and then releasing /RST. During update, after erase, the firmware is written starting just after the initial SP/initial PC reset vector pair. As the last step of the update, the initial PC/SP are written to the first two 32 bit words of the flash. The critical window is now only the write of these two words, reducing the chance of failure by orders of magnitude.

What are sensible strategies to deal with stated problem? Are the options presented above viable?

\$\endgroup\$
  • 3
    \$\begingroup\$ Add a persistent L1 bootloader coded by yourself which will implement the integrity checking. \$\endgroup\$ – Eugene Sh. Apr 2 at 14:50
  • 2
    \$\begingroup\$ Moreover, it looks like the STM32 bootloader has the "Get" command allowing you to read back the data, so you can implement the check o the programming host. \$\endgroup\$ – Eugene Sh. Apr 2 at 14:54
  • \$\begingroup\$ Thanks, this solution is the first one in my bullet point list in the question. Do you know of any open source bootloaders for the STM32 family that would be a good fit here? \$\endgroup\$ – distributed Apr 2 at 15:00
  • \$\begingroup\$ Unfortunately, checking the contents is not enough. Consider this: During update, power is lost. The microcontroller now has an incomplete firmware. When it is allowed to start the next time, it will be running from a corrupted firmware image. \$\endgroup\$ – distributed Apr 2 at 15:02
  • 1
    \$\begingroup\$ STM32 is in general not qualified for safety-critical applications. electronics.stackexchange.com/questions/427067/… \$\endgroup\$ – Eugene Sh. Apr 2 at 15:20
1
\$\begingroup\$

booting into an erased flash leads to lockup quickly

This may or may not happen - depending what was written and what was not. Note that depending on how the flash is updated and timing there might be no erased flash page - just some with new and some with old data.

initial PC/SP [...] The critical window is now only the write of these two words

True, but there will still be a chance for failure - not good enough for safety critical applications.

Note that users might be tempted to use a standard STM32 flashing tool instead of your software - it would work just fine with ROM bootloader but defeats your migitations completely.

Write a custom bootloader into Flash

I strongly recommend this approach if the results could be catastrophic in failure conditions.

\$\endgroup\$
0
\$\begingroup\$

your first option is trivial, the time you have waited for an answer here so far you could have written about 30 different bootloaders. You already answered the question you could simply have that programmed once bootloader do a crc if you have the time or a checksum if in a hurry and either use it or not. handfuls of code, minutes to write. Now the if not case okay that might be a research project or at least some experiments pretty sure ST documents how to launch the bootloader, should be as simple as branch to a high address or more likely read the magic high address plus 4 and bx to that address. (then you are in the factory bootloader and you dont have to write/replace one).

Making your own uart based bootloader is not difficult, in like 30-50 lines of code, maybe a few handfuls more I have written XMODEM, SREC, and IHEX based ones that just sit there and wait for you to download firmware, doesnt need to be more complicated than that. can have one that you make a protocol address, data with some frame around it like srec/ihex but different perhaps. another half an hour to an hour of development (well plus the time to learn how to flash in application which is pretty easy, I think st spells it out).

If you want to write your own loader that can flash, then you either want a dual banked device and the checker/loader is in one bank and the application in the other. Or you make the loader trampoline to ram. I am pretty sure the erase size on these parts is a fraction of the whole flash so even without a dual banked flash you could trampoline to ram and erase what you have defined as application space only.

You could setup the lowest erase block to have the vector table with reset pointing at the boot checker, you could have your application live starting at the next erase block if that leaves room for the boot checker to grow over time. I assume you have VTOR control so you dont need to mess with the other vectors have them dead end into an infinite loop in the checker.

Now the quick and dirty to not have to do any of this but still offers some risk but less. Is that if the front end of the vector table is erased then the bootloader gets called, you should have already seen this with virgin parts that you dont have to assert boot0 with a new part. I think it is only the first four words but you can figure this out experimentally. So when you download new firmware change your program to first erase the first block with the vector table which you probably do already, but write that block last, erase and write the rest of the application, write the first block last and only that period of time is at risk of power loss or reset or other event causing a corrupt image.

Lastly you could write perfect code that never ever needs a firmware update...grin...that would solve it...

These are COTS parts so not safety-critical as mentioned. But you could put a few hours of this extra effort in to help some.

This doesnt necessarily mean that if you lose power or reset at the right time the part doesnt corrupt or wipe out your backup bootloader, have not read flash manuals that closely but know some eeproms used to work that way, if you powered off just right or timed things just right you could lose data. Testing wouldnt prove there is never a way to do it but you could setup a test fixture to power on start a download/erase and turn the part off at a random time, repeat. Repeat short of the advertised number of flash cycles for the part. Each time check to see the boot checker came up and worked (or the application). at best a warm fuzzy feeling, but not a proof.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.