Forum: Mikrocontroller und Digitale Elektronik SD-Karte: kann ich einen Schreibzugriff unterbrechen?


von bluebrother (Gast)


Lesenswert?

Hallo,

ich hab hier grad ein kleines Problem mit einem Ressourcenkonflikt am 
SPI-Bus. Ich verwende eine Transflash-Karte im SPI-Modus und noch einige 
andere SPI-Teilnehmer. Das ganze funktioniert so auch, allerdings ist 
die Karte "zu langsam" -- ich muss regelmäßig die anderen Teilnehmer 
abfragen.

Jetzt hab ich mal gesucht inwieweit ich einen block write unterbrechen 
kann -- soweit ich gesehen habe geht das nicht. Und partial write wird 
nicht von allen Karten unterstützt, ist also auch keine wirkliche 
Option. Oder hab ich da was übersehen?

Danke für alle Hinweise.

von Philipp B. (philipp_burch)


Lesenswert?

Also ich würde eher sagen, dein Geschreibsel auf die Karte ist zu 
langsam. Wie lange dauert es denn um die 512 Byte zu übertragen und in 
welchem Intervall musst du die anderen Teil abfragen?
Den Schreibzugriff wirst du nicht unterbrechen können, da die Karte beim 
Deaktivieren von CS AFAIK jegliche Komm abbricht und danach wieder mit 
einem normalen Command gestartet werden muss.

Ansonsten halt das SD-Protokoll implementieren oder Software-SPI 
verwenden falls du keine zweite SPI-Schnittstelle hast.

von bluebrother (Gast)


Lesenswert?

Also, ich hab mir mittlerweile meine Frage mehr oder weniger selbst 
beantwortet gekriegt...

Die Karte bricht jeden block write ab sobald CS wieder auf high geht. 
Also ist unterbrechen nicht. Ansonsten: meine Karte braucht ca. 6ms um 
einen Block zu schreiben. Langsam ist die Karte sicher nicht, aber ich 
kann meinen SPI-Bus leider nicht schneller wie ~3.5MHz machen aufgrund 
vom Design -- mehr schafft der Controller nicht. Da ich einen Sensor mit 
160Hz abfragen muss (und das zeitkritisch ist) habe ich also 6.25ms Zeit 
für einen Schreibzugriff. Da die Karte auch mal etwas länger braucht wie 
6ms hab ich dann ein Problem. Und partial writes kann die Karte laut CSD 
nicht (und ich will mich auch nicht auf dieses Feature verlassen).

von Fly (Gast)


Lesenswert?

Bau dir ein Software FIFO im Uc ein.
160 Hz Daten sind ja wohl gar kein Problem mit ein klein bisschen FIFO.

von Uwe (Gast)


Lesenswert?

Hi!
6ms für 512 Byte? Das kann ich garnicht recht glauben. 3,5MHz und CLK/2 
x 4096 Bit sind 2,34ms für die Übertragung nochn paar Takte fürs Init 
und wir sagen 3ms. Nun musst du nur noch auf die Response warten 
(dauernd takten) das dauert bestimmt keine 3ms bis fertig. Ich habe 
jetzt leider meinen Schlepptop nicht da sonst würde ich mal nachsehen 
wie schnell das so im allgemeinen geht. Aber >6ms für ein 1/2K, wo soll 
man denn diese Karte einsetzen? Ich denke eher dein Prog ist nicht 
optimal. Versuche doch mal die Geschwindigkeit deiner Ausgabe zu 
trimmen.

Viel Erfolg, Uwe

von holger (Gast)


Lesenswert?

Ich habe eine 64MB Nokia Mini SD Karte die schafft
selbst auf einem ARM7 nur 30kB/s. Bei 7.5MHz SPI Takt.
Und meine Routinen sind sicher nicht schlecht optimiert ;)
Eine 256MB extrememory MMC bringt es mit dem gleichen
Programm auf satte 470kB/s.

Nicht zu vergessen eine 128MB takems SD die auf 8kB/s
runtergeht wenn man zu häufig auf einen Sektor prügelt.
Da bremst wohl das eingebaute Defect-Management.

Alles im SPI Modus natürlich.

Im USB 2.0 Kartenleser schafft die Nokia auch nur gerade mal so 1MB/s
beim schreiben.

MMC und SD Karten sind schon merkwürdige Dinger ;)


von bluebrother (Gast)


