UAVCAN/CAN: tx buffer management in CAN (FD) controllers

tl;dr: do not rely on the tx buffer management services provided by your CAN controller. Make your driver manage the transmission order in software instead. Otherwise, you will run into either a priority inversion problem or data loss caused by frame reordering.

I just ran a quick survey of the TX buffer management capabilities offered by the following products:

  • TI TCAN4550 — standalone CAN FD controller chip
  • Microchip ATSAM D5x/E5x (FD-capable)
  • FDCAN & bxCAN macrocells by ST Microelectronics
  • FlexCAN macrocell by NXP Semiconductors (the reference manual is available for download after registration) (FD-capable)
  • Bosch C_CAN macrocell as implemented in NXP LPC11Cxx etc.

While the details of their implementations vary significantly, all products offer more or less similar TX scheduling policies that can be generalized as follows:

  • Queue: the next frame is chosen based on its arbitration priority (low CAN ID wins); ties are resolved based on the frame’s index in the TX buffer. The insertion order is not respected.

  • FIFO: the next frame is chosen based on the insertion order. The arbitration priority and the position in the TX buffer are not respected.

UAVCAN/CAN requires that outgoing frames are prioritized based on their arbitration priority with ties broken by their insertion order. If the first condition is not satisfied, an inner priority inversion will occur. If the second condition is not satisfied, multi-frame transfers will not be emitted properly.

@davids5 and I have recently encountered a misleading piece of documentation published by ST Microelectronics that erroneously claims that their FDCAN controller supports the correct prioritization policy, but this description does not match the actual behavior implemented in hardware:

Given these limitations, a correct implementation has to manage transmission scheduling in software, keeping at most one frame with the given CAN ID in the hardware transmission buffer, which should be configured in the Queue mode. Relevant considerations are given in the UAVCAN Specification, section Inner priority inversion.

I would like to add that the MCP2518FD standalone CAN FD controller also suffers from the frame reordering issue. It is not documented anywhere but the TXQ buffer will reorder frames with the same arbitration priority but only after a loss of arbitration.

For us this resulted in a difficult-to-diagnose bug that would only appear when several nodes were broadcasting at exactly the same time, such as after power-up. The solution was to use 4 different FIFOs with UAVCAN frames being sorted into these FIFOs by their priority.

1 Like

Have you looked at ST’s G474 MCU and it’s CAN FD support?

STM32G474 appears to integrate the same FDCAN macrocell as other modern STM32 microcontrollers. I don’t see anything that would make it special.

Good to know. I know that @tridge was working with it for a CAN node.

yes, we have STM32G4 support in ArduPilot AP_Periph. So far just an ESC based on G4, but I am encouraging other vendors to consider either G4 or H7 for new designs so that we start to build a population of sensors that are FDCAN capable.
One thing I really like about G4 is it supports 3 CAN interfaces. CAN translator nodes to map between incompatible CAN protocols will become more and more important in the future. We have 9 different CAN protocols supported in ArduPilot now, with more on the way. As vendors want to mix these, having a small low cost node with 3 CAN interfaces that can map between the protocols will be really nice.
The G4 is also ideal for triple-redundant autopilot setups, with 3 independent CAN buses in the aircraft, and the G4 acting as the key decision node for which is in control at any one time.
H7 has only two CAN interfaces max, and you lose one if you want high speed USB.