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.
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.
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).
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
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 ;)
@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.
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.
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
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
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 !
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.
@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
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
>>(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
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
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
@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
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
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