Forum: Projekte & Code MMC VFAT12/VFAT16/VFAT32 mit langen Dateinamen (vfat.c)


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Stefan Seegel (Gast)


Angehängte Dateien:

Lesenswert?

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

von Stefan Seegel (Gast)


Angehängte Dateien:

Lesenswert?

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

von dirk (Gast)


Lesenswert?

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 ?

von Daniel B. (khani)


Lesenswert?

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.

von dirk (Gast)


Lesenswert?

Habe mit XP Formatiert in FAT

von Stefan Seegel (Gast)


Lesenswert?

@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

von dirk (Gast)


Angehängte Dateien:

Lesenswert?

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

von Stefan Seegel (Gast)


Lesenswert?

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

von Oliver Erb (Gast)


Lesenswert?

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?

von Lupin (Gast)


Lesenswert?

> 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.

von Oliver Erb (Gast)


Lesenswert?

wo finde ich die dokumentation? und welches attribute muss ich prüfen?

von Schnuffler (Gast)


Lesenswert?

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

von hebel23 (Gast)


Lesenswert?

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

von M. V. (-_-)


Lesenswert?

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
Noch kein Account? Hier anmelden.