640 lines
26 KiB
ReStructuredText
640 lines
26 KiB
ReStructuredText
.. SPDX-License-Identifier: GPL-2.0-or-later
|
||
|
||
CTU CAN FD Driver
|
||
=================
|
||
|
||
Author: Martin Jerabek <martin.jerabek01@gmail.com>
|
||
|
||
|
||
About CTU CAN FD IP Core
|
||
------------------------
|
||
|
||
`CTU CAN FD <https://gitlab.fel.cvut.cz/canbus/ctucanfd_ip_core>`_
|
||
is an open source soft core written in VHDL.
|
||
It originated in 2015 as Ondrej Ille's project
|
||
at the `Department of Measurement <https://meas.fel.cvut.cz/>`_
|
||
of `FEE <http://www.fel.cvut.cz/en/>`_ at `CTU <https://www.cvut.cz/en>`_.
|
||
|
||
The SocketCAN driver for Xilinx Zynq SoC based MicroZed board
|
||
`Vivado integration <https://gitlab.fel.cvut.cz/canbus/zynq/zynq-can-sja1000-top>`_
|
||
and Intel Cyclone V 5CSEMA4U23C6 based DE0-Nano-SoC Terasic board
|
||
`QSys integration <https://gitlab.fel.cvut.cz/canbus/intel-soc-ctucanfd>`_
|
||
has been developed as well as support for
|
||
`PCIe integration <https://gitlab.fel.cvut.cz/canbus/pcie-ctucanfd>`_ of the core.
|
||
|
||
In the case of Zynq, the core is connected via the APB system bus, which does
|
||
not have enumeration support, and the device must be specified in Device Tree.
|
||
This kind of devices is called platform device in the kernel and is
|
||
handled by a platform device driver.
|
||
|
||
The basic functional model of the CTU CAN FD peripheral has been
|
||
accepted into QEMU mainline. See QEMU `CAN emulation support <https://www.qemu.org/docs/master/system/devices/can.html>`_
|
||
for CAN FD buses, host connection and CTU CAN FD core emulation. The development
|
||
version of emulation support can be cloned from ctu-canfd branch of QEMU local
|
||
development `repository <https://gitlab.fel.cvut.cz/canbus/qemu-canbus>`_.
|
||
|
||
|
||
About SocketCAN
|
||
---------------
|
||
|
||
SocketCAN is a standard common interface for CAN devices in the Linux
|
||
kernel. As the name suggests, the bus is accessed via sockets, similarly
|
||
to common network devices. The reasoning behind this is in depth
|
||
described in `Linux SocketCAN <https://www.kernel.org/doc/html/latest/networking/can.html>`_.
|
||
In short, it offers a
|
||
natural way to implement and work with higher layer protocols over CAN,
|
||
in the same way as, e.g., UDP/IP over Ethernet.
|
||
|
||
Device probe
|
||
~~~~~~~~~~~~
|
||
|
||
Before going into detail about the structure of a CAN bus device driver,
|
||
let's reiterate how the kernel gets to know about the device at all.
|
||
Some buses, like PCI or PCIe, support device enumeration. That is, when
|
||
the system boots, it discovers all the devices on the bus and reads
|
||
their configuration. The kernel identifies the device via its vendor ID
|
||
and device ID, and if there is a driver registered for this identifier
|
||
combination, its probe method is invoked to populate the driver's
|
||
instance for the given hardware. A similar situation goes with USB, only
|
||
it allows for device hot-plug.
|
||
|
||
The situation is different for peripherals which are directly embedded
|
||
in the SoC and connected to an internal system bus (AXI, APB, Avalon,
|
||
and others). These buses do not support enumeration, and thus the kernel
|
||
has to learn about the devices from elsewhere. This is exactly what the
|
||
Device Tree was made for.
|
||
|
||
Device tree
|
||
~~~~~~~~~~~
|
||
|
||
An entry in device tree states that a device exists in the system, how
|
||
it is reachable (on which bus it resides) and its configuration –
|
||
registers address, interrupts and so on. An example of such a device
|
||
tree is given in .
|
||
|
||
::
|
||
|
||
/ {
|
||
/* ... */
|
||
amba: amba {
|
||
#address-cells = <1>;
|
||
#size-cells = <1>;
|
||
compatible = "simple-bus";
|
||
|
||
CTU_CAN_FD_0: CTU_CAN_FD@43c30000 {
|
||
compatible = "ctu,ctucanfd";
|
||
interrupt-parent = <&intc>;
|
||
interrupts = <0 30 4>;
|
||
clocks = <&clkc 15>;
|
||
reg = <0x43c30000 0x10000>;
|
||
};
|
||
};
|
||
};
|
||
|
||
|
||
.. _sec:socketcan:drv:
|
||
|
||
Driver structure
|
||
~~~~~~~~~~~~~~~~
|
||
|
||
The driver can be divided into two parts – platform-dependent device
|
||
discovery and set up, and platform-independent CAN network device
|
||
implementation.
|
||
|
||
.. _sec:socketcan:platdev:
|
||
|
||
Platform device driver
|
||
^^^^^^^^^^^^^^^^^^^^^^
|
||
|
||
In the case of Zynq, the core is connected via the AXI system bus, which
|
||
does not have enumeration support, and the device must be specified in
|
||
Device Tree. This kind of devices is called *platform device* in the
|
||
kernel and is handled by a *platform device driver*\ [1]_.
|
||
|
||
A platform device driver provides the following things:
|
||
|
||
- A *probe* function
|
||
|
||
- A *remove* function
|
||
|
||
- A table of *compatible* devices that the driver can handle
|
||
|
||
The *probe* function is called exactly once when the device appears (or
|
||
the driver is loaded, whichever happens later). If there are more
|
||
devices handled by the same driver, the *probe* function is called for
|
||
each one of them. Its role is to allocate and initialize resources
|
||
required for handling the device, as well as set up low-level functions
|
||
for the platform-independent layer, e.g., *read_reg* and *write_reg*.
|
||
After that, the driver registers the device to a higher layer, in our
|
||
case as a *network device*.
|
||
|
||
The *remove* function is called when the device disappears, or the
|
||
driver is about to be unloaded. It serves to free the resources
|
||
allocated in *probe* and to unregister the device from higher layers.
|
||
|
||
Finally, the table of *compatible* devices states which devices the
|
||
driver can handle. The Device Tree entry ``compatible`` is matched
|
||
against the tables of all *platform drivers*.
|
||
|
||
.. code:: c
|
||
|
||
/* Match table for OF platform binding */
|
||
static const struct of_device_id ctucan_of_match[] = {
|
||
{ .compatible = "ctu,canfd-2", },
|
||
{ .compatible = "ctu,ctucanfd", },
|
||
{ /* end of list */ },
|
||
};
|
||
MODULE_DEVICE_TABLE(of, ctucan_of_match);
|
||
|
||
static int ctucan_probe(struct platform_device *pdev);
|
||
static int ctucan_remove(struct platform_device *pdev);
|
||
|
||
static struct platform_driver ctucanfd_driver = {
|
||
.probe = ctucan_probe,
|
||
.remove = ctucan_remove,
|
||
.driver = {
|
||
.name = DRIVER_NAME,
|
||
.of_match_table = ctucan_of_match,
|
||
},
|
||
};
|
||
module_platform_driver(ctucanfd_driver);
|
||
|
||
|
||
.. _sec:socketcan:netdev:
|
||
|
||
Network device driver
|
||
^^^^^^^^^^^^^^^^^^^^^
|
||
|
||
Each network device must support at least these operations:
|
||
|
||
- Bring the device up: ``ndo_open``
|
||
|
||
- Bring the device down: ``ndo_close``
|
||
|
||
- Submit TX frames to the device: ``ndo_start_xmit``
|
||
|
||
- Signal TX completion and errors to the network subsystem: ISR
|
||
|
||
- Submit RX frames to the network subsystem: ISR and NAPI
|
||
|
||
There are two possible event sources: the device and the network
|
||
subsystem. Device events are usually signaled via an interrupt, handled
|
||
in an Interrupt Service Routine (ISR). Handlers for the events
|
||
originating in the network subsystem are then specified in
|
||
``struct net_device_ops``.
|
||
|
||
When the device is brought up, e.g., by calling ``ip link set can0 up``,
|
||
the driver’s function ``ndo_open`` is called. It should validate the
|
||
interface configuration and configure and enable the device. The
|
||
analogous opposite is ``ndo_close``, called when the device is being
|
||
brought down, be it explicitly or implicitly.
|
||
|
||
When the system should transmit a frame, it does so by calling
|
||
``ndo_start_xmit``, which enqueues the frame into the device. If the
|
||
device HW queue (FIFO, mailboxes or whatever the implementation is)
|
||
becomes full, the ``ndo_start_xmit`` implementation informs the network
|
||
subsystem that it should stop the TX queue (via ``netif_stop_queue``).
|
||
It is then re-enabled later in ISR when the device has some space
|
||
available again and is able to enqueue another frame.
|
||
|
||
All the device events are handled in ISR, namely:
|
||
|
||
#. **TX completion**. When the device successfully finishes transmitting
|
||
a frame, the frame is echoed locally. On error, an informative error
|
||
frame [2]_ is sent to the network subsystem instead. In both cases,
|
||
the software TX queue is resumed so that more frames may be sent.
|
||
|
||
#. **Error condition**. If something goes wrong (e.g., the device goes
|
||
bus-off or RX overrun happens), error counters are updated, and
|
||
informative error frames are enqueued to SW RX queue.
|
||
|
||
#. **RX buffer not empty**. In this case, read the RX frames and enqueue
|
||
them to SW RX queue. Usually NAPI is used as a middle layer (see ).
|
||
|
||
.. _sec:socketcan:napi:
|
||
|
||
NAPI
|
||
~~~~
|
||
|
||
The frequency of incoming frames can be high and the overhead to invoke
|
||
the interrupt service routine for each frame can cause significant
|
||
system load. There are multiple mechanisms in the Linux kernel to deal
|
||
with this situation. They evolved over the years of Linux kernel
|
||
development and enhancements. For network devices, the current standard
|
||
is NAPI – *the New API*. It is similar to classical top-half/bottom-half
|
||
interrupt handling in that it only acknowledges the interrupt in the ISR
|
||
and signals that the rest of the processing should be done in softirq
|
||
context. On top of that, it offers the possibility to *poll* for new
|
||
frames for a while. This has a potential to avoid the costly round of
|
||
enabling interrupts, handling an incoming IRQ in ISR, re-enabling the
|
||
softirq and switching context back to softirq.
|
||
|
||
More detailed documentation of NAPI may be found on the pages of Linux
|
||
Foundation `<https://wiki.linuxfoundation.org/networking/napi>`_.
|
||
|
||
Integrating the core to Xilinx Zynq
|
||
-----------------------------------
|
||
|
||
The core interfaces a simple subset of the Avalon
|
||
(search for Intel **Avalon Interface Specifications**)
|
||
bus as it was originally used on
|
||
Alterra FPGA chips, yet Xilinx natively interfaces with AXI
|
||
(search for ARM **AMBA AXI and ACE Protocol Specification AXI3,
|
||
AXI4, and AXI4-Lite, ACE and ACE-Lite**).
|
||
The most obvious solution would be to use
|
||
an Avalon/AXI bridge or implement some simple conversion entity.
|
||
However, the core’s interface is half-duplex with no handshake
|
||
signaling, whereas AXI is full duplex with two-way signaling. Moreover,
|
||
even AXI-Lite slave interface is quite resource-intensive, and the
|
||
flexibility and speed of AXI are not required for a CAN core.
|
||
|
||
Thus a much simpler bus was chosen – APB (Advanced Peripheral Bus)
|
||
(search for ARM **AMBA APB Protocol Specification**).
|
||
APB-AXI bridge is directly available in
|
||
Xilinx Vivado, and the interface adaptor entity is just a few simple
|
||
combinatorial assignments.
|
||
|
||
Finally, to be able to include the core in a block diagram as a custom
|
||
IP, the core, together with the APB interface, has been packaged as a
|
||
Vivado component.
|
||
|
||
CTU CAN FD Driver design
|
||
------------------------
|
||
|
||
The general structure of a CAN device driver has already been examined
|
||
in . The next paragraphs provide a more detailed description of the CTU
|
||
CAN FD core driver in particular.
|
||
|
||
Low-level driver
|
||
~~~~~~~~~~~~~~~~
|
||
|
||
The core is not intended to be used solely with SocketCAN, and thus it
|
||
is desirable to have an OS-independent low-level driver. This low-level
|
||
driver can then be used in implementations of OS driver or directly
|
||
either on bare metal or in a user-space application. Another advantage
|
||
is that if the hardware slightly changes, only the low-level driver
|
||
needs to be modified.
|
||
|
||
The code [3]_ is in part automatically generated and in part written
|
||
manually by the core author, with contributions of the thesis’ author.
|
||
The low-level driver supports operations such as: set bit timing, set
|
||
controller mode, enable/disable, read RX frame, write TX frame, and so
|
||
on.
|
||
|
||
Configuring bit timing
|
||
~~~~~~~~~~~~~~~~~~~~~~
|
||
|
||
On CAN, each bit is divided into four segments: SYNC, PROP, PHASE1, and
|
||
PHASE2. Their duration is expressed in multiples of a Time Quantum
|
||
(details in `CAN Specification, Version 2.0 <http://esd.cs.ucr.edu/webres/can20.pdf>`_, chapter 8).
|
||
When configuring
|
||
bitrate, the durations of all the segments (and time quantum) must be
|
||
computed from the bitrate and Sample Point. This is performed
|
||
independently for both the Nominal bitrate and Data bitrate for CAN FD.
|
||
|
||
SocketCAN is fairly flexible and offers either highly customized
|
||
configuration by setting all the segment durations manually, or a
|
||
convenient configuration by setting just the bitrate and sample point
|
||
(and even that is chosen automatically per Bosch recommendation if not
|
||
specified). However, each CAN controller may have different base clock
|
||
frequency and different width of segment duration registers. The
|
||
algorithm thus needs the minimum and maximum values for the durations
|
||
(and clock prescaler) and tries to optimize the numbers to fit both the
|
||
constraints and the requested parameters.
|
||
|
||
.. code:: c
|
||
|
||
struct can_bittiming_const {
|
||
char name[16]; /* Name of the CAN controller hardware */
|
||
__u32 tseg1_min; /* Time segment 1 = prop_seg + phase_seg1 */
|
||
__u32 tseg1_max;
|
||
__u32 tseg2_min; /* Time segment 2 = phase_seg2 */
|
||
__u32 tseg2_max;
|
||
__u32 sjw_max; /* Synchronisation jump width */
|
||
__u32 brp_min; /* Bit-rate prescaler */
|
||
__u32 brp_max;
|
||
__u32 brp_inc;
|
||
};
|
||
|
||
|
||
[lst:can_bittiming_const]
|
||
|
||
A curious reader will notice that the durations of the segments PROP_SEG
|
||
and PHASE_SEG1 are not determined separately but rather combined and
|
||
then, by default, the resulting TSEG1 is evenly divided between PROP_SEG
|
||
and PHASE_SEG1. In practice, this has virtually no consequences as the
|
||
sample point is between PHASE_SEG1 and PHASE_SEG2. In CTU CAN FD,
|
||
however, the duration registers ``PROP`` and ``PH1`` have different
|
||
widths (6 and 7 bits, respectively), so the auto-computed values might
|
||
overflow the shorter register and must thus be redistributed among the
|
||
two [4]_.
|
||
|
||
Handling RX
|
||
~~~~~~~~~~~
|
||
|
||
Frame reception is handled in NAPI queue, which is enabled from ISR when
|
||
the RXNE (RX FIFO Not Empty) bit is set. Frames are read one by one
|
||
until either no frame is left in the RX FIFO or the maximum work quota
|
||
has been reached for the NAPI poll run (see ). Each frame is then passed
|
||
to the network interface RX queue.
|
||
|
||
An incoming frame may be either a CAN 2.0 frame or a CAN FD frame. The
|
||
way to distinguish between these two in the kernel is to allocate either
|
||
``struct can_frame`` or ``struct canfd_frame``, the two having different
|
||
sizes. In the controller, the information about the frame type is stored
|
||
in the first word of RX FIFO.
|
||
|
||
This brings us a chicken-egg problem: we want to allocate the ``skb``
|
||
for the frame, and only if it succeeds, fetch the frame from FIFO;
|
||
otherwise keep it there for later. But to be able to allocate the
|
||
correct ``skb``, we have to fetch the first work of FIFO. There are
|
||
several possible solutions:
|
||
|
||
#. Read the word, then allocate. If it fails, discard the rest of the
|
||
frame. When the system is low on memory, the situation is bad anyway.
|
||
|
||
#. Always allocate ``skb`` big enough for an FD frame beforehand. Then
|
||
tweak the ``skb`` internals to look like it has been allocated for
|
||
the smaller CAN 2.0 frame.
|
||
|
||
#. Add option to peek into the FIFO instead of consuming the word.
|
||
|
||
#. If the allocation fails, store the read word into driver’s data. On
|
||
the next try, use the stored word instead of reading it again.
|
||
|
||
Option 1 is simple enough, but not very satisfying if we could do
|
||
better. Option 2 is not acceptable, as it would require modifying the
|
||
private state of an integral kernel structure. The slightly higher
|
||
memory consumption is just a virtual cherry on top of the “cake”. Option
|
||
3 requires non-trivial HW changes and is not ideal from the HW point of
|
||
view.
|
||
|
||
Option 4 seems like a good compromise, with its disadvantage being that
|
||
a partial frame may stay in the FIFO for a prolonged time. Nonetheless,
|
||
there may be just one owner of the RX FIFO, and thus no one else should
|
||
see the partial frame (disregarding some exotic debugging scenarios).
|
||
Basides, the driver resets the core on its initialization, so the
|
||
partial frame cannot be “adopted” either. In the end, option 4 was
|
||
selected [5]_.
|
||
|
||
.. _subsec:ctucanfd:rxtimestamp:
|
||
|
||
Timestamping RX frames
|
||
^^^^^^^^^^^^^^^^^^^^^^
|
||
|
||
The CTU CAN FD core reports the exact timestamp when the frame has been
|
||
received. The timestamp is by default captured at the sample point of
|
||
the last bit of EOF but is configurable to be captured at the SOF bit.
|
||
The timestamp source is external to the core and may be up to 64 bits
|
||
wide. At the time of writing, passing the timestamp from kernel to
|
||
userspace is not yet implemented, but is planned in the future.
|
||
|
||
Handling TX
|
||
~~~~~~~~~~~
|
||
|
||
The CTU CAN FD core has 4 independent TX buffers, each with its own
|
||
state and priority. When the core wants to transmit, a TX buffer in
|
||
Ready state with the highest priority is selected.
|
||
|
||
The priorities are 3bit numbers in register TX_PRIORITY
|
||
(nibble-aligned). This should be flexible enough for most use cases.
|
||
SocketCAN, however, supports only one FIFO queue for outgoing
|
||
frames [6]_. The buffer priorities may be used to simulate the FIFO
|
||
behavior by assigning each buffer a distinct priority and *rotating* the
|
||
priorities after a frame transmission is completed.
|
||
|
||
In addition to priority rotation, the SW must maintain head and tail
|
||
pointers into the FIFO formed by the TX buffers to be able to determine
|
||
which buffer should be used for next frame (``txb_head``) and which
|
||
should be the first completed one (``txb_tail``). The actual buffer
|
||
indices are (obviously) modulo 4 (number of TX buffers), but the
|
||
pointers must be at least one bit wider to be able to distinguish
|
||
between FIFO full and FIFO empty – in this situation,
|
||
:math:`txb\_head \equiv txb\_tail\ (\textrm{mod}\ 4)`. An example of how
|
||
the FIFO is maintained, together with priority rotation, is depicted in
|
||
|
||
|
|
||
|
||
+------+---+---+---+---+
|
||
| TXB# | 0 | 1 | 2 | 3 |
|
||
+======+===+===+===+===+
|
||
| Seq | A | B | C | |
|
||
+------+---+---+---+---+
|
||
| Prio | 7 | 6 | 5 | 4 |
|
||
+------+---+---+---+---+
|
||
| | | T | | H |
|
||
+------+---+---+---+---+
|
||
|
||
|
|
||
|
||
+------+---+---+---+---+
|
||
| TXB# | 0 | 1 | 2 | 3 |
|
||
+======+===+===+===+===+
|
||
| Seq | | B | C | |
|
||
+------+---+---+---+---+
|
||
| Prio | 4 | 7 | 6 | 5 |
|
||
+------+---+---+---+---+
|
||
| | | T | | H |
|
||
+------+---+---+---+---+
|
||
|
||
|
|
||
|
||
+------+---+---+---+---+----+
|
||
| TXB# | 0 | 1 | 2 | 3 | 0’ |
|
||
+======+===+===+===+===+====+
|
||
| Seq | E | B | C | D | |
|
||
+------+---+---+---+---+----+
|
||
| Prio | 4 | 7 | 6 | 5 | |
|
||
+------+---+---+---+---+----+
|
||
| | | T | | | H |
|
||
+------+---+---+---+---+----+
|
||
|
||
|
|
||
|
||
.. kernel-figure:: fsm_txt_buffer_user.svg
|
||
|
||
TX Buffer states with possible transitions
|
||
|
||
.. _subsec:ctucanfd:txtimestamp:
|
||
|
||
Timestamping TX frames
|
||
^^^^^^^^^^^^^^^^^^^^^^
|
||
|
||
When submitting a frame to a TX buffer, one may specify the timestamp at
|
||
which the frame should be transmitted. The frame transmission may start
|
||
later, but not sooner. Note that the timestamp does not participate in
|
||
buffer prioritization – that is decided solely by the mechanism
|
||
described above.
|
||
|
||
Support for time-based packet transmission was recently merged to Linux
|
||
v4.19 `Time-based packet transmission <https://lwn.net/Articles/748879/>`_,
|
||
but it remains yet to be researched
|
||
whether this functionality will be practical for CAN.
|
||
|
||
Also similarly to retrieving the timestamp of RX frames, the core
|
||
supports retrieving the timestamp of TX frames – that is the time when
|
||
the frame was successfully delivered. The particulars are very similar
|
||
to timestamping RX frames and are described in .
|
||
|
||
Handling RX buffer overrun
|
||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||
|
||
When a received frame does no more fit into the hardware RX FIFO in its
|
||
entirety, RX FIFO overrun flag (STATUS[DOR]) is set and Data Overrun
|
||
Interrupt (DOI) is triggered. When servicing the interrupt, care must be
|
||
taken first to clear the DOR flag (via COMMAND[CDO]) and after that
|
||
clear the DOI interrupt flag. Otherwise, the interrupt would be
|
||
immediately [7]_ rearmed.
|
||
|
||
**Note**: During development, it was discussed whether the internal HW
|
||
pipelining cannot disrupt this clear sequence and whether an additional
|
||
dummy cycle is necessary between clearing the flag and the interrupt. On
|
||
the Avalon interface, it indeed proved to be the case, but APB being
|
||
safe because it uses 2-cycle transactions. Essentially, the DOR flag
|
||
would be cleared, but DOI register’s Preset input would still be high
|
||
the cycle when the DOI clear request would also be applied (by setting
|
||
the register’s Reset input high). As Set had higher priority than Reset,
|
||
the DOI flag would not be reset. This has been already fixed by swapping
|
||
the Set/Reset priority (see issue #187).
|
||
|
||
Reporting Error Passive and Bus Off conditions
|
||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||
|
||
It may be desirable to report when the node reaches *Error Passive*,
|
||
*Error Warning*, and *Bus Off* conditions. The driver is notified about
|
||
error state change by an interrupt (EPI, EWLI), and then proceeds to
|
||
determine the core’s error state by reading its error counters.
|
||
|
||
There is, however, a slight race condition here – there is a delay
|
||
between the time when the state transition occurs (and the interrupt is
|
||
triggered) and when the error counters are read. When EPI is received,
|
||
the node may be either *Error Passive* or *Bus Off*. If the node goes
|
||
*Bus Off*, it obviously remains in the state until it is reset.
|
||
Otherwise, the node is *or was* *Error Passive*. However, it may happen
|
||
that the read state is *Error Warning* or even *Error Active*. It may be
|
||
unclear whether and what exactly to report in that case, but I
|
||
personally entertain the idea that the past error condition should still
|
||
be reported. Similarly, when EWLI is received but the state is later
|
||
detected to be *Error Passive*, *Error Passive* should be reported.
|
||
|
||
|
||
CTU CAN FD Driver Sources Reference
|
||
-----------------------------------
|
||
|
||
.. kernel-doc:: drivers/net/can/ctucanfd/ctucanfd.h
|
||
:internal:
|
||
|
||
.. kernel-doc:: drivers/net/can/ctucanfd/ctucanfd_base.c
|
||
:internal:
|
||
|
||
.. kernel-doc:: drivers/net/can/ctucanfd/ctucanfd_pci.c
|
||
:internal:
|
||
|
||
.. kernel-doc:: drivers/net/can/ctucanfd/ctucanfd_platform.c
|
||
:internal:
|
||
|
||
CTU CAN FD IP Core and Driver Development Acknowledgment
|
||
---------------------------------------------------------
|
||
|
||
* Odrej Ille <ondrej.ille@gmail.com>
|
||
|
||
* started the project as student at Department of Measurement, FEE, CTU
|
||
* invested great amount of personal time and enthusiasm to the project over years
|
||
* worked on more funded tasks
|
||
|
||
* `Department of Measurement <https://meas.fel.cvut.cz/>`_,
|
||
`Faculty of Electrical Engineering <http://www.fel.cvut.cz/en/>`_,
|
||
`Czech Technical University <https://www.cvut.cz/en>`_
|
||
|
||
* is the main investor into the project over many years
|
||
* uses project in their CAN/CAN FD diagnostics framework for `Skoda Auto <https://www.skoda-auto.cz/>`_
|
||
|
||
* `Digiteq Automotive <https://www.digiteqautomotive.com/en>`_
|
||
|
||
* funding of the project CAN FD Open Cores Support Linux Kernel Based Systems
|
||
* negotiated and paid CTU to allow public access to the project
|
||
* provided additional funding of the work
|
||
|
||
* `Department of Control Engineering <https://control.fel.cvut.cz/en>`_,
|
||
`Faculty of Electrical Engineering <http://www.fel.cvut.cz/en/>`_,
|
||
`Czech Technical University <https://www.cvut.cz/en>`_
|
||
|
||
* solving the project CAN FD Open Cores Support Linux Kernel Based Systems
|
||
* providing GitLab management
|
||
* virtual servers and computational power for continuous integration
|
||
* providing hardware for HIL continuous integration tests
|
||
|
||
* `PiKRON Ltd. <http://pikron.com/>`_
|
||
|
||
* minor funding to initiate preparation of the project open-sourcing
|
||
|
||
* Petr Porazil <porazil@pikron.com>
|
||
|
||
* design of PCIe transceiver addon board and assembly of boards
|
||
* design and assembly of MZ_APO baseboard for MicroZed/Zynq based system
|
||
|
||
* Martin Jerabek <martin.jerabek01@gmail.com>
|
||
|
||
* Linux driver development
|
||
* continuous integration platform architect and GHDL updates
|
||
* theses `Open-source and Open-hardware CAN FD Protocol Support <https://dspace.cvut.cz/bitstream/handle/10467/80366/F3-DP-2019-Jerabek-Martin-Jerabek-thesis-2019-canfd.pdf>`_
|
||
|
||
* Jiri Novak <jnovak@fel.cvut.cz>
|
||
|
||
* project initiation, management and use at Department of Measurement, FEE, CTU
|
||
|
||
* Pavel Pisa <pisa@cmp.felk.cvut.cz>
|
||
|
||
* initiate open-sourcing, project coordination, management at Department of Control Engineering, FEE, CTU
|
||
|
||
* Jaroslav Beran<jara.beran@gmail.com>
|
||
|
||
* system integration for Intel SoC, core and driver testing and updates
|
||
|
||
* Carsten Emde (`OSADL <https://www.osadl.org/>`_)
|
||
|
||
* provided OSADL expertise to discuss IP core licensing
|
||
* pointed to possible deadlock for LGPL and CAN bus possible patent case which lead to relicense IP core design to BSD like license
|
||
|
||
* Reiner Zitzmann and Holger Zeltwanger (`CAN in Automation <https://www.can-cia.org/>`_)
|
||
|
||
* provided suggestions and help to inform community about the project and invited us to events focused on CAN bus future development directions
|
||
|
||
* Jan Charvat
|
||
|
||
* implemented CTU CAN FD functional model for QEMU which has been integrated into QEMU mainline (`docs/system/devices/can.rst <https://www.qemu.org/docs/master/system/devices/can.html>`_)
|
||
* Bachelor theses Model of CAN FD Communication Controller for QEMU Emulator
|
||
|
||
Notes
|
||
-----
|
||
|
||
|
||
.. [1]
|
||
Other buses have their own specific driver interface to set up the
|
||
device.
|
||
|
||
.. [2]
|
||
Not to be mistaken with CAN Error Frame. This is a ``can_frame`` with
|
||
``CAN_ERR_FLAG`` set and some error info in its ``data`` field.
|
||
|
||
.. [3]
|
||
Available in CTU CAN FD repository
|
||
`<https://gitlab.fel.cvut.cz/canbus/ctucanfd_ip_core>`_
|
||
|
||
.. [4]
|
||
As is done in the low-level driver functions
|
||
``ctucan_hw_set_nom_bittiming`` and
|
||
``ctucan_hw_set_data_bittiming``.
|
||
|
||
.. [5]
|
||
At the time of writing this thesis, option 1 is still being used and
|
||
the modification is queued in gitlab issue #222
|
||
|
||
.. [6]
|
||
Strictly speaking, multiple CAN TX queues are supported since v4.19
|
||
`can: enable multi-queue for SocketCAN devices <https://lore.kernel.org/patchwork/patch/913526/>`_ but no mainline driver is using
|
||
them yet.
|
||
|
||
.. [7]
|
||
Or rather in the next clock cycle
|