2010-07-08 02:43 AM
DMA transfer on multi block write to SD card
#sdio-dma2011-05-17 04:57 AM
I had a similar problem in the single block read routine, and the error was that a DMA error could occur without an SD error being flagged. The while() loop simply waits for either completion or an SD error, thus it waited for ever. My fix in the single block read routine was this:
[code] ... else if (DeviceMode == SD_DMA_MODE) { SDIO_ITConfig(SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_DATAEND | SDIO_IT_RXOVERR | SDIO_IT_STBITERR, ENABLE); SDIO_DMACmd(ENABLE); DMA_RxConfiguration(readbuff, BlockSize); while ((DMA_GetFlagStatus(DMA2_FLAG_TC4) == RESET) && (DMA_GetFlagStatus(DMA2_FLAG_TE4) == RESET) && (TransferError == SD_OK)); // TransferError set by interrupt handler. if (DMA_GetFlagStatus(DMA2_FLAG_TE4)==SET) TransferError = SD_ERROR; //uart_puts(''DMA Transfer error\n''); if (TransferError!=SD_OK) return(TransferError); } return(errorstatus); [/code] You may have the same problem in the write, i.e. a DMA error is occurring. Chris.2011-05-17 04:57 AM
Hi! Chris,
Thanks for your reply. Both of us has the same problem that, not only it can be stuck, shows a very complex situation need to be handle.I had do some more experiments this morning and hope someone can figure out what the cuase it migth be:
This function was called as below where the block size was fixed at 512 bytes:
SD_WriteMultiBlocks(addr, *writebuff, 512, 4) and the line while (DMA_GetFlagStatus(DMA2_FLAG_TC4) == RESET) {} was modified to include a timeout check.Using a Transcend's 2GB SD card(which was detected as a SDIO_STD_CAPACITY_SD_CARD_V2_0).
1. Set the Timeout to 0.1S and SDIO_CK to 4MHz, call it 0x400 times. The Timeout will occur with the SDIO_DCOUNT = 0 and the DMA2_ISR = 0x7000. It means no errors, just wait not long enough. So, after the Timeout was changed to 1S, everything goes fine. 2. Set Timeout = 1S and SDIO_CK to7.2MHz
, call it 0x400 times. The Timeout will occur, with the SDIO_DCOUNT = 0x0600 and the DMA2_ISR = 0. It means, after first 512 bytes(the block size) has been transfered, the card is dead???Using a Kingston's 2GB SD card(which is also detected as a SDIO_STD_CAPACITY_SD_CARD_V2_0).
1. The same result as above. 2. It can pass at SDIO_CK = 7.2MHz, but fail at SDIO_CK = 12MHz and the failure pattern is the same as above.I also have some tests on using the single_block_write function ''SD_WriteBlock''. It never fail, even running at the default SDIO_CK = 24MHz speed. But an interest thing is that the big difference of the time to finish a 0x1000 times of calls between a 2GB card and a 64MB card. The 64MB card(which was detected as a SDIO_STD_CAPACITY_SD_CARD_V1_1) has a SD_CardInfo->CardBlockSize = 0x200, can be finished in ~4 seconds. The 2GB card(was detected as a SDIO_STD_CAPACITY_SD_CARD_V2_0) has a SD_CardInfo->CardBlockSize = 0x400, need ~22 seconds to finish!
I know the SD card need time to process data by doing move/erase/write.. actions on its internal NAND pages. But for the best performance, the block size passed to these functions should paly a big role in it. Now it seems that all those problems are related to an improper block_size was chosen, but I just don't know how to deal with it.
2011-05-17 04:57 AM
Just set datatimeout value proportional blocks number you writing
Here what I did
SDIO_DataInitStructure.SDIO_DataTimeOut = NumberOfBlocks * SD_DATATIMEOUT;
Thus DMA will able finish transfering data before
timeout. The original value SD_DATATIMEOUT set to 0x000FFFFF
and good enough write only 1 block, so it's make sense multiply
to number blocks you write
Regards Sergey
2011-05-17 04:57 AM
Dear all,
We fixed some limitations observed in the SDIO Driver, please refer tohttp://www.st.com/stonline/products/support/micro/files/stm32f10x_stdperiph_lib.zip
version 3.4.0 and use the lasted driver to upgrade your demo with the mass-storage one. we will update it as well later on on web to be inline with the StdPeriph library. Please be aware also that we have a silicon with multibyte support that are not power of 2, Section 2.17 that may helps you as well. Cheers, STOne-32.2011-05-17 04:57 AM
STOne-32
The reason DMA was loop indefinetly, because trasmission was canceled in
SD_ProcessIRQSrc, due StopCondition flag ( set to 1 in SD_WriteMultiBlock)
So even if timeout has been set we still cancel transmission on sd card, so
no real data will be written to sd card, just because the timeout was wrong.
And this not a fix. The real fix would be either no longer set
SDIO_IT_TIMEOUT flag in SDIO_ITConfig call( than timeout condition will
not trigget interrupt ) or set correct timeout value as I suggest in previous post
2011-05-17 04:57 AM
STOne-32
Call SDIO_ITConfig(T_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_DATAEND | SDIO_IT_TXUNDERR | SDIO_IT_STBITERR, ENABLE);
create a race condition what is trigger interrupt, if SDIO_IT_DATAEND hit first
all data already was written to sd card, and cacelation transmission really
do nothing, but if SD_IT_TIMEOUT hit first, than this mean DMA still working
move user data to sd card, and since StopCondition set to 1 we cancel anyway,
those making user data not being written, and I think it's not right and should be fixed.
Regadrs Sergey