v0.6.2-esp32
google/comprehensive-rustv0.6.2-esp32Apr 20, 2026by ruvnet
AI Summary
Introduces the ADR-081 Adaptive CSI Mesh Kernel with a 5-layer architecture and replaces raw CSI with a 60-byte packet format to reduce bandwidth. Includes a critical fix for the Timer Service stack overflow.
Key Highlights
- 5-layer adaptive CSI kernel (Radio Abstraction → Adaptive Controller → Mesh Plane → Feature State → Rust handoff)
- ~99.7% bandwidth reduction via 60-byte `rv_feature_state_t` packets (magic `0xC5110006`)
- Mesh sensing plane with 4 roles, 7 message types, and CRC32 integrity
- Host-testable pure decision policy with 33/33 assertions
- Added 4 MB ESP32-S3 SuperMini variant to CI builds
Breaking Changes
- Wire format default changed to `rv_feature_state_t` (magic `0xC5110006`); raw ADR-018 CSI remains available as a debug stream gated by the channel plan.
New Features
- ADR-081 Adaptive CSI Mesh Kernel
- 60-byte feature state packets
- Mesh sensing plane (HEALTH/ANOMALY_ALERT)
- Timer Service stack overflow fix
- 4 MB variant support
Full Release Notes
First firmware release of the **ADR-081 Adaptive CSI Mesh Kernel**, plus the Timer Service stack-overflow regression fix caught by on-device validation. Ships both 8 MB and 4 MB variants from CI. ## Highlights - **5-layer adaptive CSI kernel** (Radio Abstraction → Adaptive Controller → Mesh Plane → Feature State → Rust handoff) — swap radio silicon without touching the Rust signal/ruvector/mat crates - **60-byte `rv_feature_state_t` packet** (magic `0xC5110006`) replaces raw CSI as the default upstream — **~99.7 % bandwidth reduction** (300 B/s at 5 Hz vs ~100 KB/s raw) - **Mesh sensing plane** (`rv_mesh`) with 4 roles, 7 message types, CRC32-integrity envelope — HEALTH every 30 s, ANOMALY_ALERT on state transitions - **Host-testable pure decision policy** (`adaptive_controller_decide.c`) — **33/33 assertions**, `decide()` at 3.2 ns/call - **4 MB variant** (ESP32-S3 SuperMini) now built in CI alongside the 8 MB default ## Validated on real hardware ESP32-S3 QFN56 rev v0.2 (MAC `3c:0f:02:e9:b5:f8`), 38 s continuous run after flash: - `App version: 0.6.2` ✅ - **0** stack-overflow / panic / reboot markers - **28** `adaptive_ctrl` medium ticks, steady state, no drift - **149** `rv_feature_state_t` emissions at ~5 Hz on earlier 30 s validation - Real WiFi CSI: 37 – 72 pps yield, RSSI -43 to -57 dBm ## Fixes | Fix | Detail | | --- | --- | | Timer Svc stack overflow (new) | `emit_feature_state()` + `stream_sender` network I/O runs inside FreeRTOS Timer Svc; ESP-IDF default 2 KiB stack overflows ~1 s after boot. Bumped `CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=8192` in all three `sdkconfig.defaults*`. Follow-up: move heavy work out of the timer daemon. | | `adaptive_controller.c` implicit decl (#404) | `fast_loop_cb` called `emit_feature_state()` before its static definition, tripping `-Werror=implicit-function-declaration`. Added forward declaration. | | `provision.py` esptool v5 compat (#391) | `write-flash` (hyphenated) in dry-run hint for esptool ≥ 5. | | `provision.py` silent NVS wipe (#391) | Now refuses to run without `--ssid`, `--password`, `--target-ip` unless `--force-partial` is passed; `--force-partial` prints which keys will be wiped. | | Defensive `node_id` capture (#232, #375, #385, #386, #390) | `csi_collector_init()` now captures `g_nvs_config.node_id` once into a module-local; a canary WARN fires on divergence. | ## CI change `firmware-ci.yml` is now a matrix job building both variants in parallel and uploading variant-named artifacts — 6-binary releases no longer need local ESP-IDF. ## Installing Six binaries are attached below. The default flash layout for **ESP32-S3 8 MB**: ```bash esptool.py --chip esp32s3 --port /dev/ttyUSB0 --baud 460800 \ --before default_reset --after hard_reset \ write_flash -z --flash_mode dio --flash_freq 80m --flash_size 8MB \ 0x0 bootloader.bin \ 0x8000 partition-table.bin \ 0xf000 ota_data_initial.bin \ 0x20000 esp32-csi-node.bin ``` For **ESP32-S3 SuperMini 4 MB**, use `esp32-csi-node-4mb.bin` at `0x20000` and `partition-table-4mb.bin` at `0x8000` (reuse the same bootloader and OTA data). After flash, provision WiFi + target (replaces the full `csi_cfg` NVS namespace — pass all creds at once): ```bash python firmware/esp32-csi-node/provision.py \ --port /dev/ttyUSB0 \ --ssid <SSID> --password <PSK> --target-ip <DEST_IP> ``` ## Artifacts | File | Size | Target | | --- | --- | --- | | `esp32-csi-node.bin` | 1.06 MB | 8 MB app (flash @ `0x20000`) | | `esp32-csi-node-4mb.bin` | 851 KB | 4 MB app (flash @ `0x20000`) | | `bootloader.bin` | 18 KB | Both (flash @ `0x0`) | | `partition-table.bin` | 3 KB | 8 MB layout (flash @ `0x8000`) | | `partition-table-4mb.bin` | 3 KB | 4 MB layout (flash @ `0x8000`) | | `ota_data_initial.bin` | 8 KB | OTA data (flash @ `0xf000`) | ## Compatibility - **ESP-IDF:** v5.4 - **Target:** ESP32-S3 (Xtensa dual-core). **Not supported:** ESP32 (original), ESP32-C3 (single-core, can't run CSI DSP). - **Supersedes:** [v0.6.1-esp32](../../releases/tag/v0.6.1-esp32) - **Wire format:** `rv_feature_state_t` magic `0xC5110006` is the new default upstream; raw ADR-018 CSI (magic `0xC5110001`) remains available as a debug stream gated by the channel plan. ## Reference - ADR-081 — Adaptive CSI Mesh Firmware Kernel (`docs/adr/ADR-081-adaptive-csi-mesh-firmware-kernel.md`) - Full changelog entry: [`CHANGELOG.md#v062-esp32`](../../blob/v0.6.2-esp32/CHANGELOG.md) - Source tag: [`ae40e2b`](../../commit/ae40e2b)