embedded-workbench
The problem
Coding agents are strong on general software and weak on embedded firmware, for specific, addressable reasons: they can’t observe hardware state directly, they confabulate pin assignments and register values fluently and confidently, and bring-up work spans more sessions than a single context window holds. Rather than work around those failure modes ad hoc per project, I built the harness itself as the deliverable — infrastructure that makes agent-assisted embedded work verifiable, not infrastructure that papers over the gaps.
What it actually is
A two-part repository: an agent harness (bench daemon, hardware-fact provenance rules, a MISRA static-analysis gate, Renode emulation, hardware-in-the-loop flashing) and, built on top of it, STM32 firmware projects that report status honestly against an explicit verification ladder — L0 (builds) through L5 (a human physically confirms the hardware behaves correctly). A project states the highest gate it has actually reached; “L2 green, L4 not run” is the expected way to describe progress, not a failure to hide.
Technical decisions worth mentioning
-
Split trust model. The agent’s shell (cross-compiler, linter, Renode, git) never touches USB or hardware directly. A separate daemon (
benchd) on the physical bench host exposes only five allow-listed verbs (inventory/flash/reset/serial/selftest) over a UNIX socket, refuses any board not in a human-edited inventory file, and requires a fresh human acknowledgement token before touching anything that spins, heats, or runs above 50 V. -
Hardware-fact provenance. Every claimed pin, register, or clock value in
docs/hardware/*.mdcarries asource:field (document, revision, section) and averified/unverifiedstatus. Unverified facts can’t be used in code. In practice this caught a real mistake mid-project: a seeded fact sheet assumed one board was the official STM32F072B-DISCO; reading the actual schematic and runningst-infoagainst the physical board showed it was a different board revision entirely (an older32F0DISCOVERYPCB later populated with a different MCU) — the wrong assumption was corrected before any driver code was written against it, not after. -
MISRA C:2012 gate with recorded deviations, not a suppressed report.
cppcheck --addon=misraplusclang-tidyrun in CI; real deviations (e.g. early-return clamping in a quantization routine, technically MISRA 15.5) are recorded as ADRs with the rule number, the construct, why the compliant alternative is worse, and the containment — not blanket-suppressed to get a green check mark. - CubeMX generates the linker script and startup code, not me. Hand-writing memory maps and vector tables is exactly the class of task an LLM will get plausibly wrong; the harness’s own CMake structure is designed so CubeMX’s own export slots in without being touched by hand.
Status, honestly
The toolchain image, bench daemon, MISRA gate, and verification-ladder tooling are built and exercised. The first firmware project (quantized inference on a memory-constrained Cortex-M0 target) has its host-testable logic passing L0/L1/L2 against the real toolchain container; the cross-compiled/on-hardware gates are queued behind generating the CubeMX project for the target board.