Jetson Nano Developer Kit Model P3450 and Waveshare CAN RS485

Hello,

We have a Jetson Nano Developer Kit Model P3450. We have installed a CAN/RS485 expansion board from Waveshare and we have also imaged the SD card with Ubuntu 20.04 per the links below.

Qengineering Ubuntu 20.04
Waveshare CAN/RS485 Wiki

When we follow the steps on the Waveshare Wiki all seems to go well until we get to the

sudo python cantest.py

at which point no data is returned. We contacted Waveshare and they provided MCP251x.dtbo which we copied into /boot and then ran the jetson-io tool. On the original Wiki from Waveshare it is suggested to configure the pins manually which only works in bringing up the /dev/spi* devices but not the can0 interface. The cantest.py script does not seem to send/receive data. If we run the jetson-io tool again and configure for compatible hardware by selecting the mcp2515 driver/module from the configuration menu it shows up in dmesg after reboot but spi fails to initialize. I have tried several approaches from the forums including this one Seedstudio CAN suggestions

Is there something basic I am missing here? Waveshare schematics show an interrupt pin 29 but others on the forums seem to be using pin 31? Maybe the 20.04 image based on the JetPack 4.6.1 is missing something?

Happy to provide any info needed that would help us get passed this hurdle.

Thank you.

Wess

Hi wess.gates,

Are you using the NVIDIA devkit rather than the custom board from Waveshare or SeeedStudio for Jetson Nano?
Are you using JP4.6.1?
Could you share the result of the following command on your board?

$ cat /etc/nv_tegra_release
$ cat /etc/nv_boot_control.conf

Since we don’t have this “CAN/RS485 expansion board”, my help could be limited.
It seems using a MCP251x module for CAN through SPI interface.
If you are using NVIDIA devkit for Jetson Nano, you could use jetson-io.py to enable SPI.
If you are using the custom carrier board , you should enable them through pinmux spreadsheet or configure the related pinmux register for SPI.

Could you load MCP251x driver successfully?
Have you verified the SPI interface working? (i.e. SPI loopback test worked)

Hi,

Yes. I have the Nvidia Jetson Nano P3450 which I understand is the P3448+P3449 module/carrier board and not a custom Nano board from Waveshare. Only the RS485/CAN board is from Waveshare and plugged into the 40 pin header on the Nano.

Here are the outputs per your requests:

 cat /etc/nv_tegra_release

# R32 (release), REVISION: 6.1, GCID: 27863751, BOARD: t210ref, EABI: aarch64, DATE: Mon Jul 26 19:20:30 UTC 2021

cat /etc/nv_boot_control.conf

TNSPEC 3448-400-0000-F.0-1-0-jetson-nano-qspi-sd-mmcblk0p1
COMPATIBLE_SPEC 3448-300-0000--1--jetson-nano-devkit-
TEGRA_CHIPID 0x21
TEGRA_OTA_BOOT_DEVICE /dev/mtdblock0
TEGRA_OTA_GPT_DEVICE /dev/mtdblock0

There are two main approaches I have tried so far. I used jetson-io to enable SPI pins manually per the Waveshare Wiki. This approach seems to enable SPI but not mcp2515.

Some outputs using this approach: Manually configuring SPI pins via Jetson IO:

jetson@nano:~$ dmesg |grep -i spi
[    0.438236] iommu: Adding device 7000d400.spi to group 7
[    0.438525] iommu: Adding device 7000d600.spi to group 8
[    0.438794] iommu: Adding device 70410000.spi to group 9
[    1.151187] tegra-qspi 70410000.spi: Prod settings list not found
[    1.152463] qspi_mtd spi32766.0: MX25U3235F (4096 Kbytes)
[    1.152474] qspi_mtd spi32766.0: mtd .name = spi32766.0, .size = 0x400000 (4MiB) .erasesize = 0x00001000 (4KiB) .numeraseregions = 0
jetson@nano:~$ lsmod |grep -i spi
spidev                 13218  0

