FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

arch/arm/src/imxrt: Keep FlexCAN TX mailbox allocation in order. by dakejahl · Pull Request #19957 · apache/nuttx · GitHub

Repository navigation

arch/arm/src/imxrt: Keep FlexCAN TX mailbox allocation in order. - #19957

Merged
xiaoxiang781216 merged 2 commits into
apache:masterfrom
dakejahl:fix/imxrt-flexcan-tx-mailbox-ordering
Aug 25, 2026
Merged

xiaoxiang781216 merged 2 commits into
apache:masterfrom
dakejahl:fix/imxrt-flexcan-tx-mailbox-ordering

Conversation

dakejahl commented Aug 24, 2026 •
edited
Loading

Copy link
Copy Markdown
Contributor

Summary

  • Why: 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. imxrt_txdone_work() re-polls after each individual TX completion, which is exactly the condition that triggers it.
  • What: arch/arm/src/imxrt/imxrt_flexcan.c, TX mailbox selection only.
  • How: a new imxrt_txmb_next() returns a mailbox above every pending one and wraps back to the bottom only once the ring has drained, so a newer frame can never win arbitration against an older one. imxrt_txringfull() is expressed in terms of it. Ordering then holds for any transfer length; the cost is that the ring stalls at a wrap rather than refilling immediately.
  • Every frame of a multi-frame transport transfer carries the same CAN ID, so any such protocol is affected. On DroneCAN the receiver sees a broken toggle bit and discards the transfer.
  • A second commit fixes pre-existing nxstyle violations in the same file, per CONTRIBUTING.md section 2.1. It is whitespace only — git diff -w against its parent is empty, and the resulting binary is byte-identical.

Impact

  • New feature? NO. Bug fix.
  • Impact on user? NO — no API, Kconfig or behaviour change to adapt to. Multi-frame CAN traffic that was silently corrupted now arrives intact.
  • Impact on build? NO.
  • Impact on hardware? YES — arch/arm/src/imxrt only, any i.MX RT board using FlexCAN via SocketCAN. s32k1xx_flexcan.c and s32k3xx_flexcan.c select a mailbox the same way and appear to share the defect, but I have no S32K hardware and have deliberately left them alone.
  • Impact on documentation? NO.
  • Impact on security? NO.
  • Impact on compatibility? NO.

Testing

I confirm that changes are verified on local setup and works as intended:

  • Build Host: Linux x86_64, arm-none-eabi-gcc 13.2.1 20231009
  • Target: ARM, i.MX RT1176 (ARK FMU-v6XRT), FlexCAN1 at 1 Mbit, SocketCAN + DroneCAN

How to reproduce: put an i.MX RT board on a CAN bus with a second node, have the board publish a message large enough to need several frames, and decode CAN-ID plus tail byte per frame with an analyser. Frames of one transfer arrive out of order, so the toggle bit breaks and the receiver drops the transfer. The second node acts as the control — its own multi-frame transfers stay intact, which places the fault on the i.MX RT transmit path rather than the bus.

Measured with an ARK X20 GNSS node (node 124) and a CUAV Babel as the analyser. incomplete counts transfers whose frames never all arrived; togerr counts toggle-bit violations, i.e. reordering.

Testing logs before change:

# BEFORE  17455 frames / 60.0s (291 fps)
 src stream                            frames  xfers  multi incomplete  togerr   loss%
   1 20030 remoteid.BasicID               240     60     60          0       4    6.67
   1 20031 remoteid.Location              360     60     60          2      47   81.67
   1 1081 indication.LightsCommand        600    600      0          0       0    0.00
   1 341 protocol.NodeStatus               60     60      0          0       0    0.00
 124 1063 gnss.Fix2                      6000    600    600          0       0    0.00
 124 1061 gnss.Auxiliary                 1800    600    600          0       0    0.00
bad transfers by source node: {1: 53, 124: 0}

Only the i.MX RT board's multi-frame streams are affected; its single-frame streams and every stream from node 124 — including 600 ten-frame gnss.Fix2 transfers — are clean.

Testing logs after change:

