Skip to main content

CPS STM32 Bench Node (USB serial)

This runbook brings up the STM32F401 access node on a bare WeAct Blackpill over USB CDC-ACM serial, with a host bridge that republishes its events into the existing MQTT ingest path. See ADR 042 for the rationale (no W5500 or PN532 on the bench, so the architecture's W5500/MQTT transport is replaced by USB serial).

Hardware

  • WeAct STM32F401CCU6 Blackpill (256 KB flash), connected by USB-C.
  • ST-Link V2 on the SWD header (SWDIO, SWCLK, GND, 3V3) for flashing and logs.
  • No external peripherals. The onboard PC13 LED and PA0 KEY button are used.

What the firmware does

  • Presents a USB serial port and emits one line per event as <topic>\t<payload> using the shared aurora-firmware-contracts format.
  • PC13 LED reflects the lock state: off when Locked, on when Unlocked, blinking under Lockdown.
  • PA0 KEY button simulates a badge read (cycling a small UID table) and requests an unlock.
  • Publishes periodic status (every 30 s) and real MCU die-temperature telemetry (every 10 s) read from the ADC internal temperature sensor.
  • Accepts commands written back over serial: unlock, lock, lockdown, lockdown_clear, keepalive. A fail-secure watchdog relocks the door if the host link goes silent for 70 s.

Flash and observe

From firmware/embassy-stm32/projects/stm32f401_access_node:

export DEVICE_ID="stm32f401-access-01"
cargo run --release # probe-rs flashes via ST-Link and streams defmt RTT

The RTT log shows boot, status, telemetry, and a line per button press. A /dev/ttyACM* serial port also appears for the USB CDC interface. To watch the raw framed lines directly:

cat /dev/ttyACM0 # topic<TAB>payload lines on the status/telemetry interval

Run the host bridge

Start Mosquitto (from infra/), then run the bridge so its lines reach the backend. The bridge is opt-in:

export SERIAL_BRIDGE_ENABLED=true
export SERIAL_BRIDGE_PORT=/dev/ttyACM0
export SERIAL_BRIDGE_DEVICE_ID=stm32f401-access-01
python -m aurorasoc.tools.cps.serial_bridge

When the API runs with SERIAL_BRIDGE_ENABLED=true, the bridge also starts automatically in the API lifespan, so a separate process is not required.

End-to-end check

  1. Press the KEY button. A badge event publishes on aurora/access/stm32f401-access-01/badge_event and an access event appears in the console CPS overview.

  2. Telemetry on aurora/sensors/stm32f401-access-01/telemetry lands as temperature_c readings.

  3. Publish a command to drive the lock:

    mosquitto_pub -t aurora/access/stm32f401-access-01/command -m unlock

    The PC13 LED turns on for the unlock window, then auto-relocks.

Notes

  • The bench node has no secure element wired, so attestation requests are not answered and the device stays in the PENDING attestation state by design.
  • For a node with a real PN532 reader and a solenoid lock, see the CPS STM32 Door Node runbook. It uses the same USB serial bridge and the pn532-async driver crate, and adds backend-authorized unlock.