Strange behavior from SPI signals, loopback gets garbage

I have a Jetson Orin Nano, and I’m trying to communicate with a device via SPI. I used jetson-io.py to configure pins 19,21,23,24,26 for SPI and rebooted. I’m using the Linux spidev driver (/dev/spidev0.0), and I’ve written my own program to perform a loopback test.

When idle:

  • The CS signal (pin 24) is high at 3.4 volts (correct)
  • The CLK signal (pin 23) is low (correct)
  • The MOSI signal (pin 19) is low (correct)
  • The MISO signal (pin 21) is low (correct)

Next, I run a loop where I’m streaming 5 bytes of 0xff back to back. I don’t have a scope, so I’m having to use a multimeter. Here’s what I get:

  • The CS signal averages about 2.5 volts. It should be low most of the time, but evidently it’s not.
  • The CLK signal is averaging about 1 volt, which seems about right, albeit a bit low.
  • When the output data is 0xff, the MOSI signal is averaging less than 0.1 volts, but it should be high most of the time.
  • When the output data is zero, the MOSI signal is about the same, but it should be zero all of the time.
  • The MISO signal is at zero, which is right, since it’s open and pulled down by the SoC.

I’m doing all of this because when I connect MOSI and MISO together, I should read back what I’m sending, but instead, I get garbage. But it’s not total garbage. When the data written is all 255, then what I get back is mostly high values, but with lots of bits randomly zero. When the data written is all 0, then what I get back is mostly 0, with lots of bits being 1’s.

I’m running at 1kHz, so there shouldn’t be any signal integrity issues.

Here’s the test code:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <unistd.h>

#include <assert.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/types.h>
#include <linux/spi/spidev.h>

int configure_spi(int fd)
{
	int ret;
	char mode = SPI_MODE_3;
	char bits = 8;
	int speed = 1000;
	char lsbfirst = 0;
	
	ret = ioctl(fd, SPI_IOC_WR_MODE, &mode);
	if(ret < 0){
		perror("SPI_IOC_WR_MODE");
		printf("can't set spi mode 'SPI_IOC_WR_MODE' %d\n", ret);
		return 1;
	}
		
	ret = ioctl(fd, SPI_IOC_RD_MODE, &mode);
	if(ret < 0){
		printf("can't set spi mode 'SPI_IOC_RD_MODE'\n");
		return 1;
	}

	ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
	if(ret < 0){
		printf("can't set bits per word 'SPI_IOC_WR_BITS_PER_WORD'\n");
		return 1;
	}

	ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits);
	if(ret < 0){
		printf("can't get bits per word 'SPI_IOC_RD_BITS_PER_WORD'\n");
		return 1;
	}

	ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
	if(ret < 0){
		printf("can't set max speed hz 'SPI_IOC_WR_MAX_SPEED_HZ'\n");
		return 1;
	}

	ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);
	if(ret < 0){
		printf("can't get max speed hz 'SPI_IOC_RD_MAX_SPEED_HZ'\n");
		return 1;
	}
	
	ret = ioctl(fd, SPI_IOC_WR_LSB_FIRST, &lsbfirst);
	if(ret < 0){
		printf("can't set max speed hz 'SPI_IOC_WR_MAX_SPEED_HZ'\n");
		return 1;
	}

	ret = ioctl(fd, SPI_IOC_RD_LSB_FIRST, &lsbfirst);
	if(ret < 0){
		printf("can't get max speed hz 'SPI_IOC_RD_MAX_SPEED_HZ'\n");
		return 1;
	}
	
	printf("spi mode: %d\n", mode);
	printf("bits per word: %d\n", bits);
	printf("max speed: %d Hz (%d KHz)\n", speed, speed/1000);
	printf("lsbfirst: %d\n", lsbfirst);

	return 0;
}

int datagram(int fd, uint8_t *tbuf, uint8_t *rbuf, size_t len)
{
	struct spi_ioc_transfer xfer[1];
	memset(xfer, 0, sizeof(xfer));
	
	xfer[0].tx_buf = (unsigned long) tbuf;
	xfer[0].rx_buf = (unsigned long) rbuf;
	xfer[0].len           = len;
	xfer[0].speed_hz      = 1000;
	xfer[0].bits_per_word = 8;
	
	// printf("tx: ");
	// for (int i=0; i<len; i++) printf("%02x ", tbuf[i]);
	// printf("\n");
	// printf("-- %llx %llx %d %d %d, fd=%d\n", xfer[0].tx_buf, xfer[0].rx_buf, xfer[0].len, xfer[0].speed_hz, xfer[0].bits_per_word, fd);
	
	int ret = ioctl(fd, SPI_IOC_MESSAGE(1), xfer);
	if(ret < 0){
		perror("Error");
		printf("SPI_IOC_MESSAGE failed.. %d\n", ret);
		return -1;
	}
	
	// printf("rx: ");
	// for (int i=0; i<len; i++) printf("%02x ", rbuf[i]);
	// printf("\n");
	
	return 0;
}

int main()
{
	int fd = open("/dev/spidev0.0", O_RDWR);
	global_fd = fd;
	printf("fd=%d\n", fd);
	configure_spi(fd);

	uint8_t rbuf[5];
	// uint8_t tbuf[5] = {1, 2, 3, 4, 5};
	uint8_t tbuf[5] = {255, 255, 255, 255, 255};
	memset(rbuf, 0, 5);

	while (1)
	datagram(fd, tbuf, rbuf, 5);
}

Hi theosib,

Are you using the devkit or custom board for Orin Nano?

I would suggest using an oscilloscope to check the signal.

Could you help to the following thread for loopback test?

and please help to provide the result of the following command.

$sudo busybox devmem 0x0243d028 //SCLK
$sudo busybox devmem 0x0243d018 //MISO
$sudo busybox devmem 0x0243d040 //MOSI
$sudo busybox devmem 0x0243d008 //CS0
$sudo busybox devmem 0x0243d038 //CS1

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