# AFTER  35513 frames / 120.0s (296 fps)
 src stream                            frames  xfers  multi incomplete  togerr   loss%
   1 20030 remoteid.BasicID               480    120    120          0       0    0.00
   1 20031 remoteid.Location              720    120    120          0       0    0.00
   1 20033 remoteid.System                600    120    120          0       0    0.00
   1 1081 indication.LightsCommand       1198   1198      0          0       0    0.00
   1 341 protocol.NodeStatus              120    120      0          0       0    0.00
 124 1063 gnss.Fix2                     12010   1201   1201          0       0    0.00
 124 1061 gnss.Auxiliary                 3603   1201   1201          0       0    0.00
bad transfers by source node: {1: 0, 124: 0}

Driver counters after the change, sampled twice 45 s apart to show nothing is accumulating:

CAN1 status:
	HW errors: 0
	IO errors: 0
	RX frames: 47623   ->   62863
	TX frames: ...
UAVCAN node status:
	Transfer errors:   4   ->   4      (static; incurred during the reflash reboot)
	RX transfers:   8580   ->  11324

This patch alone fixes the 4-frame stream and takes the 6-frame one from 81.7% to 40%. The remainder was two further bugs above this driver, fixed separately in PX4 (a frame discarded rather than retried when the ring is full, and a TX queue bypass). The "after" figures above are with all three applied — this patch is necessary but not on its own sufficient for that particular stack.

Build log:

$ make ark_fmu-v6xrt_default
Memory region         Used Size  Region Size  %age Used
           flash:     2336728 B      3968 KB     57.51%
            sram:      107668 B      1792 KB      5.87%
            itcm:      217120 B       256 KB     82.82%

./tools/checkpatch.sh -c -u -m -g master..HEAD → ✔️ All checks pass.

Copy link
Copy Markdown
Contributor Author

FYI @PetervdPerk-NXP

github-actions Bot added Arch: arm Issues related to ARM (32-bit) architecture Size: S The size of the change in this PR is small labels Aug 24, 2026
dakejahl force-pushed the fix/imxrt-flexcan-tx-mailbox-ordering branch from c4e8463 to 4f523f1 Compare August 24, 2026 17:20
dakejahl added a commit to dakejahl/NuttX that referenced this pull request Aug 24, 2026
…order.

Backport of apache/nuttx#19957.

imxrt_transmit() handed out 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. On a DroneCAN bus the receiver sees a broken toggle
bit and discards the transfer: measured on the wire on an ARK FMU-v6XRT, a
6-frame message failed 82% of the time, while a GNSS node on the same bus
was flawless over the same capture.

Hand out a mailbox above every pending one instead, and wrap back to the
bottom only once the ring has drained.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>

github-actions Bot commented Aug 24, 2026 •
edited
Loading

Copy link
Copy Markdown

MemBrowse Memory Report

No memory changes detected for:

dakejahl changed the title arch/arm/src/imxrt: flexcan: keep TX mailbox allocation in order arch/arm/src/imxrt: Keep FlexCAN TX mailbox allocation in order. Aug 24, 2026
Correct the switch case label indentation in imxrt_netinitialize(), the brace
alignment in imxrt_ioctl(), and the indentation of the ERR005829 workaround
statements so imxrt_flexcan.c passes nxstyle. The last of these is only
reported since commit c81cc02.

These predate this series; CONTRIBUTING.md section 2.1 asks that modified
files be brought into compliance even where the contributor did not introduce
the problem.

Whitespace only, no functional change: `git diff -w` against the parent is
empty.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>
imxrt_transmit() handed out 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.
imxrt_txdone_work() re-polls after each individual TX completion, which is
exactly the condition that triggers it.

Every frame of a multi-frame transport transfer carries the same CAN ID, so
this reorders transfers. On a DroneCAN bus the receiver sees a broken toggle
bit and discards the transfer: measured on the wire, a 6-frame message from
an i.MX RT1176 failed 82% of the time, while a node on the same bus running
a different controller was flawless over the same capture.

