2026-02-04 9:01 AM
Hello,
I have an STM32G441 and using DMA to transmit some SPI data. All works so far. The problem is the chipselect. I am using the software chipselect. So before I start the DMA I pull CS low. Then when the DMA complete interrupt fires I pull it high again. The problem is, it cuts off about 3 or 4 bytes. This is obvious because the DMA is done while there is still SPI data in the buffer.
What is the go-to solution for this? How can I reliably get an interrupt when the DMA is done and the SPI is done transmitting all data? At the moment I simply start a timer when the DMA is done that triggers a second interrupt after a certain time that I measure with a logic analyzer. Seems a bit makeshift and has to be adjusted each time the baudrate is changed. I also noticed that all the SPI interrupts fire premature. So is it the only solution to waste a timer on the SPI?
Solved! Go to Solution.
2026-02-05 8:48 AM
Handle the CS in the Rx DMA interrupt. That won't happen before all data are shifted out, too (there's a marginal hazard with certain CPOL/CPHA combinations but that often can be solved by relatively simple delays; or use other CPOL/CPHA combination).
It doesn't matter that you don't need Rx. You can DMA into a "dummy" single memory address (i.e. no memory increment), and you don't need to assign any pin in GPIO to it. This is just to provide the timing.
JW
2026-02-04 9:49 AM
You could use the HAL library which handles this correctly. Set CS high in the transmit complete callback.
If you want to do it yourself, you will need to poll the BSY flag to determine when the transfer is complete. The reference manual discusses this in some detail.
It's not an elegant or efficient solution, but that is what is available on this chip. Later families have better handling of the CS line and better ways to do this without polling.
2026-02-04 10:24 AM
Assume that the DMA complete interrupt happens when the DMA is complete. The SPI device transmit register got loaded and is in the process of shifting out the data, but the DMA is done, and DMA likely deposited a 32-bit pile of data, say, 3 or 4 bytes. DMA done, SPI busy.
You'll have to query the SPI device to determine when it is finished shifting out/in the data.
2026-02-05 8:48 AM
Handle the CS in the Rx DMA interrupt. That won't happen before all data are shifted out, too (there's a marginal hazard with certain CPOL/CPHA combinations but that often can be solved by relatively simple delays; or use other CPOL/CPHA combination).
It doesn't matter that you don't need Rx. You can DMA into a "dummy" single memory address (i.e. no memory increment), and you don't need to assign any pin in GPIO to it. This is just to provide the timing.
JW
2026-02-05 9:50 AM
Thanks, that's a nifty solution. Although it does sacrifice a DMA channel. But that is not so expensive as a timer as I don't need many DMAs. I will check it out and report the result.
2026-02-07 5:32 AM
Hello,
so it worked but there seems to be a slight detail that the RX DMA quit to early. Reading the SPI DR seems to solve this. Strange though it would do that.
2026-02-07 7:06 AM
Try to use the other CPHA setting, i.e. if you've used mode 0 (CPOL=0, CPHA=0), try mode 3 (CPOL=1, CPHA=1).
This may or may not suit your slaves' requirements, though.
JW