CAN Functions — allow applications and other packages to access CAN devices


#include <cyg/io/can.h>

int cyg_can_init(void);

int cyg_can_open(char* devname, cyg_can_dev* dev);

int cyg_can_close(cyg_can_dev dev);

cyg_can_msg* cyg_can_msg_alloc(void);

void cyg_can_msg_free(cyg_can_msg* msg);

int cyg_can_send(cyg_can_dev dev, cyg_can_msg* msg);

int cyg_can_send_nowait(cyg_can_dev dev, cyg_can_msg* msg);

int cyg_can_recv(cyg_can_dev dev, cyg_can_msg** msg);

int cyg_can_recv_poll(cyg_can_dev dev, cyg_can_msg** msg);

int cyg_can_recv_timeout(cyg_can_dev dev, cyg_can_msg** msg, cyg_tick_count_t timeout);

void cyg_can_poll(void);

int cyg_can_filter_set(cyg_can_dev dev, cyg_bool ide, cyg_uint32 match, cyg_uint32 mask);

int cyg_can_filter_get(cyg_can_dev dev, cyg_bool* ide, cyg_uint32* match, cyg_uint32* mask);

int cyg_can_filter_ext_set(cyg_can_dev dev, cyg_can_filter *filters, int len);

int cyg_can_filter_ext_get(cyg_can_dev dev, cyg_can_filter *filters, int *len);

int cyg_can_baud_set(cyg_can_dev dev, cyg_uint32 baud);

int cyg_can_baud_get(cyg_can_dev dev, cyg_uint32* baud);

int cyg_can_baud_fd_set(cyg_can_dev dev, cyg_uint32 baud);

int cyg_can_baud_fd_get(cyg_can_dev dev, cyg_uint32* baud);

int cyg_can_autobaud(cyg_can_dev dev);

const char cyg_can_error_string(int code);

Initialization and Device Access

Before performing any CAN system operations, the application must call cyg_can_init(). This function initializes the CAN subsystem and causes all the configured devices to initialize themselves. Only the first call to this function will initialize the subsystem, subsequent calls will do nothing, so libraries and independent systems may call it in their initialization routines without needing to ensure it is called only once.

To gain access to a specific CAN channel, the application must call cyg_can_open(). Channel names are defined in the configuration and are typically "can0" "can1" and so on. If the channel is not found this function will return CYG_CAN_NOTFOUND; it may also return errors generated by the device driver. If the channel is found the call will return CYG_CAN_NOERROR and the location pointed to by the dev parameter will be initialized with a handle on the channel. This handle must be used in all subsequent calls to access this channel.

When the application has finished with a channel it must call cyg_can_close() on the handle.

Buffer Management

The CAN subsystem uses buffers to pass messages between the application and the CAN subsystem. These buffers are allocated and managed by the CAN subsystem. The exact number of buffers is controllable in the configuration.

Each buffer contains the following fields:

cyg_can_msg * next
This field is used within the CAN subsystem to link this message buffer into lists. When the buffer is in the possession of the user (state is CYG_CAN_MSG_STATE_USER) then this may be used for application purposes.
unsigned int rtr
Remote Transmission Request. If this field is set in a transmitted message buffer, then the RTR bit on the message will be set and the data field will be ignored. On reception this field reflects the state of the RTR bit in the received message.
unsigned int ide
Extended ID. If this field is set then the id field contains a 29 bit extended ID. If it is clear then the ID is 11 bits.
unsigned int state

This field is used within the CAN subsystem to track the current state of the buffer. The following states are supported:

The message buffer is not currently being used and is on the CAN subsystem's free list.
The message buffer is currently in the possession of the application code and is outside the control of the CAN subsystem.
The message buffer is either currently being transmitted, or is in a queue of buffers awaiting transmission.
The message buffer is the current pending receive buffer for a CAN channel. The next message from that channel will be received into this buffer.
The message buffer is currently on a channel's receive queue. A message has been received into it but not yet been passed on to the user.
unsigned int len
The length of the data carried in the message. This can range from zero to 8. In a message with the RTR field set, this indicates the size of data being requested.
int result
An error code. For normal successful receptions of messages this will be CYG_CAN_NOERROR. Message buffers are also used to report special events on the channel such as transitions to passive error and bus off states. In these cases, the event will be reported using a message buffer with this field set to the appropriate error code.
cyg_uint32 timestamp
Some CAN channels contain a timer that can be used to timestamp received packets. If that is the case, then the timestamp will be stored in this field. If the channel does not have any hardware timing facility, this field will not be used. This field is used for internal purposes during message transmission.
cyg_uint32 id
Message ID. This is the ID to be transmitted with the message, or the ID received. If the ide field is set, then this will contain a 29 bit ID, otherwise it will contain an 11 bit ID.
cyg_uint8 data[8]
Message data. Only the first len bytes of data are valid. If the rtr field is set, then the contents of this field are ignored.

A message buffer may be allocated by calling cyg_can_msg_alloc() and freed by calling cyg_can_msg_free().

CAN-FD Buffers

