Problem Getting SPI Working on Jetson Nano

I have no problems opening the spidev1.0 and sending a string to it without errors, but I see no activity on any SPI pins. (I did configure the GPIO for SPI using the jetson-io.py utility.) Any suggestions on what could the issue?

Hi markg3,

Are you using the devkit or custom board for Jetson Nano?
What’s the Jetpack version in use?

How do you confirm this that you’ve sent the data successfully?
Do you use the scope to check their state?

Hi KevinFFF,

Yes, I am using oscilloscope to check for activity on SPI output signals. The SPI demo code that somebody sent to me has error checking that does not indicate an error when the function is called to open the SPI or to send a string to it. I’ve included bits of this demo code below. The version is as follows:

R32 (release), REVISION: 7.4, GCID: 33514132, BOARD: t210ref, EABI: aarch64, DATE: Fri Jun 9 04:25:08 UTC 2023

Version: 32.7.4-20230608212426

I’ve tested on both my custom board and on the devkit, with the result of no activity on any of the SPI outputs on both boards. The only difference between the boards is that on my board the chip selects are high - a default inactive state which is what I would expect. On the devkit board the chip selects stay low which it the default active state.

This ‘open/init’ code:

fd = open(device, O_RDWR);
if (fd < 0)
pabort(“can’t open device”);

/*

  • spi mode
    /
    /
    WR is make a request to assign ‘mode’ */
    request = mode;
    ret = ioctl(fd, SPI_IOC_WR_MODE32, &mode);
    if (ret == -1)
    pabort(“can’t set spi mode”);

/* RD is read what mode the device actually is in /
ret = ioctl(fd, SPI_IOC_RD_MODE32, &mode);
if (ret == -1)
pabort(“can’t get spi mode”);
/
Drivers can reject some mode bits without returning an error.

  • Read the current value to identify what mode it is in, and if it
  • differs from the requested mode, warn the user.
    */
    if (request != mode)
    printf(“WARNING device does not support requested mode 0x%x\n”,
    request);

/*

  • bits per word
    */
    ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
    if (ret == -1)
    pabort(“can’t set bits per word”);

ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits);
if (ret == -1)
pabort(“can’t get bits per word”);

/*

  • max speed hz
    */
    ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
    if (ret == -1)
    pabort(“can’t set max speed hz”);

ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);
if (ret == -1)
pabort(“can’t get max speed hz”);

This is ‘send’ code:

//---------------------------------------------------------------------------
static void transfer(int fd, uint8_t const *tx, uint8_t const *rx, size_t len)
{
int ret;
int out_fd;
struct spi_ioc_transfer tr;
// = {
// .tx_buf = (unsigned long)tx,
// .rx_buf = (unsigned long)rx,
//.len = len,
//.delay_usecs = delay,
//.speed_hz = speed,
//.bits_per_word = bits,
//len : len,
//delay_usecs : delay,
//speed_hz : speed,
//bits_per_word : bits,
//};

tr.tx_buf = (unsigned long)tx;
tr.rx_buf = (unsigned long)rx;
tr.len = len;
tr.delay_usecs = delay;
tr.speed_hz = speed;
tr.bits_per_word = bits;

if (mode & SPI_TX_OCTAL)
tr.tx_nbits = 8;
else if (mode & SPI_TX_QUAD)
tr.tx_nbits = 4;
else if (mode & SPI_TX_DUAL)
tr.tx_nbits = 2;
if (mode & SPI_RX_OCTAL)
tr.rx_nbits = 8;
else if (mode & SPI_RX_QUAD)
tr.rx_nbits = 4;
else if (mode & SPI_RX_DUAL)
tr.rx_nbits = 2;
if (!(mode & SPI_LOOP)) {
if (mode & (SPI_TX_OCTAL | SPI_TX_QUAD | SPI_TX_DUAL))
tr.rx_buf = 0;
else if (mode & (SPI_RX_OCTAL | SPI_RX_QUAD | SPI_RX_DUAL))
tr.tx_buf = 0;
}

ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
if (ret < 1)
pabort(“can’t send spi message”);

if (verbose)
hex_dump(tx, len, 32, “TX”);

if (output_file) {
out_fd = open(output_file, O_WRONLY | O_CREAT | O_TRUNC, 0666);
if (out_fd < 0)
pabort(“could not open output file”);

ret = write(out_fd, rx, len);
if (ret != len)
pabort(“not all bytes written to output file”);

close(out_fd);
}

if (verbose)
hex_dump(rx, len, 32, “RX”);
}
//---------------------------------------------------------------------------

