|
| 1 | +# ESP32 BLE Legacy DFU Template |
| 2 | + |
| 3 | +Production-ready ESP32 firmware template for OTA updates over **Bluetooth Low Energy (BLE)** using the **Nordic Legacy DFU profile**. |
| 4 | + |
| 5 | +This repository focuses on the ESP32 firmware side. |
| 6 | +The companion iOS app is maintained as a separate app/repository and is only included here as a development reference under `iOS/ESP32-DFU`. |
| 7 | + |
| 8 | +## What This Template Provides |
| 9 | + |
| 10 | +- BLE DFU service compatible with Nordic Legacy DFU UUID set. |
| 11 | +- Dual-slot OTA partition layout for safer updates. |
| 12 | +- Firmware streaming through DFU Packet characteristic. |
| 13 | +- Pre-commit validation by image size and CRC32 before activation. |
| 14 | +- Packet Receipt Notification (PRN) support. |
| 15 | +- Verbose serial diagnostics for protocol-level debugging. |
| 16 | +- Clean modular structure for long-term maintainability. |
| 17 | + |
| 18 | +## BLE Stack Overview |
| 19 | + |
| 20 | +- BLE library: `NimBLE-Arduino` |
| 21 | +- Role: GATT server on ESP32 |
| 22 | +- Service UUID: `00001530-1212-EFDE-1523-785FEABCD123` |
| 23 | +- Characteristics: |
| 24 | + - Control Point (`1531`): command/response path |
| 25 | + - Packet (`1532`): firmware and init payload stream |
| 26 | + - Version (`1534`): DFU protocol version information |
| 27 | + |
| 28 | +### Supported Legacy DFU Opcodes |
| 29 | + |
| 30 | +- `0x01` Start DFU |
| 31 | +- `0x02` Init DFU Parameters |
| 32 | +- `0x03` Receive Firmware Image |
| 33 | +- `0x04` Validate |
| 34 | +- `0x05` Activate and Reset |
| 35 | +- `0x06` Reset |
| 36 | +- `0x08` Packet Receipt Notification Request |
| 37 | + |
| 38 | +### Validation Logic |
| 39 | + |
| 40 | +Before finalizing an update, firmware validates: |
| 41 | + |
| 42 | +- expected image size (if provided) |
| 43 | +- expected CRC32 (if provided in init packet) |
| 44 | + |
| 45 | +Only after validation passes, `Update.end(true)` is called and new image is committed. |
| 46 | + |
| 47 | +## Project Structure |
| 48 | + |
| 49 | +- `platformio.ini` — PlatformIO environment and dependencies. |
| 50 | +- `partitions_ota.csv` — OTA partition table with `otadata`, `app0`, `app1`, `spiffs`, `coredump`. |
| 51 | +- `src/main.cpp` — firmware entrypoint (`setup()` / `loop()`). |
| 52 | +- `src/dfu_ble.h` — DFU module public interface. |
| 53 | +- `src/dfu_ble.cpp` — DFU BLE protocol implementation and OTA flow. |
| 54 | + |
| 55 | +## OTA Partition Strategy |
| 56 | + |
| 57 | +Template uses dual app slots: |
| 58 | + |
| 59 | +- active app runs from one slot |
| 60 | +- incoming firmware is written to the inactive slot |
| 61 | +- boot metadata in `otadata` switches active slot only after successful validation |
| 62 | + |
| 63 | +This minimizes risk of bricking during interrupted updates. |
| 64 | + |
| 65 | +## Requirements |
| 66 | + |
| 67 | +- ESP32 board supported by `espressif32` PlatformIO platform |
| 68 | +- PlatformIO Core (CLI or VS Code extension) |
| 69 | +- BLE DFU client (mobile app or custom client implementing Legacy DFU flow) |
| 70 | + |
| 71 | +## Quick Start |
| 72 | + |
| 73 | +1. Clone repository. |
| 74 | +2. Open the folder in VS Code with PlatformIO extension. |
| 75 | +3. Build firmware: |
| 76 | + |
| 77 | +```bash |
| 78 | +pio run |
| 79 | +``` |
| 80 | + |
| 81 | +4. Flash firmware: |
| 82 | + |
| 83 | +```bash |
| 84 | +pio run -t upload |
| 85 | +``` |
| 86 | + |
| 87 | +5. Open serial monitor: |
| 88 | + |
| 89 | +```bash |
| 90 | +pio device monitor |
| 91 | +``` |
| 92 | + |
| 93 | +## Typical Update Flow (Client Side) |
| 94 | + |
| 95 | +1. Connect to ESP32 DFU peripheral. |
| 96 | +2. `Start DFU` with expected app size. |
| 97 | +3. `Init DFU Params` start, send init payload, then complete init. |
| 98 | +4. `Receive FW Image`, stream binary in chunks. |
| 99 | +5. `Validate` and confirm success response. |
| 100 | +6. `Activate and Reset`. |
| 101 | + |
| 102 | +## Example Integrations |
| 103 | + |
| 104 | +- iOS app (SwiftUI + CoreBluetooth) acting as Legacy DFU client. |
| 105 | +- Android app with BLE GATT write/notify implementation. |
| 106 | +- Desktop updater script using BLE library and custom opcode sequence. |
| 107 | + |
| 108 | +## Naming and Style Conventions |
| 109 | + |
| 110 | +- Keep protocol constants explicit and close to implementation. |
| 111 | +- Use structured serial prefixes (`[DFU][STATE]`, `[DFU][ERROR]`) for fast log filtering. |
| 112 | +- Keep `main.cpp` minimal; place protocol logic in dedicated modules. |
| 113 | +- Prefer deterministic state transitions over implicit side effects. |
| 114 | + |
| 115 | +## Troubleshooting |
| 116 | + |
| 117 | +- Build fails for missing deps: |
| 118 | + - run `pio pkg update` |
| 119 | +- Device not visible in scanner: |
| 120 | + - verify BLE advertising started in serial log |
| 121 | +- Validate fails: |
| 122 | + - check expected size/CRC in init packet versus transmitted image |
| 123 | +- OTA boot issues: |
| 124 | + - confirm partition table is exactly `partitions_ota.csv` |
| 125 | + |
| 126 | +## Security Notes |
| 127 | + |
| 128 | +This template implements protocol-level integrity checks (size and CRC32), but does not include cryptographic signature verification by default. |
| 129 | +For production deployments, add signed artifacts and authenticity checks in bootloader or app-level policy. |
| 130 | + |
| 131 | +## Separate Mobile App Publication |
| 132 | + |
| 133 | +For releases, publish the mobile DFU client as a separate app/repository with its own versioning, signing, and release notes. |
| 134 | +Keep this repository focused on firmware template quality and embedded protocol behavior. |
| 135 | + |
| 136 | +## License |
| 137 | + |
| 138 | +Add your preferred license before publishing (for example, MIT or Apache-2.0). |
0 commit comments