MCP2518FD CAN module on Jetson Orin Nano 8GB Devkit

I am failry new to this thing and trying to communicate with 2 MCP2518FD CAN modules connected to my Jetson Orin Nano 8GB Devkit but even after doing all the configuration I am not able to see these devices when I run - ip link show. Moreover, the test program that I have written in Python also responds with an array of zeroes when it tries to communicate with these CAN modules.

Here’s what my setup is:

The SDI, SDO and SCK pins on both these CAN modules are connected to SPI0-MOSI , SPI0-MISO and SPI0-SCK pins on the jetson 40 pin expansion header respectively. VCC and GND pins are connected to an external power supply which is being powered through one of the USB ports on the jetson. NCS pin on can0 is connected to SPI0_CS0 pin on jetson and NCS pin on can1 is connected to SPI0_CS1 pin on jetson. For the INT pins, INT, INT0 and INT1 pins on can0 are connected to GPIO492, 460 and 433 respectively and INT, INT0 and INT1 pins on can1 are connected to GPIO401, GPIO399 and GPIO400 pins on the jetson.

I have installed the mcp251xfd driver on the jetson by following the steps related to Kernel Customization and have basically copied over the generated .ko file to the appropriate place inside jetson. The driver module seems to be loading up when I check with lsmod | grep mcp.

I have not yet connected the can high and can low lines of the can modules since i only wanna do the loop back test first.

I have also modified the device tree like below and enabled the spi1 on jetson using the jetson-io tool:

spi@3210000 {
    			status = "okay";

    			spidev0: mcp2518fd@0 {
    				compatible = "microchip,mcp2518fd";
    				reg = <0>;
   				spi-max-frequency = <10000000>;
    				interrupt-parent = <&tegra_main_gpio>;
    				interrupts = <0 0x90 0x2>; // INT for CAN1 (GPIO 492)
    				clock-frequency = <40000000>;
    				oscillator-frequency = <40000000>;
			};

			spidev1: mcp2518fd@1 {
    				compatible = "microchip,mcp2518fd";
   				reg = <1>;
    				spi-max-frequency = <10000000>;
    				interrupt-parent = <&tegra_main_gpio>;
    				interrupts = <0 0x191 0x2>; // INT for CAN2 (GPIO 401)
    				clock-frequency = <40000000>;
    				oscillator-frequency = <40000000>;
			};
		};

Is there something I am missing or have done wrong?

ip link show only displays can0.

Have you checked Controller Area Network (CAN) — NVIDIA Jetson Linux Developer Guide 1 documentation?

Hi,
Please apply this to overwrite SPI driver:
MCP2518FD not working with JetPack 6.0 GA - #22 by sevm89

And please check the reference setup:

Jetson/L4T/peripheral/ - eLinux.org

yes, unfortunately this is not useful as I am trying to communicate with 2 external CAN modules I have connected with the Jetson.

Hi pranavbansal,

What’s the Jetpack version in use?

MCP2518FD is connected on SPI interface from Orin Nano.
Before porting it on the devkit, please apply the following patch to check if it could help.
Jetson orin nano SPI Speed not changing - #9 by KevinFFF

Please share the full dmesg if you still hit the issue.

I am on Jetpack 6.2

I have been able to make some progress and the CAN modules show up now when I run - ip link show

Also the mcp modules are being initialized properly on spi0.0 and spi0.1

jetson@jetson-desktop:~$ sudo modprobe mcp251xfd
[sudo] password for jetson: 
jetson@jetson-desktop:~$ sudo dmesg | grep mcp
[   10.707370] mcp251xfd: module verification failed: signature and/or required key missing - tainting kernel
[   10.749631] mcp251xfd spi0.0 can1: MCP2518FD rev0.0 (-RX_INT -MAB_NO_WARN +CRC_REG +CRC_RX +CRC_TX +ECC -HD c:25.00MHz m:2.00MHz r:2.00MHz e:0.00MHz) successfully initialized.
[   10.776286] mcp251xfd spi0.1 can2: MCP2518FD rev0.0 (-RX_INT -MAB_NO_WARN +CRC_REG +CRC_RX +CRC_TX +ECC -HD c:25.00MHz m:2.00MHz r:2.00MHz e:0.00MHz) successfully initialized.
jetson@jetson-desktop:~$

