4.15. CAN

4.15.1. Module Files

4.15.1.1. Driver

  • src/app/driver/can/can.c

  • src/app/driver/can/can.h

  • src/app/driver/can/cbs/can_cbs.h

  • src/app/driver/can/cbs/can_helper.c

  • src/app/driver/can/cbs/can_helper.h

4.15.1.2. Configuration

  • src/app/driver/can/cbs/rx/can_cbs_rx.h

  • src/app/driver/can/cbs/rx/can_cbs_rx_aerosol-sensor.c

  • src/app/driver/can/cbs/rx/can_cbs_rx_bms-state-request.c

  • src/app/driver/can/cbs/rx/can_cbs_rx_current-sensor.c

  • src/app/driver/can/cbs/rx/can_cbs_rx_debug.c

  • src/app/driver/can/cbs/rx/can_cbs_rx_imd-info.c

  • src/app/driver/can/cbs/rx/can_cbs_rx_imd-response.c

  • src/app/driver/can/cbs/tx-async/can_cbs_tx_crash-dump.c

  • src/app/driver/can/cbs/tx-async/can_cbs_tx_crash-dump.h

  • src/app/driver/can/cbs/tx-async/can_cbs_tx_debug-build-configuration.c

  • src/app/driver/can/cbs/tx-async/can_cbs_tx_debug-build-configuration.h

  • src/app/driver/can/cbs/tx-async/can_cbs_tx_debug-response.c

  • src/app/driver/can/cbs/tx-async/can_cbs_tx_debug-response.h

  • src/app/driver/can/cbs/tx-async/can_cbs_tx_debug-unsupported-multiplexer-values.c

  • src/app/driver/can/cbs/tx-async/can_cbs_tx_debug-unsupported-multiplexer-values.h

  • src/app/driver/can/cbs/tx-async/can_cbs_tx_imd-request.c

  • src/app/driver/can/cbs/tx-async/can_cbs_tx_imd-request.h

  • src/app/driver/can/cbs/tx-async/can_cbs_tx_imd-request.c

  • src/app/driver/can/cbs/tx-cyclic/can_cbs_tx_bms-state-details.c

  • src/app/driver/can/cbs/tx-cyclic/can_cbs_tx_bms-state.c

  • src/app/driver/can/cbs/tx-cyclic/can_cbs_tx_cell-temperatures.c

  • src/app/driver/can/cbs/tx-cyclic/can_cbs_tx_cell-voltages.c

  • src/app/driver/can/cbs/tx-cyclic/can_cbs_tx_cyclic.h

  • src/app/driver/can/cbs/tx-cyclic/can_cbs_tx_pack-limits.c

  • src/app/driver/can/cbs/tx-cyclic/can_cbs_tx_pack-minimum-maximum-values.c

  • src/app/driver/can/cbs/tx-cyclic/can_cbs_tx_pack-state-estimation.c

  • src/app/driver/can/cbs/tx-cyclic/can_cbs_tx_pack-values-p0.c

  • src/app/driver/can/cbs/tx-cyclic/can_cbs_tx_pack-values-p1.c

  • src/app/driver/can/cbs/tx-cyclic/can_cbs_tx_string-minimum-maximum-values.c

  • src/app/driver/can/cbs/tx-cyclic/can_cbs_tx_string-state-estimation.c

  • src/app/driver/can/cbs/tx-cyclic/can_cbs_tx_string-state.c

  • src/app/driver/can/cbs/tx-cyclic/can_cbs_tx_string-values-p0.c

  • src/app/driver/can/cbs/tx-cyclic/can_cbs_tx_string-values-p1.c

  • src/app/driver/config/can_cfg.c

  • src/app/driver/config/can_cfg.h

  • src/app/driver/config/can_cfg_rx-message-definitions.h

  • src/app/driver/config/can_cfg_rx.c

  • src/app/driver/config/can_cfg_tx-async-message-definitions.h

  • src/app/driver/config/can_cfg_tx-cyclic-message-definitions.h

  • src/app/driver/config/can_cfg_tx_cyclic.c

