Runtime configuration is achieved by exchanging data structures with the
driver via the cyg_io_set_config()
and
cyg_io_get_config()
functions.
typedef struct cyg_can_info_st { cyg_can_baud_rate_t baud; } cyg_can_info_t; |
Device configuration is achieved by by exchanging
cyg_can_info_t
data structures with the driver
via the cyg_io_set_config()
and
cyg_io_get_config()
functions using the config keys
CYG_IO_GET_CONFIG_CAN_INFO
and
CYG_IO_SET_CONFIG_CAN_INFO
.
The field baud
contains a baud rate selection.
This must be one of the following values:
CYGNUM_CAN_KBAUD_10 CYGNUM_CAN_KBAUD_20 CYGNUM_CAN_KBAUD_50 CYGNUM_CAN_KBAUD_100 CYGNUM_CAN_KBAUD_125 CYGNUM_CAN_KBAUD_250 CYGNUM_CAN_KBAUD_500 CYGNUM_CAN_KBAUD_800 CYGNUM_CAN_KBAUD_1000 |
typedef struct cyg_can_timeout_info_st { cyg_uint32 rx_timeout; cyg_uint32 tx_timeout; } cyg_can_timeout_info_t; |
Timeout configuration is achieved by by exchanging
cyg_can_timeout_info_t
data structures with the
driver via the cyg_io_set_config()
and
cyg_io_get_config()
functions using the config keys
CYG_IO_SET_CONFIG_CAN_TIMEOUT
and
CYG_IO_SET_CONFIG_CAN_TIMEOUT
.
rx_timeout
Timeout for cyg_io_read
calls.
tx_timeout
Timeout for cyg_io_write
calls.
Timeout runtime configuration is supported if the configuration options
CYGOPT_IO_CAN_SUPPORT_NONBLOCKING
and CYGOPT_IO_CAN_SUPPORT_TIMEOUTS
are enabled.
typedef struct cyg_can_buf_info_st { cyg_int32 rx_bufsize; cyg_int32 rx_count; cyg_int32 tx_bufsize; cyg_int32 tx_count; } cyg_can_buf_info_t; |
CYG_IO_GET_CONFIG_CAN_BUFFER_INFO
- This function
retrieves the current state of the software buffers in the CAN drivers.
For the transmit buffer it returns the the total number of
cyg_can_message objects in buffer and the current number of
cyg_can_message objects occupied in the buffer.
For the receive buffer it returns the total number of
cyg_can_event objects in receive buffer and the current
number of cyg_can_event objects occupied in the buffer.
It does not take into account any buffering such as FIFOs or holding
registers that the CAN hardware device itself may have.
rx_bufsize
Total number of cyg_can_event buffers in receive queue.
rx_count
Current number of cyg_can_event buffers occupied in receive queue.
tx_bufsize
Total number of cyg_can_message buffers in transmit queue.
rtx_count
Current number of cyg_can_message buffers occupied in transmit queue.
typedef struct cyg_can_hdi_st { cyg_uint8 support_flags; cyg_uint8 controller_type; } cyg_can_hdi; |
CYG_IO_GET_CONFIG_CAN_HDI
- This function retrieves
information about the used hardware. The Hardware Description Interface
provides a method to gather information about the CAN hardware and the
functionality of the driver. For this purpose the structure
cyg_can_hdi
is defined.
support_flags
Contains information about the capabilities of the used CAN hardware.
controller_type
A number that identifies the CAN controller type.
The following flags are available in the field support_flags
:
| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | +-------+-------+-------+-------+-------+-------+-------+-------+ | res | res | res |timest.|SW-Filt|FullCAN| Frametype | |
Frametype
Bit 0 and Bit 1 of the structure describe the possibilities of the CAN controller. The following values are defined:
CYGNUM_CAN_HDI_FRAMETYPE_STD // receives only standard frame CYGNUM_CAN_HDI_FRAMETYPE_EXT_PASSIVE // can receive but not send extended frames CYGNUM_CAN_HDI_FRAMETYPE_EXT_ACTIVE // can send and receive extended frames |
FullCAN
If the Bit 2 - CYGNUM_CAN_HDI_FULLCAN
- is set to one,
the CAN controller supports more than one message buffer.
SW-Filter
If Bit 3 - CYGNUM_CAN_HDI_FILT_SW
- is set to one then
the CAN driver supports some kind of software message filtering.
Timestamp
If Bit 4 - CYGNUM_CAN_HDI_TIMESTAMP
- is set to one then
the CAN hardware supports timestamps for CAN messages
typedef struct cyg_can_msgbox_info_st { cyg_uint8 count; // number of message buffers available for this device cyg_uint8 free; // number of free message buffers } cyg_can_msgbuf_info; |
CYG_IO_GET_CONFIG_CAN_MSGBUF_INFO
- If the CAN hardware supports
more than one message buffer for reception of CAN messages (flag
CYGNUM_CAN_HDI_FULLCAN
is set while reading hardware description
interface with CYG_IO_GET_CONFIG_CAN_HDI
) then this function
reads the number of message buffers the CAN hardware supports and the number of
free message buffers.
count
Counts the number of message buffers supported by the device.
free
Contains the number of free message buffers. The free message buffers are
available for setting up remote buffers (CYG_IO_SET_CONFIG_CAN_REMOTE_BUF
)
and message filters (CYG_IO_SET_CONFIG_CAN_FILTER_MSG
).
typedef enum { CYGNUM_CAN_STATE_ACTIVE, // CAN controller active, no errors CYGNUM_CAN_STATE_STOPPED, // CAN controller in stopped mode CYGNUM_CAN_STATE_STANDBY, // CAN controller in Sleep mode CYGNUM_CAN_STATE_BUS_WARN, // CAN controller active, warning level is reached CYGNUM_CAN_STATE_ERR_PASSIVE, // CAN controller went into error passive mode CYGNUM_CAN_STATE_BUS_OFF, // CAN controller went into bus off mode CYGNUM_CAN_STATE_PHY_FAULT, // General failure of physical layer CYGNUM_CAN_STATE_PHY_H, // Fault on CAN-H detected (Low Speed CAN) CYGNUM_CAN_STATE_PHY_L, // Fault on CAN-L detected (Low Speed CAN) } cyg_can_state; |
CYG_IO_GET_CONFIG_CAN_STATE
- This function retrieves the
present state of the CAN controller. Possible values are defined in the
cyg_can_state enumeration.
CYG_IO_SET_CONFIG_CAN_MODE
- This function changes
the operating mode of the CAN controller. The identifiers for the different
operating modes are defined in the cyg_can_mode enumeration.
typedef enum { CYGNUM_CAN_MODE_STOP, // set controller into stop mode CYGNUM_CAN_MODE_START, // set controller into operational mode CYGNUM_CAN_MODE_STANDBY // set controller into standby / sleep mode } cyg_can_mode; |
Set controller into stop mode
Set controller into operational mode
Set controller into standby / sleep mode.
Before the hardware configuration of the device is changed, that means
if baud rate is changed or the message buffer and filter configuration
is changed, the CAN hardware should be set into stop mode and if
configuration is finished, then device should be set back into
operational mode. Before the device is set into standby mode, the
output buffers should be flushed or drained because transmission of a
CAN message may wake up the CAN hardware. If a received message wakes
up the CAN hardware from standby mode then
a CYGNUM_CAN_EVENT_LEAVING_STANDBY
event will be
inserted into receive message buffer or
the CYGNUM_CAN_EVENT_LEAVING_STANDBY
flag will be
set for the message that caused wake up of CAN hardware.
CYG_IO_SET_CONFIG_CAN_OUTPUT_DRAIN
- This function
waits for any buffered output to complete. This function only
completes when there is no more data remaining to be sent to the
device.
CYG_IO_SET_CONFIG_CAN_OUTPUT_FLUSH
- This function
discards any buffered output for the device.
CYG_IO_SET_CONFIG_CAN_INPUT_FLUSH
- This function
discards any buffered input for the device.
By default all calls to cyg_io_read()
and cyg_io_write()
are blocking calls. The config
keys
CYG_IO_SET_CONFIG_READ_BLOCKING CYG_IO_SET_CONFIG_WRITE_BLOCKING |
enable switching between blocking and nonblocking calls separatly for
read and write calls. If blocking calls are configured then the
read/write functions return only if a message was stored into TX
buffer or a event was received from RX buffer. If non-blocking calls
are enabled and there is no space in TX buffer or RX buffer is empty
then the function returns immediately
with -EAGAIN
.
If non-blocking calls are enabled and additionally timeouts are
supported by driver, then the read/write functions wait until timeout
value is expired and then return with -EINTR
. If
the read/write operation succeeds during the timed wait then the
functions return succesfully with
ENOERR
.
To query if cyg_io_read()
and cyg_io_write()
are blocking or non-blocking
you can use the config keys
CYG_IO_GET_CONFIG_READ_BLOCKING CYG_IO_GET_CONFIG_WRITE_BLOCKING |
Full CAN controllers often support more the one message buffer. These message buffers are often configurable for transmission or reception of certain CAN messages or as a remote buffers. If a CAN hardware supports more than one message buffer then it is possible to configure the CAN hardware to receive only CAN messages with certain identifiers or to configure hardware support for remote buffers. If message filtering is done by hardware, the number of received CAN messages decreases and so also the time for processing received CAN messages and the memory required for buffering received messages decreases. This saves valuable memory and processing time.
The eCos CAN driver supports a generic way of adding message filters
or remote buffers. By default the CAN driver is configured for
reception of any kind of CAN standard and extended
frames. Configuration of message buffers is done by
calling cyg_io_set_config()
with the config key
CYG_IO_SET_CONFIG_CAN_MSGBUF |
and by exchanging cyg_can_msgbuf_cfg data structures.
typedef struct cyg_can_msgbox_cfg_st { cyg_can_msgbuf_cfg_id cfg_id; // configuration id cyg_can_msgbuf_handle handle; // handle to message buffer cyg_can_message msg; // CAN message - for configuration of buffer } cyg_can_msgbuf_cfg; |
cfg_id
The cfg_id
field
contains the configuration ID that tells the driver what to do with a
message buffer.
handle
Contains a reference to a certain message buffer.
msg
Required for configuration of message buffer parameters.
The following configuration identifiers are supported:
CYGNUM_CAN_MSGBUF_RESET_ALL // clears alle message buffers CYGNUM_CAN_MSGBUF_RX_FILTER_ALL // cfg driver for reception of all can messages CYGNUM_CAN_MSGBUF_RX_FILTER_ADD // add single message filter CYGNUM_CAN_MSGBUF_REMOTE_BUF_ADD // add new remote response buffer CYGNUM_CAN_MSGBUF_REMOTE_BUF_WRITE // stores data into existing remote buffer |
Clears alle message buffers - no message will be received and all remote buffers are deleted.
Configure driver for reception of all can messages
Add single message filter.
Add new remote response buffer.
Stores data into existing remote buffer (remote buffer handle required).
Example code for resetting all message buffers:
cyg_can_msgbuf_cfg msgbox_cfg; msgbox_cfg.cfg_id = CYGNUM_CAN_MSGBUF_RESET_ALL; len = sizeof(msgbox_cfg); if (ENOERR != cyg_io_set_config(hDrvFlexCAN, CYG_IO_SET_CONFIG_CAN_MSGBUF, &msgbox_cfg, &len)) { // handle configuration error } |
The remote frame is a message frame which is transmitted to request a data frame. Some CAN hardware generates receive interrupts when a remote transmission request arrives. Other CAN hardware, i.e. the Motorola FlexCAN module, does not generate any receive interrupt. These CAN hardware chips like the FlexCAN module can be configured to transmit a data frame automatically in response to a remote frame. In order to support any kind of CAN hardware the eCos CAN driver provides a generic handling of remote transmission requests.
The transmission of the data frame in response to a remote frame is completely handled by the CAN driver. If the hardware driver, like the driver for the FlexCAN module, supports hardware message buffers, then the response frame is automatically transmitted if a remote transmission request with a matching ID arrives. If a CAN hardware does not provide hardware support for sending data frames in response to a remote frame, then this need to be implemented in software by the hardware device driver.
It is always possible to add remote response buffers. It does not matter if the driver is configured for reception of all CAN messages or if message filtering is used. As long as there are free message buffers available, it is possible to add remote response buffers.
In order to respond to a remote frame, a remote frame response buffer
need to be initialized before a data frame can be sent in response to
a remote frame. This is achieved by by
exchanging cyg_can_remote_buf data structures with the
driver via the cyg_io_set_config()
function using
the config key CYG_IO_SET_CONFIG_CAN_MSGBUF
. Once
the buffer is initialized, the CAN data can be changed at any time by
the application.
typedef struct cyg_can_msgbuf_cfg_st { cyg_can_msgbuf_cfg_id cfg_id; // configuration id cyg_can_msgbuf_handle handle; // handle to message buffer cyg_can_message msg; // CAN message - for configuration of buffer } cyg_can_remote_buf; |
cfg_id
The cfg_id
field contains the configuration ID that tells the driver what to do with
a message buffer (CYGNUM_CAN_MSGBUF_REMOTE_BUF_ADD
or
CYGNUM_CAN_MSGBUF_REMOTE_BUF_WRITE
).
handle
If there is no buffer initialized for this data, the value of the handle field need to be set to
CYGNUM_CAN_MSGBUF_INIT
. After the call to cyg_io_set_config()
the handle field contains a valid remote buffer handle ( >= 0) or the value
CYGNUM_CAN_MSGBUF_NA
( < 0) if no free buffer is available.
msg
The CAN frame that should be transmitted in response to a remote frame.
Example code for setting up a remote response buffer:
cyg_can_remote_buf rtr_buf; // prepare the remote response buffer rtr_buf.cfg_id = CYGNUM_CAN_MSGBUF_REMOTE_BUF_ADD; rtr_buf.handle = CYGNUM_CAN_MSGBUF_INIT; rtr_buf.msg.id = 0x7FF; rtr_buf.msg.ext = CYGNUM_CAN_ID_STD; rtr_buf.msg.rtr = CYGNUM_CAN_FRAME_DATA; rtr_buf.msg.dlc = 1; rtr_buf.msg.data[0] = 0xAB; len = sizeof(rtr_buf); if (ENOERR != cyg_io_set_config(hDrvFlexCAN, CYG_IO_SET_CONFIG_CAN_MSGBUF, &rtr_buf, &len)) { // handle configuration error } if (rtr_buf.handle == CYGNUM_CAN_MSGBUF_NA) { // no free message buffer available - handle this problem here } // change CAN data for a buffer that is already initialized rtr_buf.cfg_id = CYGNUM_CAN_MSGBUF_REMOTE_BUF_WRITE; rtr_buf.msg.data[0] = 0x11; len = sizeof(rtr_buf); if (ENOERR != cyg_io_set_config(hDrvFlexCAN, CYG_IO_SET_CONFIG_CAN_MSGBUF, &rtr_buf, &len)) { // handle configuration error } |
If message filtering is done by hardware the number of received CAN messages decreases and so also the time for processing received CAN messages and the memory required for buffering received messages decreases. This saves valuable memory and processing time. The eCos CAN driver supports a generic way of adding message filters. By default the CAN driver is configured for reception of any kind of CAN standard and extended frames. As soon as a message filter is added, the CAN driver will only receive the CAN frames with the identifier of the CAN filter. By adding a number of message filters it is possible for the CAN hardware to receive an number of different CAN messages.
Adding message filters is only possible if driver is not configured for reception of all available CAN messages. If the driver is configured for reception of all CAN messages then message buffers need to be reset before adding single message filters.
In order to add a message filter, a message buffer need to be
initialized. This is achieved by
exchanging cyg_can_filter data structures with the driver
via the cyg_io_set_config()
function using the
config key CYG_IO_SET_CONFIG_CAN_MSGBUF
. Once the
buffer is initialized, the CAN hardware can receive messages with the
identifier of the filter.
typedef struct cyg_can_msgbox_cfg_st { cyg_can_msgbuf_cfg_id cfg_id; cyg_can_msgbuf_handle handle; cyg_can_message msg; } cyg_can_filter; |
cfg_id
The cfg_id
field contains the configuration ID that tells the driver what to do with
a message buffer.
handle
After the call to cyg_io_set_config()
the handle field contains a valid value
( >= 0) or the value CYGNUM_CAN_MSGBUF_NA
( < 0) if no free buffer is available.
msg
The fields id
and ext
of the msg
configure the type of message to receive by a certain message filter.
Before adding message filters the device should be stopped and after configuration it should be set into operational mode again.
Example code for setting up a message filter:
cyg_can_msgbuf_cfg msgbox_cfg; cyg_can_filter rx_filter; // reset all message buffers msgbox_cfg.cfg_id = CYGNUM_CAN_MSGBUF_RESET_ALL; len = sizeof(msgbox_cfg); if (ENOERR != cyg_io_set_config(hDrvFlexCAN, CYG_IO_SET_CONFIG_CAN_MSGBUF, &msgbox_cfg, &len)) { // handle configuration error } // prepare the message filter rx_filter.cfg_id = CYGNUM_CAN_MSGBUF_RX_FILTER_ADD rx_filter.msg.id = 0x800; rx_filter.msg.ext = CYGNUM_CAN_ID_EXT; len = sizeof(rx_filter); if (ENOERR != cyg_io_set_config(hDrvFlexCAN, CYG_IO_SET_CONFIG_CAN_MSGBUF, &rx_filter, &len)) { // handle configuration error; } else if (CYGNUM_CAN_MSGBUF_NA == rx_filter.handle) { // no free message buffer available - handle this problem here } |
After startup of your device the CAN driver is configured for reception of all available CAN messages. If you change this configuration by adding single message filters then you can reset this default state with the configuration ID:
CYGNUM_CAN_MSGBUF_RX_FILTER_ALL |
This message buffer configuration id will clear all message filters and remote buffers and prepares the CAN hardware for reception of any kind of CAN standard and extended frames. It is not necessary to reset the message buffer configuration before this configuration step is executed because this should be done by device driver.
Example code for deactivation of message filtering:
cyg_can_filter rx_filter; // now setup a RX all configuration rx_filter.cfg_id = CYGNUM_CAN_MSGBUF_RX_FILTER_ALL; len = sizeof(rx_filter); if (ENOERR != cyg_io_set_config(hDrvFlexCAN, CYG_IO_SET_CONFIG_CAN_MSGBUF, &rx_filter, &len)) { CYG_TEST_FAIL_FINISH("Error writing config of /dev/can0"); } |