EmbeddedRelated.com
Forums

DMA read from MCI fifo

Started by Kuba Dorzak February 8, 2011
Hi everybody,

I am trying to use DMA transfer to get MCI fifo data. I used Juri
Haberland's driver, which works perfectly with 1-bit SDbus without DMA. I
can write data to MCI using the GPDMA, but reading fails. My question
concerns DMA configuration:
1) firstly, I am setting DMA source, destination and channel 1 control:



MCI burst is set for 8 bytes (as they recommend in UM), destination burst is
32 bytes. Width for both source & destination is 32 bits + destination
increment and interrupts.

2) secondly, I am starting the transfer by:



I have here flow control set for the MCI unit (I tried to change it using
DMA flow control, but that did not help).
Of course before the 2 points, I initiated DMA controller.
In the MCI ISR it turns out that the MCI data timeout flag is set.
I suspect, that my DMA configuration is wrong, because without DMA it works
fine. Maybe you, Guys have similar problems with MCI + DMA? Thanks for any
clues.

--
Regards, Kuba

An Engineer's Guide to the LPC2100 Series

Kuba,

have a look at FatFs on http://elm-chan.org/fsw/ff/00index_e.html
Download FatFs sample projects and checkout MCI.C in lpc2k\ sub-directory
The do read the MIC port via DMA

Much fun
Herbert
Many thanks Herbert- I'll check this out.
Kuba
Hi everybody,

finally I am able to write/read blocks from an SD card. I used the DMA
configuration which is in FatFs, however I did not implement the linked
lists (scatter/gather). The ISRs from MCI unit are the similar as in the
Martin's Thomas project (
http://gandalf.arubi.uni-kl.de/avr_projects/arm_projects/arm_memcards/index.html),
so after a write/read I am waiting for the flag to be zeroed by the ISR:



The problem is that I have very slow transfers. Approximately it's 100kB/s.
It's almost the same when using 1-bit mode without DMA. I tried to
manipulate ClkDiv but it did not change anything. My MCICLK is working with
the same speed as the core- 72 MHz. With my ClkDiv I have 18MHz speed for
MCI, so I assume that the average transfer should be about 9MB/s with DMA
and 4-bit mode. I checked once again MCI_CLOCK initialization, and it's ok.

In the SD PHY Simplified Spec they wrote that for my SDSC I can get DS
(default speed) up to 25MHz, however they described the Speed Classes, where
Class 0 do not specifies performance. Is it possible that this is my missing
point- Class 2 and higher requires special initialization? Have you Guys
experienced such a problem?
Thanks for any clues.

Kuba
> The problem is that I have very slow transfers. Approximately it's 100kB/s.

If you are writing single blocks only you will not write very quickly at
all.

? It's almost the same when using 1-bit mode without DMA.

Indeed. Single blocks are like that because of what the controller in the
card must do for them.

> ...so I assume that the average transfer should be about 9MB/s with DMA and 4-bit mode.

It will be--for the data phase. However, you'll be hanging around whilst
the card organizes the single block write for you and does all its
management. You will never achieve sustained 9MB/second.

This has been discussed before:

http://www.embeddedrelated.com/groups/lpc2000/show/51246.php

Search the archives. I presented some other code for MCI and SPI
performance of SD cards.

--
Paul Curtis, Rowley Associates Ltd http://www.rowley.co.uk
SolderCore arriving Summer 2011! http://www.soldercore.com
Thanks for the clues Paul. Indeed, my preliminary tests show that I can get
about 2.4MB/s for writing and 3.6MB/s for reading blocks.
Regards,
Kuba
Hi everyone,
I got my "Memory -> DMA -> MCI" working with the following setting:

MCI_DATA_CTRL:
DIRECTION = CONTROLLER_TO_CARD,
MODE = DATA_MODE_BLOCK,
BLK-Size = 512Bytes;

GPDMA_CH0_CTRL:
TRANSFER_SIZE = 128 Bytes,
SRC_BURST_SIZE = 16,
DEST_BURST_SIZE = 16,
SRC_TRANS_WIDTH = 32bit,
DEST_TRANS_WIDTH= 32bit,
SRC_INCREMENT = ENABLE,
DEST_INCREMENT = DISABLE,
PROTECTION = DISABLE,
INT_ENABLE = ENABLE;

GPDMA_CH0_CFG:
DEST_PER = MCI,
FLOW_CTRL= MEM_TO_PER CTRL_DMA,
ERR_INT = DISABLE,
TC_INT = DISABLE,
LOCKED = ENABLE;

I got it working after playing around with the following settings:

GPDMA_CH0_CTRL (TRANSFER_SIZE, SRC_BURST_SIZE, DEST_BURST_SIZE, SRC_TRANS_WIDTH, DEST_TRANS_WIDTH)
Still I do not get the logic behind. Even though I am using transfer "TRANSFER_SIZE = 128 Bytes", it is still copying 512 bytes from the linked list item buffer, before using the next one...

Can someone explain me this behaviour? What are the best settings for DMA/MCI and why?

Thanks a lot and regards,
Heinz
Hi
transfer size set to 128 does not mean that 128 bytes is going to be copied.
It means that 128*your_word_witdh bytes is going to be transfered. In your
case SRC_TRANS_WIDTH = 4 bytes and DEST_TRANS_WIDTH = 4 bytes so it is 512
bytes.

Regards,
Kuba
Take a look:
http://infocenter.arm.com/help/topic/com.arm.doc.faqs/ka12660.html
Kuba
Thanks for the answer. Now it makes more sense.
I am using a ring buffer to realize a packet transfer up to 127 * 512 bytes with one WRITE_MULTI_BLCK SD-Command.
To update the DMA buffer sequencially I have to use memcpy(), because the USB RAM is too small to store 127 * 512 bytes.

Unfortunately I have the problem, that memcpy does not keep up the speed, which the GPDMA does.

If I want to send 16 * 512bytes I need at least a 10 * 512bytes USB RAM ring buffer.
If I want to send 32 * 512bytes I need at least a 20 * 512bytes USB RAM ring buffer.

I refill a free USB RAM buffer page (512 bytes) after each TC interrupt.

I tried to decrease the MCI clk from 30MHz to 15MHz but to decrease the transfer speed, but by doing this a TxUnderrun Error Interrupt is thrown.

Do you have any idea how I could speed up copying the data from SRAM to USBRAM? Or how I can decrease the DMA->MCI speed?

Thanks in advance!
Regards,
Heinz