AnsweredAssumed Answered

STM32F405 - Support Firmware Update via Multiple Images Living in Internal Flash

Question asked by sooperuser on Sep 11, 2014
Latest reply on Aug 21, 2015 by Clive One
I'm trying attempting to wrap my head around a rather complex problem and am seeking a little guidance to get me started.

I'm developing a platform based on the STM32F405 and FreeRTOS with Atollic as the IDE of choice. I am currently investigating various "over the air" (OTA) firmware update methodologies. There are a few options I have considered, and I think the simplest (and most reliable) would be something like this:

1. Write a bootloader which is capable of "choosing" between two applications/firmware images, say app "A" and "B", both of which live in the 1MB internal flash (obviously the bootloader + "A" + "B" would be <= 1MB in size in order to fit in the internal flash). Note that "B" would essentially represent an updated version of "A".

2. The device would initially ship with bootloader and "A" on the internal flash (with ample space reserved for a subsequent update - this allows reversion to "A" should OTA FW update to "B" fail, if "B" is corrupted, etc.).

3. Some time later, a newer version of firmware, "B", is available. The application code (both "A" and "B") are capable of writing a new FW version to flash. That is to say, "A" receives "B" over the air and writes "B" to its respective home in internal flash.

4. Based on some magic value, the bootloader determines that we should now boot to "B" instead of "A". Note that "A" is still retained in flash, and the bootloader is capable of reverting to "A" should we encounter an issue with "B".

5. As additional updates roll out ("C", "D", etc.) this process is repeated. Obviously the normal update cycle would go "A" -> "B" -> "C" -> "D"... but its possible that if "A" -> "B" update fails (or user simply never gets "B" before "C" is available) we may see updates like "A" -> "C" (a firmware version is skipped, thus we cannot make any assumption about the absolute address where "C" may be placed)

From what I've read I believe what I've described is possible - I'm essentially replicating the "dual bank" feature that is present in other STM32s except the application code handles the flash update. That is, a bootloader can be used to select which FW version to boot, and each FW version should be capable of updating the sector(s) of flash it does not occupy. Can someone confirm if, in general, this methodology is sound?

Second, I've come across a few posts in this forum that discuss this process in general; [DEAD LINK /public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/STM32F4%20Dual%20images%20for%20firmware%20update%20-%20remapping%20interrupts&FolderCTID=0x01200200770978C69A1141439FE559EB459D7580009C4E14902C3CDE46A77F0FFD06506F5B&currentviews=2331]this post in particular seems to capture a lot of what I'm hoping to implement. However, I need some clarification on what special considerations are needed to accomplish this.

Beyond the need for a bootloader which can adequately jump to another image (and properly relocate the vector table) I understand there is the issue of position-independent vs position-dependent code. Can anyone shed some more light on how I can generate position-independent code (PIC)? (Perhaps this is a question better directed at Atollic?) Is there any reason to prefer one over the other? I would venture to guess that PIC likely consumes more code space than its "dependent" alternative?

Other than what I've listed here (bootloader that can properly jump to a new image, PIC vs. non-PIC), are there any other caveats to be aware of?