Hallo! Beim blockweisen Lesen von SD-Karten finde ich natürlich alles, was man bei FAT so erwartet, denn sie sind in aller Regel FAT-formatiert. Vorher ist aber ein längerer Bereich, von dem ich das Format nicht zuordnen kann, denn der FAT-Header beginnt erst z.B. bei Block 0x40000. Wo finde ich dafür die Formatbeschreibung?
Hier ein Beispiel für eine SD:
1 | sudo hd /dev/sdb |head |
2 | 00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| |
3 | * |
4 | 000001b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02 |................| |
5 | 000001c0 06 00 06 26 e6 c6 83 00 00 00 7d 77 3b 00 00 00 |...&......}w;...| |
6 | 000001d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| |
7 | * |
8 | 000001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.| |
9 | 00000200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| |
10 | * |
11 | 00010600 eb 00 90 20 20 20 20 20 20 20 20 00 02 40 01 00 |... ..@..| |
Und für eine SDHC:
1 | sudo hd /dev/sdb |head |
2 | 00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| |
3 | * |
4 | 000001b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02 |................| |
5 | 000001c0 03 01 0b 43 c3 d1 00 20 00 00 00 28 78 00 00 00 |...C... ...(x...| |
6 | 000001d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| |
7 | * |
8 | 000001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.| |
9 | 00000200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| |
10 | * |
11 | 00400000 eb 00 90 20 20 20 20 20 20 20 20 00 02 40 7e 18 |... ..@~.| |
Wie zu sehen ist, beginnt der FAT-Bootsektor erst bei 0x10600 bzw. bei 0x400000. Was bedeuten die Daten davor?
>Wie zu sehen ist, beginnt der FAT-Bootsektor erst bei 0x10600 bzw. bei >0x400000. Was bedeuten die Daten davor? Das sehe ich aber anders;) >000001b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02 >000001c0 06 00 06 26 e6 c6 83 00 00 00 7d 77 3b 00 00 00 0x1BE 00 02 06 00 06 -> Partition type 26 e6 c6 83 00 00 00 -> Bootsec offset beginnt bei 0x0083 (hmm ungewöhnlich) 7d 77 3b 00 >000001b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02 >000001c0 03 01 0b 43 c3 d1 00 20 00 00 00 28 78 00 00 00 0x1BE 00 02 03 01 0b -> Partition type 43 c3 d1 00 20 00 00 -> Bootsec offset beginnt bei 0x200 00 28 78 00
>00 20 00 00 -> Bootsec offset beginnt bei 0x200
Quark 0x2000 natürlich.
Also die Daten davor sind der Bootsektor (512 bytes) wenn du nicht davon bootest, sollte es egal sein was drin ist
Hallo und danke euch für die Antworten! Ich war deswegen stutzig geworden, weil der Bootsektor in allen Beispielen, die ich bei Wikipedia gefunden habe, mit 0xeb beginnt. Nach der Erklärung von holger ist mir klar geworden, dass man nur die Infos ab Adresse 0x1be braucht, wenn man nicht wirklich booten will. Dann kann ich meinen AVR so programmieren, dass er eine SD-Karte auch ohne FAT-Bibliothek so beschreibt, dass die Daten hinterher mit jedem PC lesbar sind. Mir gehts um einen möglichst einfachen Datenlogger.
Markus W. schrieb: > Dann kann ich meinen AVR so programmieren, dass er eine SD-Karte auch > ohne FAT-Bibliothek so beschreibt, dass die Daten hinterher mit jedem PC > lesbar sind. Mir gehts um einen möglichst einfachen Datenlogger. was verstehst du unter - mit jedem PC lesbar? Wenn du die Daten einfach so und ohne FAT 'dahinpappst' kannst du die Daten allenfalls - wie oben geschehen - als Hexdump auslesen - und dann kannst du auch bei Block 0 anfangen. Sascha
Sascha Weber schrieb: > was verstehst du unter - mit jedem PC lesbar? Wenn du die Daten einfach > so und ohne FAT 'dahinpappst' kannst du die Daten allenfalls - wie oben > geschehen - als Hexdump auslesen - und dann kannst du auch bei Block 0 > anfangen. Hi Sascha, ja, das geht natürlich. Allerdings braucht der PC-User dann meist besondere Software oder besondere Rechte, um die SD blockweise zu lesen. Mein Ziel ist es aber, dass man die gespeicherten Daten als "normale" Datei kopieren und später verarbeiten kann. Dazu muss der Logger beim Schreiben eine Partitionstabelle anlegen und die notwendigen FAT-Einträge schreiben. Sowohl Partitionstabelle als auch FAT-Header können dabei statisch sein, erst danach werden die Daten in hintereinander hängende Bocks geschrieben. So ist zumindest die Idee. Obs funktioniert, werd ich dann ja sehen. ;-)
>Dazu muss der Logger beim Schreiben eine Partitionstabelle anlegen und >die notwendigen FAT-Einträge schreiben. Wieso der Logger? Das kann der PC doch schon machen. >Sowohl Partitionstabelle als >auch FAT-Header können dabei statisch sein, Die Partitionstabelle ist immer statisch. Da wird nix neu geschrieben. Von was für einem FAT Header redest du da die ganze Zeit? Deine Datei muss clusterweise in der FAT und im Verzeichnis eingetragen sein. > erst danach werden die Daten >in hintereinander hängende Bocks geschrieben. Die Idee hatten schon viele. Wenn man allerdings mal schaut wie viele freie und durchaus auch kleine FAT Libraries es gibt, dann stellt sich die Frage nach Sinn und Unsinn dieser Methode. Die hat eigentlich nur Nachteile. Ab 1k RAM und 8kB Flash muss man solche Klimmzüge nicht machen. Wenn noch mehr RAM und Flash zur Verfügung steht wäre es sogar kompletter Blödsinn es auf deine Art zu machen.
Danke für die Tipps, aber ich werde es - wie schon geschrieben - wirklich ohne Lib machen. Dadurch spar ich Speicherplatz und CPU-Last. Und noch wichtiger, ich kann Echtzeitanforderungen garantieren, weil ich jeden CPU-Takt "in der Hand" hab. :-)
Markus W. schrieb: > Dadurch spar ich Speicherplatz und CPU-Last. Und noch wichtiger, ich > kann Echtzeitanforderungen garantieren, weil ich jeden CPU-Takt "in der > Hand" hab. :-) wie wie bringst du das der SD-karte bei. Nicht das sie mal etwas länger zu schreiben braucht.
In der Lib kannste dir ja auch Ideen holen. Is ja nich so einfach wie nen Port ansteuern, sone FAT.
>> Dadurch spar ich Speicherplatz und CPU-Last. Und noch wichtiger, ich >> kann Echtzeitanforderungen garantieren, weil ich jeden CPU-Takt "in der >> Hand" hab. :-) > >wie wie bringst du das der SD-karte bei. Nicht das sie mal etwas länger >zu schreiben braucht. Was sie durchaus öfter tut. Und da gibt es vorher auch keine Warnung. Sporadische Pausen von bis zu 300ms habe ich schon gesehen. SD und Echtzeit geht nur mit einem Arsch voll RAM;)
holger schrieb: >>> Dadurch spar ich Speicherplatz und CPU-Last. Und noch wichtiger, ich >>> kann Echtzeitanforderungen garantieren, weil ich jeden CPU-Takt "in der >>> Hand" hab. :-) >> >>wie wie bringst du das der SD-karte bei. Nicht das sie mal etwas länger >>zu schreiben braucht. > > Was sie durchaus öfter tut. Und da gibt es vorher auch keine Warnung. > Sporadische Pausen von bis zu 300ms habe ich schon gesehen. SD und > Echtzeit geht nur mit einem Arsch voll RAM;) Ihr habt Sorgen... :-) Bei der Kommunikation mit der SD-Karte hat doch der uC das Sagen, er gibt den Takt vor. Wenn die SD-Karte bummelt und statt 8 Takte mal 10000 Takte für eine Aufgabe braucht, muss der uC ja nicht aktiv drauf warten, sondern kann in aller Ruhe seine zeitkritischen Aufgaben erledigen. Klar muss ich puffern und kann nicht zu viele Daten in zu kurzer Zeit schreiben, weil sonst welche verloren gehen - das stimmt natürlich. Sollte aber zu schaffen sein.
Markus W. schrieb: > muss der uC ja nicht aktiv drauf warten, > sondern kann in aller Ruhe seine zeitkritischen Aufgaben erledigen. richtig, und warum sollte er bei der FAT-lib nichts anderes nebenbei machen können?
Peter II schrieb: > Markus W. schrieb: >> muss der uC ja nicht aktiv drauf warten, >> sondern kann in aller Ruhe seine zeitkritischen Aufgaben erledigen. > > richtig, und warum sollte er bei der FAT-lib nichts anderes nebenbei > machen können? Also... so eine Lib hat ja zwei Möglichkeiten: 1. Sie arbeitet synchron: Dann muss ich beim Schreiben drauf warten, bis sie fertig ist. In der Zwischenzeit geht nichts anderes. Außer vielleicht ISRs, aber keiner garantiert mir, dass die Lib nicht zwischendurch mal das Interrupt-Flag löscht, wenn sie selbst zeitkritische Aufgaben erledigt. (Außerdem verwende ich gar keinen Stack, aber pssst.) 2. Sie arbeitet asynchron: Dann hab ich einen parallelen Prozess (vermutlich interruptgesteuert), den ich nicht berechnen kann. Das heißt, er kann mein Hauptprogramm jederzeit kurz unterbrechen. Damit lässt sich Echtzeitverarbeitung nicht garantieren.
Markus W. schrieb: > Außer vielleicht ISRs, aber keiner > garantiert mir, dass die Lib nicht zwischendurch mal das Interrupt-Flag > löscht, wenn sie selbst zeitkritische Aufgaben erledigt. ein blick in den Quellcode dürfte da gewissheit schaffen. Und warum sollte FAT irgendwie zeitkritische sein? > Außerdem verwende ich gar keinen Stack, aber pssst.) also auch keine funktionsaufrufe? Du Schreibst es also in ASM und springt nur mit jmp rum?
Peter II schrieb: > Markus W. schrieb: >> Außer vielleicht ISRs, aber keiner >> garantiert mir, dass die Lib nicht zwischendurch mal das Interrupt-Flag >> löscht, wenn sie selbst zeitkritische Aufgaben erledigt. > > ein blick in den Quellcode dürfte da gewissheit schaffen. Und warum > sollte FAT irgendwie zeitkritische sein? Wie gesagt, ich brauche den FAT-Mechanismus gar nicht, wenn vorher nach FAT-Standard ein fester Bereich als Datei definiert ist und ich dann blockweise in diesen Bereich schreibe. >> Außerdem verwende ich gar keinen Stack, aber pssst.) > also auch keine funktionsaufrufe? Du Schreibst es also in ASM und > springt nur mit jmp rum? Das wär dann schon arg unübersichtlich. :-) Ich verwende zcall und zret für Unterprogrammaufrufe (eine Ebene reicht mir). Das heißt, ich benutze das Z-Register. Getrennte Register für Haupt- und Unterprogramm verwende ich sowieso, spart viel CPU-Zeit. Hab mir dazu diese Makros gebaut:
1 | .macro zcall ;(target) |
2 | ldi ZH,high(PC+3) |
3 | ldi ZL,low(PC+2) |
4 | rjmp @0 |
5 | .endmacro |
6 | .macro zret |
7 | ijmp |
8 | .endmacro |
Markus W. schrieb: > Das wär dann schon arg unübersichtlich. :-) > Ich verwende zcall und zret für Unterprogrammaufrufe (eine Ebene reicht > mir). Das heißt, ich benutze das Z-Register. und interupts verwendest du überhaupt nicht? Ich will ja nicht abstreiten das man es so machen kann. Aber sinnvoll ist das ganze bestimmt nicht.
Peter II schrieb: > und interupts verwendest du überhaupt nicht? Ich will ja nicht > abstreiten das man es so machen kann. Aber sinnvoll ist das ganze > bestimmt nicht. Interrupts verwende ich normalerweise sehr gerne, aber in diesem Projekt werde ich darauf verzichten. Wenn ich Interrupts zulasse, geht mir im entscheidenden Moment leicht mal eine Mikrosekunde verloren. Natürlich könnte ich für diesen Zweck auch die Hardware aufstocken, es hat halt alles zwei Seiten. Und sinnvoll? Naja, die Sinnfrage überlassen wir besser Leuten, das Problem auf philosophischer Ebene diskutieren wollen. :-) Nach allem, was ich bisher weiß, halte ich meine Design-Entscheidung für genau richtig. Falls sich deine Zweifel bewahrheiten und ich später das Konzept anpassen muss, dann ist das ja auch nicht tragisch. Ich kann mich gerne wieder melden und über das Ergebnis berichten.
kannst du etwas mehr zu dem Projekt sagen? Warum wird da verarbeitet das es auf jede µs drauf ankommt?
Peter II schrieb: > kannst du etwas mehr zu dem Projekt sagen? Warum wird da verarbeitet das > es auf jede µs drauf ankommt? Es werden mehrere digitale Eingänge aktiv abgetastet. Und ja, das kann man auch per Pinchange-Interrupt machen, nur gehen dann viele Takte verloren: Rücksprungadresse sichern, zur ISR springen, Statusregister sichern, ... Statusregister zurückspeichern, Interruptroutine verlassen und Programm fortsetzen. Viele Takte, rechne das mal zusammen. Kann dir später mehr dazu erzählen, muss leider gleich weg.
>Viele Takte, rechne das mal zusammen.
Na dann warte mal ab wie viele Takte so ne SD Karte braucht;)
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.