Lesenswert?

@Fly: wie soll das funktionieren? Ich hab genug Platz um Daten 
zwischenzuspeichern, aber wenn ich mit 160Hz pollen muss und ein 
einfaches block write an die SD-Karte länger dauert wie die freie Zeit 
zwischen zwei polls hab ich keine Chance. Jedenfalls nicht wenn das 
alles am selben SPI-Bus hängt -- und mein Controller hat nur einen.

@Uwe: das warten auf die Response dauert teilweise wirklich lange. Hab 
das schon mit dem Oszi ausgemessen. Ansonsten gibts an der Ausgabe 
leider nix groß zu trimmen, die pustet einfach die Daten der Reihe nach 
auf den SPI. Und später soll aus den 160Hz dann noch spürbar mehr 
werden, und das eben noch mit harten Echtzeitbedingungen. Wenn ich da 
die Karte nicht unterbrechen kann hab ich da keine Chance.

von Marvin (Gast)


Lesenswert?

Was wäre, wenn man einen kleinen Atmel als Puffer für die Karte nutzen 
würde? Die zu schreibenden Daten rübergeschoben und der Puffer würde 
sich dann um den Rest kümmern. Den fehlenden zweiten SPI könnte man per 
Software emulieren, der Puffer-Atmel macht ja sonst nichts anderes.

von Uwe (Gast)


Lesenswert?

Hi!
Habe gerade mal in mein Prog geschaut, die beste Karte die ich habe 
braucht 312us zum Daten schreiben, die schlechteste 1,37 ms. OK da sind 
schon Unterschiede da, aber 3ms nur fürs schreiben? Obwohl wenn ich 
lese:
>Nicht zu vergessen eine 128MB takems SD die auf 8kB/s runtergeht wenn man >zu 
häufig auf einen Sektor prügelt.
>Da bremst wohl das eingebaute Defect-Management.
könnte das sogar stimmen. Am besten mal eine andere Karte testen, oder 
den SPI-Bus extern umschalten, oder den Sensor in SW auslesen.
Jedenfalls eine böse Geschichte.

Viel Erfolg, Uwe


von Ralf (Gast)


Lesenswert?

Hi!

Ohne jetzt alles im Detail gelesen und das SD Datenblatt im Kopf zu 
haben, wie wäre es denn mit einer Verkleinerung der Blocklänge? Kann man 
bei SD Karten nicht die Lese- und Schreibblocklänge auf unter 512Byte 
einstellen? Dann wäre es doch möglich die Zugriffe zu verkürzen.

Gruß,
Ralf

von Wolfgang (Gast)


Lesenswert?

>Eine 256MB extrememory MMC bringt es mit dem gleichen
>Programm auf satte 470kB/s.
Wie kann man denn die Geschwindigkeit messen?
Wolfgang

von holger (Gast)


Lesenswert?

10ms Timerinterrupt im Programm und zusätzlich mit dem
Mehrkanalspeicherosci zur Kontrolle messen ob es auch stimmt.
Gemessen an der CS Leitung von der MMC/SD.

Der Timerinterrupt bremst die Übertragung dabei natürlich
ein wenig !

von Rolf Magnus (Gast)


Lesenswert?

Polle den Sensor mit einem Sotware-SPI. Während das stattfindet, kann 
die SD-Karte warten. Solange du das CS nicht auf high ziehst und damit 
den Transfer abbrichst, sollten der Karte irgendwelche Unterbrechungen 
egal sein.

von holger (Gast)


Lesenswert?

@Uwe

>>schon Unterschiede da, aber 3ms nur fürs schreiben? Obwohl wenn ich
>>lese:
>>Nicht zu vergessen eine 128MB takems SD die auf 8kB/s runtergeht wenn man >>zu 
>>häufig auf einen Sektor prügelt.
>>Da bremst wohl das eingebaute Defect-Management.
>>könnte das sogar stimmen. Am besten mal eine andere Karte testen, oder

Wieso könnte ?

128MB SD takems.
FAT16. Werte gemessen mit einem ATMega32 16MHz / 8 MHz SPI Speed

4 Sektoren pro Cluster ohne FAT Buffer
8 kB/s

32 Sektoren pro Cluster ohne FAT Buffer
50 kB/s

4 Sektoren pro Cluster MIT FAT Buffer
290 kB/s

32 Sektoren pro Cluster MIT FAT Buffer
327 kB/s

