cancel
Showing results for 
Search instead for 
Did you mean: 

SDIO and DMA

pacoblackxx
Associate II
Posted on November 20, 2011 at 11:03

When using the SDIO with DMA, the source code should look like this:

(assume that we refer to a read_single_block command)

1.Enable the DataPath state machine;

2.Enable the CommandPath state machine;

3.Check if command response is free of CRC/Timeout errors;

4.Check if command response R1 is free of errors

5.Enable DMA

6. get in a while() loop and wait until the end of the DMA tranfer.

That is the code tha STM Team uses in the evaluation board.

I am woried for the critical session between states 3-5. If you put some

slow code there(for example USART print), an overrun error will occur because

DMA is enabled when the overrun flag is already set.

Yeah, we know that and that is the reason for which we dont put slow codes between

states 3-5. But i am worrying about what will happen if an interrupt happens between this states. If the interrupt routine has to transfer some data via SPI(slow), It will cause an overrun.

So, i decided to enable DMA before i enable the command state machine:

1.Enable the DataPath state machine;

2.Enable DMA

3.Enable the CommandPath state machine;

4.Check if command response is free of CRC/Timeout errors;

5.Check if command response R1 is free of errors

6. get in a while() loop and wait until the end of the DMA tranfer.

Now, if an interrupt happens, it wont cause any overrun because in the worst case

DMA and CPU share the bus with round-robin, so the interrupt and the DMA tranfer

will be running alongside, and hopefully no overrun will occur.

Everything works great, but is this correct? If the FIFO is empty when i enable the DMA, will it tranfer garbage? Or it will wait until there available data in the FIFO?

As i said, i get valid data but i want to be 100% compliant with the specifications.

Thanks,

Nikos
12 REPLIES 12
tomas239955_stm1_st
Associate II
Posted on November 30, 2011 at 16:48

Thats nice result of 50kB/9ms which is 5.43MB/s, do you read the same block again and again?

I have put the efsl on sdio and the make a simple file copy, which result was only 150kB/s :-/. That means that something is gone wrong, or FAT has that much utilization.

infoinfo989
Associate III
Posted on November 30, 2011 at 17:44

Yes, the DMAs need to be aligned. I try to make sure everything's aligned, but I also have some safety checks in my code to warn me if a problem occurs, something like this:

if ( ((uint32_t)buff)%4)

     printf(''Warning: unaligned buffer in disk_write, sector %d, number of sectors = %d\n'', sector, count);

Regarding FAT32 speed to the SD card. I use the ChanFS FAT32 code. Initially it was much slower than I wanted. Then I discovered why, and it wasn't the FAT32 code's fault.

If you're using the standard ST SD code, or some similar variant of it, you use that code by writing a block of data to the card, and at the completion of the write a CMD12 is written to the card (this is triggered by the StopCondition flag within the ST code). The CDM12 orders  the sd card to stop receiving data and program its internal flash. This is very slow. Forcing this flash write to happen at the end of every write kills performance.

If you're writing extended amounts of data to the card consecutively, you should only issue the CMD12 at the completion of the entire sequence of writes. In other words, if you need to close the file you're writing, or if you need to access some other part of the card (hop over to another card block address) then you must issue the CDM12 to close off the current write. But if you're writing to consecutive blocks in the card, just keep writing and only issue a CMD12 at the very end.

The way I implemented this was to define a global variable that holds the last sd card block address written by the sd multiblock write function. That way the multiblock write function is able to check (and update) this variable, and it only issues a CDM12 if it determines its next write is not consecutive with its previous write. All other sd card functions (reads, and a single block write) do trigger a CMD12.

You do need to think about it a little bit, because your FAT32 code won't just be writing blocks of data. It'll also be performing reads and writes to other parts of the card, to update the FAT tables and directory entries for example. If you haven't done so already, you will need to get familiar with the state diagram in the (free) SD card physical layer specification to make sense of it all.

The other change I made was not to wait for a write to complete if I didn't need to. Having ping-pong data buffers means being able to write buffer1 to the card while buffer2 is being filled. Which means you can kick-off having the SDIO write buffer1 to the card and then immediately return to executing code, while the SDIO DMA is sending out buffer1 ''in the background'', so to speak. This does mean that each SD card routine (multi-block and single-block reads and writes) needs to check the SDIO is idle before proceeding.

With these changes, I'm able to write to the card at better than 8 MB/s, which is pretty amazing in my books. I've measured close to 9 MB/s at times.

tomas239955_stm1_st
Associate II
Posted on December 01, 2011 at 15:15

Hi, thx for advice, much appreciated.

I will do some corections, but first of all i have trouble witch J-Link GDB server, when using DMA and SDIO together, it is imposible to run for example a read process. After 1000 read cycles the STM32F207 halts and J-Link restarts. The interesting thing is that this only happends if:

1) Connected with J-LINK

2) Running the code

If you are stepping the code, the error doesnt occures. No i am hesitate what couse this issue, the j-link? the debug peripheral inside CPU? or the BUS matrix?

Any ideas?

PS: I did try with no success:

1) Latest/archive drivers, firmware or GDB J-link server

2) Changing JTAG speed

3) Changing inicializations steps before casting CMD17

4) Changing init/load steps for GDB server

5) Try another SD-CARD