Install SPI CAN bus module MCP2515 on SP7021 demo board V3

The goal of this document is to illustrate how to install SPI CAN bus module MCP2515 on SP7021 demo board V3.

MCP2515 is an SPI interface CAN bus controller. It supports CAN V2.0B at 1 Mbit/S. It is a standalone CAN bus controller. A CAN transceiver, TJA1050, is used to convert digital signals (i.e., TXCAN and RXCAN) to CAN bus signals and vice versa. Refer to picture of a CAN bus module below:

It consists of MCP2515, TJA1050, 8.000 MHz crystal, power LED, connectors and other passive components. Connector J4 (yellow) is SPI interface. Connector J2 (blue) is CAN bus terminals. Jumper J1 is for 120 Ohm termination. Only one CAN node needs to add 120 Ohm termination.

Please follow the following steps to install the CAN module on SP7021 demo board V3.

 1. Install hardware

Refer to schematics of MCP2515 CAN bus module board, U2 (MCP2515) is CAN controller from Microchip. It needs an 8.000 MHz crystal to operate. Pin 1 and 2 (TXCAN and RXCAN) of U2 are connected to CAN transceiver, NXP TJA1050 (U1). Pin 7 (CANH) and 6 (CANL) of U1 are then connected to J3, a CAN bus connector. J1 is for enabling 120 Ohm termination for CAN bus. Power LED indicates VCC is ready.

SP7021 demo board V3 has a Raspberry Pi compatible 40-pin pin-header. Refer to pin-assignment:

Since the CAN module is SPI interface, setup GPIO_P3_0, GPIO_P3_2, GPIO_P3_4, GPIO_P3_5 to be SPI pins and GPIO_P4_0 to be INT pin. Refer to table below:

Pin # of J4 of MCP2515 module

Pin name of J4 of MCP2515 module

Pin # of 40-pin pin-header of SP7021 demo board V3

Pin name of 40-pin pin-header of SP7021 demo board V3

1

VCC

4

+5V_VDD

2

GND

20

GND

3

CS

22

GPIO_P3_0/G_MX24

4

SO

24

GPIO_P3_2/G_MX26

5

SI

26

GPIO_P3_4/G_MX28

6

SCK

28

GPIO_P3_5/G_MX29

7

INT#

32

GPIO_P4_0/G_MX32

Refer to picture below, a MCP2515 module is connected to SP7021 demo board V3:

Note that a jumper is plugged-in J1 to enable 120 Ohm termination.

2. Modify device-tree source file

Modify node spi_controller0 in device-tree source file linux/kernel/arch/arm/boot/dts/sp7021-demov3.dts to setup channel 0 of SPI master for MCP2515 as shown below:

