Zero-Brick OTA: Implementing Dual-Bank Bootloaders with Hardware Rollback
Deploying ten thousand connected devices into the field without a reliable Over-The-Air (OTA) firmware upgrade mechanism is an existential risk for any hardware company. If a newly pushed firmware binary crashes on boot, or if power is abruptly lost mid-flash write, the device can become permanently unresponsive (“bricked”), requiring an expensive technician truck roll or RMA replacement.
A production-grade OTA system must be completely resilient against:
- Sudden power loss during flash erase and write operations.
- Interrupted network packets over unstable cellular or satellite connections.
- Corrupted binary payloads and malicious tampering.
- Logic regressions or runtime crashes in the new application image.
Here is the architectural blueprint for KRAG’s dual-bank bootloader system.
1. The Dual-Bank (A/B) Flash Memory Map
The fundamental rule of fail-safe OTA updates is simple: never overwrite the currently executing application binary in-place.
Instead, we divide internal or external QSPI flash into two identical execution slots:
┌───────────────────────────────────────────────────┐
│ Internal Flash Memory │
├───────────────────────┬───────────────────────────┤
│ Sector 0 (32 KB) │ First-Stage Bootloader │
├───────────────────────┼───────────────────────────┤
│ Sector 1 (16 KB) │ Boot State & Metadata │
├───────────────────────┼───────────────────────────┤
│ Slot A (512 KB) │ Primary Application (v1) │
├───────────────────────┼───────────────────────────┤
│ Slot B (512 KB) │ Candidate Application(v2) │
├───────────────────────┼───────────────────────────┤
│ Sector N (64 KB) │ NVS / Encryption Keys │
└───────────────────────┴───────────────────────────┘
State Machine Transitions
The boot metadata sector maintains a simple, atomic record:
- Active Slot: Slot currently considered healthy (
SLOT_AorSLOT_B). - Update State:
STABLE,TESTING, orREVERT_PENDING. - Boot Attempt Counter: Number of times the candidate image has attempted to boot without confirming health.
When a new firmware version is broadcast from the cloud:
- The currently running app in
Slot Adownloads chunks of the new image and writes them intoSlot B. - The running app verifies SHA-256 hash and cryptographic signatures.
- The metadata sector is updated to point to
Slot Bwithstate = TESTINGandboot_attempts = 0. - The system executes a controlled soft reset.
2. Cryptographic Verification at the Edge (Ed25519 & ECDSA)
To prevent unauthorized or malicious binaries from executing, all firmware images are cryptographically signed before leaving our CI/CD build servers using public-key cryptography (such as Ed25519 or NIST P-256 ECDSA).
The image header contains:
- Magic identification bytes (
0x4B524147- “KRAG”) - Image version (SemVer, e.g.
2.4.1) - Target hardware board revision
- Monotonic version counter (to prevent downgrade replay attacks)
- 64-byte cryptographic signature
┌─────────────────┬──────────┬──────────┬───────────┬───────────────┐
│ Magic (4 bytes) │ Version │ Hardware │ Monotonic │ Signature │
│ 0x4B524147 │ (4 bytes)│ ID (4B) │ Counter │ (64 bytes) │
└─────────────────┴──────────┴──────────┴───────────┴───────────────┘
│
▼
Verified against Hardcoded Public Key in Bootloader
Before transferring execution to a newly written bank, the bootloader verifies the digital signature against a trusted public key embedded in write-protected bootloader flash. If the signature is invalid or the monotonic counter is lower than the currently running image, the candidate slot is rejected instantly.
3. The Two-Stage Watchdog and Self-Test Confirmation
What happens if the new binary has a valid cryptographic signature, boots successfully, but crashes 10 seconds later because a peripheral driver locked up?
This is where the hardware watchdog and health confirmation handshake come into play:
- On power-on, the bootloader sets a hardware independent watchdog timer (IWDG) for 60 seconds.
- Execution jumps into the candidate image in
Slot B. - The candidate application must perform a comprehensive self-test:
- Initialize internal buses (I2C, SPI, UART).
- Establish cellular/Wi-Fi connection to the cloud telemetry broker.
- Transmit an acknowledgement ping and receive server response.
- If and only if all self-tests pass within 60 seconds, the application calls:
/* Mark candidate image as confirmed and healthy */
boot_confirm_update_success();
- This call transitions the boot metadata from
TESTINGtoSTABLE. - If the application hangs, enters an infinite loop, or triggers a hard fault before calling this function, the hardware watchdog timer expires and resets the MCU.
- Upon reset, the bootloader notices that
Slot Bfailed its trial run, incrementsboot_attempts, and immediately falls back to the known-good image inSlot A.
Result: Zero dead devices in the field, even in the event of an unforeseen firmware bug.
4. Differential (Delta) Updates for Bandwidth Constrained Networks
For devices connected over satellite or low-data cellular IoT plans (e.g. 5 MB/month on NB-IoT), downloading a full 512 KB or 1 MB binary is prohibitively expensive.
Using binary delta compression algorithms (like Detools or Bsdiff), we generate delta patches between the current release and the new target. This shrinks update payloads by 85% to 92%—turning a 500 KB image into a compact 35 KB patch that transmits in seconds.
Conclusion
Reliable OTA engineering requires eliminating single points of failure across flash partitioning, cryptographic validation, and execution watchdogs. By designing with dual-bank hardware failovers from day one, your IoT fleet remains field-upgradable and secure for decades.
Looking to integrate secure bootloaders or automated fleet OTA into your connected products? Get in touch with KRAG’s firmware architects or scope your project with us.