SLAAEJ4 January   2024 MSPM0G3507

 

  1.   1
  2.   2

Design Description

This subsystem demonstrates how to build a CAN-I2C bridge. CAN-I2C bridge allows a device to send/receive information on one interface and receive/send the information on the other interface Download the code for this example.Two example codes are provided to support I2C to work in controller mode or target mode respectively.

Figure 1-1 shows a functional diagram of this subsystem. Please note that one line is added for IO interrupt to implement message transmission from I2C target to I2C controller.

GUID-C01FCEF4-8B6E-4687-9F49-DFC63F9668C0-low.svg Figure 1-1 Subsystem Functional Block Diagram

Required Peripherals

This application requires CANFD and I2C.

Table 1-1 Required Peripherals
Sub-block Functionality Peripheral Use Notes
CAN interface (1x) CANFD Called MCAN0_INST in code
I2C interface (1x) I2C Called I2C_INST in code

Compatible Devices

Based on the requirements in Table 1-1, this example is compatible with the devices in Table 1-2. The corresponding EVM can be used for prototyping.

Table 1-2 Compatible Devices
Compatible Devices EVM
MSPM0G35xx LP-MSPM0G3507

Design Steps

  1. Determine the basic setting of CAN interface, including CAN mode, bit timing, message RAM configuation and so on. Consider which setting is fixed and which setting is changed in the application. In example code, CANFD is used with 250kbit/s arbitration rate and 2Mbit/s data rate.
    1. Key features of the CAN-FD peripheral include:
      1. Dedicated 1KB message SRAM with ECC
      2. Configurable transmit FIFO, transmit queue and event FIFO (up to 32 elements)
      3. Up to 32 dedicated transmit buffers and 64 dedicated receive buffers. Two configurable receive FIFOs (up to 64 elements each)
      4. Up to 128 filter elements
    2. If CANFD mode is enabled:
      1. Full support for 64-byte CAN-FD frames
      2. Up to 8Mbit/s bit rate
    3. If CANFD mode is disabled:
      1. Full support for 8-byte classical CAN frames
      2. Up to 1Mbit/s bit rate
  2. Determine the CAN frame, including data length, bit rate switching, identifier, data and so on. Consider which part is fixed and which part need to be changed in the application. In example code, identifier, data length and data can change in different frames, while others are fixed. Note that users need to modify the code if protocol communication is required.
    /**
     *  @brief  Structure for MCAN Rx Buffer element.
     */
    typedef struct {
        /*! Identifier */
        uint32_t id;
        /*! Remote Transmission Request
         *   0 = Received frame is a data frame
         *   1 = Received frame is a remote frame
         */
        uint32_t rtr;
        /*! Extended Identifier
         *   0 = 11-bit standard identifier
         *   1 = 29-bit extended identifier
         */
        uint32_t xtd;
        /*! Error State Indicator
         *   0 = Transmitting node is error active
         *   1 = Transmitting node is error passive
         */
        uint32_t esi;
        /*! Rx Timestamp */
        uint32_t rxts;
        /*! Data Length Code
         *   0-8  = CAN + CAN FD: received frame has 0-8 data bytes
         *   9-15 = CAN: received frame has 8 data bytes
         *   9-15 = CAN FD: received frame has 12/16/20/24/32/48/64 data bytes
         */
        uint32_t dlc;
        /*! Bit Rat Switching
         *   0 = Frame received without bit rate switching
         *   1 = Frame received with bit rate switching
         */
        uint32_t brs;
        /*! FD Format
         *   0 = Standard frame format
         *   1 = CAN FD frame format (new DLC-coding and CRC)
         */
        uint32_t fdf;
        /*! Filter Index */
        uint32_t fidx;
        /*! Accepted Non-matching Frame
         *   0 = Received frame matching filter index FIDX
         *   1 = Received frame did not match any Rx filter element
         */
        uint32_t anmf;
        /*! Data bytes.
         *   Only first dlc number of bytes are valid.
         */
        uint16_t data[DL_MCAN_MAX_PAYLOAD_BYTES];
    } DL_MCAN_RxBufElement;
  3. Determine the basic setting of I2C interface, including I2C mode, bus speed, target address, FIFO and so on. Consider which setting is fixed and which setting is changed in the application. One example code is used for I2C controller with 400kHz bus speed, the other one is used for I2C target with address 0x48.
    1. Key features of the I2C peripheral include:
      1. Configurable as a controller or a target with a bit rate up to 1Mbps
      2. Independent 8-byte FIFOs for reception and transmission
      3. Dual target address capability, glitch suppression
      4. Independent controller and target interrupt generation, and hardware support for DMA
      5. Controller operation with arbitration, clock synchronization, multiple controller support
  4. Determine the I2C message format. Typically I2C is transmitted in bytes. To achieve high-level communication, users can implement frame communication through software. If necessary, users can also introduce specific communication protocols. In example code, the message format is < 55 AA ID1 ID2 ID3 ID4 Length Data1 Data2 ...>. Users can send data through I2C as the same format. 55 AA is the header. ID area is 4 bytes. Length area is 1 byte, indicating the data length. Note that if users need to modify the I2C packet form, the code for frame acquisition and parsing also need to be modified.
    Table 1-3 I2C Packet Form
    Header Address Data Length Data
    0x55 0xAA 4 bytes 1 byte (Data Length) bytes
  5. Determine the bridge structure, including what messages need to be converted, how to convert messages and so on.
    1. Consider whether the bridge is one-way or two-way. Typically each interface has two functions: receiving and sending. Consider whether only some functions need to be included (such as I2C reception and CAN transmission). In example code, CAN-I2C bridge is a two-way structure. Since the receiving and transmitting of the I2C target are controlled by the I2C controller, the I2C target cannot initiate transmission to the I2C controller. To achieve communication from the target to the controller, a line is added to this design. The target's IO pull-down notifies the controller that there is information to be sent.
    2. Consider what information to convert and the corresponding carrier(variable, FIFO). In example code, identifier, data and data length are convert from one interface to the other interface. There are two FIFOs defined in code as shown in Figure 1-2.
      GUID-8961F6B9-8D81-4384-B7AF-676CA8F1F6A7-low.svg Figure 1-2 Bridge Structure
  6. (Optionally) Consider priority design, congestion situation, error handling, and so on.

