Forum: Mikrocontroller und Digitale Elektronik SD-Karte Speichergeschwindigkeit


von thomas (Gast)


Lesenswert?

Hallo zusammen,

ich möchte Daten von einem µC auf eine SD-Karte speichern.
Die Roh-Daten sind 100 16Bit Variablen, die in einem 10ms Raster 
gespeichert werden sollen.

Wie groß ist der Overhead, wenn ich FAT16 verwende?

Welchen Datendurchsatz bzw. welche Taktrate benötige ich dafür auf der 
SPI?

Über Informationen von Erfahren SD-Karten-Programmierer würde ich mich 
sehr freuen!

Liebe Grüße
Thomas

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

thomas schrieb:
> Die Roh-Daten sind 100 16Bit Variablen, die in einem 10ms Raster
> gespeichert werden sollen.

Also 200 Byte, 100 mal pro Sekunde. Das macht 20 kByte pro Sekunde.

Das ist eine Datenrate, die eine SD-Karte recht problemlos schaffen 
sollte, auch ein 1-Bit-SPI-Ansteuerung. Die sollte natürlich nicht an 
die 20 kByte pro Sekunde angepasst sein, sondern entsprechend schneller, 
was halt Dein µC so sinnvoll an der SPI-Schnittstelle zustandebekommt.

20 kByte/sec sind 72 MByte pro Stunde, damit hält Deine SD-Karte maximal 
27 Stunden lang (denn bedingt durch FAT16 sind mehr als 2 GB nicht 
möglich, bei Mehrbedarf müsstest Du dann eine SDHC-Karte und FAT32 
verwenden).

von thomas (Gast)


Lesenswert?

Danke für die schnelle Antwort!

Dass die SPI vom Microcontroller nicht an die 20kByte pro Sekunde 
angepasst werden sollte, ist mir klar - sind ja auch nur die 
Rohdaten...da kommt ja noch der Overhead des Dateisystems (FAT16 vs. 
FAT32) und der von den Kommandos, etc. der SD-Karte dazu. Doch wie groß 
ist der ungefähr?

Bezüglich der Taktrate der SPI mache ich mir zwar keine Sorgen, ich 
möchte aber wissen, wie schnell diese mindestens sein sollte.

LG

von Falk B. (falk)


Lesenswert?

@ thomas (Gast)

>Rohdaten...da kommt ja noch der Overhead des Dateisystems (FAT16 vs.
>FAT32) und der von den Kommandos, etc. der SD-Karte dazu. Doch wie groß
>ist der ungefähr?

Ich hab vor eineiger Zeit mit dem AVR@16 MHz und dem FATFs von ElmCHAN 
bis zu 500kB/s Schreibgeschwindigkeit erreicht (reiner Schreibtest ohne 
sonstige Funktion). In der realen Applikation habe ich 22kB/s 
geschrieben, das lief auch problemlos. Nebenbei wurde noch DMX512 mit 
voller Bandbreite empfangen.

von runtastic (Gast)


Lesenswert?


von Falk B. (falk)


Lesenswert?

@ runtastic (Gast)

>Elm Chan sagt dazu folgendes:

Ich glaube aber, dass diese Test mit einer älteren Version gemacht 
wurden, die noch deutlich schlechteres Caching hatte. Denn bei meinen 
Test waren die kleinen Blockgrößen nahezu genausoschnel wie die Großen!

von Frank K. (fchk)


Lesenswert?

thomas schrieb:
> Hallo zusammen,
>
> ich möchte Daten von einem µC auf eine SD-Karte speichern.
> Die Roh-Daten sind 100 16Bit Variablen, die in einem 10ms Raster
> gespeichert werden sollen.

Verlasse Dich nicht auf das Zeitverhalten von SD-Karten! Der interne 
Controller kann sich zu einer für Dich nicht vorhersehbaren Zeit eine 
Auszeit von mehreren 100ms für interne Verwaltungsgeschichten, Wear 
Levelling, etc nehmen.

fchk

von der alte Hanns (Gast)


Lesenswert?

Folglich empfiehlt es sich, einen Ringpuffer von ca. 10 kB anzulegen.

von Falk B. (falk)


Lesenswert?

@ der alte Hanns (Gast)

>Folglich empfiehlt es sich, einen Ringpuffer von ca. 10 kB anzulegen.

