SPIslave replies with wrong bytes to SPI master

Hi,
I am developing a SPI slave on NUCLEO-F746ZG and the master on NUCLEO-F103RB. I have some problems with the slave not behaving as I want it to and responding with the wrong bytes, probably something with the buffer but I’m not sure.

I want the slave to respond to certain commands from the master, in this case: while the master sends the commands 0x07, 0x14, 0xf3, 0x6c (master will always send a 4-byte command), the slave will respond with 0xff and after receiving the whole command (4 bytes) it will respond with one 0x0f and three 0xff, as seen in the picture below:

To achieve this behavior, I have written a simple test case (PLADC) that makes the slave respond with what it has read (e.g. 0x07, 0x14, 0xf3, 0x6c) if master sends the command 0x07, 0x14, 0xf3, 0x6c, to see that the slave is reading correctly and to see that the slave enters the case. It will later be replaced with 0x0f and 0xff as seen above.

Master code:

char data[4] = {0x07, 0x14, 0xf3, 0x6c};
char miso[8]; 

int main()
{
    cs = 1; 
    spi.format(8,3); 
    spi.frequency(1000000);
    spi.set_default_write_value(defaultVal);
    spi.clear_transfer_buffer();
    while(true) {
        cs = 0; 
        spi.write(data, 4, miso, 8); 
        wait_us(300);
        cs = 1;
        wait_us(1000);
    }
}

Slave code:

bool spiSendSync(uint8_t dataByte) {
    spi.reply(dataByte);
    bool sent = spi.receive();
    while (!sent){
        sent = spi.receive();
    }
    (void)spi.read();
    return sent;
}

bool spiSendReceiveSync(uint8_t sendByte, uint8_t* rxByte) {
    spi.reply(sendByte);
    bool received = spi.receive();
    while (!received){
        received = spi.receive();
    }
    if (received){
        *rxByte = spi.read();
    }
    return received;
}

int main(){
 spi.format(8,3); 
    while(1){ 
        if (spiSendReceiveSync(0xFF, &data[idx++])){
            if (idx == 4){
                idx = 0;
                cmd_data[0] = data[0];
                cmd_data[1] = data[1];
                cmd_read = cmd_data[0]<<8 | cmd_data[1];
                switch(cmd_read){
                        case PLADC:
                            spiSendSync(data[0]);
                            spiSendSync(data[1]);
                            spiSendSync(data[2]);
                            spiSendSync(data[3]);
                            break;         
                }
            }
        }
    }
}

The code above corresponds to this picture taken with a logic analyzer:

It seems like the slave’s respone is shifted one byte here. Sampling again showed the same, but shifted more than one byte so it’s not always one.

What is happening here? What should I change so that the slave’s response shifts to the right place, so the first 4 bytes ff, then the last 4 bytes to 07, 14, f3, 6c?

Hello,

it seems there is probably a problem with SPI on STM targets

BR, Jan

Hi
We tried to reproduce the issue without any success:

Did you use the same code and boards and sampled over a longer time?

Code used is as below:
Master Code

SPI spi(D11, D12, D13); // mosi, miso, sclk
DigitalOut cs(D0);

char data[4] = {0x07, 0x14, 0xf3, 0x6c};
char miso[8]; 

int main()
{
	cs = 1; 
	spi.format(8,3); 
	spi.frequency(1000000);
	spi.set_default_write_value(0xFF);
	spi.clear_transfer_buffer();
	while(true) {
		cs = 0; 
		spi.write(data, 4, miso, 8); 
		wait_us(300);
		cs = 1;
		wait_us(1000);
	}
}  

Slave code:

SPISlave spi(PB_5, PB_4, PB_3, PA_4); // mosi, miso, sclk, ssel
uint8_t data[4];

bool spiSendSync(uint8_t dataByte);
bool spiSendReceiveSync(uint8_t sendByte, uint8_t* rxByte);

bool spiSendSync(uint8_t dataByte) {
	spi.reply(dataByte);
	bool sent = spi.receive();
	while (!sent){
		sent = spi.receive();
	}
	(void)spi.read();
	return sent;
}

bool spiSendReceiveSync(uint8_t sendByte, uint8_t* rxByte) {
	spi.reply(sendByte);
	bool received = spi.receive();
	while (!received){
		received = spi.receive();
	}
	if (received){
		*rxByte = spi.read();
	}
	return received;
}

int main(){
	int idx = 0;
	char cmd_data[4];
	int cmd_read;
 spi.format(8,3); 

							 spiSendSync(data[0]);
							spiSendSync(data[1]);
							spiSendSync(data[2]);
							spiSendSync(data[3]);
	while(1){ 
		if (spiSendReceiveSync(0xFF, &data[idx++])){
			if (idx == 4){
				idx = 0;
				cmd_data[0] = data[0];
				cmd_data[1] = data[1];
				cmd_read = cmd_data[0]<<8 | cmd_data[1];
				switch(cmd_read){
						case 0x0714:
							spiSendSync(data[0]);
							spiSendSync(data[1]);
							spiSendSync(data[2]);
							spiSendSync(data[3]);
							break;         
				}
			}
		}
	}
}

We check many loop from a 1s capture.

Ok! What boards did you use?

We used NUCLEO-F767, but I don’t think there is a difference between F767 and F746

For both master and slave?

NUCLEO-F103RB as master

Hi
If issue is still present, please raise a Github issue in Issues · ARMmbed/mbed-os · GitHub
Regards