Forum: Projekte & Code SD-Card mit DMA beschreiben


von Grundschüler (Gast)


Angehängte Dateien:

Lesenswert?

* the program opens a file with f_write/f_lseek. The startsector
 * and the link-table are stored in kksectors/kkcltbl
 * if there is only one fragment, data can be written in this file with
 * cmd25 - write multiblock - beginning from the startsector.
 *
 * the spi-cmd25-sequence is
 * 0xfc-512xdata-crc-crc-response
 * crc and response are only dummies, therefore can be written
 * a stream of 516data with dma from buffer. Cause of 0xfc-token,
 * there is one byte difference between input and output
 * __SECTION(data,RAM1) uint8_t buffer[25600];
 *uint8_t *buf_cam0 =buffer+1;
 *uint8_t *buf_cam1 =buffer+1+12800;
 * Data can be written in buffer1, while dma is writing from buffer2
 *
 *With DMA speed goes up from 0,45MB/s to 1,2MB/s
 *
 *next step would be to to change code for fragmented data/cltbl[4]!=0

1
for(i=0+1;i<512+1;i++)buffer[i]='.';
2
for(i=512+1;i<12800+1;i++)buffer[i]='-';
3
buffer[12800-2]='x';
4
prepare_cmd25_write();
5
DMA_zl_blocks=25;
6
res=send_cmd(CMD25,kksectors);
7
DMA0_from_buffer_to_SSP0_init();
8
DMA0_from_buffer_to_SSP0_transfer(0,516,0xfc);
9
_delay_ms(100);
10
11
DMA0_from_buffer_to_SSP0_end();
12
_delay_ms(100);
13
14
15
//verify
16
wait;wait;wait;wait;
17
for(i=0;i<512;i++)buf_rx[i]=255;
18
res=f_open(&Fil2, Dateiname, FA_READ | FA_OPEN_EXISTING);
19
res = f_read(&Fil2, buf_rx, 512, &br);     // Read a chunk of src file
20
res = f_close(&Fil2);
21
lgi(4,1,buf_rx[0]);lw("-");li(buf_rx[1]);lw("-");li(buf_rx[2]);lw("-");li(buf_rx[3]);lw("-");li(buf_rx[4]);lw("-");li(buf_rx[5]);
22
lgi(5,1,buf_rx[0+512]);lw("-");li(buf_rx[1+512]);lw("-");li(buf_rx[2+512]);lw("-");li(buf_rx[3+512]);lw("-");li(buf_rx[4+512]);lw("-");li(buf_rx[5+512]);

von Falk B. (falk)


Lesenswert?

Unheimlich nützlich für andere Leute, ohne Bezug auf den Controller und 
die restliche Softwareumgebung.

von Grundschüler (Gast)


Lesenswert?

Falk Brunner schrieb:
> Unheimlich nützlich für andere Leute

pardon, Ausgangscode ist der von Elm Chan, verwendet wird ein LPC1768

Der code stellt dar, wie man den sd-Schreibzyclus auf nur eine 516-byte 
Datenfolge für die DMA vereinfachen kann. Wer sich mit DMA beschäftigt 
hat, kann das leicht für andere mcus umsetzen.

von Jim M. (turboj)


Lesenswert?

Vor einer ernsthafen Verwendung muss ich leider abraten, denn 
"abfr_busy()" blockiert den DMA Interrupt, je nach Karte für mehr als 
100 ms.

Außerdem gibt es keine erkennbare Behandlung der übrig bleibenden Daten 
im RX-FiFo des SSP, was nachfolgende Kommunikation beeinträchtingen 
kann.

Multiple Block Write scheint in der Tat bei vielen SD Karten schneller 
zu sein als single Write.

DMA halte ich aber in diesem Fall für überflüssig. Man erhält eine 
praktisch idenische Geschwindigkeit durch das Ausnutzen des FIFO im SSP 
(8 Einträge á 16 Bit) bei weniger aufwändigem Code.

von Grundschüler (Gast)


Lesenswert?

Jim Meba schrieb:
> "abfr_busy()" blockiert den DMA Interrupt, je nach Karte für mehr als
> 100 ms

Märchen. Bei meiner 8GB-Karte jedenfalls nicht. Ich habe natürlich 
überlegt, was ich mit der Readyabfrage mache - eigene DMA oder eigene 
Timerroutine. Das Debugging hat aber gezeigt, dass hier kaum ein 
Eintritt in die Schleife stattfindet. Das zeigt auch die erzielte 
Datenrate. Mit DMA hat sich diese gegenüber Multiple Block Write mehr 
als verdoppelt. Nach meiner Einschätzung lassen sich durch den Ersatz 
von abfr_busy keine nennenswerten weiteren Geschwindigkeitszuwächse 
erzielen. Deine Aussage gilt vielleicht für ältere Karten, nich jedoch 
für moderne 8GB-Karten. Anderes sollte man sich aber heute nicht mehr 
antun.

Jim Meba schrieb:
> Außerdem gibt es keine erkennbare Behandlung der übrig bleibenden Daten
> im RX-FiFo des SSP, was nachfolgende Kommunikation beeinträchtingen
> kann.

Ein Problem, das mich wirklich fast zur Verzweifelung gebracht hat. Im 
Ausgangscode von Elm Chan wird in der Sequenz
>token-512databyte-crc-crc-response
jeweils der rxfifo geleert und response ausgewertet. Verzichtet man auf 
diese Auswertung, braucht man den rxfifo nicht leeren, so dass ein 
einheitlicher 516Byte-Schreibvorgang entsteht.

