Enabling CAN on Nvidia Jetson Xavier Developer Kit
The Nvidia Jetson Xavier is equipped with two Controller Area Network (CAN) controllers, but it does not have any CAN transceivers. These transceivers can be easily added to the Jetson Xavier developer kit to enable CAN bus communication with other devices. In this tutorial I’ll go through all the steps needed to enable the CAN controllers on the Jetson Xavier developer kit. I start with configuring the GPIO pins on the Jetson Xavier and enabling the CAN controllers, and then go through the transceiver installation steps.
A Chinese translation of this tutorial is now available here, thanks to Tuan Misaka.
Part 1: Enabling CAN Controllers
The CAN controllers in the Jetson Xavier developer kit can be accessed through the GPIO expansion header. By default, the CAN controllers’ pins are configured to have GPIO functionalities to comply with the Raspi 40-pin standard, so the first thing we need to do is to reconfigure these pins to enable CAN functionalities. According to this post on the Nvidia Xavier developer forum, there are two ways to reconfigure these pins. The first way involves flashing the Xavier with a particular pinmux configuration. Since I do not want to re-flash my Xavier, I’ll go with the second solution.
The second solution is using a register read/write tool to overwrite the register values corresponding to the CAN controller pins. The only catch in this solution is that these settings are not persistent, meaning that they need to be repeated every time the Jetson Xavier developer kit is powered on. We will take care of this problem by writing a configuration script that runs automatically at system startup. Let’s get started by opening a terminal on the Jetson Xavier and following the steps below.
- We start by installing a tool for changing the register values on the Xavier:
sudo apt-get install busybox
- Then we need to reconfigure four register values corresponding to the CAN controllers’ pins. The following commands will reconfigure these pins:
sudo busybox devmem 0x0c303000 32 0x0000C400
sudo busybox devmem 0x0c303008 32 0x0000C458
sudo busybox devmem 0x0c303010 32 0x0000C400
sudo busybox devmem 0x0c303018 32 0x0000C458
- Now that the register values are modified, we can mount the CAN controllers and load the drivers using the
modprobe
command:
sudo modprobe can
sudo modprobe can_raw
sudo modprobe mttcan
- The next step is configuring the CAN Controllers according to your CAN bus and transceivers’ specifications. Here I set the CAN bitrate to 500 Kbps, enable the flexible data rate (FD), set the payload bitrate to 2 Mbps and enable the Bus Error Reporting. If you are not sure about all these settings, you can just set the
bitrate
value and ignore other options after that.
sudo ip link set can0 type can bitrate 500000 \
dbitrate 2000000 berr-reporting on fd on
sudo ip link set can1 type can bitrate 500000 \
dbitrate 2000000 berr-reporting on fd on
- Now we just need to bring the CAN interfaces up:
sudo ip link set up can0
sudo ip link set up can1
- To check if the CAN controllers are successfully enabled, use the
ifconfig
command. In the output you should be able to seecan0
andcan1
among your network devices as shown in the figure below:
- To make the above CAN controllers configuration automatically done at system startup, create a file named
enable_CAN.sh
in the root directory and make it executable:
touch /enable_CAN.sh
chmod 755 /enable_CAN.sh
- Add the following lines to this file and save it. These are basically the same commands we ran to configure the CAN controllers.
#!/bin/bashsudo busybox devmem 0x0c303000 32 0x0000C400
sudo busybox devmem 0x0c303008 32 0x0000C458
sudo busybox devmem 0x0c303010 32 0x0000C400
sudo busybox devmem 0x0c303018 32 0x0000C458sudo modprobe can
sudo modprobe can_raw
sudo modprobe mttcan
sudo ip link set can0 type can bitrate 500000 dbitrate 2000000 berr-reporting on fd on
sudo ip link set can1 type can bitrate 500000 dbitrate 2000000 berr-reporting on fd on
sudo ip link set up can0
sudo ip link set up can1
exit 0
- If the file
/etc/rc.local
already exists on your Jetson Xavier, skip to the next step. If it does not exist, go ahead and create it by running the following commands in terminal:
printf '%s\n' '#!/bin/bash' 'exit 0' | sudo tee -a /etc/rc.local
sudo chmod +x /etc/rc.local
- Add the following line to the
/etc/rc.local
file before theexit 0
line:
sh /enable_CAN.sh &
- Your
/etc/rc.local
file should look like this now:
Now the enable_CAN.sh script should be run automatically at system startup and configure the CAN controllers. To test it, reboot your Jetson Xavier and check if you still see the can0
and can1
devices when you run the ifconfig
command in a terminal.
Part 2: Installing the CAN Transceivers
I’m using two KNACRO CAN bus transceivers for my setup so that I can interface with two CAN buses at the same time. You can install just one transceiver if you need to communicate with one CAN bus only. The transceivers I use run at 3.3V and have 120 Ohm terminating resistors already soldered across the bus.
The pinout for the expansion header on the Jetson Xavier as well as the location of pin #1 is shown in the figure below.
We start by connecting pin #29 (CAN0_DIN) and pin #31(CAN0_DOUT) of the Expansion Header connector to the CRX and CTX pins on one of the transceivers. Similarly, pin #37 (CAN1_DIN) and pin #33 (CAN1_DOUT) need to be connected to the CRX and CTX pins on the other transceiver. We also need to connect two sets of 3.3V and GND pins on the expansion header connector to the 3V3 and GND pins on the transceivers. The following diagram demonstrates how the transceivers’ pins are connected to the expansion header pins.
The CANH and CANL pins on the transceivers need to be connected to the CAN High and CAN Low wires of the two CAN buses that you want to communicate with. We will also need some kind of structure to fix the transceivers and the Jetson Xavier developer kit on. We have made a simple platform to mount the boards and the transceivers on. Figure below shows the transceivers connected to the Jetson Xavier developer kit and mounted on this platform.
As seen in the figure above, I used a DB-9 connector to interface with the CAN bus. The two sets of twisted wires are the CANH and CANL wires for CAN0 and CAN1. To keep the error rate low, the CAN High and CAN Low wires are usually twisted. On the DB-9 connector, I’ve used pins 1 and 8 for CAN0 Low and High and pins 2 and 7 for CAN1 Low and High, but you can use any other pinout that fits your application.
Notes
- According to the Jetson AGX Xavier Developer Kit Carrier Board Specification document, pins 37, 29, 33 & 31 are pulled to 3.3V when system is powered on due to internal 3.3V pull-ups in the SoC enabled by default. So the transceiver you use must be able to handle the initial 3.3V on its CTX and CRX pins. The transceiver used in this tutorial seems to be handling this initial 3.3V with no problem.
- A very good set of scripts for configuring and testing the CAN controllers on the Jetson Xavier is published by a Jetson Xavier user in this repository.