Add external QSPI staging for nRF52 OTA
This commit is contained in:
1 parent
56afcb8fd9
commit
509f831442
40 files changed
+1671
-157
No files matched your search
@@ -41,7 +41,7 @@ retain 50 because their MQTT discovery tables are constrained by internal DRAM.
|
||||
| ESP32 MQTT observer or ESP-NOW bridge | Always uses the expanded FULL partition profile. The build never substitutes a reduced CLI to fit the legacy application slot. |
|
||||
| FULL ESP32 | Uses the matching MQTT target with logging off and keeps the complete command surface supported by that role and hardware. |
|
||||
| FULL ESP32 logging | Uses the matching non-MQTT target with debug and packet logging enabled, session-only `get/set usb.logging` control, and the complete command surface supported by that role and hardware. |
|
||||
| `no_external_sensors` | Removes optional external-sensor drivers and their settings; it does not remove core repeater discovery or routing commands. |
|
||||
| `no_external_sensors` | Removes optional external-sensor drivers and their settings; it does not remove core repeater discovery or routing commands. On RAK3401, this profile also compiles out GPS, so RAK12501 requires the ordinary full-sensor build. |
|
||||
|
||||
`logging`, `OTA`, and `FULL` describe independent build features. Do not infer
|
||||
that a command is missing merely because `logging` appears in the filename.
|
||||
|
||||
@@ -163,7 +163,7 @@ fix, no WiFi connection, an inactive bridge, or an nRF52 bootloader without
|
||||
| LoRa OTA | [`ota`; `ota status`; `ota st`](ota_protocol.md#11-cli-surface-otaclicpp) | LoRa OTA build | No | No | Yes |
|
||||
| LoRa OTA | [`ota stats`](ota_user_guide.md#1-see-what-im-running-and-whether-anything-is-going-on) | LoRa OTA build | No | No | Yes |
|
||||
| LoRa OTA | [`ota ls`; `ota neighbors`; `ota nbrs`; `ota updates`; `ota n`](ota_protocol.md#11-cli-surface-otaclicpp) | LoRa OTA build | No | No | Yes |
|
||||
| LoRa OTA | [`ota get`; `ota pull`; `ota download`](ota_protocol.md#11-cli-surface-otaclicpp) | LoRa OTA build; nRF52 installs in-place deltas | No | No | Yes |
|
||||
| LoRa OTA | [`ota get`; `ota pull`; `ota download`](ota_protocol.md#11-cli-surface-otaclicpp) | LoRa OTA build; internal-store nRF52 installs in-place deltas, while matched SD/QSPI nRF52 also accepts full images | No | No | Yes |
|
||||
| LoRa OTA | [`ota install`; `ota apply`; `ota applydelta`](ota_protocol.md#11-cli-surface-otaclicpp) | Compatible bootloader and completed update | No | No | Yes |
|
||||
| LoRa OTA | [`ota rescue install <base_hash16>`](ota_protocol.md#12-apply-bootloader-contract) | Internal-flash nRF52 LoRa OTA build with failed app-side EndF validation | No | No | Feature |
|
||||
| LoRa OTA | [`ota cancel`; `ota drop`; `ota stop`](ota_protocol.md#11-cli-surface-otaclicpp) | LoRa OTA build | No | No | Yes |
|
||||
|
||||
+2
-1
@@ -9,8 +9,9 @@ Below are a few quick start guides.
|
||||
- [Filter Policy Playground](./filter_tool.md)
|
||||
- [Telemetry Decoder](./telemetry_decoder.md)
|
||||
- [CLI Availability by Firmware Build](./cli_build_matrix.md)
|
||||
- [Easy LoRa OTA: ESP32 full images and nRF52 deltas](./ota_easy.md)
|
||||
- [Easy LoRa OTA: ESP32 and nRF52 firmware updates](./ota_easy.md)
|
||||
- [Scripted LoRa OTA: Bash and PowerShell](./lora_ota_automation.md)
|
||||
- [nRF52 repeater OTA with external QSPI](./ota_nrf52_qspi.md)
|
||||
- [MeshTower V2 microSD self-updates](./ota_meshtower_v2_sdcard.md)
|
||||
- [GPS Tracking](./gps_tracking.md)
|
||||
- [Companion Protocol](./companion_protocol.md)
|
||||
|
||||
@@ -61,6 +61,7 @@ while the same link carries framed folder requests. BLE remains available.
|
||||
| --- | --- | --- | --- |
|
||||
| ESP32 | Full application image | OTA-enabled image with an A/B partition table | Builds a full mOTA from the matching non-merged application `.bin` |
|
||||
| nRF52, internal flash | In-place delta | Exact-board OTAFIX bootloader with mOTA apply support | Requires `--base` with the exact image currently running |
|
||||
| nRF52 repeater, external QSPI | Full image or in-place delta | QSPI-aware exact-board OTAFIX bootloader and matched repeater build | Builds a full mOTA; adding `--base` requests a delta |
|
||||
| MeshTower V2 nRF52, microSD | Full image or in-place delta | SD-aware exact-board OTAFIX bootloader and compatible card | Builds a full mOTA; adding `--base` requests a delta |
|
||||
|
||||
The firmware inside a raw ZIP must have a valid MeshCore `EndF` trailer. An
|
||||
@@ -68,7 +69,7 @@ ESP32 merged/factory image is not an application image and is rejected. A
|
||||
generic vendor DFU ZIP may also be unusable if it does not contain the raw
|
||||
EndF-bearing `.hex` or `.bin`.
|
||||
|
||||
For an internal-flash nRF52, the exact base image is irreducible information.
|
||||
For an internal-staging nRF52, the exact base image is irreducible information.
|
||||
The node reports its eight-byte body hash, but that hash cannot reconstruct the
|
||||
firmware bytes needed to create a delta. Keep the `.pio/build/ENV/firmware.hex`
|
||||
that was actually flashed. A matching filename or version alone is not enough.
|
||||
@@ -177,7 +178,8 @@ ota stats
|
||||
|
||||
The script uses `get bootloader.ver` to distinguish ESP32 from nRF52 and, for
|
||||
nRF52, report the installed bootloader version. It then requires `ota self` to
|
||||
report `bootloader: apply OK` or `bootloader: SD apply OK` and checks the
|
||||
report `bootloader: apply OK`, `bootloader: QSPI apply OK`, or
|
||||
`bootloader: SD apply OK` and checks the
|
||||
reported bootloader ABI and codec mask against the selected package. If the
|
||||
version command is unavailable on older firmware, the script warns and falls
|
||||
back to the legacy `ota self` platform marker. If an nRF52 bootloader lacks
|
||||
@@ -238,7 +240,7 @@ Prefer the environment variable or the interactive password prompt. Passing
|
||||
local processes. The runner keeps the password out of child `meshcli` command
|
||||
lines and removes its protected temporary command file after each call.
|
||||
|
||||
## 5. Run an internal-flash nRF52 update
|
||||
## 5. Run an nRF52 update
|
||||
|
||||
If the input ZIP already contains a compatible in-place delta `.mota`, no
|
||||
base argument is needed: its embedded base hash is compared with the live
|
||||
@@ -258,16 +260,25 @@ node. If the ZIP contains raw new firmware, supply the exact running image:
|
||||
--source-serial COM8
|
||||
```
|
||||
|
||||
Before building the delta, the runner proves that the base's target ID,
|
||||
Before building a delta, the runner proves that the base's target ID,
|
||||
hardware identity, firmware version when available, and `EndF` body hash match
|
||||
the live destination. It then asks `motatool` for codec 2, the nRF52 in-place
|
||||
format. The normal workspace is `0x98000`.
|
||||
|
||||
For the SD-backed MeshTower V2 target, a raw ZIP becomes a full image without
|
||||
`--base`. Supplying an exact base requests a smaller in-place delta and
|
||||
automatically selects its `0xC7000` workspace. An explicit
|
||||
For a QSPI-backed repeater or the SD-backed MeshTower V2 target, a raw ZIP
|
||||
becomes a full image without `--base`. Supplying an exact base requests a
|
||||
smaller in-place delta and automatically selects the conservative external
|
||||
workspace `0xC6000`, which is safe for S140 v6 and v7 application layouts. An explicit
|
||||
`--inplace-memory` overrides the automatic value.
|
||||
|
||||
The live runner detects QSPI from `ota self` (`QSPI apply OK`) or `ota status`
|
||||
(`bl:QSPI`) and refuses an explicit `QSPI store:ERR 0K` report even when the
|
||||
bootloader itself advertises QSPI apply support. Offline `--prepare-only` runs
|
||||
must supply `--nrf-qspi`; do not use that switch for a board that only exposes
|
||||
QSPI pins or uses the chip as a
|
||||
Companion filesystem. The application and bootloader must both be from the
|
||||
matched repeater list in [the nRF52 QSPI guide](ota_nrf52_qspi.md).
|
||||
|
||||
## 6. Add intermediate relays
|
||||
|
||||
List relays from farthest to nearest so each command is sent before its route
|
||||
|
||||
+81
-37
@@ -9,12 +9,14 @@ For an end-to-end controller that accepts a release ZIP or ready mOTA, see
|
||||
| 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 |
|
||||
| nRF52, internal staging | In-place delta | Exact running `firmware.hex` and new `firmware.hex` | Exact-board OTAFIX bootloader |
|
||||
| Supported nRF52 QSPI repeater | Full firmware or in-place delta | New `firmware.hex`; a delta also needs the exact running `firmware.hex` | Matching QSPI-aware OTAFIX bootloader |
|
||||
| MeshTower V2 SD target | Full firmware or in-place delta | New `firmware.hex`; a delta also needs the exact running `firmware.hex` | Matching SD-aware OTAFIX bootloader |
|
||||
|
||||
A normal nRF52 target cannot install a full-image container. It deliberately accepts only an in-place
|
||||
delta built against its exact running firmware. The MeshTower V2 microSD target is the exception because
|
||||
it stages the complete container off-chip; see [MeshTower V2 microSD LoRa OTA](ota_meshtower_v2_sdcard.md).
|
||||
An internal-staging nRF52 target accepts only an in-place delta built against its exact running firmware.
|
||||
Matched QSPI repeater targets and the MeshTower V2 microSD target can also install a full image because the
|
||||
complete container stays off-chip. See [nRF52 repeater OTA with external QSPI](ota_nrf52_qspi.md) and
|
||||
[MeshTower V2 microSD LoRa OTA](ota_meshtower_v2_sdcard.md).
|
||||
|
||||
## Temporary OTA channel used in this guide
|
||||
|
||||
@@ -44,10 +46,11 @@ configurations. Confirm that it is permitted in your location and change it when
|
||||
|
||||
Both paths require:
|
||||
|
||||
- An OTA-enabled build whose artifact filename contains `-ota-` on the destination. The `-ota-` stamp confirms
|
||||
that the node can discover, download, verify, and install LoRa OTA. Intermediate repeaters do **not** need an
|
||||
OTA-enabled build: current repeater firmware relays OTA packets opaquely without storing or installing them.
|
||||
Standard logging and untagged builds cannot install LoRa OTA; FULL MQTT and FULL logging OTA builds can.
|
||||
- A destination artifact explicitly identified by its release table as install-capable. Some lean internal
|
||||
nRF52 builds carry `lora_ota_no_external_sensors` in the filename, while matched QSPI boards enable install
|
||||
support in the normal full-sensor repeater artifact, so filename text alone is not authoritative. Confirm
|
||||
support with `ota self` and `ota status`. Intermediate repeaters do **not** need an install-capable build:
|
||||
current repeater firmware relays OTA packets opaquely without storing or installing them.
|
||||
- An OTA-enabled MeshCore source connected to the computer by USB serial, or
|
||||
an ESP32 WiFi companion/FULL source connected over WiFi as described below.
|
||||
- Overlapping `tempradio` windows on the source, destination, and every repeater needed between them.
|
||||
@@ -57,14 +60,23 @@ apply their normal forwarding filters, duplicate checks, and flood limits; they
|
||||
payload. If any required window closes, the transfer stops making progress and can resume during a later
|
||||
overlapping window.
|
||||
|
||||
`build.sh` provides a `*_repeater_lora_ota_no_external_sensors` build for every standalone ESP32 and nRF52
|
||||
repeater target. The normal repeater build keeps its external-sensor support and can serve as an intermediate
|
||||
OTA relay, but it cannot download or install an update for itself. The `-ota-` sibling omits optional external
|
||||
I2C environmental sensors to preserve the update workspace, while retaining board-native features such as its
|
||||
display, buttons, battery monitoring, and integrated GPS. ESP32 `-ota-` siblings also retain the lightweight
|
||||
browser WiFi uploader (`start ota`), the complete CLI, and a 254-entry neighbor table. RP2040 and STM32 repeaters do not
|
||||
currently have a safe self-apply path, but current repeater firmware can still relay OTA packets opaquely
|
||||
during TempRadio.
|
||||
`build.sh` provides a `*_repeater_lora_ota_no_external_sensors` build for standalone ESP32 and nRF52 repeater
|
||||
targets that need a smaller internal update workspace. Those siblings omit optional external I2C
|
||||
environmental sensors while retaining board-native features such as displays, buttons, battery monitoring,
|
||||
and integrated GPS where the target uses the GPS-preserving lean profile. The
|
||||
RAK3401 target is an explicit exception:
|
||||
`RAK_3401_repeater_lora_ota_no_external_sensors` compiles out GPS and cannot
|
||||
use a RAK12501. Use the ordinary full-sensor `RAK_3401_repeater` build with a
|
||||
RAK12501 in sensor slot A when GPS is required; slot D conflicts with the
|
||||
RAK13302 radio's BUSY/DIO1 lines. Selected nRF52 boards with matched external
|
||||
QSPI application and bootloader support can instead make the normal full-sensor
|
||||
repeater install-capable; those targets do not need to reserve internal flash
|
||||
for the downloaded container. Other normal repeaters can still serve as
|
||||
intermediate relays but cannot necessarily install an update themselves. ESP32
|
||||
`-ota-` siblings also retain the lightweight browser WiFi uploader (`start
|
||||
ota`), the complete CLI, and a 254-entry neighbor table. RP2040 and STM32
|
||||
repeaters do not currently have a safe self-apply path, but current repeater
|
||||
firmware can still relay OTA packets opaquely during TempRadio.
|
||||
|
||||
nRF52 `-ota-` siblings are compiled with size optimization instead of the Adafruit platform's default
|
||||
speed optimization. This prevents the retained software Ed25519 fallback from expanding beyond the fixed
|
||||
@@ -153,16 +165,17 @@ identity trailer so `motatool` and the destination can verify the target, hardwa
|
||||
|
||||
Do not continue if `motatool verify` reports a failure.
|
||||
|
||||
## nRF52: package an in-place delta
|
||||
## nRF52: package a full image or 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
|
||||
[OTAFIX 2.4 nRF52 bootloader release](https://github.com/mikecarper/Adafruit_nRF52_Bootloader_OTAFIX/releases/tag/0.9.2-OTAFIX2.4).
|
||||
Follow the release'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.
|
||||
[OTAFIX nRF52 bootloader releases](https://github.com/mikecarper/Adafruit_nRF52_Bootloader_OTAFIX/releases).
|
||||
Internal-staging delta updates require OTAFIX 2.4 or newer. External QSPI and SD staging require OTAFIX
|
||||
2.4.1 or newer and release notes that explicitly list the exact board and storage mode. Follow the release'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:
|
||||
|
||||
@@ -172,17 +185,33 @@ ota self
|
||||
```
|
||||
|
||||
The first command identifies the installed nRF52 bootloader. Continue only if
|
||||
the `ota self` reply includes:
|
||||
the `ota self` reply includes the apply mode required by this target:
|
||||
|
||||
```text
|
||||
bootloader: apply OK
|
||||
bootloader: QSPI apply OK
|
||||
bootloader: SD 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
|
||||
### 2. Choose full or delta packaging
|
||||
|
||||
For a QSPI- or SD-backed target, a full update needs only the new raw
|
||||
`firmware.hex`:
|
||||
|
||||
```bash
|
||||
mkdir -p ./motas
|
||||
motatool build --fw ./LilyGo_T-Echo_repeater-new.hex --out-dir ./motas
|
||||
motatool verify ./motas/*.mota
|
||||
```
|
||||
|
||||
Use a full package when an exact base image is unavailable. Use the delta path
|
||||
below when reducing airtime is worth retaining the exact running image.
|
||||
|
||||
### 3. Keep the exact current and new application images for a delta
|
||||
|
||||
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,
|
||||
@@ -190,13 +219,16 @@ 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
|
||||
cp .pio/build/Heltec_t114_repeater_lora_ota_no_external_sensors/firmware.hex \
|
||||
./Heltec_t114_repeater_lora_ota_no_external_sensors-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
|
||||
cp .pio/build/Heltec_t114_repeater_lora_ota_no_external_sensors/firmware.hex \
|
||||
./Heltec_t114_repeater_lora_ota_no_external_sensors-new.hex
|
||||
```
|
||||
|
||||
Replace `Heltec_t114_repeater` with the destination's exact PlatformIO environment. The two images must be
|
||||
Replace `Heltec_t114_repeater_lora_ota_no_external_sensors` 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.
|
||||
|
||||
@@ -206,14 +238,19 @@ running application. The hash check in the next step proves that it is the right
|
||||
On RAK4631 repeaters, use the
|
||||
`RAK_4631_repeater_lora_ota_no_external_sensors` environment. It retains built-in battery monitoring but
|
||||
omits optional external environmental sensor packages so the delta fits the safe in-place workspace.
|
||||
If the device has a RAK15001 installed in sensor slot C and the matching
|
||||
RAK15001 OTAFIX bootloader, use
|
||||
`RAK_4631_repeater_rak15001_slot_c_lora_ota` instead. That target retains the
|
||||
full sensor/GPS set and can install either a full image or a delta from the
|
||||
external 2 MiB store.
|
||||
|
||||
### 3. Build and check the in-place delta
|
||||
### 4. 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 \
|
||||
--base ./Heltec_t114_repeater_lora_ota_no_external_sensors-running.hex \
|
||||
--fw ./Heltec_t114_repeater_lora_ota_no_external_sensors-new.hex \
|
||||
--patch-type in-place \
|
||||
--out-dir ./motas
|
||||
motatool verify ./motas/*.mota
|
||||
@@ -233,9 +270,12 @@ Check all three of these before serving it:
|
||||
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.
|
||||
Current layout-aware `motatool` derives the safe workspace from the new firmware's authenticated EndF layout
|
||||
record, so the normal recipe deliberately omits `--inplace-memory`. If older tooling requires an explicit
|
||||
override, use `0xC6000` only for matched external SD/QSPI staging and `0x98000` for an internal-staging nRF52
|
||||
such as the RAK4631 lean OTA build. Do not substitute the external value on an internal target, and do not
|
||||
override either value unless you have verified the exact app base, bootloader, and package geometry. Do not
|
||||
continue if verification or any identity check fails.
|
||||
|
||||
## Transfer and install either package
|
||||
|
||||
@@ -290,8 +330,9 @@ ota ls
|
||||
```
|
||||
|
||||
Discovery is asynchronous. `ota ls` says `refreshing`; wait a few seconds and run it again even if it first
|
||||
shows an older row. Select `[same target]`: it should say `full` for the ESP32 path or `delta` for the nRF52
|
||||
path. Do not select `[unsupported]` (for example, a source's self-served full image on a single-slot nRF52).
|
||||
shows an older row. Select `[same target]`: it can say `full` for ESP32 and external SD/QSPI nRF52 targets,
|
||||
or `delta` for any supported nRF52 target. Do not select `[unsupported]` (for example, a source's self-served
|
||||
full image on an internal-staging nRF52).
|
||||
Use the row's stable eight-hex manifest ID rather than its changing list position:
|
||||
|
||||
```text
|
||||
@@ -335,8 +376,9 @@ ota install
|
||||
```
|
||||
|
||||
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.
|
||||
its inactive A/B slot. nRF52 checks the bootloader and storage capabilities and, for a delta, the base hash,
|
||||
then reboots into OTAFIX. The bootloader independently rechecks the package, installs the external full image
|
||||
or 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.
|
||||
@@ -357,7 +399,9 @@ ota status
|
||||
- **The update shows another environment or a raw `[hw XXXXXXXX]`:** it is for a different board or firmware
|
||||
role. Do not install it.
|
||||
- **An internal-flash nRF52 marks a full update `[unsupported]`:** it can install only an in-place delta.
|
||||
The MeshTower V2 microSD target accepts full images with its matching SD-aware bootloader.
|
||||
A matched QSPI repeater or MeshTower V2 microSD target accepts full images with its corresponding bootloader.
|
||||
- **A QSPI nRF52 reports `QSPI store:ERR 0K` or `bl:NO-QSPI`:** do not download an install package. Install
|
||||
the exact QSPI-aware bootloader and check that the selected application matches the board's flash wiring.
|
||||
- **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
|
||||
|
||||
@@ -0,0 +1,190 @@
|
||||
# nRF52 repeater LoRa OTA with external QSPI
|
||||
|
||||
Selected nRF52840 repeater builds use their dedicated external QSPI NOR flash as
|
||||
a raw LoRa OTA staging device. This removes the internal-flash staging conflict:
|
||||
the complete `.mota` stays off-chip, and the bootloader can use the entire
|
||||
internal application region while it installs either a full image or an
|
||||
in-place delta.
|
||||
|
||||
This is a matched application-and-bootloader feature. A board merely having an
|
||||
nRF52840, free RAM, or pins named QSPI is not enough. Both halves must use the
|
||||
exact flash wiring, and `ota self` must confirm the store and bootloader before
|
||||
an update is downloaded.
|
||||
|
||||
## Supported repeater families
|
||||
|
||||
QSPI staging is enabled only for repeater-role environments on these currently
|
||||
matched families:
|
||||
|
||||
- Seeed XIAO nRF52840 and XIAO nRF52840 Sense modules, including the
|
||||
`Xiao_nrf52`, SolarXiao 30S/33S, and XIAO-module Ikoka handheld, Nano, and
|
||||
Stick repeaters
|
||||
- original LilyGo T-Echo
|
||||
- Elecrow ThinkNode M1 and M6
|
||||
- Seeed Wio Tracker L1
|
||||
- Seeed SenseCAP Solar Node P1
|
||||
- RAK4631 with a RAK15001 in WisBlock sensor slot C, using the dedicated
|
||||
`RAK_4631_repeater_rak15001_slot_c_lora_ota` application and matching
|
||||
`wiscore_rak4631_board_rak15001_slot_c` OTAFIX bootloader
|
||||
|
||||
Heltec T114 is intentionally not in this list. Its public V1, V2.0, and V2.1
|
||||
schematics show U9 (MX25R1635F) as an optional QSPI footprint, so standard T114
|
||||
application and bootloader targets do not assume that external NOR is populated.
|
||||
|
||||
The XIAO-module derivatives use the matching XIAO or XIAO Sense OTAFIX
|
||||
bootloader shown by the module's `INFO_UF2.TXT`. Do not substitute a similar
|
||||
bootloader for a board with different QSPI pins. For example, the T-Echo Card
|
||||
and T-Echo Lite have different flash wiring and are not enabled by the original
|
||||
T-Echo target.
|
||||
|
||||
Companion builds are intentionally excluded. Some companion targets use the
|
||||
same external QSPI as a LittleFS message/data store, where raw OTA staging
|
||||
would corrupt the filesystem; other companions simply do not assign that chip
|
||||
to OTA. Room-server, sensor, KISS, and repeater-bridge roles are also unchanged.
|
||||
Raw QSPI OTA is scoped to the explicitly matched repeater environments.
|
||||
|
||||
### RAK15001 placement and module conflicts
|
||||
|
||||
[RAK15001](https://docs.rakwireless.com/product-categories/wisblock/rak15001/datasheet/)
|
||||
is a 2 MiB GD25Q16C **standard SPI** module, not a quad-I/O flash. The dedicated
|
||||
RAK4631 target uses the nRF52840 QSPI peripheral in its single-data-line
|
||||
FAST_READ/page-program modes at 8 MHz and accepts only the module's exact
|
||||
`C8 40 15` JEDEC ID. `ota self` reports `QSPI store:2048K` only when the
|
||||
expected module responds. An empty slot or a different SPI device reports
|
||||
`QSPI store:ERR 0K`, and install is refused.
|
||||
|
||||
The module is electrically usable in sensor slot A-D because those slots share
|
||||
the SPI signals and RAK15001 has onboard 10 kOhm pull-ups on WP# and HOLD#.
|
||||
The supported MeshCore/OTAFIX combination nevertheless requires **slot C**. It
|
||||
is the placement that remains safe when a
|
||||
[RAK12501 GNSS](https://docs.rakwireless.com/product-categories/wisblock/rak12501/datasheet/)
|
||||
is fitted in either of its supported slots, A or D: slot C avoids the GNSS
|
||||
PPS/reset nets on IO1/IO2 and IO5/IO6. In particular, GPS in A plus flash in B
|
||||
would share IO1/IO2 through the modules' auxiliary pins.
|
||||
|
||||
Only one device that uses the shared WisBlock SPI chip-select may be fitted.
|
||||
Do not combine this target with RAK13800 Ethernet, RAK15002 SD, or another SPI
|
||||
module. RAK13800 and RAK15001 cannot coexist because they use the same SPI
|
||||
chip-select. Update a RAK13800 Ethernet build locally over USB using the
|
||||
release's **Manual UF2** or **Serial DFU (.zip)** download; it cannot use this
|
||||
RAK15001 LoRa-OTA staging target.
|
||||
|
||||
RAK3401 is intentionally unsupported. Its external RAK13302 1 W radio already
|
||||
uses the same WisBlock SPI clock/data pins **and the same chip-select** as
|
||||
RAK15001. Firmware cannot independently select or detect the two chips, so a
|
||||
stock RAK3401 + RAK15001 assembly cannot provide reliable OTA staging without
|
||||
a hardware chip-select rework.
|
||||
|
||||
## One-time prerequisite
|
||||
|
||||
Install a QSPI-capable OTAFIX 2.4.1 preview.8 or newer bootloader for the exact
|
||||
board from the
|
||||
[OTAFIX releases](https://github.com/mikecarper/Adafruit_nRF52_Bootloader_OTAFIX/releases)
|
||||
before using LoRa OTA. The release notes must explicitly list that board's QSPI
|
||||
mode. Also install the SoftDevice version expected by that target. The
|
||||
application refuses the install handoff when the bootloader does not advertise
|
||||
QSPI support.
|
||||
|
||||
For the first migration from the ordinary `wiscore_rak4631_board` bootloader to
|
||||
`wiscore_rak4631_board_rak15001_slot_c`, use Nordic serial DFU or a compatible
|
||||
BLE DFU client with the exact slot-C OTAFIX **combined bootloader + SoftDevice
|
||||
DFU package** (or use SWD), then reinstall the slot-C MeshCore application. The
|
||||
release filename has this form:
|
||||
|
||||
```text
|
||||
wiscore_rak4631_board_rak15001_slot_c_bootloader-<OTAFIX-version>_s140_6.1.1.zip
|
||||
```
|
||||
|
||||
Do not copy the slot-C bootloader-update UF2 onto the stock UF2 drive. The
|
||||
stock loader is bound to `DEVICE_NAME=4631_DFU`, while the slot-C image is bound
|
||||
to `4631_15001C_DFU`, so that UF2 is intentionally rejected. After the one-time
|
||||
DFU/SWD migration, later canonical slot-C bootloader UF2 files work normally.
|
||||
The combined OTAFIX package above is not the MeshCore application's Serial DFU
|
||||
`.zip`; an application package does not migrate the bootloader.
|
||||
|
||||
After installing the repeater application, check:
|
||||
|
||||
```text
|
||||
get bootloader.ver
|
||||
ota self
|
||||
ota status
|
||||
```
|
||||
|
||||
A ready target reports all of the following:
|
||||
|
||||
```text
|
||||
QSPI store:2048K
|
||||
bootloader: QSPI apply OK
|
||||
bl:QSPI
|
||||
```
|
||||
|
||||
Other supported boards can report a capacity different from 2048K; the
|
||||
RAK15001 target must report exactly 2048K. `QSPI store:ERR 0K`, `NO QSPI`, or
|
||||
`bl:NO-QSPI` means the flash wiring, flash power, or bootloader does not match.
|
||||
Do not start an install in that state.
|
||||
|
||||
## Capacity and package types
|
||||
|
||||
The store reads the JEDEC capacity at runtime and accepts supported 1 MiB
|
||||
through 16 MiB devices using 24-bit addressing. QSPI capacity is not the final
|
||||
firmware limit. The reconstructed application, including its 56-byte `EndF`
|
||||
trailer, must fit below InternalFS at `0xED000`:
|
||||
|
||||
| SoftDevice layout | Application region | Maximum image |
|
||||
| --- | --- | --- |
|
||||
| S140 v7, app base `0x27000` | `0x27000..0xED000` | `0xC6000` (811,008 bytes) |
|
||||
| S140 v6, app base `0x26000` | `0x26000..0xED000` | `0xC7000` (815,104 bytes) |
|
||||
|
||||
A full package needs only the new raw `firmware.hex` or non-merged application
|
||||
image. An in-place delta still needs the exact image currently running. The
|
||||
automation uses a conservative `0xC6000` detools workspace for external nRF52
|
||||
staging so one package setting is safe for both layouts.
|
||||
|
||||
For online automation, QSPI is detected from `ota self` or `ota status`. For
|
||||
offline preparation, identify it explicitly:
|
||||
|
||||
```bash
|
||||
./tools/lora_ota/lora_ota.sh ./release.zip target-name \
|
||||
--prepare-only \
|
||||
--platform nrf52 \
|
||||
--nrf-qspi \
|
||||
--target-id 12345678 \
|
||||
--target-hw Xiao_nrf52
|
||||
```
|
||||
|
||||
Use the real target ID and hardware identity from the destination. A ready
|
||||
full `.mota` normally uses that target ID for discovery and routing. An
|
||||
operator can deliberately override the routing target for a role change, so
|
||||
`target_id` is not an apply-time safety assertion; the destination still
|
||||
enforces the package's hardware identity before approval.
|
||||
|
||||
## Storage ownership and recovery
|
||||
|
||||
The QSPI store is raw, not a file inside LittleFS. It owns the flash from
|
||||
offset zero, erases 4 KiB sectors as blocks arrive, writes data before progress
|
||||
metadata, and verifies every programmed page. A previously interrupted
|
||||
download is reopened only when its header and trailer are valid; every claimed
|
||||
block is re-hashed before it is trusted. Between a probe, transfer operation,
|
||||
or checkpoint, firmware puts the NOR into deep power-down, deactivates the nRF
|
||||
QSPI peripheral, and turns off a board-provided flash power-enable pin. The
|
||||
next operation powers and identifies the chip again, so merely running
|
||||
`ota self` does not leave QSPI drawing active-mode current.
|
||||
|
||||
Installing a QSPI repeater build over a former companion build therefore
|
||||
repurposes the external flash and destroys companion filesystem data as OTA
|
||||
sectors are written. Back up anything important first. Returning to a companion
|
||||
build may require formatting its external data store.
|
||||
|
||||
Before changing internal application flash, the application verifies package
|
||||
integrity, hardware identity, signature policy, and bootloader capabilities.
|
||||
The target ID selects discovery/fetch routing and can be deliberately
|
||||
overridden; it is not a second hardware gate. The bootloader then verifies a
|
||||
full payload before its first application erase. For a delta, the application
|
||||
rejects invalid detools geometry before approval and the bootloader independently
|
||||
repeats the base and geometry checks before applying it.
|
||||
It clears the one-shot approval marker before invalidating the running image.
|
||||
If power is lost after application writes begin, the bank remains invalid and
|
||||
OTAFIX enters USB/BLE recovery rather than booting a partial image.
|
||||
|
||||
See [Easy firmware updates over LoRa](ota_easy.md) for the transfer commands and
|
||||
[the OTA protocol](ota_protocol.md) for the container and handoff details.
|
||||
+45
-25
@@ -126,9 +126,13 @@ established target-specific 1920 KiB or larger A/B app layout and are checked ag
|
||||
partition. For every standalone ESP32 and nRF52 repeater, `build.sh` also exposes an explicit
|
||||
`*_lora_ota_no_external_sensors` artifact: the ordinary repeater remains sensor-enabled, while that sibling
|
||||
disables optional external environmental-sensor drivers for LoRa distribution. Integrated GPS and other
|
||||
board-native telemetry remain enabled. ESP32 siblings retain the compact browser WiFi updater and use the
|
||||
full 254-entry neighbor table. RP2040 and STM32 targets are not offered because those platforms do not yet
|
||||
have a safe bootloader/apply path.
|
||||
board-native telemetry remain enabled where the target selects the GPS-preserving lean profile. RAK3401 is
|
||||
the explicit exception: `RAK_3401_repeater_lora_ota_no_external_sensors` undefines `ENV_INCLUDE_GPS`, so it
|
||||
does not detect or use a RAK12501. RAK12501 GPS requires the ordinary full-sensor `RAK_3401_repeater` build
|
||||
and sensor slot A; slot D conflicts with the RAK13302 radio's BUSY/DIO1 lines.
|
||||
ESP32 siblings retain the compact browser WiFi updater and use the full
|
||||
254-entry neighbor table. RP2040 and STM32 targets are not offered because
|
||||
those platforms do not yet have a safe bootloader/apply path.
|
||||
|
||||
nRF52 LoRa-OTA siblings use size optimization rather than the Adafruit platform's default `-Ofast`. This
|
||||
keeps the runtime software Ed25519 fallback from being expanded into tens of kilobytes of repeated curve
|
||||
@@ -257,7 +261,7 @@ cover `approval` or `leaves[]`:
|
||||
|
||||
| `codec_id` | Meaning | Used by |
|
||||
|---|---|---|
|
||||
| 0 | full / raw | PAYLOAD = reconstructed image (`BODY||EndF`). ESP32 A/B or the SD-backed MeshTower V2 target. |
|
||||
| 0 | full / raw | PAYLOAD = reconstructed image (`BODY||EndF`). ESP32 A/B or an external SD/QSPI nRF52 target. |
|
||||
| 1 | detools **sequential** | random read of base + sequential write of result -> ESP32 A->B inactive slot. |
|
||||
| 2 | detools **in-place** | bounded scratch; rewrites the app region in place -> nRF52 single-slot. |
|
||||
|
||||
@@ -266,9 +270,9 @@ delta only if `base_hash` matches its own `EndF.body_hash`. After applying, the
|
||||
(sha2-256:32) to `image_hash` before it is booted - the hard security gate.
|
||||
|
||||
**A fetcher only requests firmware it can apply.** Each node declares the codec(s) it can apply
|
||||
(`set_apply_codec`/`set_apply_codec2`): ESP32 accepts `full` + `sequential` (+ `in-place`). Normal nRF52
|
||||
targets accept only `in-place` because internal flash cannot stage a full application image. The
|
||||
MeshTower V2 SD target accepts `full` + `in-place` because the card holds the container. A `.mota` with
|
||||
(`set_apply_codec`/`set_apply_codec2`): ESP32 accepts `full` + `sequential` (+ `in-place`). Internal-staging
|
||||
nRF52 targets accept only `in-place` because internal flash cannot hold a second full application image.
|
||||
Matched SD and raw-QSPI nRF52 targets accept `full` + `in-place` because external media holds the container. A `.mota` with
|
||||
an unsupported codec is rejected at discovery time, before any blocks are requested. A manual pull to
|
||||
an external folder may accept other codecs because that path captures bytes and never installs them.
|
||||
|
||||
@@ -599,8 +603,9 @@ transmission per hop.
|
||||
independent of signature.
|
||||
- **Signing & allowlist:** a node keeps a runtime allowlist of trusted Ed25519 signer pubkeys (none embedded
|
||||
in firmware; `ota key add/list/rm`). A `.mota` is eligible for **auto-install** only if signed by an
|
||||
allowlisted key, the signature verifies, and `image_hash` matches; otherwise it is manual-apply only with
|
||||
explicit confirmation. **Transfer needs no trust** - blocks are content-addressed against the signed root.
|
||||
allowlisted key, the signature verifies, and `image_hash` matches. Manual install permits unsigned packages,
|
||||
but a package that claims to be signed must have a valid signature from an allowlisted key or it is rejected.
|
||||
**Transfer needs no trust** - blocks are content-addressed against the manifest's merkle root.
|
||||
- **Policies (persisted):** `autofetch` in {off, any, signed} (default off) gates automatic block fetching of
|
||||
own-target adverts; `autoinstall` in {off, trusted} (default off) gates auto-apply of a COMPLETE signed +
|
||||
allowlisted fetch. Conservative defaults: a fresh node discovers + announces but never fetches/installs
|
||||
@@ -758,26 +763,31 @@ ota dev ... bring-up helpers (stage/recv/serve/verify)
|
||||
- **ESP32 (A/B):** applied in-firmware via the detools decoder into the inactive OTA slot
|
||||
(`OtaApply.cpp::ota_apply_detools_mota` + `OtaStoreFlashEsp32`), then set-boot + reboot (power-safe,
|
||||
rollback-capable). No bootloader changes. Erase ranges must be sector-aligned (4096).
|
||||
- **nRF52 (single-slot):** the running firmware **never** flashes the app. `ota applydelta` verifies fully
|
||||
(`image_hash`, `base_hash`, signature/allowlist, `hw_id`), writes `approval = "APRV"`, then reboots into
|
||||
the modified bootloader (`Adafruit_nRF52_Bootloader_OTAFIX`). The bootloader:
|
||||
1. **scans flash for `MAGIC`** to find the staged `.mota` (it must NOT trust any stored size),
|
||||
2. re-checks `TRAILER`, `image_hash`, `approval == "APRV"`, and that the delta's `base_hash` equals the
|
||||
running firmware's `EndF.body_hash` (recomputed by scanning for `EndF` - never trust `bank_0_size`),
|
||||
3. applies the in-place codec over the app region and boots only if the result hashes to `image_hash`.
|
||||
- **nRF52 internal staging ceiling:** the application derives the ceiling from facts available in every
|
||||
build, not a board-name list. A companion that actually links the internal ExtraFS datastore stays below
|
||||
`0xD4000`; a default linker region, QSPI secondary storage, or a role that does not mount ExtraFS can
|
||||
reclaim the unused 100 KiB through `0xED000`. The application uses the larger window only when the
|
||||
- **nRF52 (single-slot):** the running firmware **never** flashes the app. `ota install` verifies the
|
||||
container fully (`image_hash`, codec, signature/allowlist, `hw_id`, and `base_hash` for a delta), writes
|
||||
`approval = "APRV"`, then reboots into the modified bootloader
|
||||
(`Adafruit_nRF52_Bootloader_OTAFIX`). The bootloader:
|
||||
1. locates the staged `.mota` in the approved internal, raw-SD, or raw-QSPI store without trusting an
|
||||
unchecked stored size,
|
||||
2. re-checks `TRAILER`, `image_hash`, and `approval == "APRV"`; for a delta it also checks that
|
||||
`base_hash` equals the running firmware's `EndF.body_hash` (recomputed by scanning for `EndF` - never
|
||||
trust `bank_0_size`),
|
||||
3. writes a full external-media payload or applies the in-place codec over the app region, then boots only
|
||||
if the result hashes to `image_hash`.
|
||||
- **nRF52 internal staging ceiling:** an internal-store application derives the ceiling from facts available
|
||||
in every build, not a board-name list. A companion that actually links the internal ExtraFS datastore stays
|
||||
below `0xD4000`; a default linker region or a role that does not mount ExtraFS can reclaim the unused
|
||||
100 KiB through `0xED000`. The application uses the larger window only when the
|
||||
installed bootloader advertises the GPREGRET2 ceiling-handoff capability. The bootloader treats every
|
||||
unknown/legacy handoff value as
|
||||
`0xD4000`, and accepts a container only at the bottom-aligned position for the selected ceiling.
|
||||
- **nRF52 dynamic apply window:** the post-build hook records the resolved app base, linked app end,
|
||||
storage flags, and desired staging ceiling immediately before `EndF`. `motatool` reads that authenticated
|
||||
internal-ExtraFS/SD/QSPI storage flags, and desired staging ceiling immediately before `EndF`. `motatool` reads that authenticated
|
||||
firmware record and chooses `memory_size` from the actual patch size and bottom-aligned stage address;
|
||||
firmware without the record retains the conservative `0x98000` default. Before writing `APRV`, the app
|
||||
verifies the detools header fits below the staged container, and the bootloader independently repeats
|
||||
the geometry check before its first application write. Expanded auto-sized packages require a bootloader
|
||||
firmware without the record retains the conservative `0x98000` default. Before writing `APRV`, an
|
||||
internal-store app validates the staged-address bound; an external SD/QSPI app validates the full detools
|
||||
geometry against the application workspace. The bootloader independently parses and validates the same
|
||||
geometry before its first application write. Expanded auto-sized packages require a bootloader
|
||||
with the ceiling-handoff capability; use `--inplace-memory 0x98000` when intentionally targeting an older
|
||||
bootloader and the images still fit that window.
|
||||
- **nRF52 EndF rescue:** `ota rescue install <base_hash16>` is a pre-provisioned recovery path for an
|
||||
@@ -798,8 +808,18 @@ ota dev ... bring-up helpers (stage/recv/serve/verify)
|
||||
publishes its raw sector range in a checksummed handoff record outside the MBR partition. The matching
|
||||
bootloader reads the card without mounting FAT, supports either a full image or an in-place delta,
|
||||
verifies the staged/full result hash, and never writes through `0xED000` where InternalFS begins.
|
||||
- **Matched external-QSPI nRF52 repeaters:** the application reserves the board's dedicated QSPI NOR as a
|
||||
raw store beginning at offset zero. It obtains a 1-16 MiB capacity from JEDEC, checkpoints payload before
|
||||
leaf metadata, and verifies each erased/programmed page. GPREGRET2 `0x51` selects QSPI only when the
|
||||
matching bootloader advertises the QSPI storage bit; legacy markers retain the internal scan path. The
|
||||
bootloader pre-hashes a full payload before invalidating the app, or applies an in-place delta with the
|
||||
complete internal application region as workspace. Companion builds never enable this raw store: some use
|
||||
QSPI as a filesystem, while others simply leave that chip outside OTA ownership. See
|
||||
[the nRF52 QSPI guide](ota_nrf52_qspi.md).
|
||||
|
||||
The signature proves author authenticity; `approval` proves local owner consent - both required to apply.
|
||||
A signature, when present, proves author authenticity and must pass the device allowlist. Unsigned packages
|
||||
remain installable when local policy permits them. The one-shot `approval` marker records local consent for
|
||||
either form before the bootloader may apply it.
|
||||
|
||||
> **Bootloader testing note:** always test apply with a *real different* image (base != target). A same-image
|
||||
> (X->X) "delta" trivially reproduces the target and gives a false positive.
|
||||
|
||||
+45
-18
@@ -4,9 +4,12 @@ This guide is for **node operators**: how to update your MeshCore device's firmw
|
||||
plain language. No cables, no programmer - your node can download a new firmware from a neighbour and
|
||||
install it. (For the technical wire format, see [the OTA protocol spec](ota_protocol.md).)
|
||||
|
||||
LoRa OTA download and installation are present only in supported Keymind destination artifacts whose filename
|
||||
contains `-ota-`; the receiver must already be running one of those install-capable builds. A source can be an
|
||||
OTA-enabled infrastructure node or a source-only Full Companion backed by `motatool`. Intermediate repeaters
|
||||
LoRa OTA download and installation are present only in supported Keymind destination artifacts; the receiver
|
||||
must already be running one of those install-capable builds. Some internal-staging nRF52 targets use a lean
|
||||
`lora_ota_no_external_sensors` target, while matched external-QSPI boards can retain their normal full-sensor
|
||||
repeater features. Release filenames include an OTA marker, but capability must still be confirmed on the
|
||||
running device. A source can be an OTA-enabled infrastructure node or a source-only Full Companion backed
|
||||
by `motatool`. Intermediate repeaters
|
||||
do not need OTA-enabled firmware: current repeater builds transport OTA floods opaquely, subject to their normal
|
||||
forwarding filters, duplicate checks, and flood limits. OTA radio traffic is accepted, generated, and relayed
|
||||
only while `tempradio` is actually running on that node. Every source, receiver, and intermediate repeater must
|
||||
@@ -21,23 +24,45 @@ tempradio 909.950,250,5,5,120
|
||||
|
||||
Use the node's current permitted regional frequency in place of `909.950` when necessary.
|
||||
|
||||
> **Can my node install the update?** Choose a supported repeater artifact carrying the `-ota-` filename stamp.
|
||||
> **Can my node install the update?** Choose a release-table artifact explicitly labelled LoRa-OTA capable,
|
||||
> then confirm `ota self` and `ota status` expose install support; do not infer support from the filename alone.
|
||||
> LoRa OTA firmware is available for supported **ESP32** boards and nRF52 repeater targets. Every nRF52
|
||||
> installation also requires the OTAFIX bootloader built for that exact board; having an OTA-capable
|
||||
> application image alone is not enough. An intermediate repeater only relays packets and needs neither the
|
||||
> `-ota-` image nor OTAFIX. Check the bootloader release for an exact board match before attempting an update.
|
||||
> application image alone is not enough. An intermediate repeater only relays packets and needs neither an
|
||||
> install-capable image nor OTAFIX. Check the bootloader release for an exact board match before attempting an update.
|
||||
|
||||
The following nRF52 repeater targets gained firmware-side LoRa OTA support in this release without losing
|
||||
their normal external-sensor support:
|
||||
The following nRF52 repeater families gained firmware-side LoRa OTA targets in
|
||||
this release. Their ordinary repeater remains the full-sensor build; the
|
||||
install-capable `lora_ota_no_external_sensors` sibling is smaller:
|
||||
|
||||
- Heltec Mesh Solar, T1, and Tower V2
|
||||
- Keepteen LT1, LilyGo T-Impulse Plus, Mesh Pocket, and Nano G2 Ultra
|
||||
- Minewsemi ME25LS01, RAK3401, SenseCAP Solar, and Wio WM1110
|
||||
|
||||
The full-sensor `RAK_4631_repeater` image is too large for the safe nRF52 in-place update limit. Use
|
||||
`RAK_4631_repeater_lora_ota_no_external_sensors` when LoRa OTA is required. That target removes optional
|
||||
external environmental/GPS sensor packages, but retains the RAK4631's built-in battery-voltage reading,
|
||||
battery telemetry, and `battery.alert` behavior.
|
||||
RAK3401 is an important GPS exception: its
|
||||
`RAK_3401_repeater_lora_ota_no_external_sensors` image compiles out GPS support
|
||||
as well as the optional environmental sensors. It will not detect or use a
|
||||
RAK12501. For RAK12501 GPS, use the ordinary full-sensor
|
||||
`RAK_3401_repeater` build and install the GPS in sensor slot A. Slot D's GPS
|
||||
reset/PPS lines conflict with the RAK13302 radio's BUSY/DIO1 lines. The
|
||||
full-sensor RAK3401 build is not the self-updating target described by the
|
||||
RAK3401 compact OTA chain.
|
||||
|
||||
Selected nRF52 repeaters with dedicated external QSPI can now stage the
|
||||
complete package off-chip, so their normal full-sensor repeater build can
|
||||
install a full image or an in-place delta. The current matched families are
|
||||
XIAO nRF52840 and its XIAO-module derivatives, original LilyGo T-Echo,
|
||||
ThinkNode M1/M6, Wio Tracker L1, SenseCAP Solar, and the dedicated RAK4631 +
|
||||
RAK15001 slot-C target. These require the corresponding QSPI-aware OTAFIX bootloader; see
|
||||
[the nRF52 QSPI guide](ota_nrf52_qspi.md).
|
||||
|
||||
The ordinary full-sensor `RAK_4631_repeater` image remains too large for the
|
||||
safe internal in-place update limit. Without external flash, use
|
||||
`RAK_4631_repeater_lora_ota_no_external_sensors`; it removes optional external
|
||||
environmental/GPS packages but retains battery monitoring. A RAK4631 fitted
|
||||
with RAK15001 in sensor slot C can instead use
|
||||
`RAK_4631_repeater_rak15001_slot_c_lora_ota` to retain the full sensor/GPS set
|
||||
and stage full images or deltas off-chip.
|
||||
|
||||
---
|
||||
|
||||
@@ -112,7 +137,8 @@ long ago it was seen. The fit marker:
|
||||
- **[same target]** - the advertised target ID matches this hardware-and-role build. Download and apply
|
||||
still enforce codec, bootloader, signed hardware tag, base hash, and integrity checks.
|
||||
- **[unsupported]** - the target may match, but this build or its bootloader cannot apply that codec. A common
|
||||
example is the source node's self-served **full** image on a single-slot nRF52, which needs an in-place delta.
|
||||
example is the source node's self-served **full** image on an internal-staging nRF52, which needs an
|
||||
in-place delta. A matched external-QSPI nRF52 can accept that full codec.
|
||||
- **[rescue]** - an installable in-place nRF52 delta for the same target, but this running firmware has no
|
||||
valid app-side EndF. It requires the explicit rescue download and install flow below.
|
||||
- **[name]** - a different known board or role (for example `[ProMicro_companion_radio_usb]`). Don't install it.
|
||||
@@ -184,9 +210,9 @@ ota install
|
||||
```
|
||||
|
||||
The node verifies the firmware one last time, and if everything checks out it installs it and **reboots
|
||||
into the new version**. If the check fails, it tells you why and does **not** install. (If you haven't
|
||||
added the signer's key, an unsigned/untrusted image will only install with this explicit command - never
|
||||
automatically.)
|
||||
into the new version**. If the check fails, it tells you why and does **not** install. Unsigned images
|
||||
install only through this explicit command. A signed image whose signer is not in the device allowlist is
|
||||
rejected; trusted signed images can auto-install only when that policy is enabled.
|
||||
|
||||
After it reboots, run `ota status` to confirm the new version.
|
||||
|
||||
@@ -263,8 +289,9 @@ ota key list # show trusted signers
|
||||
ota key rm <public-key-hex> # stop trusting one
|
||||
```
|
||||
|
||||
Only updates signed by a trusted key are eligible for auto-install. Manual `ota install` still lets you
|
||||
install anything yourself, on your own responsibility.
|
||||
Only updates signed by a trusted key are eligible for auto-install. Manual `ota install` permits an unsigned
|
||||
package after all integrity, hardware, base, and bootloader checks pass. A signed package whose signer is not
|
||||
in the device allowlist is rejected rather than silently treated as unsigned.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -34,6 +34,16 @@ target:
|
||||
- endpoint packed version: `0x01110102` (EndF tools render this as `1.17.1.2`)
|
||||
- deployment target key: `63d8df6387eaffd2e25db7d2a8ad967a65202182a48d681d7e7a9260f917280d`
|
||||
|
||||
### GPS limitation
|
||||
|
||||
This chain's exact `RAK_3401_repeater_lora_ota_no_external_sensors` endpoint
|
||||
compiles with `ENV_INCLUDE_GPS` removed. It will not detect, configure, or read
|
||||
a RAK12501 GPS module. GPS requires the ordinary full-sensor
|
||||
`RAK_3401_repeater` firmware and the RAK12501 must be installed in sensor slot
|
||||
A. Do not use slot D with the RAK13302 1 W radio: the GPS reset/PPS signals
|
||||
would overlap the radio's BUSY/DIO1 signals. The full-sensor build is a
|
||||
different target and is not an endpoint of this compact OTA chain.
|
||||
|
||||
Do not use the chain on another target ID, hardware family, starting image, or
|
||||
firmware body hash. The runner checks all four.
|
||||
|
||||
|
||||
Reference in new issue
Block a user