2024-10-30 11:51 AM
I am using STM32F105xx family, working with HAL_SPI API. I have discovered that the call to HAL_SPI_Receive_IT causes whatever data is in the provided buffer to be clocked out on MOSI. This issue is also discussed to some extent in this thread, but that thread is more focused on fixing the system behavior than discussing whether it's actually a bug in HAL.
So...am I crazy or is this a bug? If I call a "Receive" method that only takes a receive buffer, I shouldn't expect it to transmit that data, should I?
I'm working with TI's ADS1258 ADC which has a "direct read" mode meaning no command needs to be sent to read the next conversion result (technically, it watches the first three bits of MOSI; if they are all 1s or all 0s, it ignores the rest of MOSI and continues clocking out data on MISO for 32 bits). If there is stale data in the buffer provided to HAL_SPI_Receive_IT, and that data happens to have a first byte that the ADS1258 recognizes as a command, then my attempt to "direct read" turns into an unexpected reconfiguring of the ADC.
Why does HAL_SPI_Receive_IT clock out any data at all? Seems to me MOSI should be left alone.
I can observe the MOSI signal with a logic analyzer and see that it's clocking out the bits that were in the receive buffer, and I can fix my ADC issue by clearing the buffer before providing it to HAL_SPI_Receive_IT. But...I shouldn't have to do that, right?
Is there some use case I'm not imagining where one would want the "receive" API method to transmit data? HAL_SPI_TransmitReceive_* are the methods meant to enable full-duplex operation...
As an aside, I haven't bothered trying to find out whether HAL_SPI_Transmit_* also puts received data into the buffer it was given...but I have definitely noticed that the HAL API is not const-correct so it certainly could.
Solved! Go to Solution.
2024-11-01 03:19 AM
Hello @Brian H
Thank you for bringing this issue to our attention.
I reported your request internally.
Internal ticket number: 195562 (This is an internal tracking number and is not accessible or usable by customers).
2024-10-30 04:15 PM - edited 2024-10-30 04:19 PM
Hi,
SPI is full-duplex. Except for a couple of odd single wire modes.
I don't use HAL. However, HAL_SPI_TransmitReceive_IT() is the function you are looking for...
Kind regards
Pedro
2024-10-31 01:44 AM
Hello @Brian H
In SPI, data is always exchanged between the master and the slave. Even if you are only interested in receiving data, the master must send dummy data to generate the clock pulses required for the slave to send data back. The HAL_SPI_Receive_IT function uses the provided buffer for this purpose, which is why you see the data being clocked out on the MOSI line.
The behavior you are observing is expected due to the full-duplex nature of SPI. To avoid unintended data being sent to your ADC, you should clear the buffer before passing it to HAL_SPI_Receive_IT. This ensures that only dummy data is clocked out on the MOSI line during the receive operation.
2024-10-31 02:27 AM
@Saket_Om wrote:The HAL_SPI_Receive_IT function uses the provided buffer for this purpose, which is why you see the data being clocked out on the MOSI line.
The behavior you are observing is expected due to the full-duplex nature of SPI. To avoid unintended data being sent to your ADC, you should clear the buffer before passing it to HAL_SPI_Receive_IT. This ensures that only dummy data is clocked out on the MOSI line during the receive operation.
This should be clearly stated in the HAL_SPI_Receive_IT function documentation.
Also HAL_SPI_Receive and HAL_SPI_Receive_DMA
2024-10-31 02:33 AM
2024-10-31 09:02 AM
I know how SPI works. Yes, I know SPI is full-duplex. Yes, I know the slave is always paying attention to MOSI when the clock is pulsing (if SS is asserted), and the master is always paying attention to MISO.
My complaint is that a method named "Receive" implies that data is not being fed into the SPI transmit buffer. The documentation of that method does not indicate otherwise. Similarly, I would not expect HAL_SPI_Transmit to put the received bytes into the buffer I gave it. (Required car analogy: My car has a "go faster pedal" (gas) and a "go slower pedal" (brake). If I get in my car and step on the gas, I do not expect it to also apply the brake at the same time.)
Here's an excerpt from RM0008 that clears up what's going on, I think.
Start sequence in master mode
Clearly the peripheral is operating in full-duplex mode, meaning that writes to DR are required in order to generate clock pulses. My complaint is that the function named HAL_SPI_Receive implies receive-only mode. The fact that it is writing to DR the bytes in the receive buffer needs to be documented. As it stands, as documented, the bytes it writes are undefined. It happens to be using the data in the caller's receive buffer, but there's no intuitive reason that it should use those bytes instead of any other bytes.
My opinion is that HAL_SPI_Receive either:
This boils down to a documentation issue. @Andrew Neil understands my frustration.
Thanks to all who contributed.
2024-10-31 09:21 AM
@Brian H wrote:My complaint is that a method named "Receive" implies that data is not being fed into the SPI transmit buffer.
No, I don't think that's true.
It's simply a method that doesn't require or allow you to present any data to be transmitted.
@Brian H wrote:Here's an excerpt from RM0008 that clears up what's going on, I think.
That shows that the STM32F105xx hardware itself could do a receive-only operation without the necessity of loading anything into the TX buffer - but that's not what the HAL does.
@Brian H wrote:This boils down to a documentation issue.
Indeed.
2024-11-01 03:19 AM
Hello @Brian H
Thank you for bringing this issue to our attention.
I reported your request internally.
Internal ticket number: 195562 (This is an internal tracking number and is not accessible or usable by customers).