&spi_controller0 { #address-cells = <1>; #size-cells = <0>; pinctrl-names = "default"; pinctrl-0 = <&pins_spi0>; can@0 { compatible = "microchip,mcp2515"; reg = <0x0>; clocks = <&clk8m>; interrupt-parent = <&intc>; interrupts = <120 IRQ_TYPE_LEVEL_LOW>; spi-max-frequency = <5000000>; status = "okay"; }; };

Note that spi_controller0 is a label of node spi@9c002d80. Refer to specification of MCP2515, maximum operating frequency of SPI is 10 MHz. Property spi-max-frequency is set to 5,000,000 Hz. Also note that property clocks is defined here for getting handle of clock of oscillator of MCP2515. Interrupt number is set to 120 which is for external interrupt 0 (GPIO_INT0).

At root of device-tree source, add a node mcp2515_osc for clock of oscillator of MCP2515 (a fixed clock) as shown below:

/ { : : clocks { clk8m: mcp2515_osc { #clock-cells = <0>; compatible = "fixed-clock"; clock-frequency = <8000000>; }; }; : : };

Also, add a sub-node pinmux_spi0-pins to node pctl to setup pins:

&pctl { : : pins_spi0: pinmux_spi0-pins { sunplus,pins = < SPPCTL_IOPAD(24, SPPCTL_PCTL_G_PMUX, MUXF_SPIM0_EN, 0) SPPCTL_IOPAD(26, SPPCTL_PCTL_G_PMUX, MUXF_SPIM0_DI, 0) SPPCTL_IOPAD(28, SPPCTL_PCTL_G_PMUX, MUXF_SPIM0_DO, 0) SPPCTL_IOPAD(29, SPPCTL_PCTL_G_PMUX, MUXF_SPIM0_CLK, 0) SPPCTL_IOPAD(32, SPPCTL_PCTL_G_PMUX, MUXF_GPIO_INT0, 0) >; }; : };

where G_MX24 is set to SPIM0_EN, G_MX26 is set to SPIM0_DI, G_MX28 is set to SPIM0_DO, G_MX29 is set to SPIM0_CLK, and G_MX32 is set to GPIO_INT0.

Please note that to comply with Linux rules, after version 5.10.59, 4 property-names of pin node of SP7021 are changed as shown in table below:

5.4.35

5.10.59

5.4.35

5.10.59

sppctl,function

function

sppctl,groups

groups

sppctl,pins

sunplus,pins

sppctl,zero_func

sunplus,zerofunc

3. Enable Linux device drivers

Run make kconfig in project top folder. When “Linux/arm Kernel Configuration” menu pops up, move cursor to go to “Device Drivers”. Enable “SPI support”. Refer to screenshot below:

Enter menu “SPI support”. Enable “Sunplus SPI controller”. Refer to screenshot below:

Move cursor to go to “Networking support”, then enter “CAN bus subsystem support”. Enable “Raw CAN Protocol (raw access with CAN-ID filtering)”, “Broadcast Manager CAN Protocol (with content filtering)” and “CAN Gateway/Router (with netlink configuration). Refer to screenshot below:

Then, enter menu “CAN Device Drivers”. Enable “Platform CAN drivers with Netlink support” and “CAN bit-timing calculation”. Refer to screenshot below:

Move cursor down, and enter “CAN SPI interfaces”. Enable “Microchip MCP251x and MCP25625 SPI CAN controllers”. Refer to screenshot below:

Finally, save configuration.

4. Build Linux image

Go to top folder. Run make all to build Linux image.

5. Boot Linux

Boot Linux with the built image. Refer to kernel messages when Linux is booting, line 10 shows “[ 1.035731] mcp251x spi0.0 can0: MCP2515 successfully initialized.”.

Use ifconfig command to check CAN socket interface. Refer to report of ifconfig can0 command:

Network interface can0 was created.

Refer to network interface can0 in sysfs:

6. Socket interface setup and test

6.1 Setup and activate interface can0

Use ip link command to setup can0 device. For example,

Set bit-rate of net interface can0 to 125,000 bps. Other available speeds are 50,000, 250,000 and 500,000 bps.

Use ifconfig or ip command to activate can0 device. For example,

or

6.2 Send a CAN frame and receive it in remote host

Use cansend command to send a CAN frame and use candump command to dump CAN frames in remote host (CAN link partner). For example, issue cansend command as below:

to send out a standard CAN frame with id = 100 and data = 12345678. Refer to snapshot of oscilloscope which was captured while the command is running:

where C1 (yellow) is signal CANH, C2 (red) is signal CANL and C3 (blue) is signal INT#. Z1, Z2 and Z3 are zoom-in of C1, C2 and C3, respectively.

From snapshot of oscilloscope, the raw (stuffed) bit sequence is:

00010000010000010010000011001000110100010101100111100011101110100010110

where bit with red color is stuffing bits.

Unstuffed bit sequence (Stuffing-bits are removed) is:

0 001000000000 000100 00010010001101000101011001111000 1110111010001011 0

where id = 100 (hex), RTR = 0 (send), IDE = 0 (base frame), DLC = 4 (hex), data = 12345678 (hex), CRC = 7745 (hex), ACK = 0 (ack)

Meanwhile, in remote host (CAN link partner), network interface, can0, is activated and candump is run to dump CAN frame as below:

A CAN frame is received. Its id is 100 (hex), data length is 4, received data is 12 34 56 78 (hex).

6.3 Send a remote transmission request CAN frame

Use cansend command to send a remote transmission request CAN frame and use candump command to dump CAN frames in remote host (CAN link partner). For example, issue cansend command as below:

to send out a standard CAN frame with id = 100 (hex). Refer to snapshot of oscilloscope which was captured while the command is running:

where C1 (yellow) is signal CANH, C2 (red) is signal CANL and C3 (blue) is signal INT#. Z1, Z2 and Z3 are zoom-in of C1, C2 and C3, respectively.

From snapshot of oscilloscope, the raw (stuffed) bit sequence is:

0001000001000001000001011100000100101010

where bit with red color is stuffing bits.

Unstuffed bit sequence (Stuffing-bits are removed) is:

0 001000000000 000000 0111000000010101 0

where id = 100 (hex), RTR = 0 (send), IDE = 0 (base frame), DLC = 0, CRC = 380A (hex), ACK = 0 (ack)

Meanwhile, in remote host (CAN link partner), network interface, can0, is activated and candump is run to dump CAN frame as below:

A CAN frame is received. Its id is 100 (hex) and its data length is 0. It’s a remote transmission request frame.

6.4 Send a CAN frame but not acknowledged by any remote host

A CAN frame is sent but no remote host acknowledge it. An error frame is sent just right after ACK slot bit. For example, issue cansend command as below:

to send a standard CAN frame with id = 010 (hex) and data = 10 (hex). Refer to snapshot of oscilloscope which was captured while the cansend command is running:

where C1 (yellow) is signal CANH, C2 (red) is signal CANL and C3 (blue) is signal INT#. Z1, Z2 and Z3 are zoom-in of C1, C2 and C3, respectively.

From snapshot of oscilloscope, the raw (stuffed) bit sequence is:

00000100100000100000110001000001111010111011001100000011111111

Unstuffed bit sequence (Stuffing-bits are removed) is:

0 000000100000 000001 00010000 0111010111011001 1 00000011111111

where id = 10, RTR = 0 (dominate), IDE = 0 (base frame), DLC = 1, data = 10, CRC = 3AEC, ACK = 1 (non-ack), Error-flag = 000000

Since the frame is not acknowledged (ACK = 1). An error frame

00000011111111

is sent just right after the ACK slot bit. Note also that no interrupt asserts.

6.5 De-activate interface can0

Use ifconfig or ip command to de-activate can0 device. For example,

or

6.6 Examples of cansend and candump commands

For your reference, some examples of cansend commands are listed below:

Some examples of candump command are listed below:

7. CAN frame format

7.1 Standard frame format

7.2 Extended frame format

7.3 Error frame format