Community
cancel
Showing results for 
Search instead for 
Did you mean: 
GGan5
New Contributor I
871 Views

libmraa mraa_spi_transfer_buf sometimes delay its sending, not atomic

!

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 https://github.com/intel-iot-devkit/mraa/blob/master/src/spi/spi.c 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.

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

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

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

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.

3 Replies
MGilm
New Contributor I
46 Views

Silly question: Are there other, and can you turn off, interrupts when sending the data?

GGan5
New Contributor I
46 Views

Nope there are no other interrupts while sending the data, except kernel tasks which might interrupts at any point. Still that doesn't explain the delay while sending those bytes via SPI though. Hope to have some advice.

Sergio_A_Intel
Employee
46 Views

Hi,

This seems to be related to the issue some users have been having with SPI. There are a couple of bugs in the SPI in the current release. The bug affects timing issues very similar to yours as well as an improper behavior and added delays to the bus. We hope to have this fixed soon.

Some links of interest:

Sergio