Track B: STM32G0 wired-UART door sensor (bench/dev firmware)#13
Merged
Conversation
First firmware in the repo, matching the architect's STM32G0 + door contact choice in spar/wohl_system.aadl and spar/wohl_firmware.aadl (DoorFirmware thread). The crate is no_std/no_alloc and splits cleanly into a pure-logic library (CCSDS encoder, debouncer, state machine — host-testable) and a thin HAL binding to USART1/SysTick/GPIO on the STM32G031K8 reference board. Hardware notes (pin map, clocking, UART framing, linker memory) live in boards/stm32g0/README.md so reviewers can audit them independently of the Rust code. The CCSDS encoder is intentionally vendored — byte- identical to relay-ccsds::sensor_wire::encode_packet, with a host-side golden-byte test that locks the layout to spec — to keep the firmware free of transitive deps like wit-bindgen. HAL: stm32g0xx-hal 0.2.0 (synchronous embedded-hal 0.2 traits) over embassy-stm32. Picked for reviewability on the first firmware: every peripheral interaction is a plain function call, no executor, no codegen magic. Async can replace this once the OTA bootloader thread needs to share radio time. Verification (gates that pass locally; CI integration is a follow-up): cargo build -p wohl-fw-door --target thumbv6m-none-eabi --release cargo test -p wohl-fw-door # 16/16 pass cargo fmt -p wohl-fw-door --check cargo clippy -p wohl-fw-door --all-targets -- -D warnings Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Documents the exact Cargo.toml edit (one line in the workspace members list) the orchestrator needs to apply when integrating the new firmware crate, plus the rationale for deferring CI changes until cross-compilation for thumbv6m-none-eabi has been scoped. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The firmware in crates/wohl-fw-door targets an STM32G031K8 with a wired UART link to the hub. The AADL only modelled DoorWindowNode.Battery (nRF52840 + Thread mesh), so model and code disagreed on the door node. Architect's call: keep BOTH deployment shapes modelled rather than replacing the battery variant. - wohl_hardware.aadl: new `processor STM32G031` (Cortex-M0+, UART, no radio) + `memory SRAM_STM32G031` (8 KB) + `memory Flash_STM32G031` (64 KB). - wohl_nodes.aadl: new `system implementation DoorWindowNode.WiredG0` wiring the reed switch + STM32G031 + UART bus + DoorFirmwareProcess. Also fixes crates/wohl-fw-door/memory.x: the header said "STM32G031K8" but FLASH LENGTH was 32K. The K8 part is 64 KB flash — corrected so the linker map, the AADL Flash_STM32G031 size, and the part number all agree. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The STM32G0 + wired-UART firmware is a bench/development tool, not a field door sensor — point-to-point UART does not scale to a real home. Field door nodes will use STM32WL55 (sub-GHz) or a CAN-FD bus with a transport-agnostic CCSDS layer (tracked separately). - Renamed crate wohl-fw-door -> wohl-fw-door-bench (package, [lib], [[bin]], doc comments, boot banner, .cargo/config comment). - Root Cargo.toml: added crates/wohl-fw-door-bench to workspace members (applies the WORKSPACE_INTEGRATION.md handoff; that file is removed). - boards/stm32g0/README.md: reframed as the bench board; fixed the STM32G031K8 flash size (it is 64 KB, not 32 KB — the K8 suffix denotes 64 KB; the linker-map example block was also wrong). - spar AADL: DoorWindowNode.WiredG0 comment now states it is a bench/development node; processor STM32G031 comment updated. The wireless field shape stays modelled as DoorWindowNode.Battery. Verified from the worktree: cargo build -p wohl-fw-door-bench --target thumbv6m-none-eabi --release OK cargo test -p wohl-fw-door-bench 16/16 cargo +1.85.0 clippy -p wohl-fw-door-bench --all-targets -- -D warnings clean cargo +1.85.0 fmt -p wohl-fw-door-bench -- --check clean Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Lockfile follow-up to the crate rename — the package entry is now wohl-fw-door-bench. No dependency-version changes. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Reviewer flagged that the processor declared Clock_Period => 15625 ps (64 MHz) while the firmware boots on HSI16 at 16 MHz (main.rs leaves the PLL off). Model the actual boot clock: 62500 ps / 16 MHz, with a comment noting 64 MHz is the unused PLL ceiling. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Phase 2 Track B. New
crates/wohl-fw-door-bench— the first firmware crate in the repo. STM32G031 + reed switch, emitting 14-byte CCSDS sensor packets over UART.Bench tool, NOT a field sensor
This is explicitly a bench/development firmware. Point-to-point UART does not scale to a real home (one cable run per sensor). Its job: exercise the hub's
--ccsdsingest path against real CCSDS framing without needing radio or bus hardware. It is the test fixture every future transport will be validated against.The field door firmware — STM32WL55 sub-GHz (wireless) + CAN-FD (wired bus), both over a transport-agnostic CCSDS layer — is Phase 3, tracked in #10. The crate name (
-bench), the AADL comments, and the board README all say this plainly so no one mistakes it for the product.What's in it
crates/wohl-fw-door-bench/—no_std, ARMv6-M (thumbv6m-none-eabi)ccsds.rs— vendored 14-byte CCSDS encoder, golden-byte test cross-checks therelay-ccsdsspecdebounce.rs— reed-switch edge debouncer (50 ms default)door.rs— debounce → CCSDS packet state machinemain.rs— STM32G031 binary (GPIO + SysTick + USART1); collapses to a host stub off-target socargo testworksstm32g0xx-hal(sync) — chosen over embassy for reviewabilityboards/stm32g0/README.md— pin map, framing, clockingDoorWindowNode.WiredG0+processor STM32G031+ memories. Architect's call — keep both deployment shapes modelled (.WiredG0bench,.Batterywireless field).memory.x: STM32G031K8 is 64 KB flash, not 32 KB (the header said K8 but the linker LENGTH was 32K — corrected so part number, linker map, and AADL all agree).Verification
cargo build -p wohl-fw-door-bench --target thumbv6m-none-eabi --release— OKcargo test -p wohl-fw-door-bench— 16/16 (incl. proptests + CCSDS golden-byte cross-check)cargo +1.85.0 clippy --all-targets -- -D warnings+fmt— cleanNotes / follow-ups
rustup target add thumbv6m-none-eabi) not added —ci.ymluntouched per track scope. The hostcargo test --workspacejob exercises the library automatically now that the crate is a workspace member.DEVICE_ID/ZONE_IDare hard-coded constants — flash-resident provisioning is future work.🤖 Generated with Claude Code