Hallo zusammen,
eine kurze Frage an die, die es vielleicht direkt wissen oder schonmal
gemessen haben:
elm-chans FatFs Bibliothek: Datensenden vom uC auf die SD-KArte
Wir gehen der Einfachheit halber davon aus das alles perfekt angebunden
ist und funktioniert.
Das ganze findet über einen normalen SPI statt: Frequenz aktuell 24 MHz.
Das senden von Datenpaketen ohne irgendwelchen Overhead sollte jetzt ja:
Daten(Bytes) 8 1/24 MHz = Dauer der Datenübertragung.
also gehen wir von 500 Bytes aus, sind es ca 170 us reine
Datenübertragungsdauer.
Gemessen am Oszi dauert die ganze Routine als mit elm chan overhead ca 8
ms.
Jetzt bin ich mir nicht sicher ob das normal ist, dass der Overhead der
SD-Karte soviel Zeit in anspruch nehmen sollte, oder ob ich irgendetwas
falsch eingestellt oder programmiert habe.
SPI-clock habe ich am Oszi überprüft, der stimmt.
Die Datenübertragung funktioniert auch vollkommen korrekt, lediglich die
Dauer dieser Schreibvorgänge machen mich etwas stutzig, ich hätte es
gerne schneller, gerne einen Faktor 10 :)
Dankeschön schonmal für das lesen und ich freue mich auf jegliche
sachdienlichen Hinweise.
PS: Ich habe mir jetzt vergleichsthreads durchgelesen und bei elmchan
nochmal im forum nachgelesen bzgl. speed.
Also Fazit dort, wenn ich das richtig gelesen habe:
Je größer die Dateien die man schreiben will, desto größer der
Datenumsatz pro Sekunde. Also besser 100kB schreiben auf einmal anstelle
von 100 Byte.
Allerdings weiss keiner so recht wo man den Datenbuffer umstellen kann
innerhalb des elmchan codes, er sthet dort glaube ich standartmässig auf
512 Byte.
Wir senden 200 Bytes explizit, aber innerhalb der elmchan Routine im
SPI-Aufruf stehen dann auch wieder 512 Bytes als Bytecounter drin, also
sendet er nicht 200 Byte wie ich dachte, sondern 512.
Und aufgefallen ist noch, wir haben leider aktuell nur 2 verschiedene SD
Karten zum testen, eine 4 GB noname, dauer ca 8 ms unser Schreibzyklus,
eine transcent 32 GB KArte, dort dauert es nur 3 ms, also schon ein
Faktor 2, was alleine eine unterschiedliche SDKarte ausmacht, also
vermutlcih mit internen SD-Kartenpuffern zu tun.
Das nur als Ausblick, dankeschön nochmals und viele Grüße.
Naja, 8 Bytes sagen wenig aus.
Teste mal mit einem Megabyte Random Daten.
Bei 8 Bytes ist der Overhead durch Fileverwaltung, Buffer und öffnen der
Datei schon gewaltig.
rg423g schrieb:> ca 8 ms. ....> dort dauert es nur 3 ms
Lass die Karte zwischendurch mal etwas "Housekeeping" (Garbage
Collection, vorsorgliches Löschen von freien Sektoren...) machen, dann
kann diese Zeit noch bedeutend länger werden. Laut Standard darf das
Busy bis zu 250ms lang dauern.
> also sendet er nicht 200 Byte wie ich dachte, sondern 512
Stichwort: Sektorgröße
BTW: beim Powerfail musst du die Versorgung der Karte laut Standard noch
bis zu 500ms (streng empfohlen sogar noch länger) nach dem letzten
Schreibbefehl puffern. So manch einer, der das nicht tut, wundert sich
dann über korrupte Daten. Dagegen hilft dann eine "Sekunden-USV" aus
Diode und Elko für die SD-Karte.
rg423g schrieb:> Jetzt bin ich mir nicht sicher ob das normal ist, dass der Overhead der> SD-Karte soviel Zeit in anspruch nehmen sollte
Ja, das ist normal. Die tatsächlichen Flash-Blöcke sind viel größer, bis
4 MiB ("Allocation Unit") bei SDSC/SDHC. Wenn du nur so wenige Daten
schreibst, muss so ein kompletter Block gelesen, die 512 Bytes
modifiziert, und dann wieder zurückgeschrieben werden. Am Effizientesten
ist es, wenn du immer 4 MiB auf Einmal schreibst, und zwar auf zuvor
gelöschte Blöcke deren Anfang eben auch Vielfaches von 4 MiB ist. So
gehen bis 10 MiB/s (bei Karten mit Speed Class 10). Wie man das bei der
elm-chan Library erreicht weiß ich aber nicht - hab sowas mal selbst
implementiert.
Manche Karten (z.B. Toshiba und SanDisk) machen zwischendurch bis zu 2s
Pause. Das muss man abfangen können. Gute Erfahrungen habe ich mit
Samsung-Karten gemacht.
SD-Karten garantieren übrigens bei SPI überhaupt keine Geschwindigkeit -
nur bei Nutzung des SD bus ("SDIO") gilt die Geschwindigkeitsangabe.
Lothar M. schrieb:> Dagegen hilft dann eine "Sekunden-USV" aus> Diode und Elko für die SD-Karte.
Den µC muss man aber auch puffern, damit der die Schreiboperationen
abschicken kann, um das Dateisystem in einem sauberen Zustand zu
hinterlassen.
> Wir senden 200 Bytes explizit, aber innerhalb der elmchan Routine im> SPI-Aufruf stehen dann auch wieder 512 Bytes als Bytecounter drin, also> sendet er nicht 200 Byte wie ich dachte, sondern 512.
Tja so ist das wenn du Leute immer fertige Libaries nutzen und sich
nicht selber mit der Hardware beschaeftigen. .-)
SD-Karten arbeiten nach aussen hin generell mit Bloecken von 512Byte.
Lediglich zum lesen konnte man wohl auch mal kleinere Bloecke einstellen
und da war es nicht sicher das sowas von allen Karten unterstuetzt
wurde.
Und das ist jetzt der Wissenstand von vor 10Jahren. :) Ich wuerde davon
ausgehen das die Karten heute intern ausschliesslich mit sehr viel
grosseren Bloecken arbeiten. Da wird es also schon die Geschwindigkeit
veringern wenn man 512Byte grosse Bloecke verteilt ueber die Karte
schreibt weil die Karte dann jedes mal erst viele Kilobyte liesst,
loesscht und dann neu schreibt wenn man nur einen kleinen Block aendert.
Und dann kann es dir noch passieren das die Karten beim schreiben Pausen
einlegen wo sie sich mit internen Verwaltungsaufgaben beschaeftigen. Je
nach Hersteller der Karte natuerlich unterschiedlich!
Wenn du Wert auf Geschwindigkeit legst dann wirst du wohl einen grossen
Buffer in deinem Controller benoetigen.
Olaf
Olaf schrieb:> Je nach Hersteller der Karte natuerlich unterschiedlich!
Da gibt es extreme Unterschiede, die Spitze der Spitze des Eisbergs hat
rg423g ja schon entdeckt.
Und das Hässlichste ist, dass manche Karten mit kleinen Datenmengen gar
nicht gut zurechtkommen und einen Block totschreiben. Dann ist die Karte
quasi zu 99,999% neu, aber beim letzten Schreiben auf den einen Block
ging was schief (Consumer Karten mit dem lausigen TLC-Flash können so
einen Block z.B. nur noch 100..500 mal beschreiben, dann ist der
"ausgelutscht", wird als defekt markiert und nicht mehr verwendet).
Lesenwert ist neben dem Standard z.B. das hier:
https://media.kingston.com/pdfs/MKF_283.1_Flash_Memory_Guide_DE.pdf
Dann kommt noch dazu, dass das Löschen eines Block auch die physikalisch
daneben liegenden eine wenig "mitlöscht", was bei ungünstigem
Wearleveling im schlechtesten Fall dazu führt, dass die Karte gar nicht
mehr startet. Denn die Firmware der Karte selber liegt ja auch auf dem
Flash und wird beim PowerUp ins RAM des Controllers geladen und dort
ausgeführt.
Fazit: Consumer-Karten sind gut darin, ein paar wenige Male mit großen
Dateien beschrieben zu werden (Fotos, MP3s, Filme,...).
Dankeschön für die vielen und schnellen Antworten.
Ich fass mal kurz zusammen:
Nachgemessen am Oszi wielange denn der Overhead ist hat noch keiner.
Eigentlich sollte man die SD-Karte nicht so benutzen wie wir es machen,
nämlich mit kleinen Datenmengen dauerhaft beschreiben, weil es zu Busy
zuständen an der SD-Karte kommen kann, die dann meinen Code dauerhaft
anhalten könnten.
Sinnvoll wäre es wohl intern einen Puffer für zB 250ms oder besser 500
ms bereitzustellen und dann immer diretk die volle Datenmenge periodisch
in die SD-Karte zu schreiben.
Das sollte eigentlich machbar sein, wobei unser uC RAM vlt max 4 kB als
SD Puffer bereitstellen könnte, und extern haben wir grad keinerlei RAM
dran, also wir könnten dann maximal Datenpakete von 4 kB
zwischenspeichern, aber damit sollte es dann ähnlich schnell
funktionieren nur eben nicht so häufig wie jetzt gerade.
Motivation ist die dass wir alle 50 ms etwas messen und verarbeiten, die
50 ms müssen per timing stehen, daher wäre es schön gewesen innerhalb
dieser Zeit auch einen Zugriff auf die SD-Karte gewährleisten zu können,
aber das sollte ja eventuell schon wegen dem random BUSY manchmal nicht
möglich sein, wenn ich das richtig verstanden habe.
Also lieber weniger oft speichern dafür größere Mengen, dann habe ich
statistisch weniger oft meine Messzeiten zerstört, richtig?
Vielen Dank weiterhin.
rg423g schrieb:> Nachgemessen am Oszi wielange denn der Overhead ist hat noch keiner.
Doch, ich habe da einige Messungen gemacht!
rg423g schrieb:> Das sollte eigentlich machbar sein, wobei unser uC RAM vlt max 4 kB als> SD Puffer bereitstellen könnte
Das ist sehr wenig. Könnt ihr keinen größeren Controller benutzen?
Bei 4KiB-Blöcken hatte selbst meine "gute" Samsung-Karte regelmäßig
Busy-Zeiten bis 60ms. Die Busy-Zeit variiert wie gesagt stark nach
Modell und Blockgröße; daher sollte man unbedingt einen großzügigen
Puffer bereit stellen und auch eine Überlauf-Erkennung implementieren.
> Ich fass mal kurz zusammen:> Nachgemessen am Oszi wielange denn der Overhead ist hat noch keiner.
Doch, hab ich schon mal gemacht. Aber mit Karten die es nicht mehr gibt
und meiner eigenen FAT Implementation.
Oh..und noch ein Tip. Wenn du das nicht nur fuer dich selber brauchst
sondern an Kunden verteilen willst, besorg dir erstmal einen moeglichst
grossen Berg unterschiedlicher Karten zum testen.
Am schlimmsten sind Karten mit eigener Intelligenz, also SD-Karten die
auch noch gleichzeitig USB koennen oder WLAN integriert haben.
Olaf
rg423g schrieb:> Also lieber weniger oft speichern dafür größere Mengen, dann habe ich> statistisch weniger oft meine Messzeiten zerstört, richtig?
Ja, und vor allem: zeitlich und ablaufmäßig entkoppelt von den 50ms.
> dann habe ich statistisch weniger oft meine Messzeiten zerstört, richtig?
Warum machst du die Messung nicht "einfach" so, dass die wichtiger ist
als das Speichern? Oder warum speicherst du zu den Daten nicht einen
Zeitstempel mit, statt sich auf dieses "20-Messungen-pro-Sekunde" Raster
zu verlassen?
Bombastische Antwortrate, danke nochmals und auch weiterhin für die
guten Infos aus euren Erfahrungen.
Ich schau grad durch, unsere MSP430 haben maximal 32 kB RAM, und davon
benutzen wir natürlich schon einiges im normalen PRogrammablauf usw.
also zu 400 kB komme ich mit dieser Platform niemals.
Wir haben jetzt ja auch schon ein paar Systeme im Einsatz und davon
"funktionieren" :) eigentlich alle sehr zuverlässig, ohne Pufferungen
und so weiter, was natürlich nicht bedeutet dass es nicht vorkommt und
wir es einfach übersehen bzw nichts ausmacht.
Kurz zu Lothar:
Das Speichern asynchron wäre natürlich gut kann ich auch einplanen, mein
Problem gedankleich dabei ist:
Im Code hat mein Messen natürlich höchste Priorität, aber sobald ein
SD-Kartenspeicherzyklus kommt hängt der Code ja im SD-Code fest, der
elmchan code sperrt sogar die IRQs innerhalb des low level SPI sendens.
Also muss ich, insofern ich den elmchan benutzen will, dafür sorgen dass
das speichern einfach schneller oder zu definierten Zeitpunkten
auftritt.
Ich bin jetzt leider nicht tief genug im SD_Code mit FAT System drin um
mir zu überlegen wie man auf eine KArte schreibt ohne den normalen
while(1)-code zu verlassen, das ist aber dann vielleicht auch eher was
für rasp-pis als für kleinere uCs :)
Weiterhin Danke und ich schau mal wie wir das lösen und halte euch auf
dem laufenden.
rg423g schrieb:> Eigentlich sollte man die SD-Karte nicht so benutzen wie wir es machen,> nämlich mit kleinen Datenmengen dauerhaft beschreiben, weil es zu Busy> zuständen an der SD-Karte kommen kann,
Glaub ich nicht so ganz.
> die dann meinen Code dauerhaft> anhalten könnten.
Dann hat dein Code ein Problem.
> Sinnvoll wäre es wohl intern einen Puffer für zB 250ms oder besser 500> ms bereitzustellen
Ja, nennt sich FIFO.
> und dann immer diretk die volle Datenmenge periodisch> in die SD-Karte zu schreiben.
Nein. FATfs puffert selber schon einen Sektor, darüberhinaus muss man
nicht unbedingt noch größere Datenmengen puffern bzw. als großen Block
schreiben. Wohl aber die einigen hunder MS Wartezeit im Extremfall
puffern.
> Das sollte eigentlich machbar sein, wobei unser uC RAM vlt max 4 kB als> SD Puffer bereitstellen könnte,
Das reicht aber nicht für 500ms, oder? Wie hoch ist deine Datenrate?
> Motivation ist die dass wir alle 50 ms etwas messen und verarbeiten, die> 50 ms müssen per timing stehen,
Kein Thema, das macht man mit einem Timer-Interrupt.
> daher wäre es schön gewesen innerhalb> dieser Zeit auch einen Zugriff auf die SD-Karte gewährleisten zu können,
Falsch! Die zeitkritische Datenerfassung macht man in einem Interrupt.
Der hat Priorität und kann den normalen Programmablauf JEDERZEIT
unterbrechen. Die Daten werden in einen FIFO geschrieben. Ein
Funktion in der Hauptschleife, also außerhalb eines Interrupts, prüft
periodisch, ob Daten zum Schreiben im FIFO stehen und schreibt die auf
SD-Karte. Wenn dann Wartezeiten auftreten, spielt das keine Rolle, denn
der Interrupt läuft ungestört weiter.
> Also lieber weniger oft speichern dafür größere Mengen, dann habe ich> statistisch weniger oft meine Messzeiten zerstört, richtig?
Falsch.
Beitrag "Re: Geschwindigkeitsfrage AVR auf SD"Beitrag "Re: Atemega328p - schaffst du das?"
rg423g schrieb:> Im Code hat mein Messen natürlich höchste Priorität, aber sobald ein> SD-Kartenspeicherzyklus kommt hängt der Code ja im SD-Code fest,
Dann stimmt dein Konzept nicht. Siehe mein vorheriger Beitrag.
> der> elmchan code sperrt sogar die IRQs innerhalb des low level SPI sendens.
Nur für Mikrosekunden!
> Also muss ich, insofern ich den elmchan benutzen will, dafür sorgen dass> das speichern einfach schneller oder zu definierten Zeitpunkten> auftritt.
Nein!
> Ich bin jetzt leider nicht tief genug im SD_Code mit FAT System drin um> mir zu überlegen wie man auf eine KArte schreibt ohne den normalen> while(1)-code zu verlassen, das ist aber dann vielleicht auch eher was> für rasp-pis als für kleinere uCs :)
Nö, das ist was für Leute, die Multitasking verstanden haben.
>> Weiterhin Danke und ich schau mal wie wir das lösen und halte euch auf> dem laufenden.
rg423g schrieb:> der> elmchan code sperrt sogar die IRQs innerhalb des low level SPI sendens.
Eigentlich sollte das nicht zeitkritisch sein. Du kannst das auch durch
Interrupts unterbrechen lassen, musst aber natürlich aufpassen auf
welche Daten du da zugreifen kannst.
rg423g schrieb:> Ich schau grad durch, unsere MSP430 haben maximal 32 kB RAM,
Bloß was bringt ein super-stromsparender MSP430 wenn der eine
stromverschwendende SD-Karte benutzt...! Ein STM32F407 mit SDIO, DMA und
192 KiB SRAM kann eine SD-Karte mit 1 MiB/s befeuern und dabei noch
viel CPU-Zeit frei haben - aber nicht mit der elm-chan-Bibliothek.
Falk B. schrieb:> Falsch.
Meinen ausführlichen Messungen zufolge: Richtig. Je mehr auf einmal,
desto besser.
rg423g schrieb:> Wir senden 200 Bytes explizit, aber innerhalb der elmchan Routine im> SPI-Aufruf stehen dann auch wieder 512 Bytes als Bytecounter drin, also> sendet er nicht 200 Byte wie ich dachte, sondern 512.
Eure Beobachtungen sind ... unvollständig.
Hätte man mal das Hirn eingeschaltet (und die SD Spec gelesen) würde
sofort auffallen das man bei 200 Bytes den Sektor vorher einlesen muss.
D.h. man liest auch erstmal Daten von der Karte. Die 512 Bytes ergeben
sich dabei als Sektor direkt von der SD(HC) Spec.
Im ungüstigen Fall liegen die Daten quer über 2 512 Byte Sektoren
verteilt, dann müsste FatFS zwei Sektoren lesen. Falle er den 1. Sektor
im Cache hat, ist das dann aber immer noch ein Schreibzyklus unmittelbar
gefolgt von einem Lesezyklus mit jeweils 512 Bytes.
Oh, apropos FAT: Bei 32 GB Fat32 könnte die Suche nach dem "nächsten
freien Cluster" im zweistelligen Sekundenbereich dauern, wenn die
Fragmentierung nur fies genug ist.
Außerdem schwankt selbst die reine Schreibzeit auf SD Sektoren noch
stark, selbst wenn man das Low Level misst. Denn die Karten machen ja
Wear Leveling.
Jim M. schrieb:> Oh, apropos FAT: Bei 32 GB Fat32 könnte die Suche nach dem "nächsten> freien Cluster" im zweistelligen Sekundenbereich dauern, wenn die> Fragmentierung nur fies genug ist.
Es geht besser, kostet aber RAM. Allerdings längst nicht so viel, wie
man glauben könnte. Es muss keine vollständige "Bitmap" der freien
Sektoren im Speicher gehalten werden. Ein klug implementierter binärer
Baum reduziert den Speicherbedarf auf log(n). Und er kann dynamisch
aufgebaut und gepflegt werden.
Aber selbst im worst case, also frisch "gemountetes" FS und somit leerer
Baum und letzter Cluster ist einziger freier Cluster im FS, kostet die
Sache nur das lineare Einlesen der kompletten FAT.
Wenn das zweistellige Sekundenzeiten dauert, ist am Code oder der
Hardware irgendwas dramatisch kaputt...
c-hater schrieb:> Wenn das zweistellige Sekundenzeiten dauert, ist am Code oder der> Hardware irgendwas dramatisch kaputt...
Nö. Braucht nur "normalen" µC mit SPI.
FAT bei 32GB ist 4MB groß, und man kann sie via SPI nicht schneller als
mit 25 MHz einlesen. Blöderweise muss man jedes Wort auch noch mit dem
µC auswerten - das schafft zumindest ein 8-Bit AVR nicht in 10 Sekunden.
Chan FATFS kann AFAIK nicht gleichzeitig lesen und auswerten.
Ein richtig flotter 32-Bitter mit 600MHz schafft das sicherlich in unter
10s, aber der hat dann auch SDIO. Diese µC finden hier im Forum aber
selten Verwendung.
Jim M. schrieb:> Nö. Braucht nur "normalen" µC mit SPI.>> FAT bei 32GB ist 4MB groß, und man kann sie via SPI nicht schneller als> mit 25 MHz einlesen. Blöderweise muss man jedes Wort auch noch mit dem> µC auswerten - das schafft zumindest ein 8-Bit AVR nicht in 10 Sekunden.
Rechnen wir: SPI-Vmax für einen AVR8 ist 10Mbit/s.
D.h.: Er kann die 4MByte (=32Mbit) in 3.2s einlesen (protocol overhead
sei mal außen vor). Und er hat während dieser Zeit schon reichlich
freie Takte, um die Daten zu beschauen. Es kommt dann nämlich nur alle
16 Takte ein Byte rein. Nun ist ein Eintrag in einer FAT32 sogar 4 Bytes
groß, also stehen 64 Takte zur Verfügung (abzüglich der Takte, die nötig
sind, um die ersten drei Bytes zu buffern, bei intelligenter
Programmierung in einer effizienten Sprache also genau drei Takte). In
den verbleibenden 61 Takten kann man eine Menge Nützliches tun...
> Chan FATFS kann AFAIK nicht gleichzeitig lesen und auswerten.
Doch, mit entsprechenden "Adaptierungen" kann es das sehr wohl. Er ist
nur nicht "von Hause aus" dafür gedacht...
Jim M. schrieb:> Ein richtig flotter 32-Bitter mit 600MHz schafft das sicherlich in unter> 10s, aber der hat dann auch SDIO. Diese µC finden hier im Forum aber> selten Verwendung.
Der ziemlich beliebte STM32F407 kann das in 0.22s. Modernere STM32 bei
denen der Bug mit dem Taktteiler behoben ist können das in 0.18. SDIO
mit 4bit und DMA ist sowieso Pflicht. Man kann immer einen Sektor der
FAT einlesen und während der nächste per DMA angeliefert wird wertet man
den vorigen aus.
Das ist aber eh alles unnötig. Man sollte sowieso immer nach freien
4MB-Blöcken suchen. Das kann "parallel"/abwechselnd zum Schreiben
passieren, im Voraus ist gar nicht nötig.
Jim M. schrieb:> Oh, apropos FAT: Bei 32 GB Fat32 könnte die Suche nach dem "nächsten> freien Cluster" im zweistelligen Sekundenbereich dauern, wenn die> Fragmentierung nur fies genug ist.
Auch dieses Problem wurde schon gelöst, nennt sich Preallocation.
http://elm-chan.org/fsw/ff/doc/lseek.html> Außerdem schwankt selbst die reine Schreibzeit auf SD Sektoren noch> stark, selbst wenn man das Low Level misst. Denn die Karten machen ja> Wear Leveling.
Richtig, darum braucht man einen ausreichend großen FIFO. Aber all das
hintert am Ende niemanden daran, auch schnelle Echtzeitdaten dauerhaft
auf SD-Karte zu schreiben.