mirror of
https://github.com/liquidraver/ZephCore.git
synced 2026-09-01 20:38:19 +00:00
upgrade formatted to be flasher compatible
This commit is contained in:
@@ -46,6 +46,11 @@ rtt_*.log
|
||||
*.a
|
||||
*.zip
|
||||
|
||||
# ...except the prebuilt formatter DFU packages. These are shipped artifacts, not
|
||||
# build output: build.sh publishes them as the Mesh America configurator's `erase`
|
||||
# packages (see formatter/README.md, PROVIDER_CATALOG.md), so they must be tracked.
|
||||
!formatter/*.zip
|
||||
|
||||
# OS junk
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
+15
-13
@@ -65,19 +65,21 @@ Notes on the mapping:
|
||||
boards without dedicated art fall back to a neutral LoRa icon. Swap in ZephCore-branded
|
||||
art by pointing `img` at your own absolute HTTPS URLs.
|
||||
|
||||
> [!WARNING]
|
||||
> **The configurator's "Erase Flash" is not ZephCore-aware — do not use it on a ZephCore node.**
|
||||
> `erase` is a MeshCore device-level field, not a provider field, so a folded nRF52 device
|
||||
> inherits the *base* device's formatter (e.g. Wio Tracker L1 → `WioTrackerL1_QSPIFlash_Format`).
|
||||
> That formatter targets MeshCore/Ripple's flash layout, which does not match ZephCore's
|
||||
> LittleFS — so it performs a partial, inconsistent wipe (observed: nukes `channels`, leaves
|
||||
> identity/prefs/contacts) and can leave the filesystem half-corrupted. New tiles inherit no
|
||||
> `erase` at all, so Erase Flash is a no-op there.
|
||||
>
|
||||
> To factory-reset a ZephCore node, use ZephCore's own mechanism, which formats **all** of
|
||||
> `/lfs` + `/ext` (and the NVS bond partition) and reboots: the `erase` command over the USB
|
||||
> serial CLI, the companion app's factory reset, or simply reflash (ZephCore auto-formats on
|
||||
> first boot when it detects an incompatible/blank FS).
|
||||
- **Erase / "wipe settings" (nRF52) uses ZephCore's own formatter.** MeshCore's official erase
|
||||
targets a different flash layout and only *partially* wipes a ZephCore node (observed on a Wio
|
||||
Tracker L1: nuked `channels`, left identity/prefs/contacts, LittleFS half-corrupted). Since spec
|
||||
§4a we override it: each nRF52 firmware option carries an `erase` pointing at ZephCore's
|
||||
formatter. The formatter is **SoftDevice-specific** (v6 and v7 have different partition maps), so
|
||||
`SOFTDEVICE` in the generator maps every nRF52 board to `SoftDevice_v6_formatter.zip` or
|
||||
`SoftDevice_v7_formatter.zip`; `build.sh` publishes both from `formatter/` under stable, un-hashed
|
||||
names so the erase URLs never change. The `.zip` drives the automated DFU erase flow; the `.uf2`
|
||||
is published too as the manual drag-and-drop fallback.
|
||||
- `erase` goes on the **firmware option**, never the device object — a device-level `erase` is an
|
||||
official-only field that providers get silently ignored + warned for (§4a).
|
||||
- ESP32 has no `erase` (the field is nRF52-only); `flash-wipe` already reinstalls cleanly.
|
||||
- Users can still factory-reset on-device without the flasher: the `erase` command over the USB
|
||||
serial CLI, the app's factory reset, or a reflash (ZephCore auto-formats on first boot when it
|
||||
detects an incompatible/blank FS). All format `/lfs` + `/ext` + the NVS bond partition.
|
||||
|
||||
## Local test
|
||||
|
||||
|
||||
@@ -82,6 +82,26 @@ if [[ $1 == "nrf" ]]; then
|
||||
mv build/zephyr/zephyr.zip firmware/"$board"-repeater-noscreen-"$COMMIT_HASH".zip
|
||||
fi
|
||||
done
|
||||
|
||||
# ZephCore's storage formatter — published as the `erase` package for the
|
||||
# Mesh America configurator (spec §4a). MeshCore's official erase targets a
|
||||
# different flash layout and only partially wipes a ZephCore node, so each
|
||||
# nRF52 board points `erase` at the formatter for its SoftDevice (v6/v7 have
|
||||
# different partition maps; see SOFTDEVICE in gen_provider_catalog.py).
|
||||
# Copied under stable, un-hashed names so the catalog's erase URLs stay
|
||||
# stable. The .zip drives the configurator's automated DFU erase flow; the
|
||||
# .uf2 is the manual drag-and-drop fallback. Skipped if not built yet.
|
||||
for sd in 6 7; do
|
||||
for ext in zip uf2; do
|
||||
f="formatter/SoftDevice_v${sd}_formatter.${ext}"
|
||||
if [[ -f "$f" ]]; then
|
||||
cp "$f" firmware/
|
||||
echo "Published formatter: $f"
|
||||
else
|
||||
echo "NOTE: $f not present — erase package for SoftDevice v${sd} will 404"
|
||||
fi
|
||||
done
|
||||
done
|
||||
fi
|
||||
|
||||
if [[ $1 == "linux" ]]; then
|
||||
|
||||
+50
-7
@@ -1,7 +1,50 @@
|
||||
nRF formatter tools
|
||||
|
||||
- QSPI is formatted for all supported boards
|
||||
- Watch out for softdevice version! Flashing the wrong version can corrupt the node and you'll need a full bootloader reflash with adafruit-nrfutil!
|
||||
- You can check what softdevice version you use if you open INFO_UF2.TXT on the storage drive when in DFU mode. Bootloader should say "sxxx 6.x.x" for v6 and "sxxx 7.x.x" for v7
|
||||
- Formatter output logs from the process over serial
|
||||
- After format, it puts back the device to Mass Storage DFU mode
|
||||
nRF formatter tools
|
||||
|
||||
- QSPI is formatted for all supported boards
|
||||
- Watch out for softdevice version! Flashing the wrong version can corrupt the node and you'll need a full bootloader reflash with adafruit-nrfutil!
|
||||
- You can check what softdevice version you use if you open INFO_UF2.TXT on the storage drive when in DFU mode. Bootloader should say "sxxx 6.x.x" for v6 and "sxxx 7.x.x" for v7
|
||||
- That warning applies to the **`.uf2`** files, which have no version guard. The **`.zip`** packages carry an `--sd-req` guard (v6 = `0x00B6`, v7 = `0x0123`), so the bootloader *rejects* a mismatched package instead of corrupting the node.
|
||||
- Formatter output logs from the process over serial
|
||||
- After format, it puts back the device to Mass Storage DFU mode
|
||||
|
||||
## Files
|
||||
|
||||
| SoftDevice | Boards |
|
||||
|------------|--------|
|
||||
| **v6** | RAK4631, RAK3401 1W, ThinkNode M1/M3/M6, RAK WisMesh Tag, LilyGo T-Echo, LilyGo T-Impulse Plus, ProMicro SX1262, Heltec T114, Heltec T096, GAT562 30s |
|
||||
| **v7** | Wio Tracker L1, T1000-E, Ikoka Nano 30dBm, SenseCAP Solar, XIAO nRF52840 |
|
||||
|
||||
- **`.uf2`** — manual drag-and-drop onto the UF2 mass-storage drive.
|
||||
- **`.zip`** — Adafruit DFU package. Used by the Mesh America configurator as ZephCore's
|
||||
`erase` package (its automated erase flow), and flashable by hand with
|
||||
`adafruit-nrfutil dfu serial -pkg <zip> -p COMx -b 115200 --singlebank --touch 1200`.
|
||||
See `PROVIDER_CATALOG.md` for how the catalog wires these up per board.
|
||||
|
||||
`build.sh nrf` copies all four files into `firmware/` under these exact names so the
|
||||
catalog's `erase` URLs stay stable across releases — don't rename them.
|
||||
|
||||
## Rebuilding
|
||||
|
||||
Two universal builds, one per SoftDevice. Source is `zephcore/tools/formatter`. The
|
||||
partition map comes from the build board's overlay, and `qspi_probe.c` probes QSPI
|
||||
bare-metal, so one image covers every board on that SoftDevice.
|
||||
|
||||
```bash
|
||||
# SoftDevice v6 (universal target: rak4631)
|
||||
west build -b rak4631 zephcore/tools/formatter --pristine -d build_fmt6
|
||||
cp build_fmt6/zephyr/zephyr.uf2 formatter/SoftDevice_v6_formatter.uf2
|
||||
cp build_fmt6/zephyr/zephyr.zip formatter/SoftDevice_v6_formatter.zip
|
||||
|
||||
# SoftDevice v7 (universal target: t1000_e)
|
||||
west build -b t1000_e zephcore/tools/formatter --pristine -d build_fmt7
|
||||
cp build_fmt7/zephyr/zephyr.uf2 formatter/SoftDevice_v7_formatter.uf2
|
||||
cp build_fmt7/zephyr/zephyr.zip formatter/SoftDevice_v7_formatter.zip
|
||||
```
|
||||
|
||||
The `.zip` needs `adafruit-nrfutil` on PATH (`pip install adafruit-nrfutil`); the build
|
||||
prints `Formatter DFU zip: ENABLED (sd-req=...)` when wired up, and silently skips the
|
||||
zip otherwise. `--sd-req` is read automatically from the build board's `board.conf`
|
||||
(`CONFIG_ZEPHCORE_SD_FWID`), so it always matches the SoftDevice being targeted.
|
||||
|
||||
To support a new board, add its QSPI pin mapping to `known_boards[]` in
|
||||
`zephcore/tools/formatter/src/qspi_probe.c` — no DTS or Kconfig changes needed.
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+25
-3
@@ -175,6 +175,21 @@ BOARDS = [
|
||||
|
||||
DEVICE_TYPE = {"nrf": "nrf52", "esp32": "esp32", "linux": "noflash"}
|
||||
|
||||
# nRF52 erase package (spec §4a). ZephCore's LittleFS layout differs from MeshCore's,
|
||||
# so the official erase would wipe the wrong region — we point `erase` at ZephCore's
|
||||
# own formatter tool instead. The formatter is SoftDevice-specific (partition map
|
||||
# differs between SD v6 and v7), so each board maps to its SD's formatter .zip.
|
||||
# Files are published to firmware-dist by build.sh (stable names, no hash).
|
||||
SOFTDEVICE = {
|
||||
"rak4631": 6, "rak3401_1watt": 6, "thinknode_m1": 6, "thinknode_m3": 6,
|
||||
"thinknode_m6": 6, "rak_wismesh_tag": 6, "lilygo_techo": 6,
|
||||
"lilygo_timpulse_plus": 6, "promicro_sx1262": 6, "heltec_t114": 6,
|
||||
"heltec_t096": 6, "gat562_30s": 6,
|
||||
"wio_tracker_l1": 7, "t1000_e": 7, "ikoka_nano_30dbm": 7,
|
||||
"sensecap_solar": 7, "xiao_nrf52840": 7,
|
||||
}
|
||||
FORMATTER_FILE = {6: "SoftDevice_v6_formatter.zip", 7: "SoftDevice_v7_formatter.zip"}
|
||||
|
||||
# Companion firmware is a single image that serves both transports (and, on
|
||||
# Linux, TCP). Expose it under each applicable role, all pointing at one file.
|
||||
COMPANION_ROLES = {
|
||||
@@ -241,10 +256,12 @@ def build(assets, url_base, version):
|
||||
for (t, name, title) in triples
|
||||
]
|
||||
|
||||
def add_option(dev, role, subtitle, version, triples):
|
||||
def add_option(dev, role, subtitle, version, triples, erase=None):
|
||||
opt = {"role": role, "version": {version: {"notes": "", "files": spec_files(triples)}}}
|
||||
if subtitle:
|
||||
opt["subTitle"] = subtitle
|
||||
if erase:
|
||||
opt["erase"] = erase # spec §4a: on the firmware option, not the device
|
||||
dev["firmware"].append(opt)
|
||||
used_roles.add(role)
|
||||
|
||||
@@ -275,11 +292,16 @@ def build(assets, url_base, version):
|
||||
stats["new" if board.get("new") else "fold"] += 1
|
||||
dev = devices[name]
|
||||
|
||||
# nRF52 boards get ZephCore's own SoftDevice-specific formatter as `erase`.
|
||||
erase = None
|
||||
if board["kind"] == "nrf":
|
||||
erase = f"{base}/{FORMATTER_FILE[SOFTDEVICE[board['stem']]]}"
|
||||
|
||||
if comp:
|
||||
for role in COMPANION_ROLES[board["kind"]]:
|
||||
add_option(dev, role, subtitle, version, comp)
|
||||
add_option(dev, role, subtitle, version, comp, erase)
|
||||
if repe:
|
||||
add_option(dev, "repeater", subtitle, version, repe)
|
||||
add_option(dev, "repeater", subtitle, version, repe, erase)
|
||||
|
||||
catalog = {
|
||||
"description": DESCRIPTION,
|
||||
|
||||
@@ -54,7 +54,43 @@ endif()
|
||||
message(STATUS "Formatter board overlay: ${FORMATTER_BOARD_OVERLAY}")
|
||||
message(STATUS "Formatter board conf: ${FMT_BOARD_CONF}")
|
||||
|
||||
# Read the SoftDevice firmware ID from the MAIN board.conf for this board.
|
||||
# The Adafruit bootloader rejects a DFU package whose --sd-req doesn't match the
|
||||
# SoftDevice it's running, which is exactly the guard we want: the SDv6 formatter
|
||||
# must never apply to an SDv7 node (wrong partition map = corrupted node).
|
||||
# SoftDevice v6 -> 0x00B6 SoftDevice v7 -> 0x0123
|
||||
file(GLOB_RECURSE MAIN_BOARD_CONF_CANDIDATES
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/../../boards/*/${BOARD_BASE}/board.conf")
|
||||
if(MAIN_BOARD_CONF_CANDIDATES)
|
||||
list(GET MAIN_BOARD_CONF_CANDIDATES 0 MAIN_BOARD_CONF)
|
||||
file(STRINGS "${MAIN_BOARD_CONF}" _sd_fwid_line REGEX "^CONFIG_ZEPHCORE_SD_FWID=")
|
||||
if(_sd_fwid_line)
|
||||
string(REGEX REPLACE "^CONFIG_ZEPHCORE_SD_FWID=" "" FORMATTER_SD_REQ "${_sd_fwid_line}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
|
||||
project(zephcore_formatter)
|
||||
|
||||
target_sources(app PRIVATE src/main.c src/qspi_probe.c)
|
||||
|
||||
# Generate an Adafruit DFU package (.zip) next to the .uf2. The .zip is what the
|
||||
# Mesh America configurator uses for its automated `erase` flow (spec §4a); the
|
||||
# .uf2 remains the manual drag-and-drop fallback. See PROVIDER_CATALOG.md.
|
||||
find_program(ADAFRUIT_NRFUTIL adafruit-nrfutil)
|
||||
if(ADAFRUIT_NRFUTIL AND FORMATTER_SD_REQ)
|
||||
add_custom_target(dfu_zip ALL
|
||||
COMMAND ${ADAFRUIT_NRFUTIL} dfu genpkg
|
||||
--dev-type 0x0052
|
||||
--sd-req ${FORMATTER_SD_REQ}
|
||||
--application ${CMAKE_BINARY_DIR}/zephyr/zephyr.hex
|
||||
${CMAKE_BINARY_DIR}/zephyr/zephyr.zip
|
||||
DEPENDS ${CMAKE_BINARY_DIR}/zephyr/zephyr.hex
|
||||
COMMENT "Generating formatter DFU package: zephyr.zip (sd-req=${FORMATTER_SD_REQ})"
|
||||
VERBATIM
|
||||
)
|
||||
add_dependencies(dfu_zip zephyr_final)
|
||||
message(STATUS "Formatter DFU zip: ENABLED (sd-req=${FORMATTER_SD_REQ})")
|
||||
else()
|
||||
message(STATUS "Formatter DFU zip: DISABLED (adafruit-nrfutil or SD_FWID missing)")
|
||||
endif()
|
||||
|
||||
Reference in New Issue
Block a user