8.1.1. How to Use the CAN Module

8.1.1.1. How to add a new CAN Message

  1. Add the new CAN message to the symbol file (tools/dbc/foxbms.sym).

    1. If the message is foxBMS 2 specific prefix it with foxBMS.

    2. Set the DLC

    3. Add a comment that follows the pattern

      Message direction

      Comment

      transmit

      optional comment text (in<file>:<function>, fv:tx) optional comment text

      receive

      optional comment text (in<file>:<function>, fv:rx) optional comment text

      The message direction is specified as seen from the BMS view.

  2. Export the symbol file as dbc file to tools/dbc/foxbms.dbc.

  3. Declare the callback function for the message in the appropriate file:

    Message type

    File

    cyclic transmit callbacks

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

    asynchronous transmit callbacks

    src/app/driver/can/cbs/tx-async/can_cbs_tx_<my-file-name>.h

    receive callbacks

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

    Note 1: every asynchronous transmit callback is implemented in an separate file, that only consists of this one, specific callback.

    Note 2: the name callback is kept for the asynchronous transmit callbacks for consistency reasons although they are not callbacks in the classical meaning of the word.

    Note 3: Only the transmitted messages are separated in cyclic and asynchronous callbacks, therefore there is only one file for receive callbacks. This file includes the callbacks for the cyclic and asynchronously received messages. The same reason applies for splitting things between asynchronous transmit, cyclic transmit and receive is consistently through the document and code.

  4. Implement a callback in a new file and the accompanying test file/files in the appropriate directories at:

    Message type

    New file

    cyclic transmit callbacks

    src/app/driver/can/cbs/tx-cyclic/* and tests/unit/app/driver/can/cbs/tx-cyclic/*

    asynchronous transmit callbacks

    src/app/driver/can/cbs/tx-async/* and tests/unit/app/driver/can/cbs/tx-async/*

    receive callbacks

    src/app/driver/can/cbs/rx/* and tests/unit/app/driver/can/cbs/rx/*

  5. Add the message ID and message details

    Message type

    Declaration file

    cyclic transmit callbacks

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

    asynchronous transmit callbacks

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

    receive callbacks

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

  6. Add the message to the respective callback array:

Message type

cyclic transmit callbacks

array can_txMessages in the file src/app/driver/config/can_cfg_tx_cyclic.c

asynchronous transmit callbacks

The callbacks for asynchronous transmit messages are not stored in some array. These callbacks are only called asynchronously in some specific code paths and so there is no central “processing” function for these callbacks.

receive callbacks

array can_rxMessages in the file src/app/driver/config/can_cfg_rx.c

  1. Verify that the CAN message is defined and implemented as expected:

    .\fox.ps1 run-script tests\can\check_ids.py
    .\fox.ps1 run-script tests\can\check_implemented.py
    

Warning

These script do no syntactical or similar checks of the implementation. These scripts do text based comparisons in order to help to get a consistent style for the CAN message implementations. The correct implementation etc. must be checked by compiling and ** **debugging.

8.1.1.1.1. Example for a Cyclic Transmit Message

8.1.1.1.1.1. Creating the Cyclic Transmit Message

In this example a message to transmit the system status is implemented. The name of the message is therefore BmsState (following PascalCase naming convention). In the symbol file the message is implemented as f_BmsState (prefix f followed by the message name) and the message ID 0x220. As the message is transmitted (tx) from the point of view of the BMS, the comment in the symbol file must be Message containing the foxBMS system state (in:can_cbs_tx_bms-state.c:CANTX_BmsState, fv:tx). The changed symbol file must be saved and - as changes are applied - the dbc file must be exported again.

8.1.1.1.1.2. Required Macros

The name of the macros to be implemented in src/app/driver/config/can_cfg_tx-cyclic-message-definitions.h need to be prefixed with CANTX (as CANTX is the module prefix) and the message name in uppercase (BMS_STATE), i.e., all macro names start with CANTX_BMS_STATE. The message’s

  • ID with suffix _ID,

  • ID type with suffix _ID_TYPE,

  • period with suffix _PERIOD_ms,

  • phase with suffix _PHASE_ms,

  • endianness with suffix _ENDIANNESS and

  • DLC with suffix _DLC

need to be defined through macros:

Listing 8.1 Adding the new message ID to the cyclic transmit message definition file src/app/driver/config/can_cfg_tx-cyclic-message-definitions.h
 1/** CAN message properties for BMS state message. Required properties are:
 2 * - Message ID
 3 * - Identifier type (standard or extended)
 4 * - Message period and phase in ms
 5 * - Endianness of message data
 6 * - data length of the message @{*/
 7#define CANTX_BMS_STATE_ID         (0x220u)
 8#define CANTX_BMS_STATE_ID_TYPE    (CAN_STANDARD_IDENTIFIER_11_BIT)
 9#define CANTX_BMS_STATE_PERIOD_ms  (100u)
