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 KB | Entry point; forwards to bootloader |
| Bootloader | 24–32 KB | DFU logic, signature verification |
| Bootloader settings | 4 KB | Version info, image validation flags |
| SoftDevice (BLE stack) | ~140 KB | Nordic S132/S140 |
| Application | Remaining flash | User firmware |
| DFU staging area | ~Equal to app size | Incoming 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 constraintsapp_update.bin— the firmware binaryapp_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-update | Battery depleted or removed | Check battery level before initiating; use dual-bank |
| Connection drop | Interference, distance, phone movement | DFU protocol supports resume; dual-bank preserves state |
| Signature verification failure | Wrong key, corrupted package | Validate package hash before transfer; version check in manifest |
| Version downgrade | Accidental deployment of old firmware | Set fw_version monotonically; bootloader enforces minimum version |
| Stuck in bootloader | Boot flag set but no DFU initiator present | Bootloader 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.