When CAN-FD is enabled the message buffer contains some extra and modified fields:

unsigned int fdf
FD Format. This marks a message as being in FD format. If this field is set in a transmitted message then it will be sent in CAN-FD format. A message with a len value of more than 8 will also be considered to be in FD format regardless of the state of this field. On reception this field reflects the state of the FDF bit in the received message.
unsigned int brs
Bit Rate Switch. This indicates whether the message is transmitted with a higher bit rate for the data portion. This field is only valid for FD format messages. If this field is set in a transmitted message then its data bytes will be transmitted at the FD bit rate. On reception this field reflects the state of the BRS bit in the received message.
unsigned int esi
Error State Indicator. This field indicates the error state of the transmitting node, 0 for error active and 1 for error passive. This field is only valid for FD format messages. If this field is set in a transmitted message then the ESI bit on the message will be set. On reception this field reflects the state of the ESI bit in the received message.
unsigned int len

This field is expanded for FD messages to permit any value between 0 and 64. The CAN-FD protocol only permits a limited selection of message sizes: 0 to 8, 12, 16, 20, 24, 32, 48 and 64, encoded into a 4 bit field. This encoding is not used in this field, instead the actual number of bytes are used, with the translation being done in the device driver.

On transmission if this value is greater than 8 then the message is sent in FD format, regardless of the value of fdf. If the supplied value is not one of the protocol-permitted sizes it will be increased to the next greater size.

On reception this field will be translated from the protocol encoding into the correct number of bytes.

cyg_uint8 data[64]
When CAN-FD is enabled, this field is increased to 64 bytes. Only the first len bytes will be valid. If, on transmission, the length has been increased to the next supported size, some extra bytes at the end of the supplied data in the buffer may be sent. On reception, bytes beyond the end of the specified length may have been written by the driver.

Transmit and Receive

To transmit a message an application must acquire a message buffer from the CAN subsystem, fill it in with the message to be sent and call cyg_can_send(). Following a successful call the buffer becomes the property of the CAN subsystem and will be returned to the free pool when the message has been transmitted. If an error is detected then the call will return an error code and the message buffer will be returned to the user for reuse or retransmission.

To send a message without waiting for it to complete, the application can call cyg_can_send_nowait().

To receive a message the application calls cyg_can_recv(). If there is a message waiting, then a pointer to the message buffer will be installed in the location pointed to by the msg argument and CYG_CAN_NOERROR is returned.

If the application does no want to wait for a message to arrive, it can call cyg_can_recv_poll() which will just test for a message and return. If a message is present then CYG_CAN_NOERROR is returned and the msg filled in with a pointer to a message buffer. If no message is present then the function will return CYG_CAN_AGAIN.

The application can also wait for a defined length of time for a message to arrive by calling cyg_can_recv_timeout(). The additional timeout argument supplies an absolute timeout in system ticks. If a message is present then CYG_CAN_NOERROR is returned and the msg filled in with a pointer to a message buffer. If no message arrives before the timeout expires then the function will return CYG_CAN_TIMEOUT.

Regardless of which receive function is used, a successful return results in a message buffer being passed back to the caller. The result field of this message buffer will either contain CYG_CAN_NOERROR for a normal message, or it will contain an error code indicating an event that has occurred on the channel. When the application has finished with the buffer it must return it to the CAN subsystem by calling cyg_can_msg_free().

The function cyg_can_poll() may be called to force all channels to check for transmission completion or pending receptions. When using interrupt driven devices it is unnecessary to call this. However, if there are any polled devices, this is the only way to ensure timely processing of received messages. This function should therefore be called from the application main loop, or from a separate timer driven thread, or by any other appropriate means to ensure communication proceeds in a timely fashion.

Basic Filtering

The functions cyg_can_filter_set() and cyg_can_filter_get() allow the basic hardware filter to be set and queried. The basic filter model consists of a match value, such that if an ID when bitwise ANDed with the mask equals mask equals the match value ANDed with the mask, then the message is accepted. If the hardware does not support a filter that conforms to this model then no hardware filtering is done, but the filter will still be applied by the CAN subsystem to all incoming packets.

In cyg_can_filter_set(), the match and mask arguments define the filter. The ide indicates whether the filter is for normal or extended IDs. It is hardware dependent what happens when the filter ID size does not match the ID size being used on the network.

Extended Filtering

The functions cyg_can_filter_ext_set() and cyg_can_filter_ext_get() implement an extended filtering mechanism. In this case the application can submit an array of filters which will accept a message if any one of them matches the received ID. If it is possible, extended filtering will be implemented in the CAN controller hardware. Otherwise it will be implemented in software. Setting the extended filters will invalidate the basic filter and vice versa.

The filters are an array of cyg_can_filter structures. Each filter consists of a mask and a match field. For each filter, if the received ID bitwise ANDed with the mask equals the match field ANDed with the mask, then the message is accepted. In addition to the 11 or 29 bits of the ID, the mask and match fields can contain two extra bits: CYG_CAN_FILTER_IDE matches the message IDE bit for 29 bit addressing, and CYG_CAN_FILTER_RTR matches the message RTR bit.