4.15.1.3. Unit Test

  • tests/unit/app/driver/can/cbs/rx/test_can_cbs_rx_aerosol-sensor.c

  • tests/unit/app/driver/can/cbs/rx/test_can_cbs_rx_bms-state-request.c

  • tests/unit/app/driver/can/cbs/rx/test_can_cbs_rx_current-sensor.c

  • tests/unit/app/driver/can/cbs/rx/test_can_cbs_rx_debug.c

  • tests/unit/app/driver/can/cbs/rx/test_can_cbs_rx_imd-info.c

  • tests/unit/app/driver/can/cbs/rx/test_can_cbs_rx_imd-response.c

  • tests/unit/app/driver/can/cbs/tx-async/test_can_cbs_tx_crash-dump.c

  • tests/unit/app/driver/can/cbs/tx-async/test_can_cbs_tx_debug-build-configuration.c

  • tests/unit/app/driver/can/cbs/tx-async/test_can_cbs_tx_debug-response.c

  • tests/unit/app/driver/can/cbs/tx-async/test_can_cbs_tx_debug-unsupported-multiplexer-values.c

  • tests/unit/app/driver/can/cbs/tx-async/test_can_cbs_tx_imd-request.c

  • tests/unit/app/driver/can/cbs/test_can_helper.c

  • tests/unit/app/driver/can/cbs/test_can_helper.h

  • tests/unit/app/driver/can/cbs/tx-cyclic/test_can_cbs_tx_bms-state-details.c

  • tests/unit/app/driver/can/cbs/tx-cyclic/test_can_cbs_tx_bms-state.c

  • tests/unit/app/driver/can/cbs/tx-cyclic/test_can_cbs_tx_cell-temperatures.c

  • tests/unit/app/driver/can/cbs/tx-cyclic/test_can_cbs_tx_cell-voltages.c

  • tests/unit/app/driver/can/cbs/tx-cyclic/test_can_cbs_tx_pack-limits.c

  • tests/unit/app/driver/can/cbs/tx-cyclic/test_can_cbs_tx_pack-minimum-maximum-values.c

  • tests/unit/app/driver/can/cbs/tx-cyclic/test_can_cbs_tx_pack-state-estimation.c

  • tests/unit/app/driver/can/cbs/tx-cyclic/test_can_cbs_tx_pack-values-p0.c

  • tests/unit/app/driver/can/cbs/tx-cyclic/test_can_cbs_tx_pack-values-p1.c

  • tests/unit/app/driver/can/cbs/tx-cyclic/test_can_cbs_tx_string-minimum-maximum-values.c

  • tests/unit/app/driver/can/cbs/tx-cyclic/test_can_cbs_tx_string-state-estimation.c

  • tests/unit/app/driver/can/cbs/tx-cyclic/test_can_cbs_tx_string-state.c

  • tests/unit/app/driver/can/cbs/tx-cyclic/test_can_cbs_tx_string-values-p0.c

  • tests/unit/app/driver/can/cbs/tx-cyclic/test_can_cbs_tx_string-values-p1.c

  • tests/unit/app/driver/can/test_can.c

  • tests/unit/app/driver/can/test_can_1.c

  • tests/unit/app/driver/can/test_can_2.c

  • tests/unit/app/driver/config/test_can_cfg.c

  • tests/unit/app/driver/config/test_can_cfg_rx.c

  • tests/unit/app/driver/config/test_can_cfg_tx_cyclic.c

  • tests/unit/app/engine/diag/cbs/test_diag_cbs_can.c

  • tests/unit/support/test_can_mpu_prototype_queue_create_stub.h

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. Fox example, if data is 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.

If all mailboxes on the CAN are full when the message is sent, it cannot be transmitted. In this case, it will be stored in the queue ftsk_canTxUnsentMessagesQueue. With the next call of the function CAN_PeriodicTransmit(), the unsent messages will be pulled from this queue and resent with the function CAN_DataSend().

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.

Listing 4.6 Queue handle for CAN receive
1OS_QUEUE ftsk_canRxQueue = NULL_PTR;
Listing 4.7 Supporting variables for the queue of the CAN receive module
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.

Unfortunately, using HALCoGen, only the complete CAN interface and not the individual message boxes can be configured if standard or extended identifiers shall be used.

For this reason, four receive mailboxes (mailboxes 61-64) are hard-coded during the initialization and overwrite the respective HALCoGen configuration for these mailboxes. The mailboxes are configured to receive all CAN messages with an extended 29-bit identifier. This configuration is done in function CAN_ConfigureRxMailboxesForExtendedIdentifiers()

4.15.2.4. Configuration errors in HALCoGen

4.15.3. Using the CAN1 mailbox 42

Additionally, there is a bug in HALCoGen regarding the CAN1 mailbox 42 as described in HALCoGen tool documentation. The missing configuration for this mailbox is also done in function CAN_ConfigureRxMailboxesForExtendedIdentifiers(). Mailbox 42 is configured to receive all CAN messages with a standard 11-bit identifier.

4.15.4. Using the CAN4 interface

If the CAN Module should be extended to the CAN4 interface, a workaround for a bug in HALCoGen has to be applied. For details, please refer to HALCoGen tool documentation.

4.15.4.1. 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.