Stimmt, ich hab bei mir ~50kB, externer SRAM. Ist leider real auch 
nötig, weil es ab und an zu längeren Aussetzern kommt, das ist aber vom 
SD-Kartentyp abhängig. :-(

Beitrag "SD-Karte mit sporadischen Schlafpausen?"

von der alte Hanns (Gast)


Lesenswert?

Die 10 kB bezogen sich auf die Anforderung von thomas.
Von dem einen Dutzend verschiedener Karten, die ich bislang hatte, 
pausierte keine länger als 350 ms; bei meinen 95 kB/s ist's aber ein 
Ärgernis, ich bräuchte ja ca. 33 kB Speicher.

von thomas (Gast)


Lesenswert?

Danke für die vielen Antworten - das hilft mir schon viel weiter.

Frank K. schrieb:
> Verlasse Dich nicht auf das Zeitverhalten von SD-Karten! Der interne
> Controller kann sich zu einer für Dich nicht vorhersehbaren Zeit eine
> Auszeit von mehreren 100ms für interne Verwaltungsgeschichten, Wear
> Levelling, etc nehmen.

Das RTOS auf dem µC, an den ich die SD-Karte anschließen möchte, läuft 
schon. Das Zeitfenster von 10ms kann ich relativ genau einhalten.

Wie sieht es denn nun mit dem Overhead für das Schreiben bei FAT16/32 
aus? Hat noch keiner Erfahrungen damit gemacht oder lässt sich das nicht 
so allgemein sagen?

von Falk B. (falk)


Lesenswert?

@ thomas (Gast)

>Wie sieht es denn nun mit dem Overhead für das Schreiben bei FAT16/32
>aus? Hat noch keiner Erfahrungen damit gemacht oder lässt sich das nicht
>so allgemein sagen?

Darum kümmert sich die FAT-Lib deines Vertrauens. Aber grob geschätzt 
ist das nicht soooo viel, wenn man bedenkt, dass man mit 500kB/s 
schreiben kann, der Bus aber maximal ~1,1 MB/s übertragen kann, bezogen 
auf mein Projekt. Beim Lesen kam ich auf ~800kB/s. Not bad!

Mit diesem Wissen würde ich NIEMALS wieder darüber nachdenken, eine 
SD-Karte ohne FAT zu nutzen. Lohnt sich nicht.

von c-hater (Gast)


Lesenswert?

thomas schrieb:

> Frank K. schrieb:
>> Verlasse Dich nicht auf das Zeitverhalten von SD-Karten! Der interne
>> Controller kann sich zu einer für Dich nicht vorhersehbaren Zeit eine
>> Auszeit von mehreren 100ms für interne Verwaltungsgeschichten, Wear
>> Levelling, etc nehmen.

Das kann man nur sehr dick unterstreichen!

> Wie sieht es denn nun mit dem Overhead für das Schreiben bei FAT16/32
> aus? Hat noch keiner Erfahrungen damit gemacht oder lässt sich das nicht
> so allgemein sagen?

Das ist doch simpel: Pro Cluster geschriebener Daten ist ein Update der 
FAT nötig. Wie häufig das passiert (passieren muß), hängt logischerweise 
direkt von der Clustergröße ab. Zusätzlich muß spätestens in diesem 
Moment die Suche nach dem nächsten freien Cluster erfolgen, was im worst 
case ein Lesen fast der gesamten FAT erfordert.

Zusätzlich wird "irgendwann" auch immer mal wieder der 
Verzeichniseintrag bezüglich der Dateigröße und der Zugriffszeit 
aktualisiert. Das ist allerdings Implementierungsabhängig. Manche 
Implementierungen schreiben schon bei einem Flush() andere erst bei 
einem Close(), manche aber auch zwischendurch immer mal wieder.

Der Code ist doch quelloffen. Schau halt einfach nach, wie er sich 
verhält. Vermutlich ist das sogar konfigurierbar, genauso wie die 
Allozierungsstrategie.

Tja, ist schon Scheiße, wenn man copy&paste-Code verwendet, den man 
nicht versteht, isn't it?

von der alte Hanns (Gast)


Lesenswert?

Yeah - on the other hand, I don't understand my own brain, but try to 
use it none the less.

von Frank K. (fchk)


Lesenswert?

thomas schrieb:
> Danke für die vielen Antworten - das hilft mir schon viel weiter.
>
> Frank K. schrieb:
>> Verlasse Dich nicht auf das Zeitverhalten von SD-Karten! Der interne
>> Controller kann sich zu einer für Dich nicht vorhersehbaren Zeit eine
>> Auszeit von mehreren 100ms für interne Verwaltungsgeschichten, Wear
>> Levelling, etc nehmen.
>
> Das RTOS auf dem µC, an den ich die SD-Karte anschließen möchte, läuft
> schon. Das Zeitfenster von 10ms kann ich relativ genau einhalten.

Die Karte aber nicht. Die kann irgendwann mal die Schreibfunktion für 
beispielsweise eine halbe Sekunde blockieren. In dieser halben Sekunde 
läuft dann kein IO. Und wann die Karte das macht, und wie lange sie dann 
mit sich selber beschäftigt ist, kannst Du nicht vorhersagen.

Harte Echtzeit geht anders. ZB mit einem nackten NAND-Flash. Das hat 
keinen Controller, da hast Du alles in der Hand.

fchk

von Falk B. (falk)


Lesenswert?

@ Frank K. (fchk)

>Die Karte aber nicht. Die kann irgendwann mal die Schreibfunktion für
>beispielsweise eine halbe Sekunde blockieren.

Jain. Das hängt auch  davon ab, wie die Zugriffsfunktion gemacht wird.

>In dieser halben Sekunde
>läuft dann kein IO.

Nanana, es gibt immer noch Interrupts! Und Päemtive RTOSe. Klar muss man 
dann beim SD-Zugriff etwas mehr Aufwand treiben (atomarer Zugriff auf 
SPI etc.) aber das ist kein unlösbares Problem.

>Harte Echtzeit geht anders.

Sicher, indem man mal den Tunnelblick überwindet und elementare 
Grundlagen anwendet.

> ZB mit einem nackten NAND-Flash. Das hat
>keinen Controller, da hast Du alles in der Hand.

Ist bei SD-Karte kein bisschen anders!

von c-hater (Gast)


Lesenswert?

der alte Hanns schrieb:

> Yeah - on the other hand, I don't understand my own brain, but try to
> use it none the less.

You can do it this way until it wents wrong. But it'll be too late to 
choose a better strategy when you reached that point...

von der alte Hanns (Gast)


Lesenswert?

Boy, talk of point of no return.

von thomas (Gast)


Lesenswert?

Danke für die Antworten - das hilft mir weiter!

von Hui (Gast)


Lesenswert?

Allenfalls waere noch interessant gewesen, wieviele Daten geschrieben 
werden muessen, ob das Flasch abziehbar sein muss, oder immer eingebaut 
bleibt, usw.

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

Hui schrieb:
> das Flasch

Das heißt die Flasch ;-) Zumindest in Hessen...

