Developing on NVIDIA® Jetson™ for AI on the Edge

SPI on Jetson – Using Jetson-IO

Remember when you had to jump through all sorts of hoops to get your NVIDIA Jetson NVIDIA Kit to be able to understand Serial Protocol Interface (SPI) devices? Those days be gone. Looky here:


The introduction of JetPack 4.3 brings with it a new tool, Jetson-IO. All of the Jetson developer kits include a 40-pin GPIO expansion header. Many of the pins can be used either as General Purpose I/O (GPIO) or Special Function I/O (SFIO). SFIO are functions such as I2C, I2S, SPI, and so on.

The default configuration of the pins is defined and programmed into the Jetson when flashed. Previously you had to go through a, let’s call it less than straightforward, process to reconfigure the pins to your needs.

The new Jetson-IO tool is here to help! While the previous process is useful for system designers, the majority of developers many times just look to modify the pins to the NVIDIA recommended special functions.

For example, if we look at a typical Jetson GPIO Expansion Header (such as this one for the Jetson Nano), we see that there are several pins that list as SPI_1, but we know that in the default configuration they are GPIO.

This is similar to other Linux embedded systems such as the Raspberry Pi. The RPi has a similar utility, raspi-config, to help with configuring pins on that device.

The default configuration sets most of the pins to GPIO. Here’s how to run Jetson-IO to change that.


The Jetson-IO utility is just a youngster, and in its initial release on the Jetson in JetPack 4.3 (L4T 32.3.1) there are some issues. These issues are noted in the documentation. The following two issues have been addressed in later releases.

The first issue involves initialization of some of the code. To fix it:

$ sudo find /opt/nvidia/jetson-io/ -mindepth 1 -maxdepth 1 -type d -exec touch {}/ \;

The second issue occurs only on the Jetson Nano. On the Jetson Nano, one of the directories needs to be set up:

$ sudo mkdir /boot/dtb
$ sudo cp -v /boot/tegra210-p3448-0000-p3449-0000-[ab]0[02].dtb /boot/dtb/

Then there’s a niggle to which you should be aware. If the Terminal window that you are working in is too small, then the menus have difficulty displaying. Make sure that your Terminal window is large, so it can hold the menus.

Running Jetson-IO

After the setup, we’re ready to go:

$ sudo /opt/nvidia/jetson-io/

Which will bring us to the main screen:

Jetson-IO Main Screen – Image Courtesy NVIDIA

We select Configure 40-pin expansion header:

Configuration Screen

In our case we select SPI1 (pins 19,21,23,24,26). Use the arrow keys to navigate to the desired entry, Return selects/deselects the entry. Select Back when done. You should see the new configuration on the main menu. Save and reboot to reconfigure pins. You will go through the familiar Confirm/’Deny everything you have ever done’ prompts, then the system will reboot. After that, SPI goodness is available.

Of course, the Jetson-IO utility has much more functionality than this simple example. Look through the documentation to see what you can do to amaze your friends and confuse your enemies!

SPI Display Example

In the video, we connect to a Adafruit 1.8″ TFT Display to a Jetson Nano. The display is also available through Digikey and Adafruit. There is an excellent tutorial on the Adafruit site about the Display and how to use it. We won’t go over this too much more here.

After soldering the headers onto the display, we wire the display:

Jetson NanoAdafruit 1.8″ TFT Display
Pin 6 GNDPin 1 GND
Pin 1 3.3VPin 2 VCC
Pin 18 gpio15Pin 3 Reset
Pin 22 gpio13Pin 4 D/C
Not ConnectedPin 5 CARD_CS
Pin 24 SPI_1_CS0Pin 6 TFT_CS
Pin 19 SPI_1_MOSIPin 7 MOSI
Pin 23 SPI_1_SCKPin 8 SCK
Not ConnectedPin 9 MISO
Pin 17 3.3VPin 10 LITE

Note that while SPI is only 4 signals (6 if you count power and ground), this device has a couple of more in use. One of the extra connections provides power to the backlight of the display.

There are a couple of examples for this particular display on the JetsonHacksNano account on Github in the repository SPI-Playground. Clone the repository, and switch over that that repositories example directory:

$ git clone
$ cd SPI-Playground/examples

There you will find instructions on how to install the prerequisites in the file:

$ sudo apt-get install python3-pip
$ pip3 install adafruit-blinka
$ pip3 install adafruit-circuitpython-busdevice
$ pip3 install adafruit-circuitpython-rgb-display
$ sudo apt-get install python3-pil


There are two examples here.

Example 1 will display a shark on the screen.

$ python3

The second example shows some of the Jetson stats on the display:

$ python3

All in all, pretty straightforward. At least compared to the old days!


  • Example shown: JetPack 4.3/L4T 32.3.1
  • Jetson Nano

20 Responses

  1. Hi there,
    Thank you so much for this helpful tutorial.
    I have a question regarding the second step. After I reconfigure the GPIO header to SPI1, I save and reboot. Then when I check again the header, I find that the pins went back to their original state “unused”.
    Is that normal? and if it’s not, do you know what could be the reason?

    Thank you for your help

  2. Hi.
    Thank you so much for this tutorial.
    I always refer to this site.

    After I reconfigure the GPIO header to SPI1, I save and reboot.

    Refer to the following URL, I used the spidev_test.c to test the self loop when connect MOSI(19) and MISO(21).
    But, it displayed only zeros.(output : RX | 00 00 00 00 00 …)

    When I check again the header, I confirmed that SPI is enabled.
    I confirmed that the output of `ls /dev/spidev*` is `/dev/spidev0.0`.

    Do you get similar results? and if you don’t, do you know what could be the reason?

    URL ->
    spidev_test.c ->

    HW : Jetson AGX Xavier
    L4T/JetPack : Jetpack4.3

  3. Hi,
    In the version R32.4.2, I can config the SPI0 and run successfully in the Kit whith the SD module of B01, But when I replace to eMMC module of B01. The Jetson-IO can not run. So how to config SPI0 in the eMMC module of B01

  4. Hi,

    I would like use the SPI display like a main display, in other words, show the interfaz l4t of Jetson and run codes. Is it possible?

  5. hello,
    I am using jetpack 4.6

    when i execute “python3” i get the blow error.

    Traceback (most recent call last):
    File “”, line 20, in
    spi = board.SPI()
    File “/home/evren/.local/lib/python3.7/site-packages/”, line 311, in SPI
    return busio.SPI(SCLK, MOSI, MISO)
    File “/home/evren/.local/lib/python3.7/site-packages/”, line 286, in __init__
    self._spi = _SPI(portId)
    File “/home/evren/.local/lib/python3.7/site-packages/adafruit_blinka/microcontroller/generic_linux/”, line 22, in __init__
    self._spi = spi.SPI(device=(portid, 0))
    File “/home/evren/.local/lib/python3.7/site-packages/Adafruit_PureIO/”, line 167, in __init__
    raise IOError(“{} does not exist”.format(device))
    OSError: /dev/spidev0.0 does not exist
    Cleaning up pins

    1. Does jetson-io show that the SPI signals are set? I’m beginning to think that there might be an issue with JetPack 4.6 and that package and the way that they handle the device tree overlay.

Leave a Reply

Your email address will not be published. Required fields are marked *


Some links here are affiliate links. If you purchase through these links I will receive a small commission at no additional cost to you. As an Amazon Associate, I earn from qualifying purchases.

Books, Ideas & Other Curiosities