cancel
Showing results for 
Search instead for 
Did you mean: 

Need help configuring DMA FIFO's for SDIO Operation

coppercrimp
Associate III
Posted on February 06, 2015 at 02:29

Hello all,

I am trying to write a block of data from memory to a SDHC card through the DMA interface.

The hardware I'm using is a STM32F401 Discovery board. I've hooked my own SD card connector to the proper pins. I can write to the SD card succesfully in 1Bit mode when the DMA controller is not involved.

I am using STM32CubeMX for driver configuration.

I am using STM32Cube FW ver 1.4.0

I have updated the ''sd_diskio.c'' file to call the function BSP_SD_WriteBlocks_DMA() whenever a SD_write() is called.

The SD_WriteBlocks_DMA() function executes with no errors. But the program hangs when HAL_SD_CheckWriteOperation() is called.

The data I am trying to write to the SDIO interface is stored in a 128 element array of 32 bit integers. I pass this data in a f_write() call because I'm using FatFS.

I'm considering the problem could be coming from the way I configure the DMA FIFO's. Again, I'm transfering 32 bit values to the 32 bit SDIO interface. See the screenshot below for how I have the SDIO DMA configured.

Unfortunately I don't have a really good understanding of beats and bursts on the memory and peripheral side, and how they relate to the state of the FIFO. If someone could help me out here I'd be appreciative.

Thanks,

Rob

0690X00000603RYQAY.jpg

#stm32f401-discovery #dma #sdio
9 REPLIES 9
coppercrimp
Associate III
Posted on February 11, 2015 at 05:22

qwer.asdf
Senior
Posted on February 11, 2015 at 09:32

Hi, you can refer to ST provided examples:

STM32Cube_FW_F4_V1.4.0\Projects\STM324x9I_EVAL\Applications\Display\LTDC_PicturesFromSDCard

STM32Cube_FW_F4_V1.4.0\Drivers\BSP\STM324x9I_EVAL\stm324x9i_eval_sd.c

STM32Cube_FW_F4_V1.4.0\Drivers\BSP\STM324x9I_EVAL\stm324x9i_eval_sd.h

STM32Cube_FW_F4_V1.4.0\Middlewares\Third_Party\FatFs

coppercrimp
Associate III
Posted on February 11, 2015 at 15:30

The part I'm most confused about is setting up the burst sizes. I've scoured the internet trying to find information but cant find any complete documentation on burst sizes, beat sizes, and the Increment instructions.

I think I've determined that a burst is a continuous sequence of transfers into or out of the FIFO. A beat is a individual element of a burst. A beat can be defined as a byte, a half word, or a word. Is my understanding here correct?

I realize the DMA's FIFO can hold four words, 8 half words, or 16 bytes. These data elements can be ''packed'' and ''unpacked'' to support converting the data elements to different sizes (i.e. half-word to word etc.)

The part where I begin to get confused is setting up burst sizes on the peripheral side (assuming a memory to peripheral DMA transfer). Why is it necessary to set up the burst on the peripheral side? The peripheral itself may not have a FIFO, so performing a burst on the TX buffer of a peripheral doesnt make sense to me.

Since an answer to my original question about the SDIO port seems to be out of reach, perhaps a simpler example would help me understand how the DMA controller works. Lets say I wish to receive a 16 bit audio sample on the I2S port. In this example I'd like to use the DMA FIFO to save the half word sample as a whole-word in memory. How would I set up the burst sizes on the peripheral and memory side?

Posted on February 11, 2015 at 18:21

The SDIO peripheral has it's own FIFO, it's important that this is sustained, and also that after the DMA TX completes, that you also wait for the SDIO FIFO to vacate.

Make sure your buffers are 4-byte aligned.

If the DMA FIFO settings are of interest review the working SPL examples, and then get your head around how that translates to HAL/Cube settings.

What speed are you running your assorted buses?

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on February 11, 2015 at 18:26

This works on a F401, do THIS

void SD_LowLevel_DMA_TxConfig(uint32_t *BufferSRC, uint32_t BufferSize)
{
DMA_InitTypeDef SDDMA_InitStructure;
DMA_ClearFlag(SD_SDIO_DMA_STREAM, SD_SDIO_DMA_FLAG_FEIF | SD_SDIO_DMA_FLAG_DMEIF | SD_SDIO_DMA_FLAG_TEIF | SD_SDIO_DMA_FLAG_HTIF | SD_SDIO_DMA_FLAG_TCIF);
/* DMA2 Stream3 or Stream6 disable */
DMA_Cmd(SD_SDIO_DMA_STREAM, DISABLE);
/* DMA2 Stream3 or Stream6 Config */
DMA_DeInit(SD_SDIO_DMA_STREAM);
SDDMA_InitStructure.DMA_Channel = SD_SDIO_DMA_CHANNEL;
SDDMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)SDIO_FIFO_ADDRESS;
SDDMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)BufferSRC;
SDDMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
SDDMA_InitStructure.DMA_BufferSize = 0;
SDDMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
SDDMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
SDDMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
SDDMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
SDDMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
SDDMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
SDDMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;
SDDMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
SDDMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_INC4;
SDDMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_INC4;
DMA_Init(SD_SDIO_DMA_STREAM, &SDDMA_InitStructure);
DMA_ITConfig(SD_SDIO_DMA_STREAM, DMA_IT_TC, ENABLE);
DMA_FlowControllerConfig(SD_SDIO_DMA_STREAM, DMA_FlowCtrl_Peripheral);
/* DMA2 Stream3 or Stream6 enable */
DMA_Cmd(SD_SDIO_DMA_STREAM, ENABLE);
}

And if that doesn't work, review how you're lighting off the transfer on the SDIO end of the transaction.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
coppercrimp
Associate III
Posted on February 12, 2015 at 00:23

Thanks clive I'll give your code a try.

When you say to be sure my buffers are four byte aligned, do you simply mean that the buffered values should be stored in a 32 bit array? i.e. uint32_t SDIOTxBuffer[] 

Posted on February 12, 2015 at 03:05

Well that would have a natural alignment that is suitable. What you must watch for is randomly allocated/selected byte arrays.

Generally : Address % 4 == 0

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
coppercrimp
Associate III
Posted on February 16, 2015 at 21:20

Hi Clive,

I'm looking at your code and I notice that you configure the DMA controller for FIFO mode:

SDDMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;
SDDMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
SDDMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_INC4;
SDDMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_INC4;

But then reconfigure the SDIO interface as the flow controller:

DMA_FlowControllerConfig(SD_SDIO_DMA_STREAM, DMA_FlowCtrl_Peripheral);

I understood that when the peripheral was configured as the flow controller, then the DMA FIFO did not come into play. Am I misunderstanding? It seems like some of the functions you're using belong to custom libraries because I'm not finding reference to them in STM32Cube firmware.
Posted on February 16, 2015 at 21:34

These are from the SPL (Standard Peripheral Library) examples/demos, I'm not a subscriber to the Cube/HAL methodology, for a host of reasons. I'm providing the example as one configuration that does work, you'll have to triangulate from there I'm afraid..

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