dakejahl opened a new pull request, #19957:
URL: https://github.com/apache/nuttx/pull/19957

   ## Summary
   
   `imxrt_transmit()` picks the lowest free TX mailbox. FlexCAN breaks an 
arbitration tie between mailboxes holding *equal* CAN IDs by taking the lowest 
mailbox number, so refilling a just-drained low mailbox while older frames are 
still pending in higher ones puts the newer frame on the wire first.
   
   Every frame of a multi-frame transport transfer carries the same CAN ID, so 
this reorders transfers. `imxrt_txdone_work()` re-polls after each individual 
TX completion, which is exactly the condition that triggers it.
   
   This hands out a mailbox above every pending one instead, and wraps back to 
the bottom only once the ring has drained. Ordering is then guaranteed 
regardless of transfer length; the cost is that the ring stalls at a wrap 
instead of refilling immediately.
   
   ## Impact
   
   i.MX RT boards using SocketCAN with any multi-frame protocol on top. 
Single-frame traffic is unaffected — it cannot be reordered.
   
   `s32k1xx_flexcan.c` and `s32k3xx_flexcan.c` select a mailbox the same way 
and look to have the same defect, but I have no S32K hardware and have 
deliberately left them alone.
   
   ## Testing
   
   i.MX RT1176 (ARK FMU-v6XRT), FlexCAN1 at 1 Mbit, DroneCAN, measured on the 
wire with a separate USB-CAN analyser decoding CAN-ID and tail byte per frame.
   
   A GNSS node on the same bus acted as the control: its 10-frame transfers 
were flawless in every capture, which rules out the bus and the analyser and 
places the fault on the i.MX RT transmit path.
   
   Before, over 60 s:
   
   | stream from the i.MX RT | frames | transfers | corrupt |
   |---|---|---|---|
   | 4-frame message | 240 | 60 | 6.7% |
   | 6-frame message | 360 | 60 | **81.7%** |
   | single-frame messages | 897 | 897 | 0% |
   
   After this patch the 4-frame stream is clean. The 6-frame stream drops to 
40%, and the rest was two further bugs above this driver (frames discarded on a 
full ring rather than retried, and a queue bypass in the CAN stack) — with all 
three fixed: **0 corrupt transfers in 84 594 frames over 5 minutes**, then 35 
029 more.
   
   Sanity-checked that constraining allocation further is not an option: 
`CONFIG_IMXRT_FLEXCAN_TXMB=1`, or serialising to one frame in flight, stops 
transmission entirely, because a 1-deep ring makes every overflow frame hit the 
discard path in `imxrt_transmit()`.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to