3 Replies Latest reply on Dec 14, 2015 10:25 AM by Intel_Alvarado

    libmraa mraa_spi_transfer_buf sometimes delay its sending, not atomic

    D.Sync

      !

      Hello there Intel Edison Communities, I've been working on Intel Edison to get ADC data in 500 SPS (samples per seconds) and 1000 SPS. One issue that have been bothering me is the occasion missing samples in those sampling rates (i.e. 2ms and 1ms sampling interval respectively). In my application it is imperative NOT to have any missing samples. I've did all I could to guarantee it, including installing a RT_PREEMPT Linux patch on it. Although it helps to minimize the possibility of missing samples, it will still happen occasionally.

       

      So I've finally decided to use a hardware oscilloscope to idenfity the problem. In particular, I use it to make sure every single timing for the C program function call that I invoke. To my surprise, the main culprit is the mraa_spi_transfer_buf, which will occasionally takes a lot of time to send the buffer. Not only that the buffer is not transmitted in one shot sequentially, there seemed to be some constant clock delay when sending each byte. Above all, this function call is not atomic at all. So any process such as kernel might interrupt it while it is in the middle of transferring the whole buffer. I can only get the sample from the ADC after sending, say a series of commands. So this erratic behaviour will sometimes cause the sample to be missed.

       

      Following are the C code implementation from mraa spi.c Github page.

      mraa_spi_transfer_buf(mraa_spi_context dev, uint8_t* data, uint8_t* rxbuf, int length)
      {
          struct spi_ioc_transfer msg;
          memset(&msg, 0, sizeof(msg));
      
      
          msg.tx_buf = (unsigned long) data;
          msg.rx_buf = (unsigned long) rxbuf;
          msg.speed_hz = dev->clock;
          msg.bits_per_word = dev->bpw;
          msg.delay_usecs = 0;
          msg.len = length;
          if (ioctl(dev->devfd, SPI_IOC_MESSAGE(1), &msg) < 0) {
              syslog(LOG_ERR, "spi: Failed to perform dev transfer");
              return MRAA_ERROR_INVALID_RESOURCE;
          }
          return MRAA_SUCCESS;
      }
      
      
      
      

       

       

      ---

      Following is a program that I used to illustrate the problem. This program simply polls for a DATA_READY GPIO pins. If the interrupt is sent, then send 28 bytes with first byte = 0x12 and the rest being 0x00.

       

        const int BUFFER_LENGTH = 28;
        unsigned char txBuff[BUFFER_LENGTH] = { 0x12, 0 };
        unsigned char rxBuff[BUFFER_LENGTH] = { 0 };
      
        while (!done) {
             while (!isDataAvailable()) {} // keep on polling the DRDY pin status...
      
             spi_open(); // SPI CS LOW
             mraa_spi_transfer_buf(spi, txBuff, rxBuff, BUFFER_LENGTH);
             spi_close(); // SPI CS HIGH
        }
      

       

       

      Following images shows the logic analyzer captured.

      D5 - DATA_READY (GPIO pin set by ADS indicating data ready)

      D3 - MISO (input from ADC)

      D2 - MOSI (output to ADC)

      D1 - CLK

      D0 - CS

      S1 - Data put in the sending buffer

       

      First sample - Complete sending the whole buffer (28 bytes) without any interruption

      Delay when sending first byte (0x12) after CS LOW.

      mraa spi first byte.jpg

       

      Delay between sending first byte (0x12) to second byte (0x00). Notice the huge delay gap. This delay gap varies depending on each sample.

      mraa spi first to second byte.jpg

       

      Delay between sending second byte to n byte. This delay is very consistent between second bytes and subsequent bytes even across sample.

      mraa spi second to n byte.jpg

       

      Second sample - Interruption while sending the 28 bytes buffer, perhaps due to kernel thread interruption?

      mraa spi byte send interrupt.jpg

       

      Overall this observation shows that:

      - There is a huge delay gap before the first byte is sent

      - There is a varied delay gap between the first and the second byte

      - There is a constant delay between sending the second byte and the rest of the bytes in the buffer

       

      Hope this illustrates my problem well. Until the MCU Quark supports SPI, this is perhaps what I'll encountered while sampling.

       

      Message was edited by: Gary Gan Include logic analyzer oscilloscope picture.