SPI:Got incorret data in BBGW

Hi,

I tried to run a spidev_test.c program in my BBGW , but I got incorrect data.

My system info …

ubuntu@arm:~$ uname -r

4.4.12-ti-r30

ubuntu@arm:~$ cat /etc/issue

Ubuntu 16.04 LTS \n \l

ubuntu@arm:~$ ls /dev/spi*

/dev/spidev1.0

ubuntu@arm:~$ sudo cat /sys/kernel/debug/pinctrl/44e10800.pinmux/pingroups

registered pin groups:

group: spi0_pins_s0

pin 84 (44e10950.0)

pin 85 (44e10954.0)

pin 86 (44e10958.0)

pin 87 (44e1095c.0)

My source code :


 #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.0";  
 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;  
 }  

Connect pin 21 and pin 18 on P9. Compile and run the code.

gcc -Wall spi_test.c -o spi_test.o

I got incorrect data.

ubuntu@arm:~$ ./spi_test.o

spi mode: 0x0

bits per word: 8

max speed: 500000 Hz (500 KHz)

FF FF FF FF FF FF

00 00 00 00 00 33

FF FF FF FF FF FF

FF FF FF FF FF FF

FF FF FF FF FF FF

FC F3 FC FF CC F3

00 F3

Then I change the transfer data like this …

uint8_t tx[] = {

0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,

};

Then I got :

00 03 0C 0F 30 33 3C 3F

Convert 00 03 0C 0F 30 33 3C 3F to binary , it is

0000 0000 0000 0011 0000 1100 0000 1111 0011 0000 0011 0011 0011 1100 0011 1111

Convert the transfer data00 01 02 03 04 05 06 07 to binary ,it is

0000 0000 0000 0001 0000 0010 0000 0011 0000 0100 0000 0101 0000 0110 0000 0111

All the low four bits copied once and shifted to high…

Can someboy help?

Thanks.