2024-03-06 02:54 PM
I'm trying to read and write SPI bytes from an STM32F446RE chip with DMA. The STM32f4 is the slave and a RPi is the master. The first SPI read works fine (data read into buffer starting at index 0), but subsequent reads have the data starting at index 1 instead of index 0. I tried resetting the SPI peripheral with this bit of code I found on the forums:
#define RESETSPI {\
HAL_SPI_Abort(&hspi2);\
__HAL_RCC_SPI2_FORCE_RESET();\
__HAL_RCC_SPI2_RELEASE_RESET();\
}
This fixes the reading off by 1, but it results in the last byte sent back to the PI to be wrong.
Does anyone know what might be happening or how I might address it?
Solved! Go to Solution.
2024-03-08 03:35 AM
SPI is inherently duplex, you can't transmit without receiving. If you transmit and don't pick the received data from the data register (either reading it by processor, or by DMA), they just overflow, but one byte remains in the receiver.
If you then switch on Rx DMA, that one byte gets transferred immediately into the memory, before really receiving data.
(In slave setting, it's not just active transmission when data are arriving into the receiver, but whenever clocks arrive from the master.)
So, the solution may be to read out the SPI_DR register by processor, immediately before enabling reception. Another (and in theory better) solution is to have the Rx DMA on all the time (circular), but I admit it may can get tricky to determine, where the freshly received data exactly are in such circular buffer.
If you reset SPI in the Tx DMA transfer-complete callback, that may be too soon, it may be before the entire byte has been actually shifted out by SPI - that's why it gets corrupted.
JW
2024-03-07 12:11 PM - edited 2024-03-07 12:11 PM
That's too little context to be able to judge. DMA is set up how, circular, single-shot? If latter, how it is started, in relationship to NSS/clock incoming from master? "Read" is which direction? NSS is handled how? The "extra" datum is identical to the previous "correct" byte, or not?
JW
2024-03-07 01:49 PM
Thanks for your comment. To answer your questions:
I got the firmware working by reseting the STM32 SPI peripheral after every write, then on the Pi side I only look at 3 of the 4 crc bytes. But it would still be nice to figure out what I'm doing wrong here.
2024-03-07 02:20 PM
Why are the DMAs two different lengths (SPI_MSG_MAX_LEN and MEDULLA_RSP_LEN)? How much they are exactly? How many bytes transfers master, exactly? Do you have waveform captures to show?
JW
2024-03-07 02:24 PM
The Pi sends 4k bytes to the STM32, then the STM32 responds with 6 bytes. I'll try to get some waveform captures to post here.
2024-03-08 03:35 AM
SPI is inherently duplex, you can't transmit without receiving. If you transmit and don't pick the received data from the data register (either reading it by processor, or by DMA), they just overflow, but one byte remains in the receiver.
If you then switch on Rx DMA, that one byte gets transferred immediately into the memory, before really receiving data.
(In slave setting, it's not just active transmission when data are arriving into the receiver, but whenever clocks arrive from the master.)
So, the solution may be to read out the SPI_DR register by processor, immediately before enabling reception. Another (and in theory better) solution is to have the Rx DMA on all the time (circular), but I admit it may can get tricky to determine, where the freshly received data exactly are in such circular buffer.
If you reset SPI in the Tx DMA transfer-complete callback, that may be too soon, it may be before the entire byte has been actually shifted out by SPI - that's why it gets corrupted.
JW