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.

What Is a Flash Bootloader?

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:

  • Receiving firmware data over a communication channel (UDS/CAN, UART, Ethernet, USB, or OTA over cellular/Wi-Fi)
  • Verifying the image (checksum, CRC, or cryptographic signature)
  • Writing the image to non-volatile memory
  • Deciding which application image the microcontroller should boot into

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.

The Dual-Bank Memory Layout

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.

Step-by-Step: How an A/B Update Actually Happens

1. Update Trigger

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.

2. Staged Write to the Inactive Bank

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.

3. Image Verification

Once the full image has landed in the inactive bank, the bootloader validates it before touching anything else:

  • CRC32 or checksum confirms the data wasn't corrupted in transit
  • Cryptographic signature verification (ECDSA or RSA, depending on the security posture) confirms the image came from a trusted source and wasn't tampered with
  • Header/version check confirms the image is built for the correct hardware variant and isn't a downgrade to a blacklisted version

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.

4. Commit: Flipping the Active Bank Pointer

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.

5. Reboot Into the New Bank

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.

6. Post-Update Validation (the "trial run")

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:

  • A boot counter or "pending confirmation" flag is set before the jump
  • The new application must actively confirm it's healthy — usually by calling a "mark firmware valid" API after passing internal self-tests, establishing network/CAN communication, and running for some minimum stable period
  • If that confirmation never arrives (because the new firmware crashes, hangs, or bootloops), the bootloader detects it on the next reset and automatically rolls back

7. Automatic Rollback

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.

Why This Design Is "Fail-Safe" by Construction

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).

Design Considerations That Matter in Practice

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.

Dual-Bank A/B vs. Other Bootloader Update Strategies

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)

Frequently Asked Questions

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.