Peripherals and the Type State Pattern
Why the HAL makes misconfigured pins fail to compile.
Peripherals::take() returns Option and yields None on the second call. That’s a
singleton enforced at runtime — there is exactly one set of hardware registers, so exactly one
owner.
Then the HAL encodes pin configuration in the type:
let pin: Pin<Output<PushPull>> = gpioa.pa5.into_push_pull_output(&mut gpioa.crl);
pin.set_high(); // exists
let pin: Pin<Input<Floating>> = /* ... */;
pin.set_high(); // does not compile — no such method
This is the type state pattern: calling set_high() on an input pin isn’t a bug you
debug with an oscilloscope, it’s a compile error. Embedded Rust’s real pitch isn’t speed —
C is already fast — it’s that a whole category of hardware misconfiguration stops being
possible.