Moin! Hier ist mal der Sourcecode meiner FAT Unterstützung für MMC/SD Karten. Den mmc Teil hatte ich hier schon mal reingestellt, neu ist der VFAT Teil, mit dem man von FAT12, FAT16 und FAT32 Partitionen mit langen Dateinamen lesen kann. Zunächst noch ein paar Anmerkungen für die, die immer nur die erste Hälfte lesen :-): Auf der Karte muss ein MASTERBOOTRECORD sein, viele sind "nur" im Superfloppyformat formatiert. Ich liefere noch ein kleines Tool nach, mit dem man einen MBR erzeugen kann. Vorteil des ganzen ist, dass man die FAT Partition z.B. nur halb so groß wie die Karte machen kann, und die andere Hälfte z.B. für RAW-Daten zur Verfügung hat. Der Code wurde so geschrieben dass er möglichst wenig RAM braucht, sollte auch auf einem MEGA16 funktionieren. Dadurch dass nur ein einziger Sektorbuffer (512 Bytes) verwendet wird, muss immer wieder die FAT neu geladen werden. Da ich aber das ganze in einem MEGA16 haben wollte und die Geschwindigkeit in meinem Fall keine so große Rolle gespielt hat hab' ich das eben so gemacht. Hier ein Beispiel (Pseudocode!!!) wie man mit dem Interface arbeitet: So wird das root directory ausgelesen: int void { uint8_t parttype; uint16_t entry; char filename[100]; unsigned long filesize; unsigned char fileattrib; uint32_t fstcluster = 0; fattype = vfat_init(); switch (fattype) { case 0x00: puts("No partition found"); return 0; case PARTTYPE_FAT12: puts("FAT12 partition found"); break; case PARTTYPE_FAT16L: puts("FAT32 partitoin found"); break; case PARTTYPE_FAT32: puts("FAT32 partition found"); break; } for (entry=0; entry<1000; entry++) { fstcluster = vfat_readDirEntry(0, entry, &filesize, &fileattrib, filename); if (fstcluster == 0xFFFFFFFF) break; printf("Name: %s, size: %u", filename, filesize); } } Und so liest man eine Datei, dessen startcluster mit vfat_readDirEntry erhalten wurde: unsigned char *lpbuffer; unsigned short filesector; for (filesector = 0; filesector < (filesize / 512); filesector++) { lpbuffer = vfat_readfilesector(fstcluster, filesector); for (i=0; i<512; i++) putchar(lpbuffer[i]); } (Es werden immer ganze Sectoren ausgelesen, wenn die Dateigröße kein Vielfaches von 512 ist muss das noch berücksichtigt werden) So, viel Spaß, Stefan
Und hier noch wie angedroht das Tool mit dem man einen MBR für MMC/SD Karten erzeugen kann. Das Tool schreibt nicht direkt auf die Karte, sondern erzeugt lediglich einen MBR in einer Datei (mbr.bin), den man dann mit einem Diskeditor auf Sector 0 der Speicherkarte schreiben muss. Stefan
Was muß man bei dem Tool eintippen, wenn ich die 512 nehme bekomme in FAT16 ( 4 ) ich habe eine 16MB und 32MB karte (MMC) eine Paratitiongrösse von 255 KByte Und wenn ich mbr.bin angucke stehen nur Nullen drin, ich denke mal das es nicht sein kann. Die MMC wurde mit FAT12 formatiert. FAT12 steht als Text sogar drinne. Aber will es mit dein Tool in FAT16 formstieren. Als Diskeditor benütze ich den TinyHexer auf www.mirkes.de. Bitte erkläre mal für nicht so eingeweihte wie man jetzt die MMC Formatiert. Welchen Diskeditor benutzt du den ?
Hallo Stefan, ich habe mir heute mal Deinen Code zu Gemüte geführt. Wenn ich das richtig sehe, überprüfst Du nicht, ob der LFN (für die Ungeübten : Long-File-Name) mit dem SFN (dasselbe mit short) konsistent ist. Hat Dir das schon mal Probleme beschert ? Oder ist das kein Thema, wenn man nur Systemen arbeitet die LFN voll unterstützen ? Ich arbeite auf einer Festplatte und die kommt auch mal mit DOS in Berührung, daher muss ich die Sicherheitsmechanismen ausschöpfen. Vielleicht kannst Du Deinen Code ja noch ein bißchen kommentieren ? Das würde dem echt viel bringen. Leute die noch so viel mit FAT gearbeitet haben, werden sonst nur wenig verstehen. Meine eigene Aufgabenstellung (selbst auferlegt) sieht ein wenig anders aus : Ich implementiere Lesen und Schreiben in FAT. Im Moment bin ich wenig beim Redesign meiner FAT-Architektur. Daher werde ich erst mal ein keinen Code dazu hier posten. Es sind durch den Redeign-Prozess noch einige Codedopplungen und Inkonsistenzen im Design vorhanden. Ein Ansatzpunkt zur Performance-Verbesserung wäre es, sich den aktuellen Sektor zu merken (und nicht nur den Cluster), dann muss man nicht erst die ganze Clusterchain abhecheln, wenn man einen Eintrag lesen möchte... Ansonsten ist Dein Ansatz eine nette Implementierung mit ein paar echt schönen Ideen. Welche Resourcen hast Du zur Erstellung verwendet ? Meine Resourcen beschränken sich auf (die ATA-Spec im Voraus), einer kleinen Webseite mit dem MBR und dem MS-Whitepaper zum Thema FAT. MfG, Daniel.
@dirk Sorry, ich kann Deinen Satz >Was muß man bei dem Tool eintippen, wenn ich die 512 nehme bekomme in >FAT16 ( 4 ) ich habe eine 16MB und 32MB karte (MMC) nicht ganz verstehen was du damit meinst !? Du musst zunächst rausfinden wieviele Sektoren Deine Karte insgesamt hat. Dazu nimmst du z.B. Hex Workshop. Meine 16MB Karte hat z.B. 31tausend nochwas Sektoren. Diese Zahl gibst du dem Tool als erstes. Wegen der FAT12: Wenn du auf einer 16MB Karte eine FAT16 Partition anlegst und diese dann mit Windows formatierst, baut Windows die Partition in eine FAT12 um, frag mich nicht warum, warscheinlich weil FAT12 für die Größe ausreicht, und so Platz in der FAT gespart wird. >Und wenn ich mbr.bin angucke stehen nur Nullen drin, ich denke mal >das es nicht sein kann. Es stehen in der Tat viele Nullen drin, aber nicht nur Nullen, bitte nochmal genau reinschauen! Ein Partitionseintrag besteht aus 16 Bytes, wenn du 4 Partitionen (Maximum) anlegst sind also lediglich 64 Bytes belegt. Diese stehen ziemlich am Ende im MBR. Der restliche Platz wird normalerweise für ausführbaren (boot-)Code benutzt. @Daniel: - Nein, die Konsistenz wird nicht geprüft. Aber kurze Dateinamen funktionieren natürlich trotzdem... - Im Header File oben hab ich glaub ich ein paar URLs reingeschrieben von wo ich meine Infos zusammengetragen habe. - Performance Verbesserung: Sich den aktuellen Cluster zu merken würde eigentlich schon reichen um nicht bei jedem Zugriff durch die ganze FAT-Kette laufen zu müssen. Ich hatte mir überlegt den Cluster der read-Funktion als Pointer zu übergeben, so dass der "neue" Cluster damit gleich zurückgegeben wird. Dazu wird aber der Aufruf im Hauptprogramm etwas komplizierter, da man nicht mehr direkt linear in der Datei (sektorweise) adressieren kann. Mir war zunächst mal wichtig dass man mit recht wenig Code und RAM mein Interface benutzen kann. Wenn mir was anderes gescheites einfällt werd ich das mal umbauen. Stefan
Anbei die mbr.bin , als Sektoren habe 31250 ( 16 MB Karte MMC ) 16000000/512=31250 Sektoren rausbekommen die ich angegeben habe. Ich habe nur eine Partition erstellt mit FAT16 ( 4 ). Und die mbr.bin ist im Anhang. Ist das OK? Hex Workshop habe ich jetzt auch noch installiert. Ich habe nur eine Partition erstellt mit FAT16 ( 4 ). Ich will ja die MMC am AVR anschliessen können. Bei FAT12 bekomme ich mit den Ulrich Rahig Code 2.4 nach erkennen der Karte nur : System OK Karte gefunden!! 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 Directory Directory Ende FERTIG!! Obwohl zwei Text Dateien drauf sind. Ich denke es liegt an FAT12, aber ich habe keine Ahnung ob es das ist. mfg Dirk
Hi, ja, der mbr sieht soweit gut aus, was mich nur wundert ist der Partitionstyp, da steht 6 (= DOS 16bit FAT (FAT16, BIGDOS) >=32MB) drin, siehe http://www.datasource.de/programmierung/tab35_partitionstypen.html Ich habe auf meiner 16er Karte den Typ 4 (DOS 16bit FAT (FAT16) <32MB) angelegt, und Windows hat dass dann beim formatieren in Typ 1 (DOS 12bit FAT (FAT12)) umgewandelt. Gruß Stefan
Hallo Stefan, habe da ein Problem mit deiner vfat.c u. vfat.h wenn ich mir das root Verzeichniss anzeigen lasse, dann werden auch gelöschte Einträge angezeigt. Wie kann ich das verhindern?
> Wie kann ich das verhindern?
Indem man die FAT dokumentation liest und den code entsprechend
abändert. Oder einfach mal die attribute checken und vlt mit den
gegebenen Konstanten auf gelöschtheit prüfen.
wo finde ich die dokumentation? und welches attribute muss ich prüfen?
Wenn das erste byte des Dateinamen 0xe5 ist dann handelt es sich um eine gelöschte Datei. Ist doch auch auffällig, dass alle gelöschten Dateien mit den gleichen Zeichen anfangen? http://www.win.tue.nl/~aeb/linux/fs/fat/fat-1.html
Hi Stefan, ich habe mir gerade Deine Code zu gemüte geführt und habe festgestellt, dass Deine FAT32-Implementation nicht so richtig zu stimmen scheint. Hast Du das ganze mal mit einer FAT32-Partition ausprobiert? Da wäre z.B. Die Sache mit der FAT12/FAT16/FAT32-Erkennung über das Byte in der Partitionstabelle "mbr->sector.partition[i].typeId". Das geht, so wie ich die FAT-Spezifikationen verstehe, maximal noch bei FAT12 und FAT16 gut. Spätestens bei FAT32 und unter >WIN95 formatierten Datenträgern geht das schief. Zum zweiten berechnest Du in der Funktion vfat_init() den Wert für "RootDirectoryRegionSize" aus "vbr->bsRootEntCnt" und verwendest ihn später in der Funktion vfat_readDirEntry(...). Nun ist der Wert für "vbr->bsRootEntCnt" aber bei FAT32 immer 0 und somit geht vfat_readDirEntry(...) immer mit einem 0xFFFFFFFF (End of root dir region reached) raus. Man kann so also keinen Eintrag lesen An sonsten sieht der Code ziemlich gut aus und ich würde ihn gern als Grundlage für meine eigenen Implementationen verwenden ;o). Bis denne Andreas
Moin, also im allgemeinen gefällt mir diese Lib gut, bloss komm ich aufgrund diverser Compilerfehler nicht weiter. avr-gcc -Wall -pedantic -mmcu=atmega32 -std=c99 -Os -DF_CPU=4000000UL -c -o vfat .o vfat.c In file included from vfat.c:3: vfat.h:80: warning: ISO C doesn't support unnamed structs/unions vfat.h:80: warning: declaration does not declare anything vfat.h:86: warning: ISO C doesn't support unnamed structs/unions vfat.h:86: warning: declaration does not declare anything vfat.h:87: warning: union has no members vfat.h:87: warning: ISO C doesn't support unnamed structs/unions vfat.h:87: warning: declaration does not declare anything vfat.c: In function `vfat_init': vfat.c:66: error: structure has no member named `SecPerFAT32' vfat.c: In function `vfat_readDirEntry': vfat.c:146: warning: comparison is always true due to limited range of data type make: *** [vfat.o] Error 1 Die Warnungen stören ja nicht weiter, allerdings wird wohl die union in der struct nicht anerkannt und demnach das SecPerFAT32 nicht in dieser struct gefunden. Winavr version vom 21.4.06. Welche hattest du verwendet? Danke im vorraus
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.