10#define CANTX_BMS_STATE_PHASE_ms   (0u)
11#define CANTX_BMS_STATE_ENDIANNESS (CAN_BIG_ENDIAN)
12#define CANTX_BMS_STATE_DLC        (CAN_DEFAULT_DLC)
13/**@}*/

Now the details of the ID need to be added in an additional macro, that is then used for the initialization of the transmitted messages macro. The macro must be named Module prefix (CANTX) followed by the message name (BMS_STATE) and suffixed with MESSAGE.

Listing 8.2 Adding the details of the new message ID to the cyclic transmit message definition file src/app/driver/config/can_cfg_tx-cyclic-message-definitions.h
 1#define CANTX_BMS_STATE_MESSAGE                                                \
 2    {                                                                          \
 3        .id         = CANTX_BMS_STATE_ID,                                      \
 4        .idType     = CANTX_BMS_STATE_ID_TYPE,                                 \
 5        .dlc        = CANTX_BMS_STATE_DLC,                                     \
 6        .endianness = CANTX_BMS_STATE_ENDIANNESS,                              \
 7    },                                                                         \
 8    {                                                                          \
 9        .period = CANTX_BMS_STATE_PERIOD_ms, .phase = CANTX_BMS_STATE_PHASE_ms \
10    }

8.1.1.1.1.3. Callback Function

The callback declaration must be added to the file src/app/driver/can/cbs/tx/can_cbs_tx_cyclic.h.

Listing 8.3 Declaration of the callback function in src/app/driver/can/cbs/tx/can_cbs_tx_cyclic.h
1extern uint32_t CANTX_BmsState(
2    CAN_MESSAGE_PROPERTIES_s message,
3    uint8_t *pCanData,
4    uint8_t *pMuxId,
5    const CAN_SHIM_s *const kpkCanShim);

The callback definition must be done in the appropriate implementation file, i.e., for the BMS state message in src/app/driver/can/cbs/tx/can_cbs_tx_bms-state.c.

Listing 8.4 Definition of the callback function in src/app/driver/can/cbs/tx/can_cbs_tx_bms-state.c
1extern uint32_t CANTX_BmsState(
2    CAN_MESSAGE_PROPERTIES_s message,
3    uint8_t *pCanData,
4    uint8_t *pMuxId,
5    const CAN_SHIM_s *const kpkCanShim) {
6    /* Do message handling stuff */
7    return 0;
8}

8.1.1.1.1.4. Required Variables Adaptations

The message needs to be added the transmitted messages array as follows:

Listing 8.5 Adding the new message to the registry of transmitted messages src/app/driver/config/can_cfg_tx_cyclic.c
1const CAN_TX_MESSAGE_TYPE_s can_txMessages[] = {
2    /* other messages */
3    {CAN_NODE_1, CANTX_BMS_STATE_MESSAGE, &CANTX_BmsState, NULL_PTR}, /*!< BMS state */
4};

8.1.1.1.1.5. Verification

Run the check scripts to verify that the messages are implemented as described in this how-to.

.\fox.ps1 run-script tests\can\check_ids.py
.\fox.ps1 run-script tests\can\check_implemented.py

8.1.1.1.2. Example for an Asynchronous Transmit Message

8.1.1.1.2.1. Creating the Asynchronous Transmit Message

In this example a message to asynchronously transmit some debug information on request is implemented. The name of the message is therefore DebugResponse (following PascalCase naming convention). In the symbol file the message is implemented as foxBMS_DebugResponse (prefix foxBMS followed by the message name) and the message ID 0x227. As the message is transmitted (tx) from the point of view of the BMS, the comment in the symbol file must be Message containing some debug information (in:can_cbs_tx_debug-response.c:CANTX_DebugResponse, fv:tx). The changed symbol file must be saved and - as changes are applied - the dbc file must be exported again.