Der "geprügelte" Sektor ist ein/mehrere Sektor/en in der FAT.
Die Karte kann durchaus Höchstleistungen bringen.
Die Frage ist nur "WIE" ;)

Holger


von Wolfgang (Gast)


Lesenswert?

Ich habe jetzt mit dem Oszi an CS bzw. CLK gemessen und bin zu folgenden 
Ergebnissen gekommen:
(MSP430 läuft mit 8 MHz;  CLK mit 4MHz)
1 Byte benötigt rechnerisch sowie auch messtechnisch 2µs,
aber jetzt kommt der Hammer: die Zeit zwischen 2 Bytes beträgt 13µs, 
sodass für einen Sektor mit 512 Bytes ca. 8ms gebraucht werden, was 
einem Datendurchsatz von 64 kB/s entsprechen würde.

> 4 Sektoren pro Cluster MIT FAT Buffer 290 kB/s
> 32 Sektoren pro Cluster MIT FAT Buffer 327 kB/s
Was müsste ich tun, um auf ähnliche Werte zu kommen?
Es handelt sich um eine 128MB SD-Karte, welche mit FAT32 formatiert ist, 
wobei das FAT- System nur genutzt wird, um eine Datei bestimmter Größe 
zu erzeugen. Der µC schreibt direkt in einen festgelegten Sektor. (wie 
hier im Forum unter "SD Karte--Sektor für Dateianfang festlegen /64367 " 
beschrieben)

Wolfgang

von holger (Gast)


Lesenswert?

>>(MSP430 läuft mit 8 MHz;  CLK mit 4MHz)

Oh, ein Exot ;)

>>1 Byte benötigt rechnerisch sowie auch messtechnisch 2µs,
>>aber jetzt kommt der Hammer: die Zeit zwischen 2 Bytes beträgt 13µs,
>>sodass für einen Sektor mit 512 Bytes ca. 8ms gebraucht werden, was
>>einem Datendurchsatz von 64 kB/s entsprechen würde.

>>> 4 Sektoren pro Cluster MIT FAT Buffer 290 kB/s
>>> 32 Sektoren pro Cluster MIT FAT Buffer 327 kB/s
>>Was müsste ich tun, um auf ähnliche Werte zu kommen?