von thomas (Gast)


Lesenswert?

Hui schrieb:
> Allenfalls waere noch interessant gewesen, wieviele Daten geschrieben
> werden muessen, ob das Flasch abziehbar sein muss, oder immer eingebaut
> bleibt, usw.



Da die Karte fix eingebaut wird, habe ich mich jetzt dafür entschieden, 
auf das Dateisystem zu verzichten.

Die Daten werde ich über die serielle Schnittstelle an den PC schicken.

Habe ich richtig verstanden, dass ich für die initalisierung der 
SD-Karte im SPI-Modus folgendes machen muss:

- SPI-CLK auf 400kHz setzen
- 80-CLK-Cycles ausgeben
- CMD0 mit richtiger CRC senden

bis idle-bit 'clear'
- CMD55 (Next command will be application-specic)
- ACMD41 (Initialize the card)
- SPI-CLK auf maximum (<25MHz)



Um dann 512 byte Daten zu schreiben:
- CMD24 + 32-bit Block Address + CRC (wird nicht von der Karte geprüft)
- 0xFE senden (Startblock)
- 512 byte Daten senden
- MOSI auf HIGH (0xFF senden) bis MISO auf LOW

Bezüglich der Adresse: Darf ich gleich von der Adresse 0x00 weg 
schreiben?

Danke und LG

von leluno (Gast)


Lesenswert?

Dieser thread endet leider mit einer unbeantworteten Fragestellung. Kann 
man bei einer sd-Karte den ganzen Fat-Überbau weglassen und wie von 
thomas dargestellt schnell sequentiell schreiben?