8.1.1.1.2.2. Required Macros

The name of the macros to be implemented in src/app/driver/config/can_cfg_tx-async-message-definitions.h need to be prefixed with CANTX (as CANTX is the module prefix) and the message name in uppercase (DEBUG_RESPONSE), i.e., all macro names start with CANTX_DEBUG_RESPONSE. The message’s

  • ID with suffix _ID,

  • ID type with suffix _ID_TYPE,

  • endianness with suffix _ENDIANNESS and

  • DLC with suffix _DLC

need to be defined through macros:

Listing 8.6 Adding the new message ID to the cyclic transmit message definition file src/app/driver/config/can_cfg_tx-async-message-definitions.h
 1/** CAN message properties for BMS state message. Required properties are:
 2 * - Message ID
 3 * - Identifier type (standard or extended)
 4 * - Endianness of message data
 5 * - data length of the message @{*/
 6#define CANTX_DEBUG_RESPONSE_ID         (0x301u)
 7#define CANTX_DEBUG_RESPONSE_ID_TYPE    (CAN_STANDARD_IDENTIFIER_11_BIT)
 8#define CANTX_DEBUG_RESPONSE_ENDIANNESS (CAN_BIG_ENDIAN)
 9#define CANTX_DEBUG_RESPONSE_DLC        (CAN_DEFAULT_DLC)
10/**@}*/

8.1.1.1.2.3. Callback Function

The callback declaration must be done in file src/app/driver/can/cbs/tx-async/can_cbs_tx_debug-response.h.

Listing 8.7 Declaration of the callback function in src/app/driver/can/cbs/tx-async/can_cbs_tx_debug-response.h
1extern STD_RETURN_TYPE_e CANTX_DebugResponse(CANTX_DEBUG_RESPONSE_ACTIONS_e action);

The callback definition must be done in the appropriate implementation file, i.e., for the BMS state message in src/app/driver/can/cbs/tx-async/can_cbs_tx_debug-response.c.

Listing 8.8 Definition of the callback function in src/app/driver/can/cbs/tx-async/can_cbs_tx_debug-response.c
1extern STD_RETURN_TYPE_e CANTX_DebugResponse(CANTX_DEBUG_RESPONSE_ACTIONS_e action) {
2    STD_RETURN_TYPE_e success = STD_NOT_OK;
3    /* Do message handling stuff */
4    return success;
5}

As last step, the function CANTX_DebugResponse needs to be called in the appropriate code path of the user code. This cannot be covered by the how to as this is too user specific. See already implemented asynchronous transmitted messages as starting point.

8.1.1.1.2.4. Verification

Run the check scripts to verify that the messages are implemented as described in this how-to.

.\fox.ps1 run-script tests\can\check_ids.py
.\fox.ps1 run-script tests\can\check_implemented.py

8.1.1.1.3. Example for a Receive Message

The implementation of a receive message is done analogous for cyclic transmit functions, by replacing tx with rx in paths, prefixes, function names etc.

8.1.1.2. Multi-string Support when using Isabellenhuette IVT Current Sensors

In Multi-string systems multiple current sensors must be used in order to measure the current in each string. In case CAN-based Isabellenhuette IVT current sensors are used, the CAN message IDs indicate which current sensor is in which string.

Note

This of course means, that the current sensors must be correctly configured, i.e., that all current sensors in the system use unique CAN messages IDs. Furthermore, the current sensors must be placed in the correct string (accordingly to their CAN message IDs), as otherwise the current measurements would be assigned to the wrong strings.

The string-selection code in the function CANRX_CurrentSensor right at the beginning of the function must be adapted as shown in Listing 8.9.

Listing 8.9 String selection for the current sensor measurement in multi-string systems based on the CAN message ID
1 if (message.id <= CANRX_STRING0_ENERGY_COUNTER_ID) {
2     stringNumber = 0u;
3 } else if (message.id <= CANRX_STRING1_ENERGY_COUNTER_ID) {
4     stringNumber = 1u;
5 } else {
6     FAS_ASSERT(FAS_TRAP);
7 }

8.1.1.3. Further Reading

Implementation details of the CAN module are found in CAN.