[PATCH] c-user: CAN framework docs
Gedare Bloom
gedare at rtems.org
Wed Nov 16 15:48:46 UTC 2022
On Tue, Nov 15, 2022 at 11:14 PM Prashanth S <fishesprashanth at gmail.com> wrote:
>
> Hi Gedare,
>
> > What are the images?
> There three images:
> images/c_user/CAN-framework.jpg -> Overview of CAN-Framework
> images/c_user/CAN-rx-data-path.jpg -> Rx Data Path flow
> images/c_user/CAN-tx-data-path.jpg -> Tx Data Path flow
>
We don't have many images in the docs. And as I recall we had a
discussion about image formats in docs awhile back. I don't remember
the details, but I think it is preferred to provide images generated
from a text-based format where possible. From
rtems-docs.git/README.txt, we have
Images can be created from source using PlantUML and Ditaa.
Please have a look to see if you can do that instead.
> > This is not exactly correct. It is actually recessive where | CANH -
> > CANL | < t1 for some threshold t1,
> > and dominant where | CANH - CANL | > t2. And there is a gap where the
> > bus is not defined at t1 < | CANH - CANL| < t2
> > This detail is not so important here, but if we're going to describe
> > it then we need it to be correct.
> >
> > > +A 0 data bit encodes a dominant state, while a 1 data bit encodes a recessive
> > > +state, supporting a wired-AND convention, which gives nodes with lower ID
> > > +numbers priority on the bus.
> >
> > I see this text has been copied from Wikipedia. This is not acceptable
> > without proper attribution/reference. Please rewrite, remove, or
> > reference cited material properly. Please identify if any of the below
> > text is also copied from anywhere else.
>
> I will rewrite this text.
>
> >
> > > +
> > > +This document covers, the CAN framework and its usage by BSP CAN drivers and
> > Remove the comma after covers
>
> > typo: Initialize
> > typo: Further
>
> I will update these typo errors.
>
> Regards
> Prashanth S
>
> On Tue, 15 Nov 2022 at 20:34, Gedare Bloom <gedare at rtems.org> wrote:
>>
>> Hi Prashant,
>>
>> What are the images?
>>
>> On Tue, Nov 15, 2022 at 7:49 AM Prashanth S <fishesprashanth at gmail.com> wrote:
>> >
>> > ---
>> > bsp-howto/can.rst | 201 +++++++++++++++++++++++++++++
>> > bsp-howto/index.rst | 1 +
>> > images/c_user/CAN-framework.jpg | Bin 0 -> 146625 bytes
>> > images/c_user/CAN-rx-data-path.jpg | Bin 0 -> 187438 bytes
>> > images/c_user/CAN-tx-data-path.jpg | Bin 0 -> 128765 bytes
>> > 5 files changed, 202 insertions(+)
>> > create mode 100644 bsp-howto/can.rst
>> > create mode 100644 images/c_user/CAN-framework.jpg
>> > create mode 100644 images/c_user/CAN-rx-data-path.jpg
>> > create mode 100644 images/c_user/CAN-tx-data-path.jpg
>> >
>> > diff --git a/bsp-howto/can.rst b/bsp-howto/can.rst
>> > new file mode 100644
>> > index 0000000..36d6a04
>> > --- /dev/null
>> > +++ b/bsp-howto/can.rst
>> > @@ -0,0 +1,201 @@
>> > +.. SPDX-License-Identifier: CC-BY-SA-4.0
>> > +
>> > +.. Copyright (C) 2022 Prashanth S <fishesprashanth at gmail.com>
>> > +
>> > +CAN Library
>> > +***********
>> > +
>> > +Introduction
>> > +============
>> > +
>> > +The Controller Area Network is a robust multi-master serial communication
>> > +protocol extensively used in automobiles for reliable data transfer. Two or more
>> > +nodes are required on the CAN network to communicate. All nodes are connected to
>> > +each other through a physically conventional two-wire bus. The wires are a
>> > +twisted pair with a 120 Ω (nominal) characteristic impedance.
>> > +
>> > +This bus uses differential wired-AND signals. Two signals, CAN high (CANH) and
>> > +CAN low (CANL) are either driven to a "dominant" state with CANH > CANL or not
>> > +driven and pulled by passive resistors to a "recessive" state with CANH ≤ CANL.
>> This is not exactly correct. It is actually recessive where | CANH -
>> CANL | < t1 for some threshold t1,
>> and dominant where | CANH - CANL | > t2. And there is a gap where the
>> bus is not defined at t1 < | CANH - CANL| < t2
>> This detail is not so important here, but if we're going to describe
>> it then we need it to be correct.
>>
>> > +A 0 data bit encodes a dominant state, while a 1 data bit encodes a recessive
>> > +state, supporting a wired-AND convention, which gives nodes with lower ID
>> > +numbers priority on the bus.
>>
>> I see this text has been copied from Wikipedia. This is not acceptable
>> without proper attribution/reference. Please rewrite, remove, or
>> reference cited material properly. Please identify if any of the below
>> text is also copied from anywhere else.
>>
>> > +
>> > +This document covers, the CAN framework and its usage by BSP CAN drivers and
>> Remove the comma after covers
>>
>> > +applications.
>> > +
>> > +The CAN framework allows the applications to be written in a portable manner,
>> > +which implies that an application can access the CAN bus without knowing the
>> > +details of the CAN hardware, the platform specific translations are taken care
>> > +by the CAN framework (So the application can focus more on the CAN protocol
>> > +specific implementation).
>> > +
>> > +The CAN framework aims to be compatible with classical CAN and CAN FD.
>> > +
>> > +CAN Framework
>> > +-------------
>> > +
>> > +The CAN framework is located in the cpukit/dev/can directory.
>> > +
>> > +.. figure:: ../../../images/c_user/CAN-framework.jpg
>> > + :width: 100%
>> > + :align: center
>> > + :alt: CAN Framework
>> > +
>> > +This Fig shows the control flow and data flow of application and BSP CAN driver
>> > +with the CAN framework.
>> > +
>> > +Once the BSP CAN driver registers with the CAN framework, the interface for an
>> > +application to access the CAN hardware will be created (``/dev/can{0, 1, *}``).
>> > +Through this interface, applications can access the CAN hardware with the
>> > +features provided by the CAN framework (buffer management (Tx and Rx buffers),
>> > +multi-threaded access to the CAN hardware, synchronization and concurrency
>> > +handling between threads)
>> > +
>> > +Registering with CAN Framework
>> > +==============================
>> > +
>> > +Every BSP CAN driver should register itself with the CAN framework to use its
>> > +services and allow access of CAN hardware to the application.
>> > +
>> > +The registration is done by calling ``can_bus_init`` followed by
>> > +``can_bus_register`` with ``can_bus`` data structure as an argument. The BSP
>> > +CAN driver should populate the ``can_bus`` data structure with appropriate data
>> > +for a successful registration (``can_bus`` data structure can be allocated by
>> > +BSP CAN driver and passed to ``can_bus_init`` for initialization or call
>> > +``can_bus_alloc_and_init`` directly which allocates and initializes ``can_bus``
>> > +data structure).
>> > +
>> > +.. code-block:: c
>> > +
>> > + can_bus *can_bus_alloc_and_init(size_t size);
>> > + int can_bus_init(can_bus *bus);
>> > +
>> > + rtems_status_code can_bus_register(can_bus *bus, const char *bus_path);
>> > +
>> > +Successful registration creates a ``/dev/can{0, 1, *}`` device file for the
>> > +application to communicate with the corresponding CAN hardware.
>> > +
>> > +.. code-block:: c
>> > +
>> > + struct can_bus *bus = can_bus_alloc_and_init(sizeof(struct can_bus));
>> > +
>> > + priv->bus = bus;
>> > +
>> > + snprintf(if_name, IF_NAME_SIZE_MAX, "/dev/can%d", i);
>> > +
>> > + /* BSP specific information */
>> > + bus->priv = priv;
>> > +
>> > + /* Intialize can_dev_ops */
>> typo: Initialize
>>
>> > + dcan_init_ops(priv);
>> > +
>> > + if (can_bus_register(bus, if_name) != 0) {
>> > + CAN_ERR("beagle_can_init: bus register failed\n");
>> > + free(priv);
>> > + return;
>> > + }
>> > +
>> > +This example shows the DCAN BSP driver registration with the CAN framework.
>> > +
>> > +Concurrency and buffer synchronization
>> > +======================================
>> > +
>> > +The CAN framework uses a counting semaphore (one for Tx FIFO and one for Rx
>> > +FIFO) and a mutex to handle concurrency and buffer synchronization. The count
>> > +value depends on the number of FIFO
>> > +buffers allocated.
>> > +
>> > +In the Tx path, at any time, the semaphore count denotes the number of empty Tx
>> > +FIFO buffers available.
>> > +
>> > +In the Rx path, at any time, the semaphore count denotes the number of valid CAN
>> > +messages in the Rx FIFO buffer available.
>> > +
>> > +Tx and Rx data flow
>> > +===================
>> > +
>> > +The ``can_msg`` data structure defined in ``cpukit/include/dev/can/can-msg.h``
>> > +represents a CAN message in application, CAN framework and BSP CAN driver.
>> > +
>> > +.. code-block:: c
>> > +
>> > + struct can_msg {
>> > + uint32_t id;
>> > + uint32_t timestamp;
>> > + uint16_t flags;
>> > + uint16_t len;
>> > + uint8_t data[CAN_MSG_MAX_SIZE];
>> > + };
>> > +
>> > +Applications use the interface ``/dev/can{0, 1, *)`` device file to communicate
>> > +with the CAN hardware. Once the device file is created by the CAN framework,
>> > +applications can do file operations (open, close, read, write, ioctl) on the
>> > +device file. Every file operation on the device file is handled by the CAN framework.
>> > +
>> > +Tx data flow
>> > +------------
>> > +Once a ``write`` is made on ``/dev/can{0, 1, *}`` from the application to send a
>> > +CAN message, it reaches the ``can_bus_write``. The ``can_bus_write`` checks for
>> > +the availability of empty Tx FIFO buffer (by calling ``rtems_semaphore_obtain``).
>> > +If an empty buffer is not available, based on the flags to the open call it sleeps
>> > +or returns).
>> > +
>> > +If an empty Tx FIFO buffer is available, the CAN message is copied to the Tx FIFO
>> > +buffer and checks whether CAN hardware is ready to accept a CAN message to transmit
>> > +(by calling the function ``can_dev_ops->dev_tx_ready``). If the device is not
>> > +ready to accept, the instance returns to the application with number of bytes
>> > +copied.
>> > +
>> > +If the device is ready, ``can_xmit`` function is called, which picks up a buffer
>> > +from Tx FIFO to transmit. Then ``can_dev_ops->dev_tx`` is called with
>> > +``can_msg`` data structure as an argument (where the CAN hardware handles the
>> > +``can_msg`` data structure to transmit). Once the CAN message is copied to the
>> > +device FIFO to transmit, ``can_dev_ops->dev_tx`` returns back to ``can_xmit``
>> > +invalidates the corresponding Tx FIFO buffer and wakes up an instance (by
>> > +calling ``rtems_semaphore_release``) that is waiting for an empty CAN Tx FIFO
>> > +buffer.
>> > +
>> > +The BSP CAN driver then sends the CAN message to the CAN bus. Once the CAN
>> > +message transmission is complete the BSP CAN driver should call ``can_txdone``,
>> > +which in turn calls ``can_xmit`` for further CAN message to send.
>> > +
>> > +.. caution::
>> > + ``can_xmit`` function runs with interrupts disabled, this means the ``can_dev_ops->dev_tx``
>> > + should return as soon as possible.
>> > +
>> > +This figure shows the Tx data path.
>> > +
>> > +.. figure:: ../../../images/c_user/CAN-tx-data-path.jpg
>> > + :width: 100%
>> > + :align: center
>> > + :alt: CAN Tx data path
>> > +
>> > +Rx data flow
>> > +------------
>> > +Once a ``read`` is made on ``/dev/can{0, 1, *}`` from the application, the
>> > +instance reaches the ``can_bus_read``. The ``can_bus_read`` function checks, if
>> > +there are any CAN messages available in the Rx FIFO (this can be checked by calling
>> > +``rtems_semaphore_obtain``). If available, the requested bytes of data are
>> > +copied to user buffer and the corresponding Rx Fifo buffers are invalidated. If no
>> > +Rx message is available, the instance goes to sleep or returns based on the
>> > +flags to the open call.
>> > +
>> > +On the BSP CAN driver, Once a CAN message is received from the CAN bus, the
>> > +message is given to the CAN Framework by calling ``can_receive`` function.
>> > +
>> > +This figure shows the Rx data path.
>> > +
>> > +.. figure:: ../../../images/c_user/CAN-rx-data-path.jpg
>> > + :width: 100%
>> > + :align: center
>> > + :alt: CAN Rx data path
>> > +
>> > +.. seealso::
>> > +
>> > + For Reference, `DCAN BSP driver <https://github.com/RTEMS/rtems/commit/26d50bdfb601b9ef71ec2b30d2d9467c2437f443>`_ is implemented which uses CAN framework.
>> > +
>> > +.. admonition:: Note
>> > +
>> > + The existing implementation creates only two FIFO (each one for Tx and Rx).
>> > + Futher implementation of creating Tx and Rx FIFO for each open call should be done.
>> typo: Further
>>
>> > diff --git a/bsp-howto/index.rst b/bsp-howto/index.rst
>> > index d095fc7..4f5af01 100644
>> > --- a/bsp-howto/index.rst
>> > +++ b/bsp-howto/index.rst
>> > @@ -32,6 +32,7 @@ RTEMS BSP and Driver Guide (|version|).
>> > getentropy
>> > i2c
>> > spi
>> > + can
>> > real_time_clock
>> > networking
>> > frame_buffer
>> > diff --git a/images/c_user/CAN-framework.jpg b/images/c_user/CAN-framework.jpg
>> > new file mode 100644
>>
>> ...
More information about the devel
mailing list