I would suggest you verifying on the devkit for all related operations first.
Please refer to Jetson Nano SPI Bus Not Working - #10 by KevinFFF for the steps to verify SPI loopback test on Jetson Nano.

Hi KevinFFF,

Thank you for the reference to the “SPI loopback” post. The “Remove GPIO usage of SPI pins” step is beyond our capabilities at this time, which is limited to downloading the latest Jenson Nano flash image to a Windows-based workstation and running a tool that creates a Jetson Nano bootable SD card. Perhaps the NVIDIA already has Jetson Nano flash image with the “remove GPIO usage of SPI pins” modification in it that we would be able to download and to make bootable SD card from it.

Sorry that we don’t have that kind of image available currently since they are configurable by customer with their specific use case.

Alternative, could you decompile the DTB on your board(/boot/dtb/kernel_xxx.dtb) to dts manually and modify that line manually to check if it could work?

Hi KevinFFF,

I did try your suggestion of disassembling dtb, editing, assembling back on the Jetson Nano itself. After all that, the results are the same - no activity on the SPI outputs.

Here are steps my steps:

  1. Found kernel_tegra210-p3448-0000-p3449-0000-b00.dtb in /boot/dtb/ folder

  2. Used ‘sudo dtc -I dtb -O dts -o temp.dts kernel_tegra210-p3448-0000-p3449-0000-b00.dtb’ to disassemble (got some warning message but the file was created)

  3. Using editor replaced ‘gpio-input = <0xd8 0xc 0xd 0xe 0xf 0xe8 0x26 0x95 0x5 0xbc 0xbd 0xbe 0xc1 0xc2 0xa8 0xc8 0xca 0x4d 0x4e 0x4c 0x4f 0x32 0x33 0x10 0x11 0x12 0x13 0x14 0x3a 0x3d 0x3e 0x41 0xe4>;’ with ‘gpio-input = <0xd8 0x26 0x95 0x5 0xbc 0xbd 0xbe 0xc1 0xc2 0xa8 0xc8 0xca 0x4d 0x4e 0x4c 0x4f 0x32 0x33 0x3a 0x3d 0x3e 0x41 0xe4>;’ in the temp.dts file

  4. Used ‘sudo dtc -I dts -O dtb -o kernel_tegra210-p3448-0000-p3449-0000-b00.dtb temp.dts’ to assemble back (got some warning messages but timestamp of the file was updated)

  5. Rebooted the Jetson Nano.

  6. Tried running ‘sudo /opt/nvidia/jetson-io/jetson-io.py’ but it exited quickly. (It worked before this procedure.)

  7. Ran ‘sudo modprobe spidev’. It worked.

  8. Got, complied and ran the spidev_test.c. It ran with no issues but there was no activity SPI outputs.

I’ve attached the dtb and dts files from /boot/dtb/ folder. Anything the matter with these steps? What else to try?

(Attachment temp.dts is missing)

(attachments)

kernel_tegra210-p3448-0000-p3449-0000-b00.txt (232 KB)
tegra210-p3448-0000-p3449-0000-b00.txt (232 KB)

I would suggest you performing this before modifying the line of gpio-input in device tree.

Please also share the /boot/extlinux/extlinux.conf after you’ve used Jetson-IO to configure the pins for SPI usage.

Hi KevinFFF,

I did successfully configure GPIO for the SPI0 and SPI1

Hi KevinFFF,

(My last post was not complete)
I did successfully configure GPIO for the SPI0 and SPI1 using jetson-io.py prior to modification to gpio-input line.

Here is a copy of extlinux.conf file from my Jetson Nano.
extlinux_conf.txt (1.2 KB)