Firmware dev loops, brought into the AI-agent era

Same question across four kinds of software — change saved → update visible — because that loop's length is what actually gates how fast an agent (or a human) can iterate. These aren't a controlled bake-off: an interpreted script hot-swap, a dev-server module patch, and a compiled-firmware rebuild are different mechanisms in different domains. The point is the order of magnitude — firmware has historically been the outlier by 1–2 orders of magnitude, and closing that gap is what the setup below actually buys.

Dev loopMechanismChange → visible
Traditional firmware edit C → incremental rebuild → flash over SWD/JTAG → MCU reboots → observe on log/LED ~20 s – 2 min1typical
Godot (GDScript) edit .gd → save → editor hot-swaps the script into the running scene, no restart <1 s2typical
JS/web (dev-server HMR) edit → Vite/webpack HMR patches the module into the running page, no full reload <1 s3typical
THIS SETUP edit C blob → relink against the flashed ELF → push over BLE, verified → runs in RAM, no reflash/reboot 0.8–0.9 s (1.8–2.1 s signed)4measured
  1. 1 — ballpark for an incremental Zephyr build + SWD/JTAG flash + reboot; not a number measured on any project referenced here — an order-of-magnitude figure, not a benchmark.
  2. 2 — personally tested this one thoroughly, not just cited — I used Godot's GDScript hot-reload a lot and loved it, and that experience is what pushed me to ask why firmware couldn't feel the same way. The number itself is still a representative range, not a stopwatch benchmark.
  3. 3 — typical Vite/webpack dev-server HMR latency (module patched into the running page in-browser); representative range, not benchmarked here. This is the local dev loop, not a production deploy — shipping a change live over CI/CD is a separate, much slower loop not shown here.
  4. 4 — measured end-to-end on real hardware (ESP32-C3 / nRF5340 DK) on the separate embedded project this widget illustrates — see that project's own transport-app README for the staged build/sign/transfer/load breakdown.

Detail: decoded-event stream — schematic

Illustrative fixture, not a live capture. The real GUI for this device stream is design-only (no capture viewer has shipped yet), so this widget hand-authors a short record sequence in the same wire shape the firmware actually emits over its dedicated BLE characteristic — HELLO / LOADED / UNLOADED / I2C_START/I2C_ADDR/I2C_DATA/I2C_STOP / OVERFLOW. The x-axis is index order, not wall-clock scale.

I2C transaction decoder load/unload ring overflow (dropped + reported)
▲ decoder hot-swapped here — new blob pushed and running in ~1 s, no reflash, no reboot, capture never stopped
#t_ussrctypepayload