XU4 odroid-wiringpi SPI VERY slow speed

Post Reply
hellhammer09
Posts: 6
Joined: Wed Jun 24, 2020 3:28 pm
languages_spoken: english, italian
ODROIDs: Odroid XU4
Has thanked: 0
Been thanked: 0
Contact:

XU4 odroid-wiringpi SPI VERY slow speed

Post by hellhammer09 » Wed Jun 24, 2020 10:06 pm

Hi everyone,
I see that the topic was discussed some times on the forum but mine is much more accentuated, so I'm asking your help again.

I'm trying to communicate on the SPI of my Odroid XU4 using the odroid-wiringpi package and it principle it works.

The problem is the very big gap between two following communications. I am communicating with an AD5065, a 16-bit DAC from Analog Devices, and I need to produce a very fast voltage ramp. Right now, I am creating a ramp with period 8s. I post a figure taken from my signal analyzer.

This first image is the single packet sent correctly at clock speed 5MHz and SPI mode 1.
Image


The second image report the sequence of packets transmitted in the same communication.
Image


As you can see, distance between two communication is around 63us, very much higher than the one reported from other discussions.
In particular, this topic (viewtopic.php?t=30582) is presenting an image with 0.5us delay between communications. How can I reach this level? It would be enough reducing the gap to 5us, but the lower, the better.

I also post the code that I am using:

Code: Select all

import odroid_wiringpi as wpi
wpi.wiringPiSetup()

# Setup
CHANNEL = 0
SPEED = 5000000 # 5MHz
wpi.wiringPiSPISetupMode(CHANNEL, SPEED, 1)

reserved = "0000"
command_bits = "0011"
DAC_code = 0
rise = False

while True:
    DAC_code_binary = '{0:016b}'.format(DAC_code)
    message = reserved + command_bits + address_bits + DAC_code_binary + reserved
    buffer = self._bin_to_ascii(message)
            
    wpi.wiringPiSPIDataRW(CHANNEL, bytes(buffer, 'utf-8')) 
            
    if DAC_code <= 0 or DAC_code >= 65535:
        rise = not rise
         
    if rise:
        DAC_code += DAC_code_increment
        DAC_code = 65535 if DAC_code >= 65535 else int(DAC_code)
    else:
        DAC_code -= DAC_code_increment
        DAC_code = 0 if DAC_code <= 0 else int(DAC_code)
I am using Ubuntu 18.04.3 with Kernel 4.14.150-170.

Thank you in advance for your help!
Last edited by hellhammer09 on Thu Jun 25, 2020 6:31 pm, edited 1 time in total.

User avatar
odroid
Site Admin
Posts: 34642
Joined: Fri Feb 22, 2013 11:14 pm
languages_spoken: English, Korean, Japanese
ODROIDs: ODROID
Has thanked: 824 times
Been thanked: 712 times
Contact:

Re: XU4 odroid-wiringpi VERY slow speed

Post by odroid » Thu Jun 25, 2020 11:30 am

Please look into this thread.
viewtopic.php?f=97&t=38804

Note that you need to send 32bit data as a packet after loading the SPI device driver with forced 32bit mode. https://wiki.odroid.com/odroid-xu4/soft ... _or_higher
modprobe spi_s3c64xx force32b=1
It will reduce the gap significantly.

hellhammer09
Posts: 6
Joined: Wed Jun 24, 2020 3:28 pm
languages_spoken: english, italian
ODROIDs: Odroid XU4
Has thanked: 0
Been thanked: 0
Contact:

Re: XU4 odroid-wiringpi VERY slow speed

Post by hellhammer09 » Thu Jun 25, 2020 6:30 pm

Thank you for your reply.

I have issued the modprobe command and it reduced the gap to 40us approximately, but it is not enough.

I have also checked the provided link. I see that you changed changed the SPI clock source in the Linux device tree. I've tried to search how to change this settings but I cannot find a guide on how to do it. Do you have some tutorial or guidance about that?

I have also tried to send packets in multiple of 60 but nothing changes.

Also, I have Kernel 4.14.150-170 -- do I need to update that to the latest version too?

Thank you for your patience!

User avatar
odroid
Site Admin
Posts: 34642
Joined: Fri Feb 22, 2013 11:14 pm
languages_spoken: English, Korean, Japanese
ODROIDs: ODROID
Has thanked: 824 times
Been thanked: 712 times
Contact:

Re: XU4 odroid-wiringpi SPI VERY slow speed

Post by odroid » Fri Jun 26, 2020 10:33 am

I agree 63us -> 40us is still a big number.
Just update the kernel to 4.14.180 via apt commands to make a more accurate clock frequency.

We've used spi_test.c sample code which can set the SPI clock without changing the device-tree stuff.
https://wiki.odroid.com/odroid-xu4/appl ... reparation

"multiple of 60" things is not related the ODROID-XU4 series.
It is applicable only for ODROID-N2 and ODROID-C4 series.

hellhammer09
Posts: 6
Joined: Wed Jun 24, 2020 3:28 pm
languages_spoken: english, italian
ODROIDs: Odroid XU4
Has thanked: 0
Been thanked: 0
Contact:

Re: XU4 odroid-wiringpi SPI VERY slow speed

Post by hellhammer09 » Fri Jun 26, 2020 5:39 pm

odroid wrote:
Fri Jun 26, 2020 10:33 am
I agree 63us -> 40us is still a big number.
Just update the kernel to 4.14.180 via apt commands to make a more accurate clock frequency.

We've used spi_test.c sample code which can set the SPI clock without changing the device-tree stuff.
https://wiki.odroid.com/odroid-xu4/appl ... reparation

"multiple of 60" things is not related the ODROID-XU4 series.
It is applicable only for ODROID-N2 and ODROID-C4 series.
Ok thank you.

I have updated the Kernel to 4.14.180-176. I can confirm that now the clock is stable up to 15MHz, while before it couldn't go beyond 5MHz.

Still, the delay remain. I don't have signal analyser that can sample at such frequencies, but when I issue the ramp cycle to my DAC, the ramp period remains constant even if I change frequency. This means that, in total, the delay between two communications is the main limitation.

If you have some other advices I will try to apply them.
In the meantime thank you for your support.

User avatar
odroid
Site Admin
Posts: 34642
Joined: Fri Feb 22, 2013 11:14 pm
languages_spoken: English, Korean, Japanese
ODROIDs: ODROID
Has thanked: 824 times
Been thanked: 712 times
Contact:

Re: XU4 odroid-wiringpi SPI VERY slow speed

Post by odroid » Mon Jun 29, 2020 11:46 am

If the SPI clock frequency is lower than 12.5Mhz, we could reduce the gap to near zero on the XU4.
We will show you a test code and an oscilloscope screen show tomorrow.

User avatar
odroid
Site Admin
Posts: 34642
Joined: Fri Feb 22, 2013 11:14 pm
languages_spoken: English, Korean, Japanese
ODROIDs: ODROID
Has thanked: 824 times
Been thanked: 712 times
Contact:

Re: XU4 odroid-wiringpi SPI VERY slow speed

Post by odroid » Mon Jun 29, 2020 1:58 pm

Here is our C test code.

Code: Select all

/*
 * SPI testing utility (using spidev driver)
 *
 * Copyright (c) 2007  MontaVista Software, Inc.
 * Copyright (c) 2007  Anton Vorontsov <avorontsov@ru.mvista.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License.
 *
 * Cross-compile with cross-gcc -I/path/to/cross-kernel/include
 */

#include <stdint.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/types.h>
#include <linux/spi/spidev.h>

#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))

static void pabort(const char *s)
{
	perror(s);
	abort();
}

static const char *device = "/dev/spidev1.1";
static uint8_t mode;
static uint8_t bits = 8;
static uint32_t speed = 500000;
static uint16_t delay;

static void transfer(int fd)
{
	int ret;
	uint8_t tx[] = {
		0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
		0x08, 0x09, 0x0A, 0x0B,	0x0C, 0x0D, 0x0E, 0x0F,
		0x10, 0x11, 0x12, 0x13,	0x14, 0x15, 0x16, 0x17,
		0x18, 0x19, 0x1A, 0x1B,	0x1C, 0x1D, 0x1E, 0x1F,
		0x20, 0x21, 0x22, 0x23,	0x24, 0x25, 0x26, 0x27,
		0x28, 0x29, 0x2A, 0x2B,	0x2C, 0x2D, 0x2E, 0x2F,
		0x30, 0x31, 0x32, 0x33,	0x34, 0x35, 0x36, 0x37,
		0x38, 0x39, 0x3A, 0x3B,	0x3C, 0x3D, 0x3E, 0x3F,	// 64 bytes

		0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
		0x48, 0x49, 0x4A, 0x4B,	0x4C, 0x4D, 0x4E, 0x4F,
		0x50, 0x51, 0x52, 0x53,	0x54, 0x55, 0x56, 0x57,
		0x58, 0x59, 0x5A, 0x5B,	0x5C, 0x5D, 0x5E, 0x5F,
		0x60, 0x61, 0x62, 0x63,	0x64, 0x65, 0x66, 0x67,
		0x68, 0x69, 0x6A, 0x6B,	0x6C, 0x6D, 0x6E, 0x6F,
		0x70, 0x71, 0x72, 0x73,	0x74, 0x75, 0x76, 0x77,
		0x78, 0x79, 0x7A, 0x7B,	0x7C, 0x7D, 0x7E, 0x7F,	// 128 bytes

		0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
		0x88, 0x89, 0x8A, 0x8B,	0x8C, 0x8D, 0x8E, 0x8F,
		0x90, 0x91, 0x92, 0x93,	0x94, 0x95, 0x96, 0x97,
		0x98, 0x99, 0x9A, 0x9B,	0x9C, 0x9D, 0x9E, 0x9F,
		0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7,
		0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
		0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7,
		0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,	// 192 bytes

		0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
		0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
		0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7,
		0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
		0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
		0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
		0xF0, 0xF1, 0xF2, 0xF3,	0xF4, 0xF5, 0xF6, 0xF7,
		0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF,	// 256 bytes

	};
	uint8_t rx[ARRAY_SIZE(tx)] = {0, };
	struct spi_ioc_transfer tr = {
		.tx_buf = (unsigned long)tx,
		.rx_buf = (unsigned long)rx,
		.len = ARRAY_SIZE(tx),
		.delay_usecs = delay,
		.speed_hz = speed,
		.bits_per_word = bits,
	};

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

	for (ret = 0; ret < ARRAY_SIZE(tx); ret++) {
		if (!(ret % 6))
			puts("");
		printf("%02X ", rx[ret]);
	}
	puts("");
}

static void print_usage(const char *prog)
{
	printf("Usage: %s [-DsbdlHOLC3]\n", prog);
	puts("  -D --device   device to use (default /dev/spidev1.1)\n"
	     "  -s --speed    max speed (Hz)\n"
	     "  -d --delay    delay (usec)\n"
	     "  -b --bpw      bits per word \n"
	     "  -l --loop     loopback\n"
	     "  -H --cpha     clock phase\n"
	     "  -O --cpol     clock polarity\n"
	     "  -L --lsb      least significant bit first\n"
	     "  -C --cs-high  chip select active high\n"
	     "  -3 --3wire    SI/SO signals shared\n");
	exit(1);
}

static void parse_opts(int argc, char *argv[])
{
	while (1) {
		static const struct option lopts[] = {
			{ "device",  1, 0, 'D' },
			{ "speed",   1, 0, 's' },
			{ "delay",   1, 0, 'd' },
			{ "bpw",     1, 0, 'b' },
			{ "loop",    0, 0, 'l' },
			{ "cpha",    0, 0, 'H' },
			{ "cpol",    0, 0, 'O' },
			{ "lsb",     0, 0, 'L' },
			{ "cs-high", 0, 0, 'C' },
			{ "3wire",   0, 0, '3' },
			{ "no-cs",   0, 0, 'N' },
			{ "ready",   0, 0, 'R' },
			{ NULL, 0, 0, 0 },
		};
		int c;

		c = getopt_long(argc, argv, "D:s:d:b:lHOLC3NR", lopts, NULL);

		if (c == -1)
			break;

		switch (c) {
		case 'D':
			device = optarg;
			break;
		case 's':
			speed = atoi(optarg);
			break;
		case 'd':
			delay = atoi(optarg);
			break;
		case 'b':
			bits = atoi(optarg);
			break;
		case 'l':
			mode |= SPI_LOOP;
			break;
		case 'H':
			mode |= SPI_CPHA;
			break;
		case 'O':
			mode |= SPI_CPOL;
			break;
		case 'L':
			mode |= SPI_LSB_FIRST;
			break;
		case 'C':
			mode |= SPI_CS_HIGH;
			break;
		case '3':
			mode |= SPI_3WIRE;
			break;
		case 'N':
			mode |= SPI_NO_CS;
			break;
		case 'R':
			mode |= SPI_READY;
			break;
		default:
			print_usage(argv[0]);
			break;
		}
	}
}

int main(int argc, char *argv[])
{
	int ret = 0;
	int fd;

	parse_opts(argc, argv);

	fd = open(device, O_RDWR);
	if (fd < 0)
		pabort("can't open device");

	/*
	 * spi mode
	 */
	ret = ioctl(fd, SPI_IOC_WR_MODE, &mode);
	if (ret == -1)
		pabort("can't set spi mode");

	ret = ioctl(fd, SPI_IOC_RD_MODE, &mode);
	if (ret == -1)
		pabort("can't get spi mode");

	/*
	 * 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");

	printf("spi mode: %d\n", mode);
	printf("bits per word: %d\n", bits);
	printf("max speed: %d Hz (%d KHz)\n", speed, speed/1000);

	transfer(fd);

	close(fd);

	return ret;
}
When we ran ./spidev_test -D /dev/spidev1.0 -b 8 -s 10000000 for 8bit / 10Mhz mode, we could see this wave form. The gap is less than 2usec only while your test result was over 40usec.
spidev_test_b8_10M.png
spidev_test_b8_10M.png (47.71 KiB) Viewed 145 times
When we ran ./spidev_test -D /dev/spidev1.0 -b 16 -s 10000000 for 16bit / 10Mhz mode, we could see this wave form.
spidev_test_b16_10M.png
spidev_test_b16_10M.png (57.1 KiB) Viewed 145 times
When we ran ./spidev_test -D /dev/spidev1.0 -b 32 -s 10000000 for 32bit / 10Mhz mode, we could see this wave form. It seems to have very narrow gap.
spidev_test_b32_10M.png
spidev_test_b32_10M.png (57.2 KiB) Viewed 145 times
We tested it on Kernel 4.14.180 as you did.
Try C code instead of Python to narrow down root causes.

hellhammer09
Posts: 6
Joined: Wed Jun 24, 2020 3:28 pm
languages_spoken: english, italian
ODROIDs: Odroid XU4
Has thanked: 0
Been thanked: 0
Contact:

Re: XU4 odroid-wiringpi SPI VERY slow speed

Post by hellhammer09 » Tue Jun 30, 2020 6:23 pm

Thank you for your answer.

Using your exact code I reproduced the same behaviour. Unfortunately, this is not what I am looking for in my case. In fact, you sent on the SPI lots of bytes in one single call, which means that the CS pin change state only one time.

In my case, to communicate with my DAC I have to send 32 bits and, to close the communication, CS should change state. Then I send another 32 bits and so on.

To simulate that, I took your code, removed all the bytes in the big list except 4 of them, and added a cycle to call the transfer function 5 times. I write the example down below (only the part I changed):

Code: Select all

for (int i=0; i<5; i++) {
    transfer(fd);
}
This is the result:
Image

As you see, the gap is still there when the CS pin has to be changed. I think that this is probably given by the management of the SPI process from the OS o something like that.

If this is the cause, I hope it can be improved in some next release of the Kernel.

User avatar
odroid
Site Admin
Posts: 34642
Joined: Fri Feb 22, 2013 11:14 pm
languages_spoken: English, Korean, Japanese
ODROIDs: ODROID
Has thanked: 824 times
Been thanked: 712 times
Contact:

Re: XU4 odroid-wiringpi SPI VERY slow speed

Post by odroid » Wed Jul 01, 2020 10:01 am

I think we need to measure "CS" state switching time.
BTW, can you tell me the part number of the SPI-DAC IC?

hellhammer09
Posts: 6
Joined: Wed Jun 24, 2020 3:28 pm
languages_spoken: english, italian
ODROIDs: Odroid XU4
Has thanked: 0
Been thanked: 0
Contact:

Re: XU4 odroid-wiringpi SPI VERY slow speed

Post by hellhammer09 » Wed Jul 01, 2020 8:21 pm

The DAC name is AD5065 from Analog Devices.

Post Reply

Return to “Hardware and peripherals”

Who is online

Users browsing this forum: No registered users and 2 guests