this is the output of ip link show type can:

3: can0: <NOARP,ECHO> mtu 16 qdisc noop state DOWN mode DEFAULT group default qlen 10
    link/can 
4: can1: <NOARP,UP,LOWER_UP,ECHO> mtu 16 qdisc pfifo_fast state UP mode DEFAULT group default qlen 10
    link/can 
5: can2: <NOARP,ECHO> mtu 16 qdisc noop state DOWN mode DEFAULT group default qlen 10
    link/can 

can0 is the internal can and can1 and can2 are the ones I have attached.

however the communication is still not working

these are the changes I have made in the device tree:

spi@3210000 {
			compatible = "nvidia,tegra210-spi\0nvidia,tegra114-spi";
			reg = <0x00 0x3210000 0x00 0x1000>;
			interrupts = <0x00 0x24 0x04>;
			#address-cells = <0x01>;
			#size-cells = <0x00>;
			clocks = <0x03 0x87>;
			assigned-clocks = <0x03 0x87>;
			assigned-clock-parents = <0x03 0x66>;
			clock-names = "spi";
			iommus = <0x04 0x04>;
			resets = <0x03 0x5b>;
			reset-names = "spi";
			dmas = <0xed 0x0f 0xed 0x0f>;
			dma-names = "rx\0tx";
			dma-coherent;
			status = "okay";

			can_clock: can_clock {
					compatible = "fixed-clock";
					#clock-cells = <0>;
					clock-frequency = <25000000>;
					clock-accuracy = <100>;
			};

			prod-settings {
				#prod-cells = <0x04>;

				prod {
					prod = <0x00 0x194 0x80000000 0x00>;
				};
			};

			spi@0 {
				compatible = "microchip,mcp251xfd";
				reg = <0x00>;
				spi-max-frequency = <2000000>;
				interrupt-parent = <&tegra_main_gpio>;
				interrupts = <0xA6 0x02>;
				clocks = <&can_clock>;
				nvidia,enable-hw-based-cs;

				controller-data {
					nvidia,enable-hw-based-cs;
					nvidia,rx-clk-tap-delay = <0x10>;
					nvidia,tx-clk-tap-delay = <0x00>;
				};
			};

			spi@1 {
				compatible = "microchip,mcp251xfd";
				reg = <0x01>;
				spi-max-frequency = <2000000>;
				interrupt-parent = <&tegra_main_gpio>;
				interrupts = <0x69 0x02>;
				clocks = <&can_clock>;
				nvidia,enable-hw-based-cs;

				controller-data {
					nvidia,enable-hw-based-cs;
					nvidia,rx-clk-tap-delay = <0x10>;
					nvidia,tx-clk-tap-delay = <0x00>;
				};
			};
		};

I am trying to test the CAN communication for CAN1 with loopback on

  • sudo ip link set can1 up type can bitrate 500000 loopback on

After bringing up can1 I can also see the interrupt is registered - sudo cat /proc/interrupts | grep gpio

244:          0          0          0          0          0          0  2200000.gpio 144 Edge      spi0.0

I dont see the interrupt getting triggered when I run cansend and candump for can1

Can you connect can1 and can2 together (i.e. CAN-H to CAN-H, CAN-L to CAN-L)?
and do not use loopback on option since it is used for internal loopback.

$ sudo ip link set can1 up type can bitrate 500000
$ sudo ip link set can2 up type can bitrate 500000
$ candump -x any &
$ cangen can1

You can also get a scope to check if there’s data on SPI bus.