Dual-bank flash versus external SPI flash for zero-downtime updates on 256KB STM32
0 reputation · 24 Mar 2024, 14:11 UTC
0 reputation · 24 Mar 2024, 14:11 UTC
A small application needs firmware updates without service interruption on an Arduino-compatible STM32 board with 256KB internal flash. The design requires the running image to stay intact while a new image is staged, and a reliable rollback path if the new image fails to boot.
Dual-bank flash uses the MCU’s two banks to hold current and candidate images. The inactive bank can be written while the application runs, and a bank swap is performed on reset via option bytes. This approach halves the usable flash for the application and depends on MCU dual-bank support. An external SPI flash approach keeps the full internal flash for the application and stages the update in external memory, with a small protected bootloader copying a validated image on boot. This adds BOM cost and requires free SPI pins and a custom linker layout.
The unresolved decision concerns atomicity of the bank swap and the size versus hardware cost trade-off under the 256KB limit.
Is the option-byte bank swap documented as atomic, or can power loss during the option byte write leave the device in an undefined boot bank? Does the Arduino_STM32 DualBankFlash library provide a documented mechanism to detect a failed boot and revert to the previous bank without application code? Can a protected bootloader with CRC validation and safe copy fit in a small reserved region while preserving enough internal flash for the application under the 256KB constraint?
35775 reputation · 24 Mar 2024, 22:06 UTC
For a 256KB Arduino-compatible STM32, dual-bank gives true zero-downtime staging only if your application fits in one bank ~128KB and the part actually supports dual-bank. External SPI flash preserves the full 256KB for the application but adds BOM cost and a bootloader copy step.
Confirmed: bank selection is controlled by option bytes, typically nSWAP_BANK / BFB2. The write to option bytes is performed by the flash peripheral and is intended to be atomic at the hardware level on families that support dual-bank. A power loss during the option byte programming sequence generally leaves the device in the previous boot bank or in system memory boot, not in an undefined half-swapped state.
Likely explanation: exact atomicity guarantees and recovery behavior are family-specific. The Reference Manual for the specific STM32 series must be consulted for the option byte programming flow and power-loss behavior. Not all 256KB parts support dual-bank.
Confirmed: the Arduino_STM32 DualBankFlash library provides APIs to erase/write the inactive bank and to trigger a bank swap via option bytes. It does not provide a documented automatic failed-boot detection and revert mechanism without application code.
Likely explanation: rollback must be implemented in application logic. Common pattern is a commit flag in backup registers or RTC backup domain. New image boots, runs health checks, then clears a boot-attempt counter and sets a committed flag. On boot failure or watchdog reset, a minimal bootloader or early init code checks the counter and toggles the option byte back to the previous bank.
Confirmed: a minimal protected bootloader that validates CRC and copies from external SPI to internal flash can fit in 4-16KB. With 256KB total, reserving 8-16KB leaves ~240KB for the application, more than the 128KB limit imposed by dual-banking.
Likely explanation: power loss during the SPI-to-internal copy can corrupt the active image. Safety requires a two-phase copy with a staging marker and final commit, plus CRC validation before activation.
Verification:
arm-none-eabi-size app.elfCheck linker script regions do not overlap bootloader and application.
Missing diagnostic detail needed to finalize recommendation: exact STM32 part number and current application binary size. Dual-bank support and bank size vary by family, which changes the recommendation.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.