Skip to content

Firmware refresh - #34

Open
filipton wants to merge 150 commits into
masterfrom
refresh
Open

filipton wants to merge 150 commits into
masterfrom
refresh

Conversation

@filipton

@filipton filipton commented Oct 16, 2026 •

Copy link
Copy Markdown
Member

Refresh the firmware dependencies and remove failure modes that could lose an attempt, stall a station, or crash on external data. Failed solve submissions now show the reason on the device, and late replies can only reset the attempt with the matching session ID. The competition workflow and production server wire format are preserved.

Changes

  • Update esp-hal to 1.2.2, esp-radio to 1.0.0-beta.1, esp-rtos to 0.4, wifimanager to 0.6.4, and the related device crates. Use upstream embedded-tls and the slim esp-nvs fork; server certificates use ECDSA.
  • Remove static mut and unchecked handling of external data. Use bounded protocol/error/log buffers, request slots with timeouts, and direct JSON serialization into the transmit buffer. Host tests compare outgoing packets with the previous serialization.
  • Split state into solve, UI, status, and battery domains; avoid holding locks across awaits. Replace heap-based button handlers with direct dispatch.
  • Unify the display screen model; update changed OLED pages/LCD characters, repair v3 LCD state periodically, and avoid timer blinking.
  • Rework BLE connection handling, timeouts, and backoff. Preserve the public/random address type from discovery through connection and bond storage; treating public addresses as random prevented a connection to the real BlueZ test display. Use a valid static BLE identity in the correct byte order, and accept encryption completion when resuming a stored bond. Existing bonds need re-pairing.
  • Make Stackmat input event-driven, support gen3 frames, validate checksums, and preserve exact stopped times.
  • Add task heartbeat watchdogs, RTC crash records, throttled error-log persistence, battery backoff, and bounded mDNS retries.
  • Vendor esp-storage 0.10.0 with a flash-capacity cache: on real ESP32-C3 hardware, a second storage instance after a ROM read reports zero capacity and prevents NVS from opening. Cache the first successful detection and log the actual NVS initialization error. Existing NVS data is retained.
  • Share heap between provisioning and normal websocket/TLS operation. Cap dynamic Wi-Fi receive/transmit buffers at 12 each to bound reconnect bursts.
  • Show solve submission errors; match success and failure replies to the attempt's session ID so a late response cannot reset or cover the next attempt with a success message. Delegate timeout behavior remains unchanged.
  • Replace the firmware e2e feature and injected test packets with esp-emu bus models, replay scenarios, fuzzing, and competition simulations. Sim patches live in this repository and builds restore Cargo.lock. The sim console exposes heap statistics during provisioning, and replay files always execute every step instead of inheriting the fuzzer's duration cutoff.

Release measurements

Measurements at 5da253d (before the BLE address-type fix) use RELEASE_BUILD=3.0.0, --no-default-features --features v3|v4, the RISC-V target, and --release. Image sizes are application binaries from espflash save-image without --merge. Master image baselines below are retained from the previous PR description; they were not remeasured in this session.

Metric Previous master baseline Current refresh
v4 image 1,439,968 B 1,344,512 B (−93.2 KiB)
v3 image 1,381,968 B 1,312,352 B (−68.0 KiB)
Heap capacity 120 KiB 112 KiB + 54 KiB reclaimed RAM
Static data excluding heap, v4 / v3 — 74,800 / 71,808 B
Linker main stack reservation, v4 / v3 — 63,248 / 69,472 B
AP provisioning peak heap, v4 / v3 — 106,124 / 106,012 B of 169,984 B
Normal sim peak heap, v4 / v3 — 117,868 / 104,840 B of 169,984 B

Static data is .data + .data.wifi + .bss + .noinit, minus the 112 KiB ordinary heap. Stack figures are the linker-reserved region, not measured stack usage. AP provisioning peaks were remeasured after the Wi-Fi cap, with the setup panel requested. Normal peaks cover competition/fuzz/reconnect paths over plain websocket traffic; these runs do not validate TLS/BLE heap peaks. These sim heap measurements precede the final flash-capacity fix; image/static/stack sizes include it.

Validation

  • Local CI-equivalent checks pass: formatting, clippy with warnings denied, and release builds for v3 and v4.
  • All 29 firmware host tests pass.
  • Sim builds and sim clippy pass for v3 and v4.
  • All 16 replay scenarios pass. The five-minute delegate timeout replay executed all 30 steps, including its final database assertions. The stale solve-success regression fails before the guard fix and passes on v3 and v4 afterwards.
  • Seed 5 fuzz campaigns pass on v3 and v4 after fixing the recovery probe to wait for a live, registered station. An earlier v3 probe missed a 120 ms press; both a traced rerun and the final untraced rerun passed, so no hardware button behavior was changed.
  • Three Python harness regression tests pass; the connector's three binary tests, clippy, and binary builds pass. Both final connector Docker targets build and start successfully (including x86/ARM builds). Simulation startup also passed against the previous connector binary.
  • Full competition seeds 13–14 with delegate rate 8 pass: 43/43 attempt records on each seed, zero final oracle mismatches, three server restarts across the two days. These campaigns use the error-screen/cleanup build, with the final stale-success guard covered separately by the regression above.
  • All 10 GitHub checks pass on 9d3a5ddcc5a80ceba711a4d158154f85a4a02298: push CI and pull-request CI.

