Skip to content

feat: harden STM32 firmware, add CI and CAN control - #2

Closed
seofernando25 wants to merge 3 commits into
mainfrom
feat/firmware-hardening-ci
Closed

feat: harden STM32 firmware, add CI and CAN control#2
seofernando25 wants to merge 3 commits into
mainfrom
feat/firmware-hardening-ci

Conversation

@seofernando25

@seofernando25 seofernando25 commented Jul 25, 2026

Copy link
Copy Markdown

Summary

This PR establishes a compile-, test-, and CI-protected C/libopencm3 firmware baseline for each STM32F072R8T6 receiver-chain board and adds the CAN functionality needed for a Raspberry Pi plus multiple receiver nodes.

The repository remains intentionally scoped to per-board firmware:

  • PE44820 phase-shifter control
  • F0480 VGA control
  • CAN bus communication and command execution
  • watchdog, fault handling, diagnostics, build and test infrastructure

Beam steering, calibration strategy, and coordination across several receiver boards belong in a separate controller-side repository.

CAN implementation

Versioned wire protocol

  • Classic CAN 2.0B extended frames at 500 kbit/s.
  • Controller node ID 0.
  • Receiver node IDs 1..30.
  • Broadcast destination 31.
  • 29-bit identifier fields:
    • bits 28:26: message type
    • bits 25:21: destination
    • bits 20:16: source
    • bits 15:0: sequence number
  • Receiver boards accept control commands only from controller node 0.
  • Standard-ID and remote frames are rejected by hardware filters.
  • Safety commands have the highest protocol arbitration priority.

Supported commands:

  • ENTER_SAFE
  • SET_COMBINED
  • SET_PHASE
  • SET_VGA
  • PING

Responses:

  • STATUS
  • ACK
  • ERROR

Broadcast commands do not generate responses, avoiding an acknowledgement storm.

Safe output sequencing

  • SET_PHASE applies 23 dB attenuation before a phase change when necessary, then restores the previous attenuation.
  • SET_COMBINED applies 23 dB → phase → requested attenuation.
  • ENTER_SAFE applies 23 dB and phase state zero.
  • Runtime SPI failures reset the MCU rather than continuing with uncertain RF state.
  • Retained safe lockout still answers unicast status requests but rejects ordinary output-changing commands.

CAN transport

  • CAN1 on PA11/PA12, AF4.
  • Compile-time-checked 500 kbit/s timing from the 48 MHz clock.
  • Automatic bus-off management and automatic retransmission.
  • Hardware filters for the local node and broadcast destination.
  • ISR drains the three-frame bxCAN FIFO into an eight-frame SPSC software queue.
  • Saturating RX-drop, TX-drop, invalid-command, clock-fallback, lockout, and bus-off health reporting.
  • Sequence-matched status, acknowledgement, and error responses.

Node-specific images

The node ID is compiled into the image:

make -C app clean all CAN_NODE_ID=1

Valid IDs are 1..30; invalid values fail compilation. The retained build identity hashes both the Git revision and node ID.

CI builds and uploads images for nodes 1, 2, and 3 for the planned Raspberry Pi bench test.

Raspberry Pi test tool

tools/can_smoke_test.py is a dependency-free SocketCAN client supporting:

python3 tools/can_smoke_test.py ping 1
python3 tools/can_smoke_test.py phase 1 146 3
python3 tools/can_smoke_test.py vga 1 23
python3 tools/can_smoke_test.py combined 1 64 4 12
python3 tools/can_smoke_test.py safe 1 3

The complete identifier layout, payloads, status flags, Pi setup, and three-node test sequence are documented in docs/CAN_PROTOCOL.md.

Existing hardening included in this PR

Build and target alignment

  • Aligns the Makefile, VS Code, J-Link target, SVD and linker generation with STM32F072R8T6.
  • Removes the tracked generated F030 linker script.
  • Embeds the exact Git revision and compiled node ID.
  • Treats compiler warnings as errors.

Phase and VGA correctness

  • Deterministic integer phase conversion.
  • Four-bit address validation and 13-bit phase frame validation.
  • PE44820 OPT derived from phase-state bit D6.
  • Known 205.3-degree/address-3 command verified as 0x092c.
  • Complete F0480 attenuation support from 0 through 23 dB.
  • Maximum attenuation command verified as 0x5c.

Fault containment

  • Bounded SPI TXE/BSY waits.
  • Bounded HSE/PLL startup with HSI48 fallback.
  • Independent watchdog.
  • Clock-security, HardFault, and unexpected-interrupt reset paths.
  • Checksummed .noinit diagnostic record.
  • Three-incomplete-boot safe lockout.

Verification

The complete gate passes in Ubuntu 24.04:

7 native C test binaries: pass
4 Python SocketCAN/conformance tests: pass
ASan + UBSan native test pass: pass
cppcheck warning/style/performance/portability: clean
ARM GNU builds for nodes 1, 2 and 3: clean with -Werror
Git whitespace check: clean

Exact final revision:

0eeb8771f1338112470f398c25e4ab485ef0b5d2

Each node image embeds that revision and uses:

text: 9012 bytes
data:    8 bytes
bss:   180 bytes
total: 9200 bytes

Hardware validation still required

This PR is software-verified, not CAN-bus or RF-hardware-validated. Before operational use, complete docs/HARDWARE_VALIDATION.md, including:

  • confirm PA11/PA12 and transceiver wiring from the schematic;
  • document the current RJ11 and future RJ45 pinouts separately;
  • verify CANH/CANL, common ground and exactly two terminators;
  • test the exact node-1, node-2 and node-3 artifacts with the Raspberry Pi CAN hat;
  • capture CAN, SPI, LE/CS and RF behavior;
  • exercise invalid frames, broadcasts, queue pressure, bus-off and recovery;
  • test watchdog, brownout, clock fallback and retained lockout.

Points to confirm during project rundown

  1. Does each board have one independently controlled VGA, as represented by the current hardware driver?
  2. Is one phase-shifter address per CAN command sufficient, or is an atomic four-address batch required?
  3. Are PA11/PA12 and the assumed external SN65HVD230-class transceiver correct for the board revision being tested?
  4. What are the authoritative RJ11 and RJ45 connector pinouts?

The protocol is versioned so those decisions can be incorporated without importing the unfinished CANDev implementation or silently changing deployed frames.

@seofernando25 seofernando25 changed the title feat: harden STM32 firmware and add CI feat: harden STM32 firmware, add CI and CAN control Jul 25, 2026
@seofernando25

Copy link
Copy Markdown
Author

Holy slop

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant