Setting SPI0 as slave and read buffer data.

Hello,

I am developing a C application to read from the SPI0 from the Beaglebone Black.

The test I am doing is with two Beaglebones, one configured as a slave which transmits data, and the other I want to act as slave.

Both run a kernel 4.4.20-ti-r43. The master it’s working fine, but the slave it doesn’t. The connection diagram I planned is attached as an image.

The device-tree for the slave Beaglebone Black is the following:

/dts-v1/;

/ {
compatible = “ti,beaglebone”, “ti,beaglebone-black”, “ti,beaglebone-green”;
part-number = “BB-SPIDEV0”;
version = “00A0”;
exclusive-use = “P9.17”, “P9.18”, “P9.21”, “P9.22”, “spi0”;

fragment@0 {
target = <0xdeadbeef>;

overlay {

pinmux_bb_spi0_pins {
pinctrl-single,pins = <
0x150 0x30 /* CLK INPUT */
0x154 0x30 /* DSO INPUT */
0x158 0x10 /* DS1 OUTPUT */
0x15c 0x30 /* CS0 INPUT */
>;
linux,phandle = <0x1>;
phandle = <0x1>;
};
};
};

fragment@1 {
target = <0xdeadbeef>;

overlay {
#address-cells = <0x1>;
#size-cells = <0x0>;
status = “okay”;
pinctrl-names = “default”;
pinctrl-0 = <0x1>;
ti,pio-mode;

channel@0 {
#address-cells = <0x1>;
#size-cells = <0x0>;
compatible = “spidev”;
reg = <0x0>;
spi-max-frequency = <0xf42400>;
spi-cpha;
};

channel@1 {
#address-cells = <0x1>;
#size-cells = <0x0>;
compatible = “spidev”;
reg = <0x1>;
spi-max-frequency = <0xf42400>;
};
};
};

symbols {
bb_spi0_pins = “/fragment@0/overlay/pinmux_bb_spi0_pins”;
};

local_fixups {

fragment@1 {

overlay {
pinctrl-0 = <0x0>;
};
};
};

fixups {
am33xx_pinmux = “/fragment@0:target:0”;
spi0 = “/fragment@1:target:0”;
};
};

and the C code used to read from the SPI is the following

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

void pabort(char *string)
{
perror(string);
abort();
}

void usage(char *progname)
{
printf(“usage: %s \n”, progname);
}

void spiRead(int fd, uint32_t *rxbuffer, uint8_t bits, size_t txlen, uint32_t spiSpeed)
{
*rxbuffer = 0;

struct spi_ioc_transfer tr =
{
.tx_buf = (uint32_t) 0,
.rx_buf = (uint32_t) rxbuffer,
.len = txlen,
.delay_usecs = 1,
.speed_hz = spiSpeed,
.bits_per_word = bits,
};

if(ioctl(fd, SPI_IOC_MESSAGE(1), &tr) == -1)
{
perror(“can’t read SPI message”);
return;
}
else
printf(“SPI read: %x\n”, *rxbuffer);

}

int main(int argc, char **argv)
{
int spifd = 0;
uint8_t mode = 3;
uint8_t bits = 32;
uint32_t speed = 500000;
uint32_t rxVal = 0;

close(spifd);
spifd = open("/dev/spidev1.0", O_RDWR);
if(spifd == -1)
{
close(spifd);
pabort("open: ");
}

if(ioctl(spifd, SPI_IOC_WR_MODE, &mode) == -1)
pabort("ioctl SPI_IOC_WR_MODE: ");

if(ioctl(spifd, SPI_IOC_WR_BITS_PER_WORD, &bits))
pabort("ioctl SPI_IOC_WR_BITS_PER_WORD: ");

if(ioctl(spifd, SPI_IOC_WR_MAX_SPEED_HZ, &speed))
pabort("ioctl SPI_IOC_WR_MAX_SPEED_HZ: ");

while(1)
{
// printf(“Sending message to %s\n”, argv[1]);

spiRead(spifd, &rxVal, bits, sizeof(rxVal), speed);
// usleep(500000);
}

close(spifd);

return 0;
}

However, the value read into rxBuffer is always 0xffffffff and ``from the SPI0_SCLK pin I can see the clock signal (through my oscilloscope) so the CLK pin is not set as input as device-tree source should configure.

From AM335x Technical Reference Manual, the SPI0 can be configured as Master and as Slave.
What’s wrong in my setup or what is the additional setting I have to do to have the SPI working as slave ?

Thank you in advance.
Regards,
Simon

BBB_SPI_CONN.png

Even I have the same problem, did you figure out why?

You need v4.13.x+

https://elinux.org/Tests:MSIOF-SPI-Slave

https://fosdem.org/2018/schedule/event/hwenablement_linux_as_spi_slave/attachments/slides/2355/export/events/attachments/hwenablement_linux_as_spi_slave/slides/2355/Linux_as_an_SPI_Slave_Handouts.pdf

Regards,