Latest commits e1ec289 and 9d3a5dd fix BLE address types, local identity, and resumed-bond encryption handling. Formatting, all 29 host tests, v3/v4 clippy/release builds, and v3/v4 sim clippy pass locally. All GitHub checks pass for 9d3a5dd. These checks do not establish bonded BLE operation on hardware.

v4 hardware validation

  • Connected ESP32-C3 rev 0.4, 4 MB flash. Saved a full flash backup before testing; preserved the PC's staged firmware manifest/lockfile edits by using isolated refresh worktrees.

  • Reproduced the unpatched NVS boot failure, then verified the capacity-cache fix opens the same NVS data without an erase. Wi-Fi, DHCP, mDNS and TLS websocket upgrade succeed on real hardware.

  • Normal-firmware TLS/idle/reconnect peak: 105,188 of 169,984 heap bytes; measured stack high-water mark 21,428 of 64,768 bytes (default v4 build with sleep/pads, unlike the release measurement rows above). Recovered from three test-server restarts; current heap returned to 98,188 bytes each time. BLE and OTA are not included in this peak.

  • Idle sleep passed: after five minutes without activity the device closed its websocket with code 4000, "Going into sleep mode". USB restart was used afterwards; physical button wake is not covered.

  • Authenticated OTA passed using the production connector, TLS, 4 KiB chunks, and RX/TX buffers capped at 12. Full 1,338,976 B transfers took 47.341–51.911 s (25.19–27.62 KiB/s); read-back verification took about 0.70 s. The new slot booted, marked itself valid, and reconnected. Restored the normal 3.0.0 build by OTA afterwards.

  • Fault tests passed: a damaged appended image digest was rejected by the bootloader, which booted the previous valid slot; an image one byte larger than the OTA partition was rejected without reboot; dropping the server during transfer triggered the existing recovery reset and retained the previous valid image. Each recovered over TLS. These cover invalid-image fallback, not rollback of an otherwise bootable app that fails to mark itself valid.

  • No application panic/watchdog crash markers appeared. Final restored-build idle heap stayed at 98,236 bytes (103,348 B peak), with stack high-water mark 21,428 B. The normal heap logger pauses during OTA, so OTA peak heap was not measured.

  • Transient OLED flush timeouts and battery-gauge communication errors appeared during some boots/transfers; the gauge recovered. Display appearance and physical inputs still need confirmation.

  • Temporary USB-controlled lab build: one software sleep/wake cycle with an unpaired BLE connection retry active passed. Heap used 133,888 B before sleep, 59,456 B asleep, and 98,268 B after Wi-Fi/TLS recovery; peak 140,704 of 169,984 B. This does not establish bonded BLE recovery or physical button wake.

  • The PC’s Baseus BA04 (Barrot 33fa:0001) receives pairing requests, but its remote-feature query never completes in captures; both connection directions stall. USB reset restores advertising after a controller power-cycle failure, but has not fixed pairing. Bonded BLE tests remain blocked by this lab setup; no adapter fix is claimed. A USB port disable/enable then left the BA04 failing USB descriptor/configuration reads, before the Bluetooth driver could bind. BlueZ and kernel package integrity checks report zero altered files, and the USB hub has no power-switching support; a remote host reboot also failed to recover the adapter, so recovery still needs a physical replug. No permanent driver or Bluetooth configuration changes were made. Temporary lab instrumentation is not included in this PR.

  • Final board state: normal default v4 9d3a5dd build, with no lab instrumentation or diagnostic dependency patches; saved Wi-Fi restored, TLS reconnected, heap stable at 98,188 B used /101,644 B peak of 169,984 B, stack 21,428/64,784 B. A temporary five-second RTC deep-sleep test produced the expected USB disappearance/reappearance; console loss prevented wake-reason capture, so this does not validate GPIO wake.

Hardware checks still required

  • v3 LCD stale-text timing: check the 100 µs wait and 2 s controller reinitialization with a logic analyser.
  • v4 BLE heap after wake.

The broader refresh still needs physical-device checks for display initialization/partial updates, physical BLE pairing and sleep/wake, button and Stackmat/pad timing, rollback of an unconfirmed bootable image, and watchdog/crash reporting.

Venue test mode and enabling sleep in competition simulations are outside this change.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant