Evaluation of CAN-FD on Multi-core Heterogeneous Architecture

What is CAN-FD?

With the advantages of real-time, anti-interference, and safety, CAN2.0 has been widely used in the industrial and automotive industries. However, its maximum rate is only 1 Mbit/s. , and each frame can only transmit 8 bytes of valid data at most. In addition, only about 50% of the bandwidth in the message is for valid data transmission. And with the industry development, the surge in the number of various sensors, controllers, and data amount on the bus makes the shortcomings of CAN2.0 bus in transmission rate and bandwidth expose more, and thus CAN-FD emerges.

CAN-FD has a significant increase in transmission rate and bandwidth.-- the baud rate is up to 8 Mbit/s, the valid data per frame is up to 64 bytes, and the transmission efficiency can increase by approximately 80%, which can further improve the bus real-time performance and transmission efficiency, and broaden the data bandwidth of the bus.

On the Forlinx OKMX8MP-C EVK, there are 2-lane CAN-FD, controlled by M-core and A-core respectively, perform mutual communication. In this article, we will take this as an example to explain the high-speed communication of CAN-FD on a multi-core heterogeneous architecture (M-core plus A-core).

Forlinx OKMX8MP-C EVK

NXP i.MX8M Plus, equipped on Forlinx Embedded OKMX8MP-C EVK, achieves high performance and features implementation of 4x Arm Cortex-A53( multi-core), operating at speed up to 1.8GHz (Industrial clock is 1.6GHz) plus 1xCortex-M7(real-time processing), which enables it to handle high-speed data throughput and a complex human-machine interface with ease.

01 M-core CAN-FD

1. CAN-FD initialization

It includes: CAN bus clock, pin and register. Details are as follows:

(1) CAN bus clock:

Set the CAN bus frequency multiplier to 800MHz and frequency division to 80MHz.

CLOCK_SetRootMux(kCLOCK_RootFlexCan1, kCLOCK_FlexCanRootmuxSysPll1); // Set CAN1 bus clock to 800MHz.
CLOCK_SetRootDivider(kCLOCK_RootFlexCan1, 2U, 5U); // The frequency division factor is 2*5=10, set CAN1 bus clock to 80MHz.

(2) Pin configuration:

Select CAN1 transmit pin as 32 and receive pin as 34.

IOMUXC_SetPinMux(IOMUXC_SAI2_TXC_CAN1_RX, 0U); // CAN1 RX  
IOMUXC_SetPinMux(IOMUXC_SAI2_RXC_CAN1_TX, 0U); // CAN1 TX	

(3) CAN baud rate:

The CAN-FD supports variable rates, i.e. the baud rate of the control area and the data area can be inconsistent, the control area up to 1 Mbit/s and the data area up to 8 Mbit/s. The subsequent program assigns the values of seg1, seg2, etc. set by the time interval according to the bus clock and the set baud rate.

pConfig->bitRate = 1000000U; // CAN-FD control area baud rate is 1Mbit/s
pConfig->bitRateFD = 8000000U; // CAN-FD data area baud rate is 8Mbit/s

(4) CAN-FD enable:

In addition to enabling CAN-FD, we may also need to enable the variable baud rate, otherwise the maximum rate of the data area is the same as that of the control area, up to 1Mbit/s.

base->MCR |= CAN_MCR_FDEN_MASK; // CAN-FD enabl
fdctrl |= CAN_FDCTRL_FDRATE_MASK; // variable baud rate enable

(5) Closing the Alb(Automatic Loop Back):

If the Alb is on, then the CAN1 data will loop back inside the chip and will not go to the external pins, which can eliminate the interference of the external terminals during program debugging, but in actual applications, it is necessary to turn off the Alb, and send and receive data from the external pins.

pConfig->enableLoopBack = false; // no loopback, use external pins

(6) Frame format:

This time, we use an 11-bit standard data frame and can also try an extended frame later. We need to set our ID for easy identification by other devices on the bus.

mbConfig.format = kFLEXCAN_FrameFormatStandard; // 11-bit standard frame, non-extended frame
mbConfig.type = kFLEXCAN_FrameTypeData; // data frame non-remote frame
mbConfig.id = FLEXCAN_ID_STD(rxIdentifier); // frame ID is used to distinguish different devices on the bus

(7) Receiving filtering:

Users can set receiving filter rules so that only data with a specific frame ID is received, reducing the amount of data processed by the application.

rxIdentifier = 0;FLEXCAN_SetRxMbGlobalMask(EXAMPLE_CAN, 
FLEXCAN_RX_MB_STD_MASK(rxIdentifier, 0, 0));//Receiving all ID data.

CAN-FD receiving and sending process

In this test, M-core plays the master role:

  • ①CAN1 first sends a frame containing 64 bytes data(received by A-core CAN2);
  • ②CAN2 sends back this 64 bytes data(received by M-core CAN1);
  • ③Check the receiving and sending 64 bytes data consistency.

Note: This process will repeat 100 times.

(1) CAN-FD sending data:

EXAMPLE_CAN represents CAN1, flexcanHandle is the CAN instance including the sending and receiving callback function, and txXfer is the 64-byte data to be sent.

