[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