Document nRF52 LoRa OTA workflow

This commit is contained in:
mikecarper committed 2026-07-17 12:53:17 -07:00
1 parent 2c4e6da63b
commit 56c26ec1bf
2 files changed
+134 -30

No files matched your search

+1 -1
View File
@@ -6,7 +6,7 @@ Below are a few quick start guides.
- [Frequently Asked Questions](./faq.md)
- [CLI Commands](./cli_commands.md)
- [Easy Full-Firmware Update over LoRa](./ota_easy.md)
- [Easy LoRa OTA: ESP32 full images and nRF52 deltas](./ota_easy.md)
- [GPS Tracking](./gps_tracking.md)
- [Companion Protocol](./companion_protocol.md)
- [Packet Format](./packet_format.md)
+133 -29
View File
@@ -1,7 +1,17 @@
# Easy full-firmware update over LoRa (ESP32)
# Easy firmware updates over LoRa
This guide shows the shortest manual path for sending a **full firmware image** from a computer to a
MeshCore node over LoRa. It uses this temporary OTA channel:
This guide shows the shortest manual path for sending firmware from a computer to a MeshCore node over
LoRa. Choose the package type for the **destination** node:
| Destination | Update type | Files needed to build the `.mota` | Installer |
| --- | --- | --- | --- |
| ESP32 | Full firmware | New non-merged application `.bin` | ESP32 A/B firmware slots |
| nRF52 | In-place delta | Exact running `firmware.hex` and new `firmware.hex` | Exact-board OTAFIX bootloader |
An nRF52 node cannot install an ESP32-style full-image container. It deliberately accepts only an in-place
delta built against its exact running firmware.
## Temporary OTA channel used in this guide
| Setting | Value |
| --- | --- |
@@ -26,24 +36,17 @@ location and change it when necessary.
## Before you start
You need:
Both paths require:
- A standard, non-logging Keymind OTA build on the source and destination nodes. Logging and MQTT builds do
not include LoRa OTA. Use the WiFi or USB connection to update those.
- An OTA-capable ESP32 destination with an A/B partition table. nRF52 has a single application slot and
cannot install this guide's full-image container; it requires an in-place delta plus the exact matching
OTAFIX bootloader. On RAK4631 repeaters, the OTA target is named
`RAK_4631_repeater_no_external_sensors_lora_ota`; it retains built-in battery monitoring but omits optional
external environmental/GPS sensor packages to fit the safe in-place update limit.
- The new, non-merged `.bin` application firmware for the destination's exact board **and role**. Do not
package an ESP32 `-merged.bin` factory image.
- Standard, non-logging Keymind OTA firmware on the source, destination, and intermediate nodes. Logging
and MQTT builds do not include LoRa OTA; use WiFi or USB to update those.
- A source node connected to the computer by USB serial.
- Overlapping `tempradio` windows on the source, destination, and every repeater needed between them.
LoRa OTA packets are generated, received, and relayed only while `tempradio` is active. If any required
window closes, the transfer stops making progress and can resume during a later overlapping window.
## 1. Install `motatool`
## Install `motatool`
Install Rust if necessary, then install the standalone packaging and serving tool:
@@ -52,7 +55,11 @@ git clone https://github.com/vk496/motatool
cargo install --path ./motatool
```
## 2. Package the full firmware
## ESP32: package a full firmware image
The destination must be an OTA-capable ESP32 with an A/B partition table. Download or build the new
non-merged `.bin` application for the destination's exact board **and role**. Do not use an ESP32
`-merged.bin` factory image.
Put the application firmware in a working directory, then build a full `.mota` container. For example:
@@ -68,7 +75,91 @@ identity trailer so `motatool` and the destination can verify the target, hardwa
Do not continue if `motatool verify` reports a failure.
## 3. Start the temporary OTA channel
## nRF52: package an in-place delta
### 1. Install and check the OTAFIX bootloader
This is a one-time prerequisite. Install the OTAFIX bootloader built for the destination's **exact board**
from the
[nRF52 OTAFIX in-place-delta repository](https://github.com/mikecarper/Adafruit_nRF52_Bootloader_OTAFIX/tree/feature/ota-delta-apply).
Follow that repository's board-specific installation and erase instructions. If it does not contain the
destination's exact board, this LoRa install path is not yet available for that board; never substitute a
similar board's bootloader.
Before preparing or downloading a LoRa update, run this on the destination:
```text
ota self
```
Continue only if the reply includes:
```text
bootloader: apply OK
```
The reply also contains the running firmware's `base_hash`. Save it for the package check below. A stock,
legacy, or older OTAFIX bootloader without `.mota` in-place-apply support will report that apply support is
missing, and `ota install` will refuse to reboot into it.
### 2. Keep the exact current and new application images
You need the raw `.pio/build/<environment>/firmware.hex` from the build that is **actually running**, plus
the corresponding `firmware.hex` from the new build. Save the current file before building the new version,
because PlatformIO reuses that path. For example:
```bash
# Save this immediately after building/flashing the version now running on the node.
cp .pio/build/Heltec_t114_repeater/firmware.hex ./Heltec_t114_repeater-running.hex
# After checking out and building the new version, save its image separately.
cp .pio/build/Heltec_t114_repeater/firmware.hex ./Heltec_t114_repeater-new.hex
```
Replace `Heltec_t114_repeater` with the destination's exact PlatformIO environment. The two images must be
for the same board and role, and both must contain their `EndF` trailers. Do not pass a release `.uf2` or
BLE-DFU `.zip` to `motatool`; those are installation containers rather than raw application images.
Keeping a file with the same version label is not enough: the base must be byte-for-byte identical to the
running application. The hash check in the next step proves that it is the right file.
On RAK4631 repeaters, use the
`RAK_4631_repeater_no_external_sensors_lora_ota` environment. It retains built-in battery monitoring but
omits optional external environmental/GPS sensor packages so the delta fits the safe in-place workspace.
### 3. Build and check the in-place delta
```bash
mkdir -p ./motas
motatool build \
--base ./Heltec_t114_repeater-running.hex \
--fw ./Heltec_t114_repeater-new.hex \
--patch-type in-place \
--out-dir ./motas
motatool verify ./motas/*.mota
```
`motatool` prints the generated filename. Inspect that file:
```bash
motatool inspect ./motas/GENERATED_FILENAME.mota
```
Check all three of these before serving it:
- `codec_id` is `2 (detools-in-place)`.
- `base_hash` is the same 8-byte value reported by the destination's `ota self` command.
- The numeric `target_id` exactly matches `target:` in the destination's `ota status`, and the hardware and
firmware version identify the intended board and role. If `inspect` shows `N/A` for the human-readable
target name, the tool's name table is older than that environment; the numeric IDs still must match.
The default `--inplace-memory 0x98000` and 4096-byte segment size match the supported MeshCore OTAFIX
builds; do not override them for this normal nRF52 flow. Do not continue if verification or any identity
check fails.
## Transfer and install either package
### 1. Start the temporary OTA channel
On the source node, destination node, and every intermediate repeater, run:
@@ -83,7 +174,7 @@ If you administer the destination over LoRa, the controller used to send later `
able to communicate on this temporary channel. For unattended nodes, use synchronized `tempradioat` entries
instead of manually starting the windows. Ensure the nodes' clocks are set before using `tempradioat`.
## 4. Serve the update from the computer
### 2. Serve the update from the computer
Close any serial terminal using the source node's USB port, find its device name, and start the server:
@@ -91,12 +182,12 @@ Close any serial terminal using the source node's USB port, find its device name
motatool serve --dir ./motas --serial /dev/ttyACM0 -v
```
Replace `/dev/ttyACM0` with the source node's serial device. `motatool` attaches the folder to the source
node, and the source advertises the full update over LoRa while its temporary-radio window is active.
Replace `/dev/ttyACM0` with the source node's serial device. `motatool` attaches the folder to the source,
which advertises the update over LoRa while its temporary-radio window is active.
Leave this command running until the destination finishes downloading.
## 5. Find and download the update
### 3. Find and download the update
On the destination node, check its state and ask for nearby updates:
@@ -105,8 +196,9 @@ ota status
ota ls
```
Discovery is asynchronous. Wait a few seconds and run `ota ls` again if the list is initially empty. Find
the entry marked `[yours]` and `full`, then use its displayed number. If it is entry 1, run:
Discovery is asynchronous. Wait a few seconds and run `ota ls` again if the list is initially empty. Select
the entry marked `[yours]`: it should say `full` for the ESP32 path or `delta` for the nRF52 path. If it is
entry 1, run:
```text
ota pull 1 flash
@@ -119,10 +211,13 @@ ota status
```
The update is ready when the status says `ready to install`. OTA is deliberately the lowest-priority mesh
traffic, so a busy channel can make a full-image transfer take longer than the example window. If necessary,
start another overlapping `tempradio` window; the download resumes rather than starting over.
traffic. At the temporary-radio settings in this guide, allow roughly **one hour** for a typical ESP32 full
image over a quiet, direct link. That is a planning estimate, not an upper bound: repeaters, retries, weak
links, and normal mesh traffic can extend it well past an hour. The 120-minute example window is
intentional. If necessary, start another overlapping `tempradio` window; the download resumes rather than
starting over.
## 6. Verify and install
### 4. Verify and install
Once the destination reports `ready to install`, run:
@@ -130,8 +225,12 @@ Once the destination reports `ready to install`, run:
ota install
```
The destination verifies the complete firmware again before approving it. If verification succeeds, it
reboots and applies the update. If verification fails, it keeps the current firmware and reports an error.
The destination verifies the complete package again before approving it. ESP32 installs the full image into
its inactive A/B slot. nRF52 checks the base hash and bootloader capability, then reboots into OTAFIX; the
bootloader independently rechecks the package, applies the delta in place, and verifies the resulting image.
Pre-install failures leave the running firmware unchanged and report the reason. If power is lost after an
nRF52 in-place apply has begun, OTAFIX will not boot a partial image; it enters recovery DFU so a known-good
application can be restored.
After the node returns, reconnect on its normal radio channel and confirm:
@@ -144,11 +243,16 @@ ota status
- **Nothing appears in `ota ls`:** confirm that `motatool serve` is still running and every required node
has an active `tempradio 909.950,125,5,5,120` window.
- **The update is marked `[other hw]`:** it is for a different board or firmware role. Do not install it.
- **An nRF52 node does not list a full update:** this is intentional. nRF52 accepts only an in-place delta.
- **nRF52 reports no bootloader apply support:** install the exact-board in-place-delta OTAFIX bootloader
before trying LoRa OTA.
- **nRF52 reports a base mismatch:** the file passed to `--base` is not the exact application running on
the destination. Rebuild the delta from the correct saved `firmware.hex`.
- **The download stalls:** check the source, destination, and intermediate repeaters. Restart matching,
overlapping temporary-radio windows if one expired.
- **The serial port is busy:** close the serial terminal before starting `motatool serve`.
- **The destination rejects the package:** verify that you used the non-merged application image with the
`EndF` trailer and that `motatool verify` succeeds.
- **The destination rejects the package:** verify the source files, their `EndF` trailers, the package's
target/hardware identity, and the result of `motatool verify`.
For additional commands and safety details, see [the full OTA user guide](ota_user_guide.md). For protocol
and container internals, see [the OTA protocol specification](ota_protocol.md).