Skip to main content
LBaum.3
Associate II
June 9, 2021
Question

Why SPI returns busy after a while of sending correctly?

  • June 9, 2021
  • 3 replies
  • 9475 views

Hello ST community,

I use a STM32F767ZI-Nucleo. There is a timer generating interrupts every 20ms. If a timer interrupt occurs I use HAL_SPI_Transmit_DMA to send some data. I monitor the return value of this function and after some time of sending without any failure the return value is HAL_BUSY (I toggle an GPIO pin if this occurs). I also use the HAL_SPI_TxCpltCallback where I toggle another GPIO to monitor when the SPI transfer is completed.

I noticed that sometimes the HAL_SPI_TxCpltCallback is not reached after a transmission. At the next trasmission I get a HAL_BUSY and also the data is corrupted.

In pic1.png you can see what I monitored with a logic analyzer.

pic2.png shows the SPI trasmission where no HAL_SPI_TxCpltCallback is reached.

pic3.png is the next trasmission after that which returns HAL_BUSY and contains the corrupted data. There you can see anohter phenomenon. The TxCpltCallback occurs during the transmission.

In pic4.png you can see how a normal or correct transmission looks like.

Is there anyone who has an idea why my SPI is sometimes busy and therefore the data is corrupted?

This topic has been closed for replies.

3 replies

TDK
June 9, 2021

If the previous transaction is not yet complete, it will return busy if you try another one.

Looks like you're using the SPI as a slave, yes? How are you synchronizing it such that the master sends clocks every 20ms exactly? Note that clocks drift with respect to each other, which will cause issues.

"If you feel a post has answered your question, please click ""Accept as Solution""."
LBaum.3
LBaum.3Author
Associate II
June 14, 2021

Ok, but why does it work most of the time and sometimes not? What is the difference at the few transactions where it doesn't work?

Yes you're right. The controlle is in slave mode.

For synchronization: Every 20ms a timer generates an interrupt and a GPIO pin is toggled (Channel INT_Tim3 at pic1.png). The master is triggered by the toggled GPIO pin and starts reading from the SPI bus.

Can the difting clocks cause the data to stay the same for the whole transaction?

TDK
June 14, 2021

> Ok, but why does it work most of the time and sometimes not? What is the difference at the few transactions where it doesn't work?

Most likely a bug in your program logic somewhere. Show the relevant portions of slave and master side code if you want.

My guess is a bug in the synchronization, or the master sending data before the slave is ready.

"If you feel a post has answered your question, please click ""Accept as Solution""."
waclawek.jan
Super User
June 9, 2021

See also errata, BSY bit may stay high at the end of a data transfer in Slave mode.

JW

[EDIT] Ah now I see you're talking about HAL_BUSY, that may be entirely unrelated then.

LBaum.3
LBaum.3Author
Associate II
June 17, 2021

I investigated the HAL_SPI_Transmit_DMA function and i determined that it also checks the BSY bit in the SPI status register. So in my opinion the BSY Bit is the reason for the failure.

The question I am facing now is how can I accomplish that the sending event after the event where BSY bit stays high works accurate?

My idea was to set the BSY bit manually to zero. But for all I know the BSY bit cannot be set to zero by software.

TDK
June 17, 2021

> So in my opinion the BSY Bit is the reason for the failure.

The reason (one, at least) for the failure is you're using data before it's actually there. Did you fix that part of it?

You haven't posted any evidence of the BSY bit misbehaving.

"If you feel a post has answered your question, please click ""Accept as Solution""."
LBaum.3
LBaum.3Author
Associate II
June 22, 2021

Yes, I changed the variables to global ones.

I noticed that the failure is at the slave side and there I don't use any data before it's actually there. So this could not be the reason for the fault.

As @Community member​ mentioned the errata sheet says that the BSY bit may stay high instead of going low at the end of transaction.

0693W00000BbgqWQAR.pngBy way of proof I monitored the BSY bit before each transmission. I transmit the BSY bit via uart as you can see in the following code segment.

0693W00000BbgvqQAB.pngThe result was as follows.0693W00000BbgwFQAR.pngThis is what I received from the uart interface. So you can see that I got five times "01" which means the BSY bit was set before the next transaction should take place and for the rest of the trasmissions I got "00" which means the BSY bit was not set.

For comparison purpose the following picture shows the same transmission recorded with a logic analyzer. You can see that during the recorded 15 seconds there are five HAL_BUSY returns (channel 4 "HAL_BUSY" is set and immediately reset five times)

0693W00000BbgswQAB.pngTherefore, in my opinion the BSY bit coresponds to the HAL_BUSY returns of the HAL_SPI_Transmit_DMA function and it's also the reason for this failure.

The question I am facing now is how can I accomplish that the sending event after the transmission where BSY bit stays high works accurate?

My idea was that the controller has to determine when the BSY bit stays high. If I know that I could reset the SPI interface before the next transmission will take place. But I have no idea how to determine this after the transmission. I can only determine it before the next transmission and there it could take to much time to reset the interface.