2

I am using the 32bit ARM STM32F439ZI microcontroller for my project. The microcontroller has 2 megabytes of flash memory organized into 2 banks of 1 megabytes each for simultaneous read and write/erase, as the datasheets points out.

I want to introduce Over The Air (OTA) firmware updates for the microcontroller.

I am using around 200-400 KB of flash storage for the firmware.

Of course, I could just only flash the download update binary using the boot loader. However, I would like to introduce a safety net by using the two 1 megabyte flash banks as a fail safe feature.

For example:

  1. The application downloads the new OTA firmware package onto an external storage.
  2. The application sets an flag with the internal flash (emulated EEPROM) as information to the boot loader to load an OTA firmware package from the external storage.
  3. The boot loader checks which "partition" (flash bank A or B) is active, switches the states and flashes the OTA firmware package onto the just activated flash bank.
  4. The boot loader resets the microcontroller.
  5. The boot loader detects, that bank B is the active bank and loads it contents as firmware.
  6. When there is a watchdog event or a crash, the boot loader detects the register flag and switches to the flash bank, which contains the previous firmware version.

I could not find resources if the "dual boot" is possible with the STM32F4 (there was something about the STM32F7 series, but that was advertised as an dedicated "feature").

Is the process possible or recommended with the STM32F4 series? Is there a better approach? And how the boot loader dispatch call (to the main function of the active flash bank) would looks like (Ansi C)?

burnersk
  • 3,320
  • 4
  • 33
  • 56
  • yes doable, on the right track for the most part, basically you want to have redundant features. ANSI-C has nothing to do with it though, not a C language thing, doesnt mean you wont use C, just means C is not relevant. – old_timer Jul 31 '18 at 11:54
  • I fact C has relevance, as I write the boot loader in C and the application in C and as the boot loader, which I write in C, I have to tell the machine that either flash bank A or B has to load - in C. And the last part is where I have no clue about. – burnersk Jul 31 '18 at 11:56
  • This sounds like it is not about dual redundant at all but instead a way to allow for updates. but you need to think through failed updates, bad images. You are relying on some percentage of good code to never be bad in order for this to work. – old_timer Jul 31 '18 at 11:57
  • Understood you are using C but C has nothing to do with this task, there is no C magic calls or anything to do with the C language that makes this work or not work any more than this conversation is happening in English, doesnt mean the English language is the key that unlocks this mystery, it is just a transport a means to the end. – old_timer Jul 31 '18 at 11:58
  • dual boot is something you have with an operating system and common/stock bootloaders for those platforms, this is your platform your bootloader so you define how things boot, its your design. – old_timer Jul 31 '18 at 11:59
  • The instruction you use to branch to some other code not compiled in is BX, you can wrap this with C in a couple/few ways, a function pointer, but need to check the disassembly to make sure the compiler is doing what you want, easiest is to just have a simple function in asm .globl HOP; HOP: bx r0 then take your destination address in C and orr in a one HOP(0x08010001). Might have to orr in the one as well with a function pointer, ideally the compiler will do the right thing though. – old_timer Jul 31 '18 at 12:01
  • as far as failed/bad images goes, how will you back out of a failed image, the watchdog timer goes off, you reset, you reset back into the same flash images. What you can do is use some ram, although that can get corrupted as well in the failure. – old_timer Jul 31 '18 at 12:03
  • You have the other problem of you will always boot into the 0x08000000 bank yes? I have not dug into the many st parts I have used but I dont think they offer a bank switch feature and if so where would that be stored through power cycles and resets? The lower address bank can be the factory version the other bank can be the upgraded version. Definitely want a checksum/crc on that image that the bootloader checks before even considering booting there. if that passes perhaps the bootloader leaves a signature, a few words in sram – old_timer Jul 31 '18 at 12:05
  • When the microcontroller resets (watchdog or crash), it must go through the boot loader. As I wrote in the question, I will check for what watchdogs have triggered or if there was a crash. When I detect a faulty firmware, I switch the active bank to e.g. A (again) and save it within the (emulated) EEPROM for the next boot. – burnersk Jul 31 '18 at 12:06
  • and starts the WDT, if that goes off and the signature is there then this is not a power on reset this is a watchdog reset and the signature may indicate that the upgraded image is no good. the bootloader can then choose to erase/corrupt it on purpose or just do the two step every time. – old_timer Jul 31 '18 at 12:06
  • so the bootloader is the only code touching the fake eeprom? that is fine for power cycles, etc. just talking through the fault cases to see if it all makes sense. – old_timer Jul 31 '18 at 12:08
  • you implied that one bank is active the other isnt and is getting the new image, I dont see how that would work unless the ST part has a non-volatile way of switching banks for you, re-mapping one into 0x08000000 (0x00000000) on power on or reset. – old_timer Jul 31 '18 at 12:09
  • You need to make a list of assumptions. Assume that at least one bank has a rock solid bootloader, no bugs. Assume the other bank can be corrupt or buggy, can fail in any way, any version string is just a small percentage of the bytes of the whole image, never trust just those bytes they can be corrupt like any other bytes in that image (checksum/crc before trusting any of it and understand those algorithms arent perfect, but assume they are). – old_timer Jul 31 '18 at 12:12
  • assume that while writing the flash power could go off unless you design the board/system to deal with that. including the eeprom that you use to determine the active bank assume that can become corrupt unless you have a system level solution. – old_timer Jul 31 '18 at 12:13
  • the dual boot nature simply means you can be executing from one bank while erasing/changing another. implying correctly that there are designs where you cannot execute from flash while erasing/changing the flash, you normally need or want to trampoline off of ram (copy a routine to ram, jump to that to execute from ram and stay off the flash). that is what the dual boot nature is. – old_timer Jul 31 '18 at 12:15
  • Now do they go beyond that and have non-volatile control registers that determine which bank is the lower address bank? I have some parts with the dual flash thing, but have not dug into if they can be remapped for booting. – old_timer Jul 31 '18 at 12:16
  • Having two versions of the firmware if you have enough FLASH is the most common way of doing it. – 0___________ Jul 31 '18 at 12:43
  • SYSCFG_MEMRMP allows you to remap the flash banks, runtime it appears, volatile. I assume you need to trampoline off of ram to do this. Dont think this is useful for this application, but interesting nevertheless. The banks are broken into sectors as one would expect so you could have more than one application per bank if you keep to these application sizes. – old_timer Jul 31 '18 at 13:56

2 Answers2

0

I'm not sure, If I understand the "Dual boot" completely, but if it is about having two versions of Firmware (Current working one to be replaced and the new firmware) in the flash, then the simplest method is to let the bootloader take a backup of the application firmware in a separate area of the flash memory before kicking-off OTA, however this reduces the total amount of usable flash. My master's thesis (Fail-proof over the air firmware upgrade for embedded systems) was on a very similar topic. You may want to take a look.

Amit
  • 327
  • 1
  • 4
  • 12
0
  1. The OTA with failover is implemented by Mongoose OS, https://mongoose-os.com for STM32 (including STM32F4). Mongoose OS repo is at https://github.com/cesanta/mongoose-os. The bootloader repo is at https://github.com/mongoose-os-apps/bootloader

  2. For STM32 setup without built-in connectivity, another approach would be to use https://vcon.io . That is, an ESP32 / ESP8266 communication module (Ethernet, WiFi, Cellular) which can OTA any attached STM32 microcontroller, and provide connectivity via varirous modes (e.g. transparent UART bridge).

Disclaimer: I represent both Mongoose OS and VCON products.

valenok
  • 827
  • 7
  • 9