title: Why my spi test C code get this result?
body: <p>At the bottom is the spi test code (spitest.c) I used, and when running it on my linux kit, I got this result:</p>
  
  <pre><code>root@abcd-kit:/system # ./spitest                                     
  open device: /dev/spidev0.0
  set spi mode: 0
  set bits per word: 8
  set max speed: 2000000 Hz (2 MHz)
  the received data is below:
  
  00 00 00 00 30 30 
  30 0A 00 00 00 00 
  00 00 00 00 2F 73 
  the received data is below:
  
  00 00 00 00 30 30 
  30 0A 00 00 00 00 
  00 00 00 00 2F 73 
  
  ...
  
  dmesg output:
  
      &lt;7&gt;[ 1254.714088] usif-spi e1100000.usif1: Pushing msg a8085ed0
      &lt;6&gt;[ 1254.714367] SPI XFER  :ae81c700  , Length : 18
      &lt;6&gt;[ 1254.714404]    TX Buf :a6207000 , TX DMA :  (null)
      &lt;6&gt;[ 1254.714425]    RX Buf :92bf5000 , RX DMA :  (null)
      &lt;6&gt;[ 1254.714445]   CS change:0, bits/w :8, delay : 0 us, speed : 2000000 Hz
      &lt;7&gt;[ 1254.714471] TX---&gt;:31 a5 bb 00 00 bb fc 76 80 84 1e 00 5c 29 7d 77
      &lt;7&gt;[ 1254.714491] TX---&gt;:44 b9
      &lt;7&gt;[ 1254.714511] RX---&gt;:00 00 00 00 30 30 30 0a 00 00 00 00 00 00 00 00
      &lt;7&gt;[ 1254.714534] RX---&gt;:2f 73
      &lt;7&gt;[ 1254.714558] usif-spi e1100000.usif1: Msg a8085ed0 completed with status 0
      &lt;7&gt;[ 1255.725936] usif-spi e1100000.usif1: Pushing msg a8085ed0
      &lt;6&gt;[ 1255.726472] SPI XFER  :ae81cc40  , Length : 18
      &lt;6&gt;[ 1255.726604]    TX Buf :a6207000 , TX DMA :  (null)
      &lt;6&gt;[ 1255.726656]    RX Buf :92bf5000 , RX DMA :  (null)
      &lt;6&gt;[ 1255.726706]   CS change:0, bits/w :8, delay : 0 us, speed : 2000000 Hz
      &lt;7&gt;[ 1255.726773] TX---&gt;:31 a5 bb 00 00 bb fc 76 94 29 7d 77 5c 29 7d 77
      &lt;7&gt;[ 1255.726829] TX---&gt;:44 b9
      &lt;7&gt;[ 1255.726875] RX---&gt;:00 00 00 00 30 30 30 0a 00 00 00 00 00 00 00 00
      &lt;7&gt;[ 1255.726925] RX---&gt;:2f 73
  </code></pre>
  
  <p>And the biggest problem is that I cannot get correct result from miso pin (read is wrong, can do write correctly). Whatever I do, e.g. connect miso to ground or 1.8V, it always give this kind of result. The fisrt 5 data are always zero (I think it is because tx buffer has size of 5 and it is half duplex), and then followed random data, even that I used memset() to set rx buffer data to be zero before each spi transfer. And if I stop the program and run it again, the data changed but they are still random.
  How could I read correct data from miso pin?
  Thanks!</p>
  
  <p><strong><em>spitest.c</em></strong></p>
  
  <pre><code>/*
   * SPI testing utility (using spidev driver)
   *
   * Copyright (c) 2007  MontaVista Software, Inc.
   * Copyright (c) 2007  Anton Vorontsov &lt;avorontsov@ru.mvista.com&gt;
   *
   * 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 &lt;stdint.h&gt;
  #include &lt;unistd.h&gt;
  #include &lt;stdio.h&gt;
  #include &lt;stdlib.h&gt;
  #include &lt;getopt.h&gt;
  #include &lt;fcntl.h&gt;
  #include &lt;sys/ioctl.h&gt;
  #include &lt;linux/types.h&gt;
  #include "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/spidev0.0";
  static uint8_t mode;
  static uint8_t bits = 8;
  static uint32_t speed = 2000000;
  static uint16_t delay;
  #define LENGTH 18
  
  static void transfer(int fd)
  {
      int ret, i;
      uint8_t tx[5] = {0x31, 0xa5, 0xbb};
      uint8_t rx[LENGTH] = {0, };
      struct spi_ioc_transfer tr = {
          .tx_buf = (unsigned long)tx,
          .rx_buf = (unsigned long)rx,
          .len = LENGTH,
          .delay_usecs = delay,
          .speed_hz = speed,
          .bits_per_word = bits,  //important, bits = 8 means byte transfer is possible
      };
  
      memset(rx, 0, LENGTH);
  
      ret = ioctl(fd, SPI_IOC_MESSAGE(1), &amp;tr);
      if (ret &lt; 1)
          pabort("can't send spi message\n");
  
      printf("the received data is below:\n");
      for (ret = 0; ret &lt; LENGTH; ret++) {    //print the received data, by Tom Xue
          if (!(ret % 6))
              puts("");
          printf("%.2X ", rx[ret]);
      }
      puts("");
  }
  
  int main(int argc, char *argv[])
  {
      int ret = 0;
      int fd;
      unsigned char rd_buf[32];
  
      fd = open(device, O_RDWR);
      if (fd &lt; 0)
          pabort("can't open device\n");
  
      /*
   *      * spi mode
   *           */
      ret = ioctl(fd, SPI_IOC_WR_MODE, &amp;mode);
      if (ret == -1)
          pabort("can't set spi mode\n");
  
      ret = ioctl(fd, SPI_IOC_RD_MODE, &amp;mode);
      if (ret == -1)
          pabort("can't get spi mode\n");
  
      /*
   *      * bits per word
   *           */
      ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &amp;bits);
      if (ret == -1)
          pabort("can't set bits per word\n");
  
      ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &amp;bits);
      if (ret == -1)
          pabort("can't get bits per word\n");
  
      /*
   *      * max speed hz
   *           */
      ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &amp;speed);
      if (ret == -1)
          pabort("can't set max speed hz\n");
  
      ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &amp;speed);
      if (ret == -1)
          pabort("can't get max speed hz\n");
  
      printf("open device: %s\n", device);
      printf("set spi mode: %d\n", mode);
      printf("set bits per word: %d\n", bits);
      printf("set max speed: %d Hz (%d MHz)\n", speed, speed/1000000);
  
      while(1){
          transfer(fd);
          //read(fd, rd_buf, 4);
          //printf("rd_buf = %s, %d, %d, %d, %d\n", rd_buf, rd_buf[0], rd_buf[1], rd_buf[2], rd_buf[3]);
          //memset(rd_buf, 0, 10);
          sleep(1);
      }
  
      close(fd);
  
      return ret;
  }
  </code></pre>
  
  <p><strong>More:</strong>
  My CPU is Intel Sofia-3gr, I guess its spec is not publicly released. I see the Tx data from my oscilloscope, and confirmed that TX is right.
  I can also printk the pinmux/pinctrl setting (use ioremap and ioread32), it is also right. I say it right also because that I can see how to set it as SPI from those dts reference files, I just follow them.</p>
  
  <p><strong>Key:</strong>
  I just find that the SPI TX interrupt is pending each time a spi transfer starts, but no SPI RX interrupt pending. Hence the spi driver code will not read the RX data at all. As the reason, I don't know.</p>