2015-02-05 05:29 PM
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.0I 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 #stm32f401-discovery #dma #sdio2015-02-10 08:22 PM
2015-02-11 12:32 AM
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\FatFs2015-02-11 06:30 AM
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?
2015-02-11 09:21 AM
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?2015-02-11 09:26 AM
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.
2015-02-11 03:23 PM
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[]2015-02-11 06:05 PM
Well that would have a natural alignment that is suitable. What you must watch for is randomly allocated/selected byte arrays.
Generally : Address % 4 == 02015-02-16 12:20 PM
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.2015-02-16 12:34 PM
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..