Das Problem ensteht aber nach Beendigung der DMA, weil dann wieder mit 
elm-chan code die response ausgewertet wird. der rxfifo muss nach der 
DMA also geleert werden.  Gelöst wird dieses Problem durch den Aufruf 
von
1
void DMA0_from_buffer_to_SSP0_end(void){
2
  DMA_STATUS=2;
3
  abfr_busy();
4
  DMA3_transfer_from_SSP0_to_buffer(32);
5
}

Hier wird der rxfifo und wohl auch ein DMA-fifo geleert, so dass 
anschließend ohne Konflikte mit elm chan weitergearbeitet werden kann. 
Warum es hier 32 bytes sein müssen, kann ich dir nicht sagen, 8bytes 
reichen jedenfalls nicht.

von Grundschüler (Gast)


Lesenswert?

Jim Meba schrieb:
> DMA halte ich aber in diesem Fall für überflüssig. Man erhält eine
> praktisch idenische Geschwindigkeit durch das Ausnutzen des FIFO im SSP
> (8 Einträge á 16 Bit) bei weniger aufwändigem Code.

Das habe ich mit der Funktion cmd25_spi_write() ausprobiert und mit DMA 
verglichen. DMA läuft mehr als doppelt so schnell. Weiterer Vorteil, DMA 
läuft -bis auf das vernachlässigbare abfr_busy- komplett im Hintergrund 
ab. Man muss also nur für Zugriffe auf die Karte auf das Ende der DMA 
warten und kann ansonsten die mcu andere Programmteile bearbeiten 
lassen.

von Detlef K. (adenin)


Lesenswert?

Grundschüler schrieb:
> Deine Aussage gilt vielleicht für ältere Karten, nich jedoch
> für moderne 8GB-Karten. Anderes sollte man sich aber heute nicht mehr
> antun.

Ich hab hier eine alte ;) 64GB SD, die hat diese Delays auch drin.
Das ist in den Spec's auch so beschrieben und als normal anzusehen.
Du musst natürlich größe Datenmengen kontinuierlich aufzeichnen, dann 
merkst Du, das (abhängig vom Kartentyp) aller sounsoviel Blocke kleinere 
und größere Delays drin sind.

Ich empfehle Kapitel 4.6.2.2 der "SD Specification Part 1" Version 4.10

von Grundschüler (Gast)


Lesenswert?

Detlef Kunz schrieb:
> aller sounsoviel Blocke kleinere
> und größere Delays

Mag sein. Es bleibt aber die Frage, ob es sich lohnt wegen delays, die 
jedenfalls nicht in jeder Schreibsequenz auftreten, eine Routine zu 
programmieren die bei jeder Schreibsequenz aufgerufen werden muss und 
die allein durch diesen Aufruf eine eigene Verzögerung des 
Schreibvorgangs mit sich bringt.

Ich meine nein. Meine Datenrate liegt bei 1,2MB/sec bei 600k Daten. Der 
Ersatz von abfr_busy könnte bestenfalls bewirken, dass 8/516 des 
Schreibvorgangs ebenfalls in den Hintergrund ausgelagert werden. 
Schneller wird der Schreibvorgang dadurch nicht. Der programmtechnisch 
erforderliche Aufwand für den Ersatz von abfr_busy lohnt sich nicht.

von Falk B. (falk)


Lesenswert?

@Jim Meba (turboj)

>Vor einer ernsthafen Verwendung muss ich leider abraten, denn
>"abfr_busy()" blockiert den DMA Interrupt, je nach Karte für mehr als
>100 ms.

Es ist, wie der Name des Posters schon sagt, ein Gefrickel vor dem 
Herrn.

Beitrag "sd-Karte Elm Chan DMA"

Der OP will keine solide Lösung (die deutlichen Aufwand bedeutet), weil 
er meint, das einfach mal so machen zu können.

Beitrag "Re: sd-Karte Elm Chan DMA"

von Grundschüler (Gast)


Lesenswert?

Falk Brunner schrieb:
> Der OP will keine solide Lösung (die deutlichen Aufwand bedeutet), weil
> er meint, das einfach mal so machen zu können.

das klingt ein bischen nach nicht-sein-kann-weil-nicht-sein-darf.

Meine DMA ist getestet und läuft stabil. DMA muss eine einfache Lösung 
sein, weil es bei DMA darum geht, große Datenmengen in einem festen 
Schema zu verarbeiten. Der Entwicklungsweg ging hier von anfangs 
kompliziert bis zum Schluss recht einfach. Gefrickel ist das 
zugegebenermaßen bei der Abfrage der Linktabel und des Anfangssektors - 
kein schöner Programmstil, der trotzdem funktioniert. Der DMA-Teil ist 
kein Gefrickel. Er funktioniert wie er soll. Kleinigkeiten kann man 
sicher noch verbessern, aber eine grundsätzlich bessere Lösung die auch 
nur annähernd vergleichbare Datenraten stabil schafft, gibt es offenbar 
nicht.


>einfach mal so machen zu können
ist wochenlange Arbeit und viele dummen Fragen ans Forum mit Antworten, 
die nur teilweise weitergeholfen haben. Ohne die Häme mancher Antworten 
hätte ich mir die Arbeit aber auch nicht gemacht.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.