How to use SPISlave when data lengths is unknown

Hello everyone,
I want to make device reacting to some SPI communication cases between some CPU and periphery. Just like reading some EEPROM memory address or writing to some address. No need to send any data back.
My board is NUCLEO-F429ZI. I’m trying to use SPISlave, and I’m just reading communication to decode command, address and data. Main part of my testing code is:

 SPISlave SPIdevice(PA_7, NC, PA_5, PA_4); //MOSI, MISO, SCLK, CS
char array[100][10];
...
  SPIdevice.frequency( 4000000) ;
    //lcd.cls();
    int max=9;
    int i=0; 
    while (!btn && i<100) {
                 if(SPIdevice.receive()) {
                     for (int ii=0;ii<max;ii++){
                         array[i][ii]=SPIdevice.read();
                     }
                i++;
               } 
        }  

So this code work a bit, array data for testing is written to SD card later, not when reading SPI.
For now first 6 columns of my array is filled with data like this:
3 1 96 0 0 3
0 3 1 9A 0 3
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 3 e 40
But real data from analyzer is:
Packet ID,MOSI
0,0x03,
0,0x01,
0,0x96,
0,0x00,
0,0x00,
1,0x03,
1,0x01,
1,0x98,
1,0x00,
1,0x00,
2,0x03,
2,0x01,
2,0x9A,
2,0x00,
3,0x03,
3,0x0E,
3,0x5E,
3,0x00,

4,0x03,
4,0x0E,
4,0x40,
My problem is every communication is unknown in data length. So how to know when to stop do read()? Or if to be more precise - how to correctly read only first 6-8 bytes of every communication? Even if some communications is shorter. Maybe there is some other methods to read and decode command, address and some first data?

Hello,

I am not sure but from my point of view you need to have fixed data length or an internal mechanism how to determine it. For example first byte of data can hold length of current packed of data, or place data between two special chars (it will mark start and end of packet) and so on.

I think, you also need checking if are some data available for every single read method call. The while loop can be (probably will) faster then SPI comunication, so you will lose data or read empty buffer or some garbage.

// inside a loop
if(SPIdevice.receive()) {
  char c  = SPIdevice.read();
  // process the c variable
} 

BR, Jan

Thank you for the reply.
My biggest problem is there is no way to know length or mark start/stop. I can’t change existing communication in functional system from other company. I’m just want to react to some control commands.

2022-01-11, an 12:49, Jan Kamidra via Arm Mbed OS support forum <mbed@discoursemail.com> rašė:

Hello,
Perhaps analyzing the CS signal will help?
You can also try to enter a timeout for receiving a byte by SPI, if you cannot use the “length” field.
It is good practice to look at the exchange on the SPI bus with an oscilloscope.

Hi,
For now I’m thinking CS signal processing is only solution for my problem. I’m just curious why there is no such function in SPI library itself. Or at least I did not found it.
Communication itself I already checked with data analyser and there CS work fine. As per my data example packed ID

Hello.
I look at SPI and see: The SPI Interface provides a Serial Peripheral Interface Master.
Probably this is the point?
SPI slave is basically a simple clocked shift register with a chip select signal.

I’m not so great at C++, especially MBED OS. So for Master usage I still need to learn a lot. Especially when most of official examples tested before was incomplete, poorly documented or for outdated OS versions… Mbed Studio also has some bugs… This makes learning more difficult :slight_smile:
For now I will try to deal with SPISlave and CS triggering

Hello,
Looks like I accidentally misled you, SPI and SPI Slave are different classes.
Usually, such problems are solved by a simplification method, maybe it makes sense to find a ready-made example of working with an SPI slave without Mbed and C ++ in pure C with or without HAL and see what comes in the debugger on the board?
Although, perhaps the problem is generally hardware, I previously wrote about the oscilloscope.
Regarding the readiness of Mbed, I can say with the phrase of one Jewish humorist “play here, don’t play here, but here they wrap the fish …”. I don’t want to offend anyone, the project team is doing a big job and a great product!
But the simplicity of the implementation of complex things in Mbed just personally motivates me to go further in the study.

Hello,
Thank you for the reply. How to deal with online registers, variables of some types of industrial PLC I know well enough. But there is completely new dark area for me… OK, I will try to find some examples.
Regarding hardware problems - I do not understand what can be wrong there and what to test. As I wrote before I see absolutely normal communication with hi-speed logic analyzer like in SPI protocol documentation. BTW I tried to write to array all received data and I’m getting the same data as in analyzer. Only there I do not know from which packet these data bits are and accordingly I do not know is there command, address or data.

So let’s sum it up… Somewhere is a SPI master that communicates with a SPI Slave device. You want connecting another SPI Slave device (base on Mbed in this moment) to same bus as a listener and react to some specific commands.
Do you know something more about one of these ends?
Also if you have an example of data from analyzer maybe you can place here a picture.

BR, Jan

You are correct about setup. For now I’m trying to check communication to EEPROM. If there are some readings from specific address or writings to specific address MBED platform must do some calculations. These readings or writings can be at any moment. Now I’m just trying to find these reading or writing commands. Picture from analyzer

Data received in MBED platform with number:
SPI data. 0 3
SPI data. 1 1
SPI data. 2 96
SPI data. 3 0
SPI data. 4 0
SPI data. 5 3
SPI data. 6 1
SPI data. 7 98
SPI data. 8 0
SPI data. 9 0

Program is changed just to write down first 100 receive() bytes
Data is identical.
BTW there is some other communication on these DATA CLOCK lines with other devices, MBED platform starts to receive data only when CS is low. By this I understand all wires connected correctly.
Also one question regarding receive() -

Return values

0 No data waiting.
1 Data waiting.
So if there was some new data on SPI but read() was not done these data will remain in some read() buffer? What will be if I do not need these new data and I will start read() data from new transmission block? Or what size of this buffer? If 1 byte I will receive correct new data anyway?

What an EEPROM? Did you try to look for a datasheet?

I am not expert but from my point of view the SPI communication assumed you know the logic what it does between all ends. Otherwise, it’s like reverse engineering

There seems to be different versions of SPI across to ST families and releases. So your question is not so simple.
According to this document it seems the F4 family is equipped with oldest SPI version, where are no FIFO buffers implemented directly in hardware.
Page 920 of this document says about SPI_DR which is 16bits long and is split into two buffers RX/TX.

Mbed also not use any buffer in background. It directly ask about state of register and then directly read it.

So it is in your hand, you are responsible what your program will do. Not processed bytes will be lost/overridden.

BR, Jan

Hello.
I wonder how the author of the topic ended his experiments?
SPI is often used, so experience will be useful.