Skip to content

fix(fdcan): model asynchronous TX so TXBRP polling blocks (#336)#342

Open
w1ne wants to merge 1 commit into
mainfrom
fix/issue336-fdcan-async-tx
Open

fix(fdcan): model asynchronous TX so TXBRP polling blocks (#336)#342
w1ne wants to merge 1 commit into
mainfrom
fix/issue336-fdcan-async-tx

Conversation

@w1ne

@w1ne w1ne commented Jun 23, 2026

Copy link
Copy Markdown
Owner

Summary

  • request_tx() previously resolved TXBRP→0, TXBTO, and IR flags synchronously on the TXBAR write, so firmware polling while (TXBRP & 1) {} never blocked in simulation.
  • This false-passed firmware that called NVIC_SystemReset before its CAN frame was actually transmitted — the udslib fix: wire I2C1 into STM32F401 descriptor #88 failure class that FDCAN async-TX needed: #88 reset smoke false-passes a firmware that resets before TX-complete #336 tracks.
  • Fix: request_tx() now sets TXBRP and queues the frame into pending_tx; drain_pending_tx() (called at the top of tick()) does the actual delivery and posts completion flags. TXBRP stays asserted from the TXBAR write until the next tick, matching real M_CAN silicon behavior.

Changes

  • crates/core/src/peripherals/fdcan.rs: added pending_tx: VecDeque<(u32, CanFrame)> field; split the old synchronous request_tx body into a deferred drain_pending_tx called from tick(); updated txfqs() to reflect pending count.
  • crates/core/tests/fdcan.rs: new test txbrp_stays_set_until_tick_then_txbto_is_set proves the fix; three existing bus-interconnect tests updated to tick the transmitting node before the bus tick (required because the frame now reaches the channel in drain_pending_tx).
  • Internal unit tests (fdcan.rs mod tests): 7 tests that asserted completion state immediately after TXBAR updated to call dev.tick() first.

Test plan

  • cargo fmt --all -- --check clean
  • cargo clippy --all-targets -- -D warnings clean
  • cargo test -p labwired-core --lib fdcan — 16/16 passed
  • cargo test -p labwired-core --test fdcan — 4/4 passed (including new txbrp_stays_set_until_tick_then_txbto_is_set)
  • cargo test --workspace --lib — all passed
  • cargo test -p labwired-core --test h563_conformance — 6/6 passed

Closes #336

TXBRP now stays asserted from the TXBAR write until the next tick(),
matching real M_CAN behavior where the bit clears only after the frame
leaves the node on the physical bus. The completion flags (TXBTO,
IR.TFE, IR.TC) are posted in drain_pending_tx(), called at the start
of every tick().

Previously, request_tx() resolved everything synchronously: firmware
polling `while (TXBRP & 1) {}` never blocked, so the simulator
false-passed code that called NVIC_SystemReset before its CAN frame
was actually transmitted (the udslib #88 failure class).

Frame delivery to loopback/bus/tx_frames is also deferred to tick()
so the frame and the completion flags are always consistent.

The new txbrp_stays_set_until_tick_then_txbto_is_set integration test
covers the issue directly. Existing tests updated to tick once after
TXBAR before inspecting completion state.
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.

FDCAN async-TX needed: #88 reset smoke false-passes a firmware that resets before TX-complete

1 participant