From ae40e2b33e7c0a559e60bb405564d52533f71af8 Mon Sep 17 00:00:00 2001 From: ruv Date: Mon, 20 Apr 2026 10:59:05 -0400 Subject: [PATCH] Release v0.6.2-esp32: ADR-081 kernel + Timer Svc fix, 4MB CI variant MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit version.txt → 0.6.2. firmware-ci.yml: matrix-build both 8MB (sdkconfig.defaults) and 4MB (sdkconfig.defaults.4mb) variants, uploading variant-named artifacts (esp32-csi-node.bin / esp32-csi-node-4mb.bin, partition-table.bin / partition-table-4mb.bin). Unblocks 6-binary releases from CI alone, no local ESP-IDF required. CHANGELOG: promote [Unreleased] ADR-081 work into [v0.6.2-esp32], plus Fixed entries for Timer Svc stack overflow and the fast_loop_cb → emit_feature_state implicit-decl compile error. Validation: 30 s run on ESP32-S3 (MAC 3c:0f:02:e9:b5:f8), 149 rv_feature_state emissions, no stack overflow, HEALTH mesh packet sent. Co-Authored-By: claude-flow --- .github/workflows/firmware-ci.yml | 58 ++++++++++++++++++++--------- CHANGELOG.md | 15 ++++++++ firmware/esp32-csi-node/version.txt | 2 +- 3 files changed, 56 insertions(+), 19 deletions(-) diff --git a/.github/workflows/firmware-ci.yml b/.github/workflows/firmware-ci.yml index 29407ee7..252a47ee 100644 --- a/.github/workflows/firmware-ci.yml +++ b/.github/workflows/firmware-ci.yml @@ -12,31 +12,50 @@ on: jobs: build: - name: Build ESP32-S3 Firmware + name: Build ESP32-S3 Firmware (${{ matrix.variant }}) runs-on: ubuntu-latest container: image: espressif/idf:v5.4 + strategy: + fail-fast: false + matrix: + include: + - variant: 8mb + sdkconfig: sdkconfig.defaults + partition_table_name: partitions_display.csv + size_limit_kb: 1100 + artifact_app: esp32-csi-node.bin + artifact_pt: partition-table.bin + - variant: 4mb + sdkconfig: sdkconfig.defaults.4mb + partition_table_name: partitions_4mb.csv + size_limit_kb: 1100 + artifact_app: esp32-csi-node-4mb.bin + artifact_pt: partition-table-4mb.bin steps: - uses: actions/checkout@v4 - - name: Build firmware + - name: Build firmware (${{ matrix.variant }}) working-directory: firmware/esp32-csi-node run: | . $IDF_PATH/export.sh + if [ "${{ matrix.variant }}" != "8mb" ]; then + cp "${{ matrix.sdkconfig }}" sdkconfig.defaults + fi idf.py set-target esp32s3 idf.py build - - name: Verify binary size (< 1100 KB gate) + - name: Verify binary size (< ${{ matrix.size_limit_kb }} KB gate) working-directory: firmware/esp32-csi-node run: | BIN=build/esp32-csi-node.bin SIZE=$(stat -c%s "$BIN") - MAX=$((1100 * 1024)) + MAX=$((${{ matrix.size_limit_kb }} * 1024)) echo "Binary size: $SIZE bytes ($(( SIZE / 1024 )) KB)" - echo "Size limit: $MAX bytes (1100 KB — includes WASM runtime + HTTP client for Seed swarm bridge)" + echo "Size limit: $MAX bytes (${{ matrix.size_limit_kb }} KB)" if [ "$SIZE" -gt "$MAX" ]; then - echo "::error::Firmware binary exceeds 1100 KB size gate ($SIZE > $MAX)" + echo "::error::Firmware binary exceeds ${{ matrix.size_limit_kb }} KB size gate ($SIZE > $MAX)" exit 1 fi echo "Binary size OK: $SIZE <= $MAX" @@ -47,14 +66,11 @@ jobs: ERRORS=0 BIN=build/esp32-csi-node.bin - # Check binary exists and is non-empty. if [ ! -s "$BIN" ]; then echo "::error::Binary not found or empty" exit 1 fi - # Check partition table magic (0xAA50 at offset 0). - # Use od instead of xxd (xxd not available in espressif/idf container). PT=build/partition_table/partition-table.bin if [ -f "$PT" ]; then MAGIC=$(od -A n -t x1 -N 2 "$PT" | tr -d ' ') @@ -64,14 +80,12 @@ jobs: fi fi - # Check bootloader exists. BL=build/bootloader/bootloader.bin if [ ! -s "$BL" ]; then echo "::warning::Bootloader binary missing or empty" ERRORS=$((ERRORS + 1)) fi - # Verify non-zero data in binary (not all 0xFF padding). NONZERO=$(od -A n -t x1 -N 1024 "$BIN" | tr -d ' f\n' | wc -c) if [ "$NONZERO" -lt 100 ]; then echo "::error::Binary appears to be mostly padding (non-zero chars: $NONZERO)" @@ -84,19 +98,27 @@ jobs: echo "Flash image integrity verified" fi + - name: Stage release binaries with variant-specific names + working-directory: firmware/esp32-csi-node + run: | + mkdir -p release-staging + cp build/esp32-csi-node.bin release-staging/${{ matrix.artifact_app }} + cp build/partition_table/partition-table.bin release-staging/${{ matrix.artifact_pt }} + if [ "${{ matrix.variant }}" = "8mb" ]; then + cp build/bootloader/bootloader.bin release-staging/bootloader.bin + cp build/ota_data_initial.bin release-staging/ota_data_initial.bin + fi + ls -la release-staging/ + - name: Check QEMU ESP32-S3 support status run: | echo "::notice::ESP32-S3 QEMU support is experimental in ESP-IDF v5.4. " echo "Full smoke testing requires QEMU 8.2+ with xtensa-esp32s3 target." echo "See: https://github.com/espressif/qemu/wiki" - - name: Upload firmware artifact + - name: Upload firmware artifact (${{ matrix.variant }}) uses: actions/upload-artifact@v4 with: - name: esp32-csi-node-firmware - path: | - firmware/esp32-csi-node/build/esp32-csi-node.bin - firmware/esp32-csi-node/build/bootloader/bootloader.bin - firmware/esp32-csi-node/build/partition_table/partition-table.bin - firmware/esp32-csi-node/build/ota_data_initial.bin + name: esp32-csi-node-firmware-${{ matrix.variant }} + path: firmware/esp32-csi-node/release-staging/ retention-days: 90 diff --git a/CHANGELOG.md b/CHANGELOG.md index 3837d3fc..7b789cbf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [v0.6.2-esp32] — 2026-04-20 + +Firmware release cutting ADR-081 and the Timer Svc stack fix discovered during +on-hardware validation. Cut from `main` at commit pointing to this entry. +Tested on ESP32-S3 (QFN56 rev v0.2, MAC `3c:0f:02:e9:b5:f8`), 30 s continuous +run: no crashes, 149 `rv_feature_state_t` emissions (~5 Hz), medium/slow ticks +firing cleanly, HEALTH mesh packets sent. + +### Fixed +- **Firmware: Timer Svc stack overflow on ADR-081 fast loop** — `emit_feature_state()` runs inside the FreeRTOS Timer Svc task via the fast-loop callback; it calls `stream_sender` network I/O which pushes past the ESP-IDF 2 KiB default timer stack and panics ~1 s after boot. Bumped `CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH` to 8 KiB in `sdkconfig.defaults`, `sdkconfig.defaults.template`, and `sdkconfig.defaults.4mb`. Follow-up (tracked separately): move heavy work out of the timer daemon into a dedicated worker task. +- **Firmware: `adaptive_controller.c` implicit declaration** (#404) — `fast_loop_cb` called `emit_feature_state()` before its static definition, triggering `-Werror=implicit-function-declaration`. Added a forward declaration above the first use. + +### Changed +- **CI: firmware build matrix (8MB + 4MB)** — `firmware-ci.yml` now matrix-builds both the default 8MB (`sdkconfig.defaults`) and 4MB SuperMini (`sdkconfig.defaults.4mb`) variants, uploading distinct artifacts and producing variant-named release binaries (`esp32-csi-node.bin` / `esp32-csi-node-4mb.bin`, `partition-table.bin` / `partition-table-4mb.bin`). + ### Added - **ADR-081: Adaptive CSI Mesh Firmware Kernel** — New 5-layer architecture (Radio Abstraction Layer / Adaptive Controller / Mesh Sensing Plane / diff --git a/firmware/esp32-csi-node/version.txt b/firmware/esp32-csi-node/version.txt index ee6cdce3..b6160487 100644 --- a/firmware/esp32-csi-node/version.txt +++ b/firmware/esp32-csi-node/version.txt @@ -1 +1 @@ -0.6.1 +0.6.2