Falk Brunner schrieb:
> Ich hab vor eineiger Zeit mit dem AVR@16 MHz und dem FATFs von ElmCHAN
> bis zu 500kB/s Schreibgeschwindigkeit erreicht

Kannst du erklären wie du das hinbekommen hast? Etwa so wie thomas dies 
im letzten Beitrag dargestellt hat?

Gibt es andere Speichermedien, die zum Zwischenspeichern großer 
Datenmengen besser geeignet sind (ca.1Mbyte, <5sec)? Die ARM-boards 
haben ja einen USB-Anschluss. Wenn man den zum Speichern von Daten 
nutzt, wie hoch ist dann der Datendurchsatz.

von Falk B. (falk)


Lesenswert?

@ leluno (Gast)

>Dieser thread endet leider mit einer unbeantworteten Fragestellung. Kann
>man bei einer sd-Karte den ganzen Fat-Überbau weglassen und wie von
>thomas dargestellt schnell sequentiell schreiben?

Das kann man. Aber es löst nicht das Problem, dass die SD-Karte ab und 
an mal ein paar hundert ms Gedenkpause machen darf, weil sie neue 
Sektoren löscht etc. Gute Karten verteilen die Gedenkpausen auf mehrere 
kleine Pause, schlechtere Karten machen auch mal größere Pausen bis zu 
1s!

>> Ich hab vor eineiger Zeit mit dem AVR@16 MHz und dem FATFs von ElmCHAN
>> bis zu 500kB/s Schreibgeschwindigkeit erreicht

>Kannst du erklären wie du das hinbekommen hast?

Einfach schreiben. Klingt komisch, ist aber so ;-)

>Etwa so wie thomas dies
>im letzten Beitrag dargestellt hat?

Kann sein, die Low Level "Drecksarbeit" erledig für mich die FAT32 Lib 
von ELM Chan. Ich rufe nur f_write() auf.

von leluno (Gast)


Lesenswert?

bei timetick 10 ms wäre das dann dieser code:
1
res=f_mount(0, &fs);
2
res = f_open( &fsrc , Dateiname , FA_CREATE_NEW | FA_WRITE);
3
Timer=0;
4
res = f_write(&fsrc, bufferx, (10240), &br);
5
tmp=Timer;
6
f_close(&fsrc);
7
lgw(2,1,"Dauer ms: ");
8
li(10240*100/tmp);

von leluno (Gast)


Lesenswert?

leluno schrieb:
> res=f_mount(0, &fs);
> res = f_open( &fsrc , Dateiname , FA_CREATE_NEW | FA_WRITE);
> Timer=0;
> res = f_write(&fsrc, bufferx, (10240), &br);
> tmp=Timer;
> f_close(&fsrc);
> lgw(2,1,"Dauer ms: ");
> li(10240*100/tmp);

ergibt 341.333 bytes/sec, wäre gerade noch ausreichend

von Frank M. (frank_m35)


Lesenswert?

leluno schrieb:
> ergibt 341.333 bytes/sec, wäre gerade noch ausreichend

und passt somit auch mit den Benchmark-Ergebnissen von elm chan überein.

Ich habe es auch mal selbst getestet, 2MB in 2kB Blöcken braucht 5.22 
Sekunden -> 392kB/s. (PIC24 mit 32MHz und Transcend 2GB micro-SD card 
TS2GUSD).


Wenn du es noch schneller haben willst und bspw. die 2MB/s oder mehr 
nutzen willst, die eine SD-Karte schaffen sollte, so musst du dich vom 
kostenlosen SPI-Interface lossagen und zum lizenzpflichtigen SDIO 
wechseln. Einige ARM Mikrocontroller haben ein SDIO Interface integriert 
und es gibt einige Beispiele in Verbindung mit FatFS, bspw.
http://mikrocontroller.bplaced.net/wordpress/?page_id=621
Die Kamera-Hersteller müssen ja auch irgendwie ihre 20MB/s Filme auf 
eine SD-Karte ablegen können.

Ein andere Möglichkeit ist keine SD-Karte sondern ein fest installierter 
NAND Speicher.

: Bearbeitet durch User
von leluno (Gast)


Lesenswert?

