cancel
Showing results for 
Search instead for 
Did you mean: 

Missing bytes during SPI TX + strange MOSI line on oscilloscope

ramses946
Associate III

Problem description:

1-2 bytes in a ~30 byte message (usually at the same spot in the msg) are sometimes missing. Usually it is the 13th byte.

If I send shorter msgs via SPI like 10 bytes, the other party receives them correctly.

If I wait 50us after pulling NSS low, the other party receives even long msgs correctly.

Let us assume, that after pulling NSS low, the transmission starts too soon. Why is a byte in the middle of the msg missing then and not at the beginning?

Maybe it's an oscillating NSS pin that goes high/low but I couldn't see anyhting on the oscilloscope. I know that the probe will add to the capacitance of the trace so any signal rise will be slower and any oscillation dampened just by hooking up the probe.

Fix for now:

Wait 50us after pulling NSS low.

Question1:

But I don't understand why the fix works... it makes no sense to me. NSS goes high/low in about 200ns (measured with probe, ultra short GND connection). A different measurement showed 1300ns (with long lead on the probe).

The datasheet states 320ns with a 50pF capacitance. So the first measurement should be ok. 200ns is about 3 clock cycles.

I initialize a 60 byte array and do a 30 byte memcpy after pulling NSS low. That should be enough time for NSS to become low.

Why does waiting fix it? Why is a byte missing in the middle? Not at the start?

Question2:

Why is MOSI on the oscilloscope so broken? How come I can even send correct messages with such a MOSI graph? See attached picture. MOSI has a rise time of about 2.5us. Which is way too long. Why? If it was because of the oscilloscope, I'd see the same phenomenon on SCK, NSS or MISO. But I don't.

Environment:

SPI speed: 8 MHz

SPI Mode: Master, Full Duplex

Clock speed: 16 MHz

MCU: STM32L0

VCC: 1V8

SCK trace: ~33mm, 8 mil

MOSI trace: ~43mm, 8 mil

SPI GPIO speed settings: highest speed

NSS speed setting: low

Oscilloscope

input capacitance: 15pF

Probe capacitance: 18-22pF

Probe compensation: 10-35pF

Probe setting: 10x

1 ACCEPTED SOLUTION

Accepted Solutions
ramses946
Associate III

Finally I think I've found the reason why there were bytes missing.

The communication was between an STM32 and a radio MCU. The command that sometimes failed was a command to fill the FIFO of the radio MCU.

Probably the reason why it only worked if I the MCU waited after NSS was driven low, was, that the radio MCU needed time to change its mode from RX to STANDBY. It didn't make a difference whether the wait happened before NSS was driven low or after that. So NSS was not the problem.

Most probably the SPI communication was fully intact but the FIFO was not filled correctly because it was done exactly at that point in time where the mode of the receiver was switching from RX to STANDBY.

Nevertheless I've reduced SPI speed from very high to high and kept that change because it's working with a lower speed and I want to avoid any EMI or over-/undershoot.

I've removed all wait code/cycles and only wait for the mode change of the radio MCU to complete now.

View solution in original post

10 REPLIES 10
ramses946
Associate III

This is NSS - the rise/fall times would be way faster without the oscilloscope probe.

0693W00000WIw8qQAD.png0693W00000WIw90QAD.png 

This is the code to send data via SPI

while (txLength > 0)
{
	//check that TX buffer is empty
	if (LL_SPI_IsActiveFlag_TXE(spiHandle))
	{
		LL_SPI_TransmitData8(spiHandle, *tx);
		tx += sizeof(uint8_t);
		txLength--;
	}
}
 
while(!LL_SPI_IsActiveFlag_TXE(spiHandle))
{
}
 
//wait for busy flag to get reset
while(LL_SPI_IsActiveFlag_BSY(spiHandle))
{
}
 
LL_SPI_ClearFlag_OVR(spiHandle); //clear RX overrun flag because we did not read data

ramses946
Associate III

