[RFC] generic CAN/CAN FD susbsytem for RTEMS from scratch (LinCAN inspired)

Pavel Pisa pisa at fel.cvut.cz
Mon Feb 12 15:03:51 UTC 2024


Dear RTEMS community, the core developers team,

Michal Lenc works on a new generic CAN/CAN FD subsystem for RTEMS under my 
supervision. The project has reached a phase where we will be very grateful 
for the review and pointing to required changes to start a discussion of 
possible inclusion into the RTEMS mainline. The project is currently being 
developed as a separate RTEMS application based on the OMK build

 https://gitlab.fel.cvut.cz/otrees/rtems/rtems-canfd

But long-term intention is to move

 https://gitlab.fel.cvut.cz/otrees/rtems/rtems-canfd/-/tree/master/lib/candrv

directory into RTEMS cpukit/dev/can directory and corresponding include files 
into cpukit/include/dev/can directory.

We have reached a state where the virtual interface has been tested on an 
MZ_APO Xilinx/AMD Zynq-based board and an LX_CPU/LX_RoCoN NXP LPC4088-based 
board. The communication with a complete CAN interface has been successfully 
tested on the MZ_APO Xilinx/AMD Zynq board with CTU CAN FD IP cores 
implemented in FPGA.

Building on other RTEMS BSP should be possible by changing a single definition 
in the config.target file

  RTEMS_MAKEFILE_PATH=/opt/rtems/6/arm-rtems6/xilinx_zynq_zedboard

To test with the controller, we can provide FPGA bitstream, which should fit 
Zed/MicroZed or other XilinX Zynq 7Z010  based boards, and thanks to the 
source availability of CTU CAN FD core, it can be ported to other FPGA+SoC 
platforms. We have QEMU CTU CAN FD PCI integration emulation so that
can be other target for continuous integration testing even on x86, but 
PCI/PCIe mapping has to be added to the RTEMS driver code.

The API to the driver is provided in the form of the POSIX character device. 
Each CAN controller (chip) is registered as a node into the "/dev" namespace 
by name (i.e., "can0", "can1", ... ). It can be opened multiple times, and 
each instance of the open can be accessed from multiple threads. Written CAN 
frames are posted into the input end of the queue (FIFO), which is connected 
to the CAN controller (chip) or other frame processor on the output side. The 
processor takes frames from FIFOs according to their priority class and 
transmits them to the network. When the frame is successfully sent, it is 
echoed back to all queues back to open file instances except the sending one 
(that filtering is configurable). The filtering is implemented in 
canque_filter_frame2edges() function. Received frames are filtered to all 
queues to applications ends of the queues, which filter matches the CAN 
identifier and frame type.

The design is based on FIFOs designed closely to support needs to provide
service optimal to CAN frames delivery. On the controller side,
multiple slots, each with one CAN frame, can be taken from FIFO and kept
until the transmission is finished. Then, the frame from the slot is 
distributed to inform even local clients about the frame that was sent.
The framework has a unique feature to allow pushback slots (frames) when some 
later scheduled low-priority frame occupies the hardware Tx buffer, which is 
urgently demanded for a higher priority pending frame to be sent. Then the 
frame push back to the FIFO head is delivered for Tx processing again.

We present (in the prepared article) how our design resolves bus arbitration
priority inversion, which is often a problem for generic CAN drivers and 
subsystems, which allows access from more applications than is the fixed
Tx buffers count. With a well-behaved controller, we are able to keep
all available Tx hardware buffers filled by the right frames instantly.
When higher priority class frame is released by the application into
queues, the controller replaces the latest lower priority frames
with higher priority one and places it in the sequence after all
frames with the same priority class but before all with lower priority.

We will present the idea in the prepared article at the
international CAN Conference in May
  https://www.can-cia.org/icc/

The design implementation choice is to use CAN-specific FIFOS queues.
The consistency is protected by rtems_interrupt_lock_acquire / 
rtems_interrupt_lock_release, and thanks to reference counting
of users iterating with given queue from both its ends, the locks
are released during most of the operations and are held
for a really short time. We consider rtems_interrupt_lock
appropriate thanks to low overhead when we keep it
for limited code sequences. But switching to semaphores
or some POSIX mutexes is possible. But we also want to keep
code usable on RTEMS build even without POSIX API enabled,
and classical API semaphores have significant size and execution
time overhead.

We have switched to BSD Tail Queues (TAILQ) to keep lists
of the queues (FIFOs) coming to/from a given frame processor node
because they are provided even by NewLib and make code portable
  #include <sys/queue.h>
The API is much harder to use than Linux struct list_head
and supporting functions. My preferred alternative is my uLUt
solution, which we use on bare metal embedded systems, Linux
RTEMS and NuttX, but it would require introducing lot of
code and complex macros into RTEMS cpukit.

We are looking for feedback and cooperation. If the solution
passes the demands of the RTEMS core community, then it would
worth to port support for other controllers on this base.
We can open a GSoC project for it.

If the solution is acceptable, we should set up a page on RTEMS devel.
The preliminary wiki is at our faculty GitLab. But it is hard to
enable for general editing access. We can move even on GitHub.

Michal Lenc will submit work as his Master's Thesis this May
so I hope that Gedare would be willing to take the thesis
reviewer role as we have already discussed.

We will present our CAN latency testing project at the embedded world
Conference 2024 as well as on OSADL booth https://www.osadl.org/
in Nuremberg from April 9 to 11. There is an option to meet and discuss
RTEMS CAN and other projects in person. Our latency testing
focuses on Linux SocketCAN, but long ago, we tested LinCAN
on Linux and even original MSM CAN on RTEMS. I plan to add RTEMS
to our actual latency tester project in the frame of some another
future student project.

Best wishes,

                Pavel

                Pavel Pisa
    phone:      +420 603531357
    e-mail:     pisa at cmp.felk.cvut.cz
    Department of Control Engineering FEE CVUT
    Karlovo namesti 13, 121 35, Prague 2
    university: http://control.fel.cvut.cz/
    personal:   http://cmp.felk.cvut.cz/~pisa
    social:     https://social.kernel.org/ppisa
    projects:   https://www.openhub.net/accounts/ppisa
    CAN related:http://canbus.pages.fel.cvut.cz/
    RISC-V education: https://comparch.edu.cvut.cz/
    Open Technologies Research Education and Exchange Services
    https://gitlab.fel.cvut.cz/otrees/org/-/wikis/home


More information about the devel mailing list