Design Considerations

  1. Consider the information flow in the application to determine the information to be received or sent by each interface, the protocols to be followed, and design appropriate information transfer carriers to connect different interfaces.
  2. The recommendation is to test the interface separately first, and then implement the overall bridge function. In addition, consider the handling of abnormal situations, such as communication failure, overload, frame format error, and so on.
  3. The recommendation is to implement interface functions through interrupts to make sure of timely communication. In example code, interface functions are usually implemented in the interrupt, and the transfer of information is completed in the main() function.

Software Flowchart

Figure 1-3 shows the code flow diagram for CAN-I2C bridge which explains how the messages received in one interface and sent in the other interface. The CAN-I2C bridge can be divided into four independent tasks: receive from I2C, receive from CAN, transmit through CAN, transmit through I2C. Two FIFOs implement bidirectional message transfer and message caching.

Note that I2C is a communication method that I2C controller control the transmit and receive. In general, I2C target cannot initiate communication. For I2C target-to-controller communication, I2C target can pull down the IO when messages needed to be sent, as shown in Figure 1-3. I2C controller can initiate I2C read command in IO interrupt when IO is detected low, as shown in Figure 1-4. In this demo, I2C can be configured as I2C target or controller.

GUID-1E17CE84-80AE-41C4-AE44-60CE3270FA61-low.svg Figure 1-3 Application Software Flowchart of CAN-I2C (I2C Controller) Bridge
GUID-0C2AE72D-87FE-4601-8514-B7E7717993D2-low.svg Figure 1-4 Application Software Flowchart of CAN-I2C (I2C Target) Bridge

Device Configuration

This application makes use of TI System Configuration Tool (SysConfig) graphical interface to generate the configuration code for the CAN and I2C. Using a graphical interface to configure the device peripherals streamlines the application prototyping process.

The code for what is described in Figure 1-3 can be found in the files from example code as shown in Figure 1-5.

GUID-979B8EDE-21A9-41CA-9514-B80F1A0CBD7B-low.png Figure 1-5 File Structure

Application Code

The following code snippet shows where to modify the interface function. Functions in table are categorized into different files. Functions for I2C receive and transmit are included in bridge_i2c.c and bridge_i2c.h. Functions for CAN receive and transmit are included in bridge_can.c and bridge_can.h. Structure of FIFO element is defined in user_define.h.

Users can easily separate functions by file. For example, if only I2C functions are needed, users can reserve bridge_i2c.c and bridge_i2c.h to call the functions.

See the MSPM0 SDK and DriverLib documentation for the basic configuration of peripherals.

Table 1-4 Functions and Descriptions
Tasks Functions Description Location
I2C receive readI2CRxMsg_controller() Send a read request to slave (I2C master only)

bridge_i2c.c

bridge_i2c.h
getI2CRxMsg_controller() Get the received I2C message (I2C master only)
getI2CRxMsg_target() Get the received I2C message (I2C slave only)
processI2cRxMsg() Convert the received I2C message format and store it into gI2C_RX_Element
I2C transmit processI2cTxMsg() Convert the gI2C_TX_Element format to be sent through I2C
sendI2CTxMsg_controller() Send message through I2C (I2C master only)
sendI2CTxMsg_target() Send message through I2C (I2C slave only)
CAN receive getCANRxMsg() Get the received CAN message

bridge_can.c

bridge_can.h

processCANRxMsg() Convert the received CAN message format and store the message into gCAN_RX_Element
CAN transmit processCANTxMsg() Convert the gCAN_TX_Element format to be sent through CAN
sendCANTxMsg() Send message through CAN

Custom_Element is the structure defined in user_define.h. Custom_Element is used as the structure of FIFO element, output element of I2C/CAN transmit and input element of I2C/CAN receive. Users can modify the structure according to the need.

typedef struct {
    /*! Identifier */
    uint32_t id;
    /*! Data Length Code*/
    uint32_t dlc;
    /*! Data bytes*/
    uint16_t data[64];
} Custom_Element;

For FIFO, there are 2 global variables used as FIFO. 6 global variables are used to trace the FIFO.

Custom_Element ItoC_FIFO[ItoC_FIFO_SIZE];
Custom_Element C2I_FIFO[C2I_FIFO_SIZE];
uint16_t ItoC_in = 0;
uint16_t ItoC_out = 0;
uint16_t ItoC_count = 0;
uint16_t C2I_in = 0;
uint16_t C2I_out = 0;
uint16_t C2I_count = 0;

Results

By using CAN analyzer, users can send and receive messages on the CAN side. As a demonstration, two launchpads can be used as two CAN-I2C bridges (one I2C master and one I2C slave) to form a loop. When the CAN analyzer sends CAN messages through master launchpad, the analyzer can receive CAN messages from the slave launchpad.

GUID-CBA90777-36D6-4911-84A4-8959AC5A61FB-low.png Figure 1-6 Demonstration
GUID-20AB64D7-A5D1-4C63-877E-04CD496A65E5-low.png Figure 1-7 Messages Sent and Received by CAN Analyzer for the Demo
GUID-DDB1DA0F-8C28-4969-9174-56A0EF3F02EB-low.png Figure 1-8 PC Terminal Program of Logic Analyzer

Additional Resources