cancel
Showing results for 
Search instead for 
Did you mean: 

SPI Overrun when using the DMA

SK
Associate

Hi,

I've run into an interesting problem when doing two simultaneous SPI transfers using the DMA.

I'm using the STM32F103ZFH6 where I am simultaneously reading a bitstream (in large chunks) from and external SPI flash device and writing in out to another device over SPI.

The 'n+1' chunk is clocked in on SPI1 (APB2) using DMA channels 2&3 (need the Tx channel to provide the SPI clock) and is moved to SRAM.

The 'nth' chunk is moved from SRAM and clocked out on SPI2 (APB1) using DMA channel 5.

They system clock is running at 72MHz.

APB2/APB1 clocks are running at 72/36MHz respectively.

The SPI peripherals are clocking at 18 MHz.

The SPI/DMA are working with 8bit data sizes.

This operation seems to work flawlessly when the CPU is 'idle' during the DMA operations. However, the problem I run into is when the CPU goes off to do other thing in the meantime. For example, if I continually read from the USART2 status register (APB1) while the transfer is in progress, the SPI1 transfer will fail where I see an OVR (overrun) in the SPI1 status register.

This suggests to me that the DMA did not have enough time to service the RXNE flag before the last byte was clocked out.

To me, it seems like the I'm exceeding the maximum throughput of the AHB/APB buses. But I can't figure out why that would be this case. I've read AN2548 but my understanding of the internal AHB/APB busses is still a bit weak. At a system clock of 72MHz and an SPI clock of 18MHz, the DMA should need to move 3 bytes every 32 AHB cycles. If I interleave some CPU instructions (that access the APB busses as well), I could see things getting congested. However what I don't get is that the RX DMA channel which services the SPI1 Rx (channel 2) should have the highest priority, an therefore should take precedence if bus access starts to get congested and the flow of data slows down. i.e. I would expect to see gaps in the SPI clocks when observed on a scope, but never an overrun.

Am I on the right track here? Is this a bus contention issue, or am I looking in the wrong place.

Any ideas would be helpful. Thanks,

-Steven

6 REPLIES 6
JJ??r
Associate

I believe I have hit a very similar issue myself. For now I can luckily just turn off the other load I have when accessing this particularly SPI device, bypassing the issue.

However I would love to dig further into this issue when I get some more time. If I find a solution I will post it here.

Thanks for your post, it helped me narrow my search area:)

/Jesper

If you're viewing this directly in a debug, or via a peripheral view of the SPI device, it is likely to be invasive. Need to instrument code so you don't interfere with the balance of the system.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
HIbil
Associate

First thing I would try is to switch SPI to unidirectional RXONLY=1 for channel2 and BIDIOE=1 for channel 3. Exceeding maximum throughput is impossible 😉 and I would expect the SPI to only clock out new data AFTER a RXNE=0... Let us know what you find.

For OP, first thing I would try is to use 16-bit SPI transfers, even at the cost of "manually" handling outstanding single bytes at the end. That would cut down the bandwidth to half.

Jesper,

please start a new thread, stating exactly what your problem is. Details do matter in this case.

JW

HIbil
Associate

That first thing I tried with SPI RXONLY mode was not that big of a succes , got OVR errors on non-DMA SPI transactions following the DMA. You can enter any number of items to be transferred into the DMA CNTDR reg but apparently the spi itself is oblivious to that fact and just keeps the sclk running. In my case leading to some 4 extra bits clocked in before I could switch of the SPI (SPE=0) and stop the transfer. Then it still generates an OVR when switched on again an writing DR so SPE=0 seems to do little to reset or clear RXNE.

This is not the same problem as the OP though since I can recover easily by just reading DR after the DMA to clear RXNE. In any case I do not get OVR during DMA's even with busy SPI, I2C and Usart. Same APB1/2 & clock parameters as OP.

> apparently the spi itself is oblivious to that fact and just keeps the sclk running.

Yes, that's a fundamental problem of the Rx-Only mode of STM32 SPI module. If the externally connected device can tolerate the extra clocks, then simply ignoring them and clearing the overrun might be a solution.

One more solution to spare the need to feed data for Tx for a Rx-only SPI at a cost of one pin may be to use SPI in slave mode and feed clock from a timer and chained timers can be used to generate an exact number of clocks.

Another solution is to switch to a STM32F2xx/4xx which has a different layout of the DMAs.

JW