Some care should be taken in setting the IDE and RTR bits in the filters. In general, if the intention is to match on either bit, then it should be set in both fields. Setting the bit only in the mask field will match packets that have the bit clear, which is unlikely to be what it wanted. Incoming message IDs are only matched against similarly sized filters: a message with a 29 bit ID is only matched against filters that have the IDE bits set, and 11 bit ID are only matched against filters with IDE clear. This approach is to ensure consistency between software and hardware filters, and between different hardware filters.

In cyg_can_filter_ext_set() the filters argument is the address of the filter array, and len defines the number of elements. An error will be returned if the filters are invalid or the list is too long. In cyg_can_filter_ext_get(), the *len argument is a pointer to the length; it should be set to the size of the filters array before the call and will be updated with the number of actual filters returned. If the filters argument is NULL, the number of filters set will be returned in *len. If the number of filters set is larger than the value of *len, or if no extended filters are set, then an error will be returned.

The configuration option CYGNUM_IO_CAN_FILTER_MAX describes the maximum number of extended filters than can be stored. Usually controller drivers will set this value according to the amount of hardware resource available in the filter system.

Baud Rate

The functions cyg_can_baud_set() and cyg_can_baud_get() allow the channel baud rate to be set and queried. Baud rates from 10kb/s to 1Mb/s may be set, although not all device drivers will necessarily support all rates, many will only support a subset. Also, due to interactions between the input clock to the device and the divider granularity, it may not be possible to set some baud rates accurately at some system clock rates; it may be necessary to alter the system clock speed to enable communication.

The functions cyg_can_baud_fd_set() and cyg_can_baud_fd_get() allow the channel FD baud rate to be set and queried. When an FD format message is sent or received, the data bytes will be transmitted at this rate rather than the standard rate.

Autobaud Support

The function cyg_can_autobaud() supports automatic baud rate detection. This will only be present if the controller driver supports autobaud or listen-only mode. It indicates this by implementing the CYGINT_IO_CAN_AUTOBAUD interface. If the driver does no support this feature then this function will not be defined.

The approach for baud detection is to switch the controller to listen-only mode, where it cannot affect the bus state. Each of a set of candidate baud rates are set and the function waits for a period of time for a valid packet to arrive. If no packet is seen, then attention moves to the next baud rate. If a packet is received, then that baud rate is selected and set in the controller in non-listen-mode. If no packets are seen at any baud rate, the original rate is restored to the controller.

There are two configuration options that control the behaviour of the autobaud mechanism:

This is the set of baud rates tested when autobaud is enabled. It is a comma separated list of rates used to initialize an array in the CAN subsystem. The default value contains all the standard CANOpen rates, but for specific applications only the subset of rates that might be used should be listed.
Maximum time in ticks that the autobaud code will wait for bus activity at each baud rate. If no packet is received or an error reported in this time, it will move on to the next baud rate. The default 50 ticks equals half a second at the default 100Hz clock frequency. If this option is set to zero, then the autobaud code will wait indefinitely at each baud rate for either a packet or an error. This is useful during testing when traffic is initiated by hand.

Autobaud support comes with a number of caveats. Baud detection depends on traffic being present on the CAN bus and being frequent enough for packets to be seen during the timeout period for each candidate baud rate. Some baud rates may not be supportable by the controller. If there is only one other node in the network sending packets, the lack of acknowledgements may cause it to move into Error Passive or Bus Off mode and stop transmitting. Consequently autobaud detection cannot be considered to be a fully reliable operation and it is quite possible for cyg_can_autobaud() to terminate without detecting the baud rate. The length of time taken to detect the baud rate may be as long as the number of candidate rates multiplied by the timeout period.


Many of the CAN API calls return error codes. The result field of the message buffer structure may also contain an error code from this set. The following error codes may be returned by API calls:

No error, the operation completed successfully.
When returned from cyg_can_open() this error code means that the named CAN channel could not be found.
When returned from cyg_can_filter_set() this error code means that the filter is invalid. When returned from cyg_can_baud_get() this error code means that the baud rate is invalid, or the hardware cannot support it with sufficient accuracy in the current system configuration.
When returned from cyg_can_recv_timeout() this error code means that the timeout has expired with no message being received.

The following error codes may be passed back in the result field of a message buffer acquired from one of the receive functions. Refer to the CAN specification for details of what these events actually mean.

The message buffer contains a CAN message that was received from the channel.
This error code indicates that the CAN channel's transmit error counter has exceeded its warning limit, which is usually 96.
This error code indicates that the CAN channel's receive error counter has exceeded its warning limit, which is usually 96.
This error code indicates that the CAN channel has gone into "error passive" mode.
This error code indicates that the CAN channel had gone into "bus off" mode.
This error code indicates that the CAN channel has lost one or more CAN messages due to all the hardware buffers being full.
This error code indicates that the controller has detected one or more low level error conditions. Support for detecting these errors may only be enabled when driver autobaud support is enabled. It may not be generated during normal operation.

The cyg_can_error_string() function translates these error codes into strings for diagnostic purposes.