Hand out a mailbox above every pending one instead, and wrap back to the
bottom only once the ring has drained. Ordering then holds for any transfer
length; the cost is that the ring stalls at a wrap rather than refilling
immediately.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>
dakejahl force-pushed the fix/imxrt-flexcan-tx-mailbox-ordering branch from 4f523f1 to 11d4a6c Compare August 24, 2026 17:31
github-actions Bot added Size: M The size of the change in this PR is medium and removed Size: S The size of the change in this PR is small labels Aug 24, 2026
dakejahl added a commit to dakejahl/NuttX that referenced this pull request Aug 24, 2026
…order.

Backport of apache/nuttx#19957.

imxrt_transmit() handed out 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. On a DroneCAN bus the receiver sees a broken toggle
bit and discards the transfer: measured on the wire on an ARK FMU-v6XRT, a
6-frame message failed 82% of the time, while a GNSS node on the same bus
was flawless over the same capture.

Hand out a mailbox above every pending one instead, and wrap back to the
bottom only once the ring has drained.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>
dakejahl marked this pull request as ready for review August 24, 2026 17:40

PetervdPerk-NXP left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Thanks a lot for fixing this long outstanding bug we had.

xiaoxiang781216 merged commit e6696d5 into apache:master Aug 25, 2026
38 checks passed
dakejahl added a commit to PX4/NuttX that referenced this pull request Aug 25, 2026
…order. (#394)

* [BACKPORT] arch/arm/src/imxrt: Fix FlexCAN coding style violations.

Correct the switch case label indentation in imxrt_netinitialize(), the brace
alignment in imxrt_ioctl(), and the indentation of the ERR005829 workaround
statements so imxrt_flexcan.c passes nxstyle.

Whitespace only, no functional change.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>

* [BACKPORT] arch/arm/src/imxrt: Keep FlexCAN TX mailbox allocation in order.

Backport of apache/nuttx#19957.

imxrt_transmit() handed out 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. On a DroneCAN bus the receiver sees a broken toggle
bit and discards the transfer: measured on the wire on an ARK FMU-v6XRT, a
6-frame message failed 82% of the time, while a GNSS node on the same bus
was flawless over the same capture.

Hand out a mailbox above every pending one instead, and wrap back to the
bottom only once the ring has drained.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>

---------

Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>
dakejahl added a commit to PX4/PX4-Autopilot that referenced this pull request Aug 25, 2026
Brings in PX4/NuttX#394 (backport of apache/nuttx#19957). imxrt FlexCAN
handed out the lowest free TX mailbox, so a refilled low mailbox could
win arbitration over an older frame of the same CAN ID still queued in a
higher one. Multi-frame DroneCAN transfers arrived out of order and were
dropped by the receiver.

Assisted-by: Claude:claude-opus-5[1m]

Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>
mrpollo pushed a commit to PX4/PX4-Autopilot that referenced this pull request Sep 10, 2026
Brings in PX4/NuttX#394 (backport of apache/nuttx#19957). imxrt FlexCAN
handed out the lowest free TX mailbox, so a refilled low mailbox could
win arbitration over an older frame of the same CAN ID still queued in a
higher one. Multi-frame DroneCAN transfers arrived out of order and were
dropped by the receiver.

Assisted-by: Claude:claude-opus-5[1m]

Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>
(cherry picked from commit 677d1fa)
Assisted-by: GitHub Copilot:gpt-6-astra
mrpollo pushed a commit to PX4/PX4-Autopilot that referenced this pull request Sep 10, 2026
Brings in PX4/NuttX#394 (backport of apache/nuttx#19957). imxrt FlexCAN
handed out the lowest free TX mailbox, so a refilled low mailbox could
win arbitration over an older frame of the same CAN ID still queued in a
higher one. Multi-frame DroneCAN transfers arrived out of order and were
dropped by the receiver.

Assisted-by: Claude:claude-opus-5[1m]

Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>
(cherry picked from commit 677d1fa)
Assisted-by: GitHub Copilot:gpt-6-astra
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Arch: arm Issues related to ARM (32-bit) architecture Size: M The size of the change in this PR is medium

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants


Back | FazBrowse Home | New Git URL