FLEXCAN_TransferFDSendNonBlocking(EXAMPLE_CAN, &flexcanHandle, &txXfer); // CAN-FD sending data.

(2) CAN-FD receiving data:

EXAMPLE_CAN represents CAN1, flexcanHandle is the CAN instance including the sending and receiving callback function, and txXfer is the 64-byte data to be received.

FLEXCAN_TransferFDReceiveNonBlocking(EXAMPLE_CAN, &flexcanHandle, &rxXfer); // CAN-FD receiving data

(3) Receiving and sending data comparison:

for (j = 0U; j <= DLC; j++) // Compare the sending and receiving data, inconsistent printing { if(txXfer.framefd->dataWord[j] != rxXfer.framefd->dataWord[j])  
    {  
        LOG_INFO("Data mismatch !!! j=%d \r\n",j);  
    }  
}

02 A-core CAN-FD

CAN2 is reserved in the A-core device tree, and the kernel parses the device tree to generate can0 under /dev. After setting the baud rate and enabling the can0 node, the open function in the application opens the interface, the write function sends data, and the read function receives data. We have used the CAN interface example as a comprehensive cross-platform demo program that can be called directly by the user with parameters.

1. Assigning nodes

(1) CAN1 is dedicated to M-core and CAN2 is dedicated to A-core.Delete the CAN1 device node and keep the CAN2 device node in OK8MP-C.dts to modify the device tree then compile a new device tree.

(2) Copy the generated OK8MP-C.dtb and Image to the directory of EVK: /run/media/mmcblk2p1/, enter the sync command to synchronize and restart the EVK;

(3) Enter the command uname -r through the A-core serial port to display the kernel version, and change the folder name under the directory: /lib/modbule to the kernel version, so that the module can be automatically loaded to generate the can0 node, and restart the EVK.

Assigning nodes

CAN1 CAN2 device node

2. Demo

Process name: can_demo

Using method: ./can_demo device name [parameter option]... ...

Parameter Options device [-b baudrate] [-id id_numb] [-filt id mask] [-e] [-fd dbaudrate] [-t data time] [-l] [-L] [-v]
Parameter Name Description
device Device name e.g.CAN0
[-b baudrate] Baud rate setting Setting range:5k to 8M;
Unit: kpbs.;
e.g.: if the baud rate is 250k, it can be written as -b 250.
[-id id_numb] CAN ID Set CAN ID for the device
[-filt id mask] ID filter setting Set ID and mask for the filter
[-e] Extended frame Extended frame(with -e), Standard frame(without-e)
[-fd dbaudrate] Data baud rate It’s valid only in the CAN-FD mode. The data byte baud rate is different from the frame baud rate and needs to be set independently. It is recommended that the data byte baud rate is 1~8 times the frame baud rate.
[-t data time] Actively sending data Set a period and send data cyclically (data format:string)
[-l] can loopback Check if enable loopback; no hardware pins are involved in this loopback.
[-L] Application data loopback The CAN interface has two pins for data sending and receiving respectively involving hardware pins.
[-v] Version Displayed version no..


Test interface is can0 (corresponding to the EVK CAN2);
Baud rate of the control area is 1Mbit/s;
Data area is up to 8Mbit/s;
11-bit standard frame doesn’t filter frame ID, send data actively and perform loopback. So the command is:

./can_demo can0-b 1000 -fd 8000.

03 Program verification

1. Hardware connection

Short circuit CAN1 and can-H of CAN2 with Jumper wire, also short circuit can-L. Be careful not to reverse the connection.

CAN1 and CAN2

2. M-core program

Set M-core self-start by modifying the uboot environment variable, and place the M-core program(forlinx_m7_tcm_firmware.bin) under the directory: /run/media/mmcblk2p1.For more details, please refer to the previous article "NXP iMX8MP - Start, Programming and Simulation of M-core for Multi-core Heterogeneous Processor".

3. A-core program

(1) Copy can_demo from the computer to the default directory of the SoM using serial port Xmodem, network FTP, SCP, U disk, TF card, etc. Input the following command to modify the permissions;

chmod 777 can_demo

(2) Input the following command, the A-core application can_demo will open the can0 node after setting the baud rate, wait for the data sent by the M-core, and then send the received data to the M-core via CAN2.

 ./can_demo can0 -b 1000 -fd 8000

4. Actual test

(1) After re-powering up the OKMX8MP-C EVK, the M-core program starts, completes the CAN1 initialization and debugs the serial output information to wait for pressing the key;

(2) Input the following command in the A-core debugging serial port and CAN2 will be in the receiving state:

./can_demo can0 -b 1000 -fd 8000

(3) First, press key A or a on the M-core serial port, then M-core CAN1 sends 64 bytes of data while A-core CAN2 receives the data and sends the received data again, and finally, M-core CAN1 receives and compares with the sent data and outputs the result, which cycles 100 times.

(4) The test shows that: owing to the i.MX8M Plus’ impressive performance, the cores can send massive data at a high rate up to 8Mbit/s without anomalies

i.MX8M Plus massive data