1
  else {        /* Multiple sector (max 4096bytes) write */
2
    if (CardType & CT_SDC) send_cmd(ACMD23, count);  /* Predefine number of sectors */
3
    if (send_cmd(CMD25, sector) == 0) {  /* WRITE_MULTIPLE_BLOCK */
4
      do {
5
        if (!xmit_datablock(buff, 0xFC)) break;
6
        buff += 512;
7
      } while (--count);
8
      if (!xmit_datablock(0, 0xFD))  /* STOP_TRAN token */
9
        count = 1;
10
    }
11
  }
12
  deselect();

Das scheint die Stelle beim Elm-Chan-Code zu sein, wo eine DMA einsetzen 
könnte: Es werden 512Datenbytes und 2CRCBytes gesendet. Der ARM wartet 
dann auf die Bestätigung der Karte. Wenn man diese Bestätigung in einen 
Interrupt legt, könnte der ARM in der Zwischenzeit etwas anderes machen, 
Gibt es sowas schon fertig als code?

Frank M. schrieb:
> SPI-Interface lossagen und zum lizenzpflichtigen SDIO
meine 8Gb-SD-Karte hat nur 8 Kontakte. Parallelen Datentransfer von 
4bits scheint es nicht mehr zu geben.

Gibt es Nand-Speicher, die man noch selber löten kann 
(Streifenraster+Lötpistole)?

von Frank M. (frank_m35)


Lesenswert?

leluno schrieb:
> Frank M. schrieb:
>> SPI-Interface lossagen und zum lizenzpflichtigen SDIO
> meine 8Gb-SD-Karte hat nur 8 Kontakte. Parallelen Datentransfer von
> 4bits scheint es nicht mehr zu geben.

Entweder du kaufst dir eine SD-Karte mit 4-bit Modus oder du schreibst 
den vorhanden fertigen 4-bit Code von elm-chan für ARM der DMA verwendet 
um, sodass er im 1-bit modus arbeitet. (siehe das lpc23xx Projekt im 
samples ordner von FatFS). Das sollte machbar sein, zumal die SD-Karte 
zu beginn im 1-bit Modus arbeitet und dann auf 4-Bit per Software 
umgeschalten werden muss.

Natürlich kannst du dir auch überlegen ob du auch wirklich diese hohe 
Datenrate brauchst und nicht vielleicht das Speichern effizienter 
gestalten kannst bzw. sogar komprimieren kannst. Kommt ganz auf deine 
Daten an.

: Bearbeitet durch User
von leluno (Gast)


Lesenswert?

Frank M. schrieb:

Danke für die Antwort. Ich habe mal eine 9Pin-Karte bestellt. Die 
LPC23xx haben eine spezielle MCI-Schnittstelle. Den Elm-Code auf 
4GPIO-Pins umzuschreiben dürfte schwierig werden. Das wäre dann eine Art 
Software-4bit-spi. Bei 100Mhz Takt und DMA aber nicht völlig 
hoffnungslos.

von Frank M. (frank_m35)


Lesenswert?

leluno schrieb:
> Frank M. schrieb:
>
> Danke für die Antwort. Ich habe mal eine 9Pin-Karte bestellt. Die
> LPC23xx haben eine spezielle MCI-Schnittstelle. Den Elm-Code auf
> 4GPIO-Pins umzuschreiben dürfte schwierig werden. Das wäre dann eine Art
> Software-4bit-spi. Bei 100Mhz Takt und DMA aber nicht völlig
> hoffnungslos.

Also ich habe noch nie mit der MCI-Schnittstelle oder gar einem ARM 
gearbeitet, aber reicht nicht einfach schon den Wide Modus nicht zu 
aktivieren?
Im Datenblatt
http://www.nxp.com/documents/user_manual/UM10211.pdf
auf Seite 498 ist das MCIClock Register beschrieben. Dort kannst du auf 
den Wide Bus umschalten, was im elm-chan code am Ende der 
Initialisierung getan wird. Im Standard mode wird anscheinend nur DATA0 
verwendet, also 1-Bit, anstatt 4-Bit.
Auf Seite 493 steht nochmal genaueres zu den zwei Bus Modi.

Es kann sein, dass noch ein paar andere Code Änderungen vorgenommen 
werden müssen, aber ein 1-Bit MCI Interface muss nicht per Software 
implementiert werden da es in Hardware vorliegt.

von leluno (Gast)


Lesenswert?

Die Idee ist gut. Ich war gedanklich schon beim 4bit-Modus, weil- wenn 
der funktionieren würde, das praktisch einen parallelen Speicher 
ersetzen würde. Danke für den Hinweis!

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.