5 years, 3 months ago.

Missing data in SPI Slave

Hello,

I am trying to send some data using SPI interface. I am using Analog Devices DC9018B https://www.analog.com/en/design-center/evaluation-hardware-and-software/evaluation-boards-kits/dc9018b-b.html#eb-overview as SPI master and FRDM-K64F as SPI slave. The sequence which i am sending from master is as below:

60 F4 6C 00 3A 2E 76 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 03
60 F4 6C 00 3A 2E 76 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 03
...

I am using keil uvision to build and run spi slave app. I am able to receive all the bytes if i use a large buffer and keep on adding the incoming data to this buffer. The program is as below:

SPI Slave using buffer

#include "mbed.h"
#include <stdio.h>

SPISlave device(PTD2, PTD3, PTD1, PTD0); // mosi, miso, sclk, cs
Serial pc(USBTX, USBRX); // tx, rx

int main()
{
    pc.printf("=================== SPI Slave ===================================\r\n");
    device.format(8, 3); 
    device.frequency(1000000);

    int reply = 0x00;
    device.reply(reply); 
    int character_count = 0;
    char received_buffer[256] = { '\0' };
    while (1)
    {
        if (device.receive())
        {
            if (character_count < 256)
            {
                received_buffer[character_count++] = device.read();
            }
            else if (character_count == 256)
            {
                character_count++;
                for (int i = 0; i < 256; i++)
                {
                    pc.printf("%02X ", received_buffer[i]);
                }
            }
        }
    }
}
Output from this program looks as below:
60 F4 6C 00 3A 2E 76 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 03
60 F4 6C 00 3A 2E 76 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 03
...

However the above code cannot be used if i want to continuously keep checking the incoming data. I used a queue to put the incoming data and then there is separate thread which will dequeue the bytes. The code is as below:

SPI Slave using queue

#include "mbed.h"
#include <stdio.h>
#include <EventQueue.h>

SPISlave device(PTD2, PTD3, PTD1, PTD0); // mosi, miso, sclk, cs
Serial pc(USBTX, USBRX); // tx, rx

typedef struct
{
    char input_data;
} message_t;

MemoryPool<message_t, 256> mpool;
Queue<message_t, 256> queue;
Thread enqueueThread;
Thread dequeueThread;

void onDequeue(void)
{
    while (true)
    {
        osEvent evt = queue.get();
        if (evt.status == osEventMessage)
        {
            message_t* message = (message_t*)evt.value.p;
            pc.printf("%02X ", message->input_data);
            mpool.free(message);
        }
    }
}

void enqueue(void)
{
    while (1)
    {
        if (device.receive())
        {
            message_t* message = mpool.alloc();
            message->input_data = device.read();
            queue.put(message);
        }
    }
}

int main()
{
    pc.printf("=================== SPI Slave ===================================\r\n");
    device.format(8, 3); 
    device.frequency(1000000); 

    dequeueThread.start(callback(onDequeue));
    enqueueThread.start(callback(enqueue));
    int reply = 0x00;
    device.reply(reply); // Prime SPI with first reply

    dequeueThread.join();
    enqueueThread.join();
}

The problem comes when i use queue. I saw printf takes considerable amount of time so i created a thread to do this job. The output from this program is as below:

60 F4 6C 00 3A 2E 76 00 00 00 00 00 00 00 00 00 00 00 00 00 03
60 F4 6C 00 3A 2E 76 00 00 00 00 00 00 00 00 00 00 00 00 00 03
...

As we can see there are some bytes which are missing. I have also attached a log file /media/uploads/ravisjce/logic_analyzer.csv from saleae logic analyzer which shows the bytes received from master and also the time interval between the bytes.

My question is even though i am using printf statement in a thread, why is it causing data loss. I tried couple of things before i posted this question

  • Change the SPI frequency to 2- 5MHz. Still there is data loss.
  • Eliminate the printf statement in thread and just insert the bytes to queue. After receiving 256 bytes of data in the queue print the values in the queue. Still there is data loss.

Looks like "put" method in queue takes some time because of which there is data loss. Is there a way to fix this data loss?

1 Answer

5 years, 3 months ago.

Hello, I would start by lowering the datarate. In K64F software reads the byte and sends reply byte. Your slave might be too slow. Creating more threads will not help. Try first with low datarate. If it helps it proves the theory correct.

Thanks for the reply Pekka. I tried to lower the data rate but unfortunately it didn't solve the issue. The reason why slave is slow is because it is using a queue. If i just use an array and add the incoming data from SPI interface then there are no issues. My question is why is the "put" method in queue taking so much time that it misses some data on SPI interface.

posted by Ravi Nagendra 28 Aug 2019