cancel
Showing results for 
Search instead for 
Did you mean: 

DMA transfer on multi block write to SD card

jfong
Associate II
Posted on July 08, 2010 at 11:43

DMA transfer on multi block write to SD card

#sdio-dma
6 REPLIES 6
daviddavid92
Associate II
Posted on May 17, 2011 at 13:57

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.

jfong
Associate II
Posted on May 17, 2011 at 13:57

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 to

7.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.

stereskc
Associate II
Posted on May 17, 2011 at 13:57

Fong 

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

Nickname12657_O
Associate III
Posted on May 17, 2011 at 13:57

Dear all,

We fixed some limitations observed in the SDIO Driver, please refer to

http://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

http://www.st.com/stonline/products/literature/es/14732.pdf

with multibyte support that are not power of 2, Section 2.17 that may helps you as well.

Cheers,

STOne-32.

stereskc
Associate II
Posted on May 17, 2011 at 13:57

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

stereskc
Associate II
Posted on May 17, 2011 at 13:57

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