4.15. CAN
4.15.2. Description
In can_cfg.c
, CAN messages are defined in two tables:
can_txMessages[]
for messages to be sent.can_rxMessages[]
for messages to be received.
4.15.2.1. Messages to send
The sent message parameters are:
CAN ID of message to be sent.
data length code, number of bytes to send. Default 8, maximum 8.
repetition time, period of transmission in ms. Must be a multiple of 10.
repetition phase, delay for the first transmission. Avoids sending all messages with same period at the same time.
byte order, endianness (big or little endian) of CAN data.
callback function, pointer to the function that is called when the message has to be sent.
multiplexer, pointer to a number. This is used to multiplex data in CAN messages. A static variable must be defined to be used as multiplexer.
The data of the CAN message is divided into signals. Data for each signal is prepared within the callback function. The developer must implement the signals as needed by the application.
Two helper functions are defined for this task,
CAN_TxSetMessageDataWithSignalData()
and
CAN_TxSetCanDataWithMessageData()
.
In the callback function, a uint64_t variable
must be defined, which
represents the CAN message.
With the function CAN_TxSetMessageDataWithSignalData()
, the signal data
can be stored in the message data. The parameters are
pointer to 64-bit CAN message.
bit position in CAN message where the signal data must be stored.
length of the signal data in the CAN message.
signal data. If data is e.g. a float, it must be cast to an integer before being passed to the function.
endianness (big or little endian) of CAN data.
Once the CAN message is ready, the function
CAN_TxSetCanDataWithMessageData()
must be called. It will
store the CAN message in the variable used by the low-level driver for
the actual transmission.
The function CAN_PeriodicTransmit()
is called every 10ms by the 10ms task.
It parses all the elements of can_txMessages[]
. If the time has been
reached to send the messages, the corresponding callback function is called.
The message is then sent with the function CAN_DataSend()
. The function
CAN_DataSend()
can also be used to send a CAN message directly anywhere
else in the code.
4.15.2.2. Messages to receive
The received message parameters are:
CAN ID of message to be received.
data length code, number of bytes to receive. Default 8, maximum 8.
byte order, endianness (big or little endian) of CAN data.
callback function: pointer to the function that is called when the message is received. The data of the CAN message is available within this function.
A receive queue called ftsk_canRxQueue
is used as shown in
Queue handle for CAN receive and
Supporting variables for the queue of the CAN receive module.
1QueueHandle_t ftsk_canRxQueue = NULL_PTR;
1 /* structure and array for static CAN RX queue */
2 static uint8_t ftsk_canRxQueueStorageArea[FTSK_CAN_RX_QUEUE_STORAGE_AREA] = {0};
3 static StaticQueue_t ftsk_canRxQueueStructure = {0};
When CAN messages are received, the CAN interrupt callback calls
CAN_RxInterrupt()
. The message received is sent to the queue.
The function CAN_ReadRxBuffer()
is called every 1ms by the 1ms task.
For each element in the queue, it checks if the CAN message ID matches
an ID of the RX message list can_rxMessages[]
. If this is the case,
the corresponding callback function is called.
In the callback function, a uint64_t variable
must be defined, which
represents the CAN message. The helper function
CAN_RxGetMessageDataFromCanData()
MUST be called at the beginning.
It copies the CAN data retrieved by the low level driver into the message
variable. If necessary, the other helper function
CAN_RxGetSignalDataFromMessageData()
can be used to retrieve signal data
easily from the message. The parameters are
64-bit CAN message.
bit position in CAN message where the signal data must be stored.
length of the signal data in the CAN message.
pointer to signal data.
endianness (big or little endian) of CAN data.
The signal data is then available in the variable pointed to by the signal data pointer.
A receive queue was used because usually the developer needs
to access the database in the callback of the receive function, but this
must not be done in an interrupt routine. With the current implementation,
the receive interrupt routine sends the received data to the queue.
The CAN_ReadRxBuffer()
function retrieves the messages from the queue
and calls the callbacks outside of the interrupt routine.
4.15.2.3. Configuration in HALCoGen
64 messages boxes are available for each CAN interface. 32 of them are
configured as transmit message boxes, the other half as receive message boxes
(with HALCoGen), so the macro CAN_NR_OF_TX_MESSAGE_BOX
is set to 32.
It must be adapted if the number of transmit message boxes is changed.
When using the CAN interface CAN4
, special care has to be taken because of
a bug in HALCoGen. For more information, refer to
HALCoGen tool documentation.
4.15.2.4. Callback definition
If a new file is needed for a new callback, it must be added in the
directory ./src/app/driver/can/cbs
. The corresponding header is the file
can_cbs.h
in the same directory. The new callback file must also be added
to the wscript
file in ./src/app/driver
. For instance, if the file
can_my_callback.c
is added, the line
os.path.join("can", "cbs", "can_my_callback.c"),
must be added.