Topics covered in this blog

  • CAN Framework in RTEMS.
    • Registering the CAN BSP driver.
    • Handling Tx and Rx fifo.
    • Concurrency and Synchronization Handling.
    • Tx and Rx data flow.
  • Writing CAN BSP driver using CAN framework.
    • Registering with the CAN Framework.
    • Tx and Rx with CAN Framework.

CAN Framework in RTEMS

The generic handling of the CAN protocol is implemented in cpukit/dev/can directory.

Registering the CAN BSP driver

Each CAN BSP driver should register with the CAN framework by calling can_bus_register. The CAN BSP driver should pass two arguments can_bus data structure and CAN device node path.

can_bus_register function creates and initializes three things:

  • Creates the device node (Example: /dev/can0).
  • Creates the necessary tx and rx queues for the corresponding CAN BSP driver.
  • Initializes the required concurrency handling mechanisms (mutex).

It supports a maximum of 255 CAN BSP driver to be registered.

Each CAN BSP driver is represented by the can_bus data structure in the CAN framework.

Handling Tx and Rx fifo

The CAN message structure in RTEMS is declared in cpukit/include/dev/can/can-msg.h

struct can_msg {                                                                
  uint32_t id;                                                                  
  uint32_t timestamp;                                                           
  uint16_t flags;                                                               
  uint16_t len;                                                                 
  uint8_t data[CAN_MSG_MAX_SIZE];                                               
};

The data structure used for handling CAN Tx and Rx messages between applications and BSP CAN driver is a Circular buffer. The size of the buffer can be configured by CAN_TX_BUF_COUNT.

Note: To modify the data structure used to handle CAN tx and rx messages can be done in the cpukit/dev/can/can-queue.h The CAN framework is designed in such a way that only changes in this file is sufficient to use a differnet data structure.

Concurrency and Synchronization Handling

The synchronization of Tx and Rx fifos between applications and BSP CAN driver is done using counting semaphores.

The counting semaphore is created and initialized for each BSP CAN driver in can_create_sem function at the time of registration with the CAN framework. The maximum semaphore count is CAN_TX_BUF_COUNT.

The instances waiting for the semaphore are dequeued on First In First Out basis.

Tx and Rx data flow

Tx Data Path

The circular buffer is synchronized between application and the BSP CAN driver by using counting semaphore. At any time, the value of the semaphore count says the number of free buffers avaliable.

CAN TX data path

Rx Data Path

The circular buffer is synchronized between application and the BSP CAN driver by using counting semaphore. At any time, the value of the semaphore count says the number of buffers to be read from the receive fifo.

CAN RX data path

Note: Ideally, the tx and rx data path should contain a tx and rx fifo individually to each open call.

Need to be implemented:
-> Each open function call from the application creates a tx, rx fifos (based on the flags) and counting semaphore for tx and rx fifos.
-> Ioctl calls.

Writing CAN BSP driver using CAN framework

Registering with the CAN Framework

Every BSP CAN driver must register itself with CAN framework to use its services.

A successful call to can_bus_register will register to the CAN framework and creates a node (/dev/can{0, 1, *}) for the application to access the CAN controller. The can_bus_register takes can_bus data structure as argument, which BSP driver should populate the nescessary fields (can_dev_ops, index, priv).

Tx and Rx with CAN Framework

Once registered with CAN framework, the Tx and Rx of CAN messages between the application and the CAN controller can be availed.

  • After every successful Tx messages sent in the physical CAN bus can_tx_done should be called. This call will notify the CAN framework that the device’s Tx buffers are free, which calls can_xmit to copy the CAN messages to device buffer which needs to be sent.
  • After every successful Rx messages received from the CAN bus, the BSP driver can push the messages to the CAN framework by calling can_receive.


For reference: BSP CAN Driver for Beaglebone Black

Note: CAN framework is a work in progress module. Your contribution and suggestions are always welcome.