CAN Driver

CAN Driver Functions

The CAN driver contains a set of functions, which are called at specific locations within the CANopen stack.

driver function calling location
Init() during start of node and bit timing switching
Enable() during start of node and bit timing switching
Send() when node needs to send a CAN message
Read() when node processing is started
Reset() when NMT resets the communication
Close() when node is stopped and bit timing switching

CAN Init

This driver function is called during the initialization phase and the bit timing switching of the CANopen stack. The function is intended to prepare the CAN controller for operation.

void DrvCanInit(void);

The function initializes the internal driver variables for managing the CAN communication and prepares the CAN controller for operation.

Note: the CAN controller must not active on the network, because at this calling time the bit timing is not known.

CAN Enable

This driver function is called during the initialization phase and the bit timing switching of the CANopen stack. The function is intended to setup the bit timing and activate the CAN controller on the network.

void DrvCanEnable(uint32_t baudrate);

The function initializes the bit timing according to the given baudrate and enables the CAN communication.

Note: check the specified sample points from the CiA specifications and from your own specification. Wrong settings may result in instable networks.

CAN Send

This driver function is called when the CANopen node needs to send a message to the CAN network. The function returns the number processed bytes sizeof(CO_IF_FRM) on success, (int16_t)0 in case transmission is not possible, or (int16_t)-1 when an error is detected.

int16_t DrvCanSend(CO_IF_FRM *frm);

Note: you must ensure that the messages on the CAN bus keeps the order. Check the behavior of your CAN controller when you want to use multiple message buffers for a queued transmission.

CAN Read

This driver function is called when the CANopen node processing is started. This function is intended to receive all messages from the CAN network. The function returns the number processed bytes sizeof(CO_IF_FRM) on success, (int16_t)0 in case of no receiption, or (int16_t)-1 when an error is detected.

int16_t DrvCanRead(CO_IF_FRM *frm);

Note: you must ensure that the messages are processed in the same order as they arrived from the CAN bus. Check the behavior of your CAN controller when you want to use multiple message buffers for a queued receiption.

CAN Reset

This driver function is called when the CANopen node needs to perform a communication reset. This function is intended to clear all errors from the CAN controller bus statistics and (re-)establishes the CAN communication.

void DrvCanReset(void);

CAN Close

This driver function is called when the CANopen node is stopped (e.g. with the API function CONodeStop()). This function is intended to remove the node from the CAN bus.

void DrvCanClose(void);

CAN Driver Integration

During design of the driver interface for usage with the CANopen stack, we want to decouple the CANopen library from the driver implementation. At the same time, we want to keep the overal usage as easy as possible.

The solution for this requirements is the implementation of the CAN driver function as static functions within a single file and an allocated interface structure of type CO_IF_CAN_DRV:

#include "co_if.h"
   :
static void    DrvCanInit   (void);
static void    DrvCanEnable (uint32_t baudrate);
static int16_t DrvCanSend   (CO_IF_FRM *frm);
static int16_t DrvCanRead   (CO_IF_FRM *frm);
static void    DrvCanReset  (void);
static void    DrvCanClose  (void);
   :
const CO_IF_CAN_DRV <MyDeviceDriverName>CanDriver = {
    DrvCanInit,
    DrvCanEnable,
    DrvCanRead,
    DrvCanSend,
    DrvCanReset,
    DrvCanClose
};

With this kind of implementation, the usage is simply the import of the interface structure as external symbol, and we are ready to go:

  :
extern const CO_IF_CAN_DRV <MyDeviceDriverName>CanDriver;
  :

To keep the drivers organized, we put the implementation in a file which follows the naming convention: co_can_<my-device-driver-name>.c, and the declaration of the external symbol in the corresponding header file co_can_<my-device-driver-name>.h.

CAN Driver Template

The files /driver/source/co_can_dummy.c and /driver/include/co_can_dummy.h are templates for CAN drivers.