The Engineering Case for OTA in Bluetooth Modules

Field firmware updates via OTA (Over-the-Air) are no longer optional for deployed Bluetooth modules. A manufacturing bug in sensor calibration, a protocol stack vulnerability, or a new feature requirement can affect tens of thousands of units in the field. Without OTA, the only recourse is physical recall or on-site servicing — both expensive and slow.

Nordic’s DFU (Device Firmware Update) over BLE is the most widely deployed OTA mechanism for nRF52-series modules. This article walks through the architecture, implementation choices, and failure modes engineers need to understand before deploying OTA in production.

OTA Architecture: Bootloader and Application Regions

A BLE module supporting OTA requires flash memory to be partitioned into at minimum three regions:

Region Typical Size (nRF52832) Contents
MBR (Master Boot Record)4 KBEntry point; forwards to bootloader
Bootloader24–32 KBDFU logic, signature verification
Bootloader settings4 KBVersion info, image validation flags
SoftDevice (BLE stack)~140 KBNordic S132/S140
ApplicationRemaining flashUser firmware
DFU staging area~Equal to app sizeIncoming image buffer

On the nRF52832 with 512 KB flash, this leaves approximately 150–160 KB for the application and DFU staging area combined. If your application is large, this can become a constraint — the nRF52840 (1 MB flash) gives significantly more headroom.

Single-Bank vs. Dual-Bank DFU

This is a fundamental architectural decision with significant trade-offs:

Dual-Bank (Default, Recommended)

The incoming image is stored in a separate flash bank. The existing application continues running during the download. Only after the full image is received and validated does the bootloader swap banks.

  • Advantage: Interrupted update does not brick the device; the old firmware remains intact and runnable
  • Disadvantage: Requires ~2× application flash; impractical for large applications on 512 KB devices

Single-Bank

The bootloader erases the application region and writes the new image directly. No staging area is needed.

  • Advantage: No flash size penalty; full flash available for application code
  • Disadvantage: If power is lost mid-update, the device is bricked. Requires robust retry and recovery design at the system level

For most production deployments, dual-bank is the right default. Single-bank is only justified when flash is genuinely insufficient and the update infrastructure can guarantee reliable delivery (e.g., wired connection, or controlled RF environment).

Image Signing and Security

Unsigned OTA is a security liability. Anyone who can connect to the module can push arbitrary firmware. Nordic’s secure bootloader uses ECDSA-p256 signing — the update package (.zip) is signed with a private key, and only the corresponding public key (embedded in the bootloader at manufacturing) can validate it.

Key management considerations:

  • Private key storage: The signing key must never leave a secure build environment. Use an HSM (Hardware Security Module) for production signing, not a developer laptop.
  • Key rotation: ECDSA with 256-bit keys provides ~128-bit security. Plan for key rotation if device lifetime extends beyond 10 years.
  • Bootloader lock: After programming, lock the bootloader flash region (APPROTECT) to prevent read-back of the public key or bootloader code.

The nRF Connect SDK generates a key pair with nrfutil keys generate. The public key is compiled into the bootloader image; the private key is used at build time to sign update packages.

DFU Package Structure

Nordic’s DFU uses a .zip package containing:

  • manifest.json — describes the image type (application/softdevice/bootloader), target hardware revision, and firmware version constraints
  • app_update.bin — the firmware binary
  • app_update.bin.dat — the init packet (hash + signature)

The manifest.json version constraints are critical for production safety:

{
  "manifest": {
    "application": {
      "bin_file": "app_update.bin",
      "dat_file": "app_update.bin.dat",
      "init_packet_data": {
        "fw_version": 3,
        "hw_version": 52,
        "sd_req": [0x0101],        // Required SoftDevice version
        "type": "application",
        "sd_size": 0,
        "bl_size": 0
      }
    }
  }
}

Setting sd_req prevents applying a firmware update on incompatible SoftDevice versions, which would cause undefined behavior.

Implementing DFU Trigger in Application Firmware

The application needs a way to enter DFU mode on demand. Common approaches:

Buttonless DFU via BLE Service

Nordic provides a Buttonless DFU service (UUID FE59). The central writes to the “Enter Bootloader” characteristic, the device disconnects, writes a boot flag to a persistent memory region, and resets into the bootloader.

// Application-side: handle DFU trigger
static void dfu_trigger_handler(void)
{
    // Store boot flag in GPREGRET register
    // This survives a soft reset
    nrf_power_gpregret_set(BOOTLOADER_DFU_GPREGRET_VALUE);
    NVIC_SystemReset();
}

Hardware Trigger

A dedicated GPIO (button or manufacturing test pad) checked by the bootloader at startup. Simpler and more reliable than the BLE service approach, but requires physical access.

Watchdog-Triggered Entry

If the application detects a fatal error and cannot self-recover, it can set the DFU boot flag and trigger a reset. This allows recovery from corrupted application state via OTA without physical access.

Connection Parameters During DFU

DFU throughput is heavily influenced by BLE connection parameters. The default DFU connection interval of 7.5 ms with PHY 1M gives approximately 60–80 KB/min transfer rate. For a 150 KB application image, that’s 2–3 minutes per update.

Optimization options:

  • BLE PHY 2M: Available on nRF52840 and nRF52833; doubles throughput to ~120–150 KB/min
  • Connection interval: Reducing to 7.5 ms (minimum) maximizes throughput but increases radio duty cycle and heat. For battery-powered devices, balance with power constraints.
  • Data Length Extension (DLE): Increases PDU size from 27 to 251 bytes; improves efficiency significantly on long payloads

Failure Mode Analysis

OTA failures in production are more common than engineers expect. The key failure modes:

Failure Mode Root Cause Mitigation
Power loss mid-updateBattery depleted or removedCheck battery level before initiating; use dual-bank
Connection dropInterference, distance, phone movementDFU protocol supports resume; dual-bank preserves state
Signature verification failureWrong key, corrupted packageValidate package hash before transfer; version check in manifest
Version downgradeAccidental deployment of old firmwareSet fw_version monotonically; bootloader enforces minimum version
Stuck in bootloaderBoot flag set but no DFU initiator presentBootloader timeout: return to application if no DFU within 30s

Testing OTA Before Production

OTA is often undertested because it’s treated as an infrastructure concern rather than a firmware feature. Minimum test coverage for production readiness:

  • Happy path at all supported distances: Update at 0m, 5m, 10m from the central
  • Interrupted update simulation: Kill the phone app mid-transfer, reconnect, verify resume
  • Low battery update: Initiate update at minimum operating voltage; verify behavior at cutoff
  • Version enforcement: Attempt to apply an older firmware version; verify rejection
  • Stress test: 50+ consecutive updates on 10 devices; check for flash wear or memory leak

Summary

OTA firmware update is a critical capability for any Bluetooth module deployment that expects to operate in the field for more than a year. The implementation decisions made early — dual vs. single bank, image signing approach, failure recovery behavior — are difficult to change post-deployment.

The most important investment is test coverage. An OTA mechanism that works in the lab but fails at 10m range, low battery, or with a dropped connection is not production-ready. Test every failure mode explicitly before shipping.