Sorry für den Witz oben :(

Gut hier ein paar Tips:

Ich benutze einen ATMega mit 8MHz SPI Speed.
Theoretisch also 1MB/s. Praktisch komme ich
beim rohen Sektor schreiben auf 360-440 kB/s.
Ohne die SPI Routinen zu optimieren.
Je nach Karte. Meine langsame Nokia habe ich da aber
noch nicht getestet. Das beinhaltet das senden des Commandos,
warten auf die Response, senden eines Blocks und abholen
der CRC.

Sagen wir mal halbieren der SPI Speed halbiert auch die
Übertragungsgeschwindigkeit. Theoretisch bei 4MHz also
mit meinen Werten 180-220 kB/s. Das ist bei dir drin.

Wie ? Vermeide Unterprogramme in der Block Loop ! Also da wo
der meiste Durchsatz gemacht wird.

Bei mir sieht das so aus (bei dir wohl ähnlich):

 for(i=0; i<BYTE_PER_SEC; i++)
  {
   SPI_WRITE(*buf++); // shift out next byte
   SPI_WAIT();    // wait for end of transmission
  }


SPI_WRITE(*buf++); und SPI_WAIT(); sind bei mir MACROS
und keine Unterroutinen. Das spart haufenweise Zeit weil kein Call,
Parameterübergabe, und Return ausgeführt werden muss.


Holger

von laurentius (Gast)


Lesenswert?

Ich habe selbst mal einen Datenlogger programmiert der immer komplette 
512 Blöcke auf die SD-Karte schreibt dieser Vorgang wird von einer 
Interuptroutine unterbrochen die Messdaten aufnimmt. Das hat die Karte 
eigentlich nie gestört. Datenverluste oder Abstürze der Karte sind nie 
aufgetreten. SPI Takte habe ich zwischen 400KHz und 12MHz gefahren und 
hat immer alles gefunzt.
Allerdings will ich nicht ganz ausschliessen das es zwischen 
verschiedenen Kartenherstellern leichte Abweichungen geben kann, die 
dann zu Problemen führen---aber eigentlich eher unwahrscheinlich.

Gruss Laurentius

von Uwe (Gast)


Lesenswert?

Hi!
@Holger
>4 Sektoren pro Cluster ohne FAT Buffer 8 kB/s

Moment mal, das ist ja schreiben mit Fatunterstützung. Wolfgang dauert 
das Schreiben eines Sektors ja zulange, also 512 Byte. Von Fat oder so 
war keine Rede. Man kann ja auch etliche Sektoren füllen ohne die Fat zu 
berichtigen, das hat nachher auch noch Zeit. Da haben wir dann 
allerdings den "geprügelten" Sektor dabei und das könnte dann natürlich 
dauern.

@ Wolfgang
>aber jetzt kommt der Hammer: die Zeit zwischen 2 Bytes beträgt 13µs,
Das meinte ich mit "Versuche doch mal die Geschwindigkeit deiner Ausgabe 
zu
trimmen." Du hast doch wohl hoffentlich die 512 Byte im Ram stehen? Bei 
der Ausgabe immer nur das "SPI-fertig-Flag abfragen und dann sofort das 
nächste Byte übergeben sollte keine 13µs dauern, höchstens(Mist kein 
Datenblatt da)2/3 Takte oder so.

Nagel mich jetzt bitte nicht auf die Bits und Register fest.(nimms als 
Pap)

Data: lds temp, x+
warte: sbic SPI_Statusregister,Sendenfertig_Flag
       rjmp warte
       out SPDR,temp
       rjmp Data

Länger darf deine Ausgabe nicht sein.

Viel Erfolg, Uwe

von holger (Gast)


Lesenswert?

@Uwe

>>Wie ? Vermeide Unterprogramme in der Block Loop ! Also da wo
>>der meiste Durchsatz gemacht wird.

Auch ohne den MSP430 zu kennen stimme ich dir zu das er
irgendwo Rechenzeit verbrennt. Die beiden Zeilen oben sind als
Tip doch gar nicht schlecht ! Oder ?

>>beim rohen Sektor schreiben auf 360-440 kB/s.

Die Zeile oben bedeutet schreiben OHNE FAT.

Holger

von Uwe (Gast)


Lesenswert?

Hi!
@Holger
>>4 Sektoren pro Cluster ohne FAT Buffer 8 kB/s

>Die Zeile oben bedeutet schreiben OHNE FAT.
Was denn nun? normales Blockschreiben ohne Fat oder Fat Buffer?
Wenn ohne Fat, lasse bitte die Cluster weg denn die gehören zur Fat.
Oder meintest du ohne Fatberichtigung? Für Holger eigentlich egal, nur 
mich hätte interessiert wie langsam deine Karte schreibt, nicht wie 
langsam dein Progr. ist.

>Die beiden Zeilen oben sind als Tip doch gar nicht schlecht ! Oder ?
Ja, das ist genau das was Holger umsetzen muss.(hatte ich glatt 
überlesen und MSP430 war auch wie weggeblasen)

@laurentius
Das mag sein, aber du hast wärend der Unterbrechungen bestimmt CS nicht 
abgeschaltet. Holger hat aber am selben Bus einen Sensor den er lesen 
will.
... habe ich jedenfalls so verstanden.
@Holger
Und du kümmerst dich mal um fullspeed am SPI Bus, dann klappts auch mitm 
Messen.

Viel Erfolg, Uwe

von laurentius (Gast)


Lesenswert?

Naja ich habe eine Funktion geschrieben die Datenaustausch mit der Karte 
handelt. Immer wenn ich die anspringe wird CS auf Low gezogen. Das 
heisst wenn ein Interrupt ansteht wird in die Interruptroutine 
gesprungen...und abgearbeitet und CS bleibt Low. Bei Rücksprung macht 
das Hauptprogramm dann dort weiter und sendet oder Empfängt weiter Daten 
von dr Karte.

Das wichtigste ist das man den ersten leeren Fat-Eintrag auffindet bevor 
man das Hauptprogramm startet. Da das bei grossen Karten die bereits 
einiges an Daten enthalten schon etwas länger dauern kann. Bei schnellen 
Messungen kann es sonst schonmal schnell passieren das einem der 
Speicher überläuft.
Also zuerst ersten freien FATEintrag suchen->dann Messdaten 
abspeichern-> Bei stark fragmentierten Karten kann es natürlich auch 
später zu verzögerungen kommen die Probleme machen.

Gruss LAurentius

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.