Blog
How a Flash Bootloader Works: Dual-Bank A/B Updates Explained
July 7, 2026
Every embedded engineer has lived this nightmare at least once: a firmware update gets interrupted mid-write (power cut in Short), CAN bus glitch, a dropped OTA package and the device is left with half-written flash. No valid application. No way to recover except a bench reflash with a JTAG probe, or worse, a truck roll to physically retrieve the unit.
Dual-bank A/B flash bootloaders exist to make that scenario impossible by design. This article breaks down exactly how they work: the memory layout, the update sequence, the rollback logic, and the failure modes a solid implementation has to defend against.
A flash bootloader is a small, privileged piece of firmware that runs before the main application and is responsible for one job: getting a new, valid application image into flash memory safely. It typically handles:
On a single-bank device, the bootloader has nowhere to put the new image except on top of the old one. If the update fails partway, the old application is gone and the new one isn't complete — the device is bricked until someone intervenes with a hardware-level recovery.
A dual-bank (A/B) bootloader solves this by keeping two full, independent copies of the application in separate flash regions, so there is always a known-good fallback.
A typical dual-bank MCU or SoC partitions non-volatile memory into four logical regions:
| Region | Purpose | Typical Size |
|---|---|---|
| Bootloader | Immutable or rarely-updated boot code | 16–64 KB |
| Bank A | Application image slot 1 | Matches app size (e.g., 512 KB–2 MB) |
| Bank B | Application image slot 2 | Same size as Bank A |
| Metadata / Swap sector | Boot flags, version info, CRC, active-bank pointer | 64 B – 1 KB |
At any given time, one bank is active (currently running) and the other is inactive (holding either the previous version, or empty space ready for the next update). This is the core trick: the device is never without a bootable image, because the update always writes to the bank that isn't currently running.
Many automotive and industrial MCUs — ST's STM32 dual-bank line, NXP's S32K3, Infineon's AURIX, and TI's Hercules — implement this natively in hardware, with a bank-swap register that the bootloader can flip without erasing anything.
The update is initiated — via a UDS diagnostic session (service 0x34 RequestDownload, 0x36 TransferData, 0x37 RequestTransferExit in automotive contexts), an OTA campaign, or a manual command. The bootloader identifies which bank is currently inactive and targets it as the write destination.
The new firmware image is streamed into the inactive bank block by block. Critically, the active bank is never touched. If the vehicle loses power, the CAN connection drops, or the OTA transfer times out during this phase, the currently running application is completely unaffected — the device reboots normally into the bank it was already using.
Once the full image has landed in the inactive bank, the bootloader validates it before touching anything else:
If any check fails, the bootloader marks the inactive bank as invalid and aborts — the active bank keeps running, and the failure is logged for diagnostics.
Only after verification passes does the bootloader update the metadata sector — a small, atomic write that flips a single "active bank" flag or pointer from A to B (or vice versa). This is the moment the update actually takes effect, and it's designed to be a single, small, power-loss-safe write rather than a large one.
On next boot, the bootloader reads the active-bank flag and jumps to the new image. The device is now running the updated firmware — but the old image is still sitting untouched in the other bank.
This is the step many naive implementations skip, and it's the one that actually delivers fail-safety. The new image isn't marked as permanently good on first boot. Instead, it runs in a provisional/trial state:
If the boot counter exceeds a threshold (e.g., 3 failed boots without confirmation) or a watchdog reset fires repeatedly, the bootloader flips the active-bank pointer back to the previous known-good bank. The device is now running the old firmware again — no user intervention, no bench reflash, no field failure.
The safety property doesn't come from any single check — it comes from the fact that there is always a complete, previously-working image available, and the switch between images is a single atomic pointer flip rather than an in-place overwrite. Compare the failure surface directly:
| Failure Point | Single-Bank Bootloader | Dual-Bank A/B Bootloader |
|---|---|---|
| Power loss during write | Bricked (partial image, no fallback) | Unaffected — active bank untouched |
| Corrupted transfer | Bricked or requires re-flash | Detected at verification, aborted safely |
| New firmware bug/crash | Device stuck on broken image | Auto-rollback to previous bank |
| Update interrupted (comms drop) | Bricked | Retry write to inactive bank, no risk to active |
| Rollback needed | Not possible without external tool | Single metadata write, instant |
This is also why dual-bank A/B is the standard architecture behind OTA updates in automotive ECUs, IoT gateways, and consumer electronics (it's the same conceptual model Android and most Linux-based embedded systems use for OS updates, and it maps directly onto AUTOSAR's flash bootloader / FBL update sequence in automotive software stacks).
Flash wear and endurance.
Since each bank absorbs writes independently, wear leveling is naturally better distributed than a single-bank scheme that rewrites the same sectors repeatedly. Still, the metadata/swap sector sees frequent small writes and should sit in flash rated for higher endurance, or use wear-leveling logic.
Differential/delta updates.
Bandwidth-constrained links (cellular OTA, low-speed CAN) often pair dual-bank architecture with binary diffing, so only the changed bytes between versions are transmitted and reconstructed in the inactive bank, rather than the full image.
Security boundary.
The bootloader itself should be immutable or protected by a hardware root of trust (secure boot), because if an attacker can compromise the bootloader, the entire A/B safety mechanism — signature checks included — can be bypassed. Signature verification of the application image is necessary but not sufficient without a trusted boot chain underneath it.
Confirmation logic must be conservative.
A too-lenient "mark as valid" condition (e.g., confirming immediately after jump, before real functional checks) defeats the purpose of the trial-boot mechanism. The confirmation should require the new firmware to prove it can actually do its job — communicate on the bus, pass self-tests, hold a stable runtime — not just execute a few instructions.
| Strategy | How It Works | Rollback Support | Typical Use Case |
|---|---|---|---|
| Single-bank overwrite | New image overwrites old in place | None | Very low-cost MCUs, low update risk tolerance |
| Dual-bank A/B (this article) | Two full banks, atomic pointer swap | Automatic | Automotive ECUs, industrial controllers, IoT |
| Golden image + working copy | One immutable factory image, one updatable copy | Manual recovery to golden image | Safety-critical fallback with fixed recovery firmware |
| A/B with delta patching | Dual-bank plus binary diff to save bandwidth | Automatic | Bandwidth-constrained OTA (cellular, LPWAN) |
What's the difference between a dual-bank bootloader and a golden image recovery scheme?
A golden image scheme keeps one fixed, unchangeable "factory" firmware as a last-resort fallback, while the working copy gets updated normally. Dual-bank A/B, by contrast, keeps two full, updatable images and simply alternates which one is active — both banks can be updated over time, and rollback returns to the previous version rather than a permanently fixed factory build.
Does dual-bank flash always require twice the flash memory?
In the strictest implementation, yes — each bank must be large enough to hold a full application image. Some designs reduce this cost using compressed or delta-based secondary images, though this adds complexity to the bootloader's decompression/patch-application logic.
How does the bootloader know which bank to boot after a reset?
It reads a small metadata/swap sector in flash containing an active-bank flag, boot counter, and validity markers. This read happens on every boot before jumping to the application, and the write to flip that flag is kept small and atomic specifically so it can't be left in a half-written, ambiguous state.
Is dual-bank A/B required for UDS-based automotive flashing?
It isn't mandated by the UDS standard (ISO 14229) itself, but it's the dominant real-world implementation pattern for OEM and Tier 1 flash bootloaders because it satisfies functional safety requirements around update robustness that single-bank designs can't meet.
What happens if both banks become corrupted?
This is the scenario every robust bootloader design has to explicitly guard against — usually via a minimal, read-only recovery bootloader stage that sits below both banks and can accept a forced re-flash over a hardware interface (JTAG/SWD or a dedicated recovery UART) as the true last resort.