jetson@nano:~$ lsmod |grep -i mcp

Waveshare also provided a MCP2515 dts file which seems to bring up the MCP2515 driver but it fails to reset. I used the Waveshare provided MCP2515 dts file to bring up the MCP2515 as a " configure for compatible hardware" via jetson-io menu. The MCP2515 driver loads but it fails to enter conf mode after reset.

Here are some outputs using the: jeston-io “configure for compatible hardware” approach

jetson@nano:~$ dmesg |grep -i spi

[    0.442384] iommu: Adding device 7000d400.spi to group 7
[    0.442652] iommu: Adding device 7000d600.spi to group 8
[    0.442915] iommu: Adding device 70410000.spi to group 9
[    1.145601] tegra-qspi 70410000.spi: Prod settings list not found
[    1.146836] qspi_mtd spi32766.0: MX25U3235F (4096 Kbytes)
[    1.146846] qspi_mtd spi32766.0: mtd .name = spi32766.0, .size = 0x400000 (4MiB) .erasesize = 0x00001000 (4KiB) .numeraseregions = 0
[    5.955028] mcp251x spi0.0: MCP251x didn't enter in conf mode after reset
[    5.955040] mcp251x spi0.0: Probe failed, err=16
[    5.955054] mcp251x: probe of spi0.0 failed with error -16
[    6.999782] mcp251x spi1.0: MCP251x didn't enter in conf mode after reset
[    7.007515] mcp251x spi1.0: Probe failed, err=16
[    7.014495] mcp251x: probe of spi1.0 failed with error -16

jetson@nano:~$ lsmod |grep -i spi

spidev                 13218  0

jetson@nano:~$ lsmod |grep -i mcp
mcp251x                13742  0
can_dev                13592  1 mcp251x

I have emailed Waveshare because there is something unclear about the dts they provided. The Waveshare Extension board schematics shows that PIN29 of the nano/40 pin header goes to the INT pin of the MCP2515 but the dts file seems to show PIN22 being used instead of pin29.

This is the dts file content Waveshare provided:

// SPDX-License-Identifier: GPL-2.0-only
/*
 * Jetson Device-tree overlay for
 *   MCP2515
 *
 * Copyright (c) 2020 Seeed Technology Co,Ltd - https://www.seeed.cc.
 * All rights reserved.
 *
 */

/dts-v1/;
/plugin/;

#include <dt-bindings/pinctrl/tegra210-p3448-0000-p3449-0000-a02.h>
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/pinctrl/pinctrl-tegra.h>
#include <dt-bindings/gpio/tegra-gpio.h>

/ {
	overlay-name = "MCP251x CAN Controller";
	compatible = JETSON_COMPATIBLE;

	fragment@1{
		target-path = "/spi@7000d400/spi@1";
		__overlay__ {
			status = "okay";
		};
	};

	fragment@4 {
		target-path = "/";
		__overlay__ {
			clocks {
				mcp251x_osc: mcp251x_osc {
					compatible = "fixed-clock";
					#clock-cells = <0x0>;
					clock-frequency = <8000000>;
					clock-accuracy = <100>;
					clock-output-names = "mcp251x_osc";
					status = "okay";
				};
			};
		};
	};

	fragment@5 {
		target = <&spi0>;
		__overlay__ {
			/* avoid dtc warning */
			#address-cells = <1>;
			#size-cells = <0>;
			compatible = "nvidia,tegra210-spi";
			pinctrl-names = "default";
			pinctrl-0 = <&spi0_pinmux>;
			nvidia,always-hw-cs;

			can0: can@0 {
				compatible = "microchip,mcp2515";
				status = "okay";
				reg = <0x0>; /* spi chip select 0 */
				clocks = <&mcp251x_osc>;
				interrupt-parent = <&gpio>;
				/* GPIO13, HDR PIN22, TEGRA spi2_miso_pb5 */
				interrupts = <TEGRA_GPIO(B, 5) IRQ_TYPE_LEVEL_LOW>;
				spi-max-frequency = <10000000>;
				controller-data {
					nvidia,enable-hw-based-cs;
					nvidia,cs-setup-clk-count = <0x1e>;
					nvidia,cs-hold-clk-count = <0x1e>;
					nvidia,rx-clk-tap-delay = <0x1f>;
					nvidia,tx-clk-tap-delay = <0x0>;
				};
			};
		};
	};

	fragment@10 {
		target = <&pinmux>;
		__overlay__ {
			spi0_pinmux: header-40pin-spi0-pinmux {
				**/* can0 /intr */**
**				pin22 {**
**					nvidia,pins = "spi2_miso_pb5";**
**					nvidia,function = "rsvd2";**
**					nvidia,pull = <TEGRA_PIN_PULL_UP>;**
**					nvidia,tristate = <TEGRA_PIN_DISABLE>;**
**					nvidia,enable-input = <TEGRA_PIN_ENABLE>;**
**				};**
				pin19 {
					nvidia,pins = "spi1_mosi_pc0";
					nvidia,function = "spi1";
					nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
					nvidia,tristate = <TEGRA_PIN_DISABLE>;
					nvidia,enable-input = <TEGRA_PIN_ENABLE>;
				};
				pin21 {
					nvidia,pins = "spi1_miso_pc1";
					nvidia,function = "spi1";
					nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
					nvidia,tristate = <TEGRA_PIN_DISABLE>;
					nvidia,enable-input = <TEGRA_PIN_ENABLE>;
				};
				pin23 {
					nvidia,pins = "spi1_sck_pc2";
					nvidia,function = "spi1";
					nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
					nvidia,tristate = <TEGRA_PIN_DISABLE>;
					nvidia,enable-input = <TEGRA_PIN_ENABLE>;
				};
				/* spi0.cs1 */
				pin24 {
					nvidia,pins = "spi1_cs0_pc3";
					nvidia,function = "spi1";
					nvidia,pull = <TEGRA_PIN_PULL_UP>;
					nvidia,tristate = <TEGRA_PIN_DISABLE>;
					nvidia,enable-input = <TEGRA_PIN_ENABLE>;
				};
			};
		};
	};
};

The kernel pin mapping dts/dtbo reaches the limit of my present knowledge but my suspicion is that if pin 22 is changed to pin 29 the mcp2515 may get past initialization but I am not certain. Not sure where to look on pin mapping registers and settings for the Nano/Linux stuff yet? I would need to learn more about this but hoping for some help so I can dive up into CAN bus and not down into registers :)

Thanks for the help!

Wess

Hi wess.gates,

I wrote an instruction in another thread for MCP2515 module on Jetson.
Although that is verified on Orin NX+p3768, you could also refer to the steps and configuration for MCP2515 on your Jetson Nano.
Jetson Orin NX(JP5.1.2_R35.4.1) mcp2515 can1 can send data, can not recieve data - #10 by KevinFFF

Hi @KevinFFF

Would you please point me to where I can read or confirm the pin registers addresses/names for our P3450 so I can follow your write up on that post ?

To configure the pinmux, you could also use Jetson-IO for P3450.
For more details about the Jetson Nano devkit, you could refer to the Jetson Nano Developer Kit Carrier Board Specification (P3449 B01) from download center.

Hi @KevinFFF

So would your post there for the OrinNX+p3768 devkit still apply to the Jetson Nano P3450 dev kit? Do I need to decompile the dtbo file and then make the stated changes and then build the dtbo file again? Am I inferring this approach correctly?

Our dts tree looks like there is much more to it than what I see on the post:

spi@7000d400 {
		compatible = "nvidia,tegra210-spi";
		reg = <0x0 0x7000d400 0x0 0x200>;
		interrupts = <0x0 0x3b 0x4>;
		iommus = <0x30 0xe>;
		#address-cells = <0x1>;
		#size-cells = <0x0>;
		dmas = <0x51 0xf 0x51 0xf>;
		dma-names = "rx", "tx";
		nvidia,clk-parents = "pll_p", "clk_m";
		clocks = <0x26 0x29 0x26 0xf3 0x26 0xe9>;
		clock-names = "spi", "pll_p", "clk_m";
		resets = <0x26 0x29>;
		reset-names = "spi";
		status = "okay";
		linux,phandle = <0xf8>;
		phandle = <0xf8>;

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

			prod {
				prod = <0x4 0xfff 0x0>;
			};

			prod_c_flash {
				status = "disabled";
				prod = <0x4 0x3f 0x7>;
			};

			prod_c_loop {
				status = "disabled";
				prod = <0x4 0xfff 0x44b>;
			};
		};

		spi@0 {
			interrupts = <0x95 0x1>;
			interrupt-parent = <0x5b>;
			clocks = <0x131>;
			nvidia,rx-clk-tap-delay = <0x7>;
			nvidia,enable-hw-based-cs;
			status = "okay";
			compatible = "microchip,mcp2515";
			reg = <0x0>;
			spi-max-frequency = <0x989680>;

			controller-data {
				nvidia,tx-clk-tap-delay = <0x0>;
				nvidia,cs-hold-clk-count = <0x1e>;
				nvidia,cs-setup-clk-count = <0x1e>;
				nvidia,enable-hw-based-cs;
				nvidia,rx-clk-tap-delay = <0x1f>;
			};
		};

		spi@1 {
			status = "disabled";
			compatible = "tegra-spidev";
			reg = <0x1>;
			spi-max-frequency = <0x1f78a40>;

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

It should be the similar steps to verify.
Since different module/platform would use different pins, device tree, SPI address…etc, you should modify the corresponding configuration for your board.

First, you should know which dtb is in use for your board.

Please add the configuration for MCP2515 in the following node.

		spi@0 {
1 Like

I posted a snippet from our dts in my prior post. From what I can tell the mcp2515 configuration is already under spi@0. Am I missing what you are asking me to do here?

Yes, it seems the related configuration has been added in device tree, but you have to check the parameters for it.
For example, the spi-max-frequency, you seems using 10MHz for it.
How do you configure the 0x131 clock for can_clock?
Is this dts the right one you are using for your board?
You could also check if the interrupt for SPI showed in /proc/interrupts.
You may also need to check the CAN connection.

Here is a summary of the Waveshare RS485 CAN for Jetson Nano. I am using the the P3450 and the simplified connection diagram based on their published schematic is:

Their board has an 8MHz OSC into the MCP2515.

I had not yet changed the values to match yours because I was still seeking guidance that I was on the right path as my original questions from that post have yet to be confirmed regarding the decompiling of the dtbo and then modifying the dts and the compiling again? Is this the correct way or approach to fulfill your instruction post?

After applying the Waveshare instructions and then using jetson-io to enable spi my /boot/extlinux/extlinux.conf points to /boot/kernel_tegra210-p3448-0000-p3449-0000-b00-user-custom.dtb

I have attached a decompiled version of this file.
kernel_tegra210-p3448-0000-p3449-0000-b00-user-custom.dts (319.6 KB)

I am unclear what the /proc/interrupts should tell me? dmesg and lsmod shows SPI coming up OK using the jetson-io manual pin configuration method per the Waveshare website.

Here is output of more /proc/interrupts |grep spi

 66:          0          0          0          0       LIC  59 Level     7000d400.spi
 67:          0          0          0          0       LIC  82 Level     7000d600.spi
 68:       2414          0          0          0       LIC  10 Level     70410000.spi

dmesg |grep -i spi

[    0.438229] iommu: Adding device 7000d400.spi to group 7
[    0.438528] iommu: Adding device 7000d600.spi to group 8
[    0.438802] iommu: Adding device 70410000.spi to group 9

dmesg |grep -i spi

spidev                 13218  0

ls /dev/spi*

/dev/spidev0.0  /dev/spidev0.1  /dev/spidev1.0  /dev/spidev1.1

These seem to suggest spi is AOK unless I am missing something?

However, there is still no sign of a can0 device nor does ip link seem to find can0.

The Waveshare MC2515 Overlay file can be retrieved via wget:

wget https://www.waveshare.net/w/upload/4/4b/MCP251x.dtbo

I am still very puzzled that PIN29 does not show up anywhere in any of the dts or overlay files since their schematic shows INT pin to PIN29 on 40 pin HDR for Jetson.

I did not find the document in the downloads nor in the archives for the Jetson Nano per the suggestion of the original post nor can I find a document that discusses the registers/address and how all these things make their way into the DTS for Nvidia specific carrier boards/ SoMs/SoCs etc… ? I did see the files for other carrier boards and SoM like Xavier and Orin etc… but nada for Jetson Nano.

`Jetson Nano Developer Kit Carrier Board Specification (P3449 B01)` 

I don’t have this “Waveshare RS485 CAN” board to verify it locally so that I could not give you the detailed steps to port this module for Jetson Nano. You should refer to the guide and parameter provided from your vendor.

Yes, you might need to decompile the dtb and modify the content in dts and then assemble it back to dtb.
You just need to confirm which dtb is in use for your board.

They seem not like the interrupts for MCP2515.

This is created by tegra-spidev driver rather than the MCP2515 driver.

I don’t see any spi node has been configured for MCP2515 in this device tree.

After you configuring the device tree for MCP2515, you may need to load the module with sudo modprobe mcp251x.

Could you see the following document in download center?

I will try to be more specific. Please refer to my attached screen shots borrowed from the specification file you are referring me to.


In your instruction post your dts modifications include lines like this

interrupt-parent = <&tegra_main_gpio>;
interrupts = <TEGRA234_MAIN_GPIO(H, 0) IRQ_TYPE_LEVEL_LOW>;

but since I am running Jetson Nano I suspect TEGERA234 is not what I need correct?
Also, how do I map pin 29 from 40 pin header to interrupt? The “Specification” manual does not seem to document or discuss where the names are coming from in the DTS file for my specific carrier board.

In the case of the Waveshare RS485/CAN board they have 8MHz OSC onboard so I believe my can_clock should look something like this:

clock-frequency = <8000000>;

but my SPI clock should probably be

spi-max-frequency = <10000000>;

I honestly have no expectation of you guys to have every hardware board. I am happy to do the work but there are probably thousands of post on CAN bus MCP2515.

Yes, you should use TEGRA_MAIN_GPIO since you are using Jetson Nano(T210).

It depends on which pin do you want to use for interrupt.
From my verification on Orin NX, I use PQ.05(which also PIN29 of 40-pin header).
It should be different from your use case because they are the different platform and board.
Which pin would you like to use as interrupt? (i.e. which pin of the carrier board do you connect to the INT of the MCP2515 module?)

Yes, according to the Waveshare schematic they show pin29. I am still hoping you can share where all this information for pin mapping is coming from? Things like PQ.05 or references to TEGRA_MAIN_GPIO? I understand some of the device tree is “Linux Standard Stuff” but the data that goes into device trees that is Nvidia specific where is that coming from?

Also, I am unclear. Some posts I read keep suggesting that I cannot change the device tree within the /boot folder and that I have to change it some where else and reflash? This seems to defeat the very idea of device trees and overlays for me. I would appreciate some insight here. Perhaps the posts i have read are old and things have changed?

Please refer to the following information to check the pin mapping and gpio number.

  1. pinmux spreadsheet
  2. carrier board specification
  3. cat /sys/kernel/debug/gpio

There should be several methods for the same purpose. You could use one of them but please know what you are modifying.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.