Regarding the MOSI scope thing:

If I select a finer resolution like 50us instead of 2ms on the scope, then I get clean edges and fast rise times of ~50ns. So it seems to have to do with the scope settings.

S.Ma
Principal

And generally, use transmitreceive function, even if not all io are exposing the spi signals.

AScha.3
Chief II

this is just wrong setting of DSO .

to see fine pulses in big time window, you have to set Acquire (button on scope) to "Peak Detect" .

then you see correct SPI signal.

+

 When your question is answered, please close this topic by choosing Select as Best.

If you feel a post has answered your question, please click "Accept as Solution".
ramses946
Associate III

@AScha.3​ thank you, yes, I noticed that the distorted MOSI signal must have to do with the scope settings. I will switch to "Peak Detect" next time following your advice.

My question about why bytes are missing when I send long messages is unanswered, but if somebody can help, I'll chose that answer.

ramses946
Associate III

This is what MOSI looks like in peak-detect acquisition mode.

There is a pretty strong overshoot of 700mV and undershoot of -500mV.

A possible explanation for the missing bytes could be that maybe SCK is ringing. So some SCK cycles could be missing maybe? But that would not explain why waiting after pulling NSS low fixes it.

I think, the ringing could even be worse without the probe. Because the rise time should be much higher without the probe capacitance...

0693W00000WJ2RKQA1.png0693W00000WJ2QbQAL.png 

P.S.:

I've changed SPI GPIO settings now from VERY HIGH to HIGH. After this change the under-/overshoot is smaller.

I've also tried MEDIUM but using this setting the communication did not work anymore.

AScha.3
Chief II

just i want write abour port speed - now you found it yourself:

always set lowest speed, that gives perfect result. more speed - more overshoot.

+

>I initialize a 60 byte array and do a 30 byte memcpy after pulling NSS low. That should be enough time for NSS to become low.

must be something in your code, i drive a TFT with F103 / SPI at 14 MHz, but clkpre div 4 (try!)

see:

0693W00000WJ4jkQAD.pngand there are many bytes to send... more than 60 🙂

i write direct to register :

0693W00000WJ4p4QAD.pngthe "useless" HAL- gpio write makes the needed delay for the spi , about 720ns ;

NSS is direct write to port gpioB bit set / reset , absolutely no delay needed !

If you feel a post has answered your question, please click "Accept as Solution".
ramses946
Associate III

Meanwhile I've removed the delay altogether and it seems to work. I don't know which change "fixed" it. I need to do some further tests with different HW revisions to be sure that it's working without the delay.

Our code is similar because the ST LL_ (low level) functions that I use are static inline or macros, that is, they are as short as possible. I do not use HAL.

The thing I don't understand about GPIO speed settings is:

The datasheet states:

50pF load, very high speed, max 17ns rise time, max 10 MHz

50pF load, high speed, max 28ns rise time, max 2 MHz

50pF load, medium speed, max 65ns rise time, max 0.6 MHz

From 17ns to 28ns -> that's not even double. But from 2 MHz to 10 MHz: that's 5x.

How are they calculating the max frequency?

I probably have a ~5pF load (MCU to MCU connection), even with medium speed setting my rise time should be less than 10ns. But medium speed did not work out. I wonder why.

Maybe it's because I initialized MISO GPIO also with medium setting?

I could try SCK, MOSI = medium

MISO = high

But MISO should be an input anyway, the speed setting should not influence it, I guess...

Many question marks in my head... 🙂

AScha.3
Chief II

i had high setting for TFT spi on all lines:

0693W00000WJ5XQQA1.pngabout port speed: basically connecting small/more../big mosfets to the output stage -> changes swichting speed, but always depending on load (xx pF) .

i made tests with the SD-card driver, at full speed (50MHz) : most micro-SDcard not responding at all, when highest port speed set. but with medium/high running perfect, at low speed no function.

so too much speed here producing reflections, that prevent function.

If you feel a post has answered your question, please click "Accept as Solution".