AnsweredAssumed Answered

Does DMA really help speed things up with a serial communications peripheral

Question asked by David Harrison on Feb 7, 2017
Latest reply on Feb 8, 2017 by David Harrison

Hi, all, I am using DMA with the STM32F7 SDMMC peripheral to read 4K buffers from the SD card. The basic SDMMC SDReadMultiBlocks function is called from disk_read which is called from Elm-Chan's fatFS f_read.


Since, when reading from a file, we need to access the sectors and buffers sequentially, we have to wait until each DMA filled buffer transfer is complete before we move on to retrieve the next one. Therefore we use the SDWaitReadOperation() function to wait until the DMA transfer is complete.


Therein lies the problem. The SDWaitReadOperation() obviously waits in a spin loop, basically wasting CPU cycles, while we wait for the DMA transfer to complete. But the transfer elapsed time is not decided by CPU speed, RAM speed or DMA transfer speed, because the flow controller is the SDMMC peripheral and its transfer speed is determined by the SD bus speed.

So unless you can actually do some useful other work in the spin loop inside SDWaitReadOperation(), I can't see how using DMA gives you any more transfer speed than a simple polled method where you fill your application buffer as the SDMMC peripheral's FIFO is able to provide data.

I am not using an OS, just the usual while (true) {} task loop.


I looked at the possible DMA interrupts to signal when the DMA transfer is half complete and then start doing some useful work with the first half of the application buffer while the DMA is filling the remaining second half. But surely that relies on the DMA knowing the size of the transfer to begin with in the SDMMC1->NDTR register. But, because the SDMMC is the flow controller, not the DMA, we set SDMMC1->NDTR  to 0;

So in that case, would the DMA actually signal a half complete interrupt at all, because it basically doesn’t know what “full” means, let alone half full.


The same sort of elapsed time issue surely applies to using DMA with ANY serial communications peripheral e.g., USART, I2C, SPI etc. - the transfer rate is determined by the bus clock rate, not by the DMA transfer, so if you have to wait in a spin loop until the DMA transfer completes, you might just as well have used a simple polled method to begin with.


Am I missing something here? What are your thoughts?