SLAAEJ3 January 2024 MSPM0G3507
This subsystem demonstrates how to build a CAN-SPI bridge. CAN-SPI bridge allows a device to send or receive information on one interface and receive or send the information on the other interface Download the code for this example. The subsystem supports SPI to work in controller mode or peripheral mode.
Figure 1-1 shows a functional diagram of this subsystem.
This application requires CANFD and SPI.
Sub-block Functionality | Peripheral Use | Notes |
---|---|---|
CAN interface | (1x) CANFD | Called MCAN0_INST in code |
SPI interface | (1x) SPI | Called SPI_0_INST in code |
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.
Compatible Devices | EVM |
---|---|
MSPM0G35xx | LP-MSPM0G3507 |
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;
Header | Address | Data Length | Data |
---|---|---|---|
0x55 0xAA | 4 bytes | 1 byte | (Data Length) bytes |
The following figure shows the code flow diagram for CAN-SPI bridge which explains how the messages received in one interface and sent in the other interface. The CAN-SPI bridge can be divided into four independent tasks: receive from SPI, receive from CAN, transmit through CAN, transmit through SPI. Two FIFOs implement bidirectional message transfer and message caching.
Note that SPI is a communication method that sends and receives at the same time. When the controller initiates sending a byte, the controller expects to receive a byte. In the design of this article, SPI RX interrupt is not only used for SPI receive, but also used to fill the TX data into SPI TX FIFO. If SPI works in controller mode, SPI communication starts immediately after SPI TX FIFO is stored by data. If SPI works in peripheral mode, SPI can wait for the controller to initiate communication after data is stored. In this demo, users can select the mode of SPI.
This application makes use of TI System Configuration Tool (SysConfig) graphical interface to generate the configuration code for the CAN and SPI. Using a graphical interface to configure the device peripherals streamlines the application prototyping process.
The user can configure the SPI to be controller or peripheral in the Sysconfig.
The code for what is described in Figure 1-3 can be found in the files from example code as shown in Figure 1-4.
The following code snippet shows where to modify the interface function. Functions in table are categorized into different files. Functions for SPI receive and transmit are included in bridge_spi.c and bridge_spi.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 SPI functions are needed, users can reserve bridge_spi.c and bridge_spi.h to call the functions.
See the MSPM0 SDK and DriverLib documentation for the basic configuration of peripherals.
Tasks | Functions | Description | Location |
---|---|---|---|
SPI receive | getSpiRxMsg() | Get the received SPI message | bridge_spi.c bridge_spi.h |
processSpiRxMsg() | Convert the received SPI message format and store it into gSPI_RX_Element | ||
SPI transmit | processSpiTxMsg() | Convert the gSPI_TX_Element format to be sent through SPI | |
sendSpiTxMsg() | Send message through SPI | ||
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 SPI/CAN transmit and input element of SPI/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 S2C_FIFO[S2C_FIFO_SIZE];
Custom_Element C2S_FIFO[C2S_FIFO_SIZE];
uint16_t S2C_in = 0;
uint16_t S2C_out = 0;
uint16_t S2C_count = 0;
uint16_t C2S_in = 0;
uint16_t C2S_out = 0;
uint16_t C2S_count = 0;
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-SPI bridges(one SPI controller and one SPI peripheral) to form a loop. When the CAN analyzer sends CAN messages through controller launchpad, it will receive CAN messages from the peripheral launchpad.