toxibunny
Posts: 1382
Joined: Thu Aug 18, 2011 9:21 pm

(resolved) unable to compile spi loopback tester :(

Mon Apr 28, 2014 6:50 pm

here's my code, copy/pasted into nano through mobaxterm through SSH:

Code: Select all

/*
 * SPI testing utility (using spidev driver)
 *
 * Copyright (c) 2007  MontaVista Software, Inc.
 * Copyright (c) 2007  Anton Vorontsov <[email protected]>
 *
 * 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 uint32_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[] = {
		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
		0x40, 0x00, 0x00, 0x00, 0x00, 0x95,
		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
		0xDE, 0xAD, 0xBE, 0xEF, 0xBA, 0xAD,
		0xF0, 0x0D,
	};
	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,
	};

	if (mode & SPI_TX_QUAD)
		tr.tx_nbits = 4;
	else if (mode & SPI_TX_DUAL)
		tr.tx_nbits = 2;
	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_QUAD | SPI_TX_DUAL))
			tr.rx_buf = 0;
		else if (mode & (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");

	for (ret = 0; ret < ARRAY_SIZE(tx); ret++) {
		if (!(ret % 6))
			puts("");
		printf("%.2X ", 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"
	     "  -N --no-cs    no chip select\n"
	     "  -R --ready    slave pulls low to pause\n"
	     "  -2 --dual     dual transfer\n"
	     "  -4 --quad     quad transfer\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' },
			{ "dual",    0, 0, '2' },
			{ "quad",    0, 0, '4' },
			{ NULL, 0, 0, 0 },
		};
		int c;

		c = getopt_long(argc, argv, "D:s:d:b:lHOLC3NR24", 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;
		case '2':
			mode |= SPI_TX_DUAL;
			break;
		case '4':
			mode |= SPI_TX_QUAD;
			break;
		default:
			print_usage(argv[0]);
			break;
		}
	}
	if (mode & SPI_LOOP) {
		if (mode & SPI_TX_DUAL)
			mode |= SPI_RX_DUAL;
		if (mode & SPI_TX_QUAD)
			mode |= SPI_RX_QUAD;
	}
}

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_MODE32, &mode);
	if (ret == -1)
		pabort("can't set spi mode");

	ret = ioctl(fd, SPI_IOC_RD_MODE32, &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: 0x%x\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;
}
I'm told to compile it thus:

Code: Select all

gcc -o spidevtester spidevtester.c
But I just get a load of error messages, like this:

Code: Select all

spidevtester.c: In function âtransferâ:
spidevtester.c:60:13: error: âSPI_TX_QUADâ undeclared (first use in this function)
spidevtester.c:60:13: note: each undeclared identifier is reported only once for each function it a                                                         ppears in
spidevtester.c:61:5: error: âstruct spi_ioc_transferâ has no member named âtx_nbitsâ
spidevtester.c:62:18: error: âSPI_TX_DUALâ undeclared (first use in this function)
spidevtester.c:63:5: error: âstruct spi_ioc_transferâ has no member named âtx_nbitsâ
spidevtester.c:64:13: error: âSPI_RX_QUADâ undeclared (first use in this function)
spidevtester.c:65:5: error: âstruct spi_ioc_transferâ has no member named ârx_nbitsâ
spidevtester.c:66:18: error: âSPI_RX_DUALâ undeclared (first use in this function)
spidevtester.c:67:5: error: âstruct spi_ioc_transferâ has no member named ârx_nbitsâ
spidevtester.c: In function âparse_optsâ:
spidevtester.c:172:12: error: âSPI_TX_DUALâ undeclared (first use in this function)
spidevtester.c:175:12: error: âSPI_TX_QUADâ undeclared (first use in this function)
spidevtester.c:184:12: error: âSPI_RX_DUALâ undeclared (first use in this function)
spidevtester.c:186:12: error: âSPI_RX_QUADâ undeclared (first use in this function)
spidevtester.c: In function âmainâ:
spidevtester.c:204:18: error: âSPI_IOC_WR_MODE32â undeclared (first use in this function)
spidevtester.c:208:18: error: âSPI_IOC_RD_MODE32â undeclared (first use in this function)
What am I doing wrong? I don't have much experience with C - I'm planning to use python for the real project, but my python test code isn't working yet either, so I'm just using this confirmed, working test code to make sure that my ports are working at all...
Last edited by toxibunny on Tue Apr 29, 2014 2:06 pm, edited 1 time in total.
note: I may or may not know what I'm talking about...

toxibunny
Posts: 1382
Joined: Thu Aug 18, 2011 9:21 pm

Re: unable to compile spi loopback tester :(

Mon Apr 28, 2014 6:57 pm

...Extra info - I'm using non-noobs raspbian, fully updated, on a model A, and following instructions about the loopback test from here: http://elinux.org/RPi_SPI , and setup instructions from here: http://www.brianhensley.net/2012/07/get ... ry-pi.html
note: I may or may not know what I'm talking about...

User avatar
joan
Posts: 14473
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: unable to compile spi loopback tester :(

Mon Apr 28, 2014 6:59 pm

The constants SPI_IOC_RD_MODE32, SPI_IOC_WR_MODE32, SPI_TX_QUAD, and SPI_TX_DUAL are not present in spidev.h on my laptop or the Pi.

Where did you get the code from?

toxibunny
Posts: 1382
Joined: Thu Aug 18, 2011 9:21 pm

Re: unable to compile spi loopback tester :(

Mon Apr 28, 2014 7:13 pm

I got it from the spi loopback section on the elinux.org page I linked to in the second post.

Looking at the code now, I can see that it's no good. Others have said it works though. Strange :S
note: I may or may not know what I'm talking about...

User avatar
joan
Posts: 14473
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: unable to compile spi loopback tester :(

Mon Apr 28, 2014 7:19 pm

toxibunny wrote:I got it from the spi loopback section on the elinux.org page I linked to in the second post.

Looking at the code now, I can see that it's no good. Others have said it works though. Strange :S
I wonder if the code was written before SPI was supported on the Pi by the bcm drivers. The constants look like they are from a more more recent version of spidev.h.

Perhaps when proper support was added an older version of spidev.h was used for compatibility with the rest of the kernel modules.

toxibunny
Posts: 1382
Joined: Thu Aug 18, 2011 9:21 pm

Re: unable to compile spi loopback tester :(

Mon Apr 28, 2014 7:32 pm

Well, I've done enough for tonight. Finally got the headless, usb-hubless model A connecting to wifi on boot, so continuing tomorrow will be easier. Thanks for the info - I was getting really frustrated there...

G'night!
note: I may or may not know what I'm talking about...

notro
Posts: 695
Joined: Tue Oct 16, 2012 6:21 pm
Location: Drammen, Norway

Re: unable to compile spi loopback tester :(

Tue Apr 29, 2014 12:59 am

Use this instead:

Code: Select all

wget https://raw.githubusercontent.com/raspberrypi/linux/rpi-3.10.y/Documentation/spi/spidev_test.c
QUAD and DUAL came in 3.12 and Linus' tree is now what's to become 3.15
I'll update the elinux page tomorrow.

toxibunny
Posts: 1382
Joined: Thu Aug 18, 2011 9:21 pm

Re: unable to compile spi loopback tester :(

Tue Apr 29, 2014 5:38 am

notro wrote:Use this instead:

Code: Select all

wget https://raw.githubusercontent.com/raspberrypi/linux/rpi-3.10.y/Documentation/spi/spidev_test.c
QUAD and DUAL came in 3.12 and Linus' tree is now what's to become 3.15
I'll update the elinux page tomorrow.

Thanks! That compiled first time no problems. I had to change the line

Code: Select all

static const char *device = "/dev/spidev1.1";
to

Code: Select all

static const char *device = "/dev/spidev0.0";
to get it to work properly though. But again, thanks very much! Now I know my wires are working... :)
note: I may or may not know what I'm talking about...

notro
Posts: 695
Joined: Tue Oct 16, 2012 6:21 pm
Location: Drammen, Norway

Re: unable to compile spi loopback tester :(

Tue Apr 29, 2014 12:06 pm

I had to change the line
Using this argument would achieve the same:

Code: Select all

-D /dev/spidev0.0

Return to “Interfacing (DSI, CSI, I2C, etc.)”