Skip to content

ESP32 decision firmware 0.2.0 — 21× faster round trip, fast link, USB-JTAG images (preview)

Pre-release
Pre-release

Choose a tag to compare

@ruvnet ruvnet released this 26 Sep 16:19
· 504 commits to main since this release

This is a preview release from PR #1018, which is not merged yet. It makes the firmware faster end to end and adds a few new options. Every speed claim below was measured on a physical ESP32-C6 with images built from the same source, and all decisions matched the previous version exactly.

Plain-language guide: https://gist.github.com/ruvnet/c994f474e94ce2efbf088b9b1406488d

What's new since 0.1.0 (measured on a physical ESP32-C6)

Change Before → after Exactness
inferx / sensorx: each value is sent as its 8-hex-digit IEEE-754 bit pattern Input parsing: 110 µs → 8 µs (13.7×) 1000/1000 identical replies
Command loop: stops waiting 50 ms for a full buffer Host round trip: 70.0 → 28.7 ms 1000/1000 identical
baud 921600 (up to 921,600): only takes effect after baud ok at the new rate, and falls back to 115,200 after 2 s Round trip: 28.7 → 5.6 ms; full OTA update: 18 s → 3.7 s 1000/1000 identical
format compact: replies carry exact hex floats and drop the label and timing fields Reply size: 232 → 86 bytes; round trip: 5.6 → 3.9 ms 1000/1000 bit-identical
Kernel: skips expf(0) and the division by the input's largest value; results are identical by construction Inference: 76.6 → 69.2 µs; now passes the ADR's ≥1.10× rule (1.108×) 3 × 84,480 exact differential checks
USB-Serial/JTAG images for S3, C3, C6, H2 and P4 boards that have no USB-UART chip New Build-only (see below)

Overall: one occupancy decision used to take 80 ms from host to board and back. It now takes 3.9 ms, about 21× faster. On-chip time per request dropped from 198 µs to about 92 µs.

Host tools: Device(baud=921600), ota.py --baud 921600. The Windows serial stalls were a host-side bug: pyserial's flush() sleeps 50 ms whenever bytes are still queued. It's fixed in tools/transport.py.

Files

Kind Files
First install (flash at 0x0) ruvector-decision-<chip>-<variant>-factory.bin
Update over serial ruvector-decision-<chip>-<variant>-ota.bin, sent with tools/ota.py
Chips esp32, esp32s2, esp32s3, esp32c2, esp32c3, esp32c6, esp32h2, esp32p4
Variants full (includes profiling), production (frees 16 KB of RAM), usbjtag (built-in USB port; S3, C3, C6, H2, P4 only)
esptool.py --chip auto write_flash 0x0 ruvector-decision-esp32c6-full-factory.bin
python3 examples/esp32-decision/tools/ota.py --port /dev/ttyUSB0 --baud 921600 ruvector-decision-esp32c6-production-ota.bin

Hardware status

  • ESP32-C6 (via a CP210x USB-UART bridge): tested on real hardware. Checked with these exact images:
    • factory boot and self-test; bench 172.0 µs
    • JSON and compact replies
    • 921,600 baud
    • OTA update committed in 3.5 s
    • a broken image rolled back in 3.7 s
  • All other chips, and every USB-Serial/JTAG image: build-only. They compile and pass CI but have never run on silicon.
  • Not yet measured: energy use, S3 hardware rounds, a real sensor capture driver, network OTA, and image signing.

All 42 images were built with espressif/idf:v5.4.4 from commit b04c3d7. Evidence files are in examples/esp32-decision/tests/evidence/, and details are in the ADR-007 follow-up sections. Verify downloads with sha256sum -c SHA256SUMS.