cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F1x(/4x?) SDIO DMA TX FIFO underruns

sanderson
Associate
Posted on August 04, 2015 at 23:32

As many others on the forums and the Interwebs have, I recently ran into a problem with SDIO TX FIFO underruns, even when using DMA at the highest priority.  I did figure out a solution though, and thought I would share it here in case it is useful to others:

First, a rough description of the problem:

In SD_WriteBlock() we have (psuedo code):

// setup DMA controller to send the block...

// send SD_CMD_WRITE_SINGLE_BLOCK command

// wait for response, handle if error.., else

// start DATA transfer to SDIO, using DMA to fill FIFO

// wait for DMA (or data transfer to finish).. etc..

So nothing too complicated, but problem is that the data transfer would occasionaly fail with a SD_TX_UNDERRUN error.  This at first blush seems impossible, with the highest priority DMA feeding the FIFO, but alas I could find an obvious way to fix it.  Note also that this (for me) depended on other activity.  In particular I have I2C interrupts at the highest priority going on, and the more of those I have, the more likely I see this under-run issue.

So here was my solution, which so far seems pretty good (hasn't failed in my testing):

// setup DMA controller to send the block, EXCEPT the first 4 words (16 bytes)

// send SD_CMD_WRITE_SINGLE_BLOCK command

// wait for response, handle if error.., else

// disable interrupts

// start DATA transfer to SDIO, without using DMA to fill FIFO

// load the first 4 words into the FIFO in code (SDIO->FIFO = *data++; 4 times...)

 

// switch the SDIO to use DMA to fill the FIFO (for the rest)

 

// re-enable interrupts

// wait for DMA (or data transfer to finish).. etc..

And that has done the trick for me.  I worry about disabling global interrupts, but in my case I had to (I2C was highest priority).  Also my I2C interrupt is highest priority for a reason, so I tried to keep this section very short and so far it hasn't hurt my I2C stability.

I hope this helps someone!

-Shane

#sdio-stm32f-sd_tx_underrun
1 REPLY 1
stm322399
Senior
Posted on August 05, 2015 at 08:54

While I really appreciate people sharing their successful experience, I would like to say that your trick to avoid FIFO underrun is not necessary. My comment is, of course, based on my own experience with STM32F4 SDIO controller.

Normally you don't have to send the command before enabling the DMA, you must perform operation in the opposite order.

The internal state machine of the SDIO controller is made in a way that the data transfer phase starts as soon as the command response arrives from the SDCard.

The proper way to do that is the following:

* Prepare DMA/SDIO transfer, do not miss to set DPSM bit !

* Enable DMA

* Start SDIO

* Send command

* Wait for completion or errors

* disable DMA, DPSM, SDIO

That way, you cannot miss the start of the data phase, it is entirely managed by the hardware, no FIFO underrun.