Name
CAN Functions — allow applications and other packages to access CAN devices
Synopsis
#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
isCYG_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:
- CYG_CAN_MSG_STATE_FREE
- The message buffer is not currently being used and is on the CAN subsystem's free list.
- CYG_CAN_MSG_STATE_USER
- The message buffer is currently in the possession of the application code and is outside the control of the CAN subsystem.
- CYG_CAN_MSG_STATE_TX
- The message buffer is either currently being transmitted, or is in a queue of buffers awaiting transmission.
- CYG_CAN_MSG_STATE_RX
- 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.
- CYG_CAN_MSG_STATE_RXQ
- 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 thertr
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:
- CYGPKG_IO_CAN_AUTOBAUD_RATES
- 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.
- CYGNUM_IO_CAN_AUTOBAUD_TIMEOUT
- 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.
Errors
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:
- CYG_CAN_NOERROR
- No error, the operation completed successfully.
- CYG_CAN_NOTFOUND
-
When returned from
cyg_can_open()
this error code means that the named CAN channel could not be found. - CYG_CAN_INVALID
-
When returned from
cyg_can_filter_set()
this error code means that the filter is invalid. When returned fromcyg_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. - CYG_CAN_TIMEOUT
-
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.
- CYG_CAN_NOERROR
- The message buffer contains a CAN message that was received from the channel.
- CYG_CAN_WARN_TX
- This error code indicates that the CAN channel's transmit error counter has exceeded its warning limit, which is usually 96.
- CYG_CAN_WARN_RX
- This error code indicates that the CAN channel's receive error counter has exceeded its warning limit, which is usually 96.
- CYG_CAN_PASSIVE
- This error code indicates that the CAN channel has gone into "error passive" mode.
- CYG_CAN_BUSOFF
- This error code indicates that the CAN channel had gone into "bus off" mode.
- CYG_CAN_OVERRUN
- This error code indicates that the CAN channel has lost one or more CAN messages due to all the hardware buffers being full.
- CYG_CAN_RXERROR
- 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.
2024-03-18 | eCosPro Non-Commercial Public License |