|
|
AVR FAT32Dies ist eine freie FAT 16/32 Bibliothek. Die Bibliothek ist modular und besteht aus folgenden Modulen:
Es gibt die Möglichkeit über Makros in der config.h den Umfang der Lib zu bestimmen, dies wirkt sich auch stark auf die Codegröße aus. Die Module sind C99 Standard-konform.
[Bearbeiten] Der Status
[Bearbeiten] Funktionalität[Bearbeiten] Code einbindenDie Module werden über die *.h Dateien bekannt gemacht. Zudem müssen noch die dazugehörigen *.c Dateien eingebunden werden. Es gibt mehrere Möglichkeiten dies zu tun. Einmal im Makefile im Bereich der "c source files" oder bei IDEs über einen Dialog der das Gleiche macht. [Bearbeiten] Die FunktionalitätIn der Datei config.h gibt es Möglichkeiten die Bibliothek zu konfigurieren.
[Bearbeiten] Die SchalterHier ein Auszug aus der config.h mit den wichtigsten Parametern:
[Bearbeiten] Bedeutung der Schalter
[Bearbeiten] Die C-FunktionenDas Modul FILE bietet in der Standard-Konfiguration folgende für den Nutzer interessante Funktionen:
Das Modul MMC/SD bietet für den Nutzer direkt nur eine interessante Funktion:
Das Modul FAT bietet für den Nutzer direkt nur zwei interessante Funktionen:
Für die Anwendungen der Funktionen gibt es Beispiele, Kommentare und Dokumentation in den Sourcen. Ein einfaches Beispiel gibt es im Abschnitt Einfaches Code-Beispiel. Alle Funktionen, die mit FAT-Namen in Zusammenhang stehen (Datei- und Ordner-Namen), müssen folgende Konvention erfüllen:
Nur vFAT unterstützt lange Datei-Namen. [Bearbeiten] Interne TechnikIn der Regel wird das Schicht-Modell eingehalten. Das heißt, jedes Modul nutzt nur die Funktionen aus der Schicht darunter. Es gibt allerdings Ausnahmen aus Gründen der Code-Größe. Beispiel: ffwrite nutzt direkt die Funktion mmc_write_sector(sector) aus dem Modul mmc.c. Aufgrund der Namenskonvention ist aber leicht zu erkennen, woher die Funktion kommt. Im Modul fat gibt es "Daten-Ketten". Die Aufgaben sind atomar aufgeteilt. Zum Lesen von Daten sind beispielsweise die Funktionalitäten, Lesen eines Sektors, Auswerten der Information und weitere Entscheidung (nächsten Sektor Laden usw.) nötig. Die Idee dabei ist, die Funktionen der atomaren Aufgabe nach zu implementieren. Beispielkette:
Diese Kette wird beispielsweise beim Öffnen einer Datei durchlaufen. Um die Datei zu öffnen, muss man wissen, ob es die Datei im aktuellen Verzeichnis gibt. Um das herauszufinden, muss man den ersten Sektor des Verzeichnisses laden. Dann muss man die Reihen (immer 32 Byte am Stück), also Datei/Ordner-Einträge des Sektors prüfen. Da ein Cluster aus verschiedenen Sektoren bestehen kann, müssen diese auch geprüft werden. Als letzte logische Einheit müssen jetzt noch die verketteten Cluster geprüft werden, also das ganze Verzeichnis. Ist diese Kette so durchlaufen, weiß man, ob die Datei da ist oder nicht. [Bearbeiten] LesenBeim Lesen einer Datei wird in der FAT nach verketteten Clustern gesucht. Bei einer unfragmentierten FAT liegen im Idealfall alle Cluster in einer Reihe. Dies wird ausgenutzt: Es wird der erste Cluster der Datei gesucht und solange gesucht, bis MAX_CLUSTERS_IN_ROW am Stück gefunden wurden oder ein Abbruch der Kette erkannt wird. Wird ein Abbruch erkannt, wird das bekannte Teilstück der kompletten Kette gelesen, danach wird das nächste Teilstück gesucht, bis die ganze Kette durchlaufen wurde. Bei einer unfragmentierten FAT kann man oft die ganze Datei lesen ohne einen weiteren FAT-Lookup. Das ist sehr effizient. [Bearbeiten] SchreibenBeim Schreiben einer Datei wird in der FAT nach leeren Clustern gesucht. Bei einer unfragmentierten FAT liegen diese im Idealfall alle nebeneinander. Das wird ausgenutzt:
Bei beiden Methoden kann es zu größerem Overhead kommen, wenn die FAT fragmentiert ist. Im Extremfall ist immer nur ein Cluster am Stück frei bzw. verkettet. [Bearbeiten] Die RichtlinienAllgemein: Es ist immer darauf zu achten, dass es sich bei MMC/SD-Karten um Flash-Speicher handelt, dieser ist NICHT unendlich oft beschreibbar. Die Schreiben/Anhängen- und Löschen- Funktionalitäten sollten so selten wie möglich benutzt werden! Richtlinien stable-mmc-0.5.x: Wenn eine Datei zum schreiben geöffnet ist, aber gerade keine Daten zum schreiben vorliegen, bringt es keinen Vorteil (Strom oder Geschwindigkeit) die Datei zu schließen, wenn später noch Daten geschrieben werden sollen. Bei jedem ffclose, wird der Datei Eintrag aktualisiert, also dieser Sektor geschrieben (möglicherweise zusätzlich sogar ein FAT-Sektor). Oftmaliges anlegen und löschen einer Datei schreibt immer die selben (logischen) Sektoren. Besser nicht löschen und einfach neu anlegen, mit anderem Namen, oder überschreiben, da dabei die schon verketteten FAT-Sektoren nicht nochmals beschrieben werden, sondern nur die Daten Sektoren überschrieben werden. [Bearbeiten] Beispiel-Beschaltung[Bearbeiten] SchaltplanMMC/SD-Karten brauchen 3,3 Volt. Wenn der Controller mit 5 Volt arbeitet, muss man die Spannungspegel anpassen. Arbeitet der Controller auch mit 3,3 Volt, kann man alle Leitungen direkt mit der Karte verbinden. Als Beispiel für die mögliche Frequenz des hier verwendeten HC4050 zur Pegelwandlung: bei +125 °C und VCC von 2 V wird das Propagationdelay mit Max 130 ns angegeben. Das macht ungefähr 7,6 MHz maximal mögliche Frequenz. Bis +85 °C und VCC von 2 V geht es bis 9,5 MHz. Da aber hier 3,3 Volt anliegen, wird er in allen Bereichen etwas schneller sein. Siehe Datenblatt für mehr Infos oder Pegelwandler. Benutzt wird der SPI-Port des Controllers (bis auf Slave Select, hier PB1). Es wäre aber auch Software-basiertes SPI möglich, siehe hierfür auch Abschnitt Die Funktionalität. Die Kondensatoren C1 und C2 (100nF) dienen nur zum Entstören (möglichst nah an ICs)und sollten an jedes digitale IC in einer Schaltung. Die MMC/SD-Leiste kann eine richtige Halterung sein. Was auch sehr gut passt ist ein Stück ISA-Bus Buchse eines alten Mainboards (nur MMC-Karten). Die Abstände passen gut. Einfach vom Board flexen und dann kleine Kabel an den Stecker löten (da wo man unten jetzt das Metall sieht) Das HC4050 IC ist ein "high to low" Level-Shifter. Es sorgt dafür, dass die 3 abgehenden Signale des µC auf 3.3 Volt gebracht werden. Das abgehende Signal der Karte zum Controller wird auch so als logisch high erkannt.
[Bearbeiten] Pinbelegung MMC/SD/SDHC
[Bearbeiten] Der Code[Bearbeiten] Sourcen
Sourcecode mit Linux Makefile und als AvrStudio-Projekt auf: Alte Versionen SVN AVR-Fat32 [Bearbeiten] Einfaches Code-BeispielEin Beispiel um in eine Datei zu schreiben/anhängen und wieder zu lesen:
[Bearbeiten] FAT 32 GrundlegendesEin Dateisystem des Typs FAT besteht aus mehreren Bereichen. FAT ist immer little Endian. Ein Dateisystem wie FAT32 ist ein Verwaltungsinstrument. Der FAT16/32 Standard beschreibt die Art und Weise wie die Daten Verwaltet werden. Im Folgenden werden die Schritte, die nötig sind, um Daten aus dem System zu lesen und in das System zu schreiben, erläutert. Die Zahlenbeispiele und Bilder sollen ein praktisches Beispiel geben. Zum Verständnis empfiehlt es sich, das ganze Kapitel FAT32 durchzulesen.
FAT bedeutet File Allocation Table (Dateizuordnungstabelle). Dateizuordnungstabelle beschreibt schon das Prinzip der FAT: Kern des Dateisystems ist eine einfach verkettete Liste, in der festgehalten wird, wo sich die Daten befinden: die Dateizuordnungstabelle. In dieser Tabelle werden Cluster verkettet. Diese verketteten Cluster können Dateien oder Ordner bilden. Dazu später mehr. Der Unterschied zwischen FAT32 und FAT16 besteht darin, dass ein FAT16-Dateisystem noch einen speziellen Teil hat. Das Root-Dir ist nicht einfach ein weiterer Ordner wie bei FAT32, sondern ein festgelegter Teil, der Platz für 512 Einträge bietet. FAT-Einträge bei FAT16 sind nur 2 Byte groß. Der Rest ist gleich. [Bearbeiten] Sektor 0 oder LBAUm das Dateisystem lesen zu können, muss man wissen, wo was steht. Die Informationen sind:
Aus diesen Daten ergibt sich demnach:
Damit sind alle nötigen Daten vorhanden. Man weiß jetzt, wo das Root-Dir beginnt. Ab da spannt sich der Verzeichnisbaum auf. So kann man alle Dateieinträge lesen. Es sind also alle Informationen, mit der man das Lesen einer Datei beginnen kann, bekannt, bzw. man weiß, wo man beim Schreiben einen Dateieintrag machen muss. Um eine Datei aber vollständig lesen zu können, muss man alle Cluster kennen, die zu der Datei gehören. Da kommt die FAT-Tabelle ins Spiel, von der man die 1. Sektornummer kennt. Dort stehen ab dem 1. Cluster der Datei, verkettet alle Folgecluster. Bei FAT-Dateisystemen können mehrere Sektoren (512 Bytes) logisch zu Clustern zusammengeschlossen werden. Ein Cluster ist für eine Datei die kleinste Speichereinheit. Das hat zur Folge, dass eine 100 Byte große Datei eventuell 2048 Bytes im Dateisystem belegt. Die rote Zahl gibt an, wieviele Sektoren einen Cluster bilden. Der Datenbereich wird immer in Clustern angegeben, das macht die Umrechnung von Sektoren zu Clustern nötig. In diesem Fall ist Cluster 2 der absolute Sektor 1003. [Bearbeiten] Die FATFolgendes Bild zeigt den ersten FAT-Sektor (512 Bytes) eines FAT32 Dateisystems (nicht den ersten Sektor der Karte). Eingetragen sind: Root-Dir und zwei darin enthaltene Ordner sowie eine Datei mit 60.000 Bytes Größe. Die Einträge 0-7 sind immer reserviert (Quasi Cluster 0 und 1)! Also beginnt die FAT ab 8 (rot, Cluster Nummer 2). Der erste Eintrag (rot) ist 4 Byte groß und zu lesen von Stelle 8 zu Stelle 11 weil little Endian, also umgedrehte Wertigkeit. 8 niedrigste Wertigkeit, dann 9 eins höher, 10 noch eine höher und 11 höchste (dazu später noch ein Beispiel). Wie von Microsoft empfohlen ist der erste mögliche Cluster das Root-Dir (rot). Welches hier nur einen Cluster lang ist. An den gelben Einträgen wird die einfach verkettete Liste der FAT deutlich. Der erste gelbe Eintrag steht an der Stelle des Clusters Nummer 5 und hat als Inhalt eine 6. Das bedeutet: Cluster 5 und 6 gehören zusammen. Würde an der Stelle des Clusters Nummer 5 ein FFFFFF0F stehen (little Endian) ist nur der Cluster 5 mit Daten belegt (wie bei rot, blau und grün). So tastet man sich vom ersten Cluster einer Datei bis zum Letzten Cluster einer Datei vor. Das ist der einzige Zweck der FAT (mit FAT ist hier die eigentliche Tabelle gemeint). Woher bekommt man aber den 1. Cluster einer Datei? [Bearbeiten] DatenEin Dateieintrag besteht aus 32 Bytes und liegt in einem Ordner/Dir im Datenbereich des Dateisystems ( 32 Bytes = eine Zeile). Dies ist der 1. Cluster eines Ordners. Hier sieht man den "." bzw ".." Eintrag in Zeile 1 bzw. 2. Diese beiden Einträge sind in jedem ersten Cluster eines Ordners vorhanden. Außer im Root-Dir, von dort spannt sich der Verzeichnis Baum ja erst auf. Der "." Eintrag hat als 1. Cluster Eintrag den eigenen Cluster, hier 4. Der ".." Eintrag ist interessanter, weil er den 1. Cluster des Übergeordneten Ordners enthält, hier 3. Ist der Übergeordnete Ordner das Root-Dir, ist der 1. Cluster Eintrag 0. Diese beiden Einträge werden in der Lib genutzt um rekursiv zu löschen. Die dritte Zeile des Bilds zeigt eine Datei namens TEST3.TXT (grün) mit 60.000 Bytes Größe (blau) und dem 1. Cluster 5,damit ist immer der 1. Daten Cluster gemeint (rot, Folgecluster siehe Bild 2). Speziell ist hier, dass die 4 Bytes des ersten Clusters aufgeteilt sind auf 2 unterschiedliche "Orte" im 32 Byte Eintrag (Wertigkeit: 26:27:20:21). Um nun die Daten der Datei lesen zu können, muss man die Daten Cluster kennen. Der erste Daten Cluster steht im Datei Eintrag, hier Cluster 5. Für die Folgenden sieht man in der FAT nach. Dort stehen die Folgecluster der Datei. An der Stelle des ersten Clusters der Datei Cluster 5 steht eine 6, d.h. der nächste Cluster ist 6. In dieser Form ist die FAT verkettet. Wenn in der FAT der letzte Cluster erreicht ist, inhalt des Clusters ist FFFFFF0F, liest man den letzten Sektor bis man insgesammt die Größe der Datei (blau) gelesen hat und ist fertig. [Bearbeiten] Root DirDie Sektornummer des Root-Dirs, bei FAT32, wird aus Sektor 0 oder dem LBA ausgelesen (siehe Bild 1). Zu Sehen ist hier in der ersten Zeile ein 32 Byte Eintrag eines Ordners. Zu erkennen ist dieser am Datei Attribut 0x10 an Stelle 11 (rot). Für den Ordnernamen ist das gleiche Feld da wie für einen Dateinamen (grün). Der 1. Cluster des Ordners ist 3 (blau, Inhalt des Ordners ist Bild 3). Bei Ordnern werden die Felder für die Größe genullt (orange). Das Root-Dir hat keinen "." bzw. ".." Eintrag. Der erste Cluster des Dirs ist ja über Sektor 0 bekannt und ab dem Root-Dir spannt sich der Verzeichnisbaum erst auf. Das Root-Dir bei FAT32 kann beliebig groß werden. [Bearbeiten] ZusammenfassungFür Dateien und Ordner sind nur zwei Bereiche eines FAT32 Dateisystems wichtig, nämlich die FAT selbst und der Datenbereich. Eine Datei wird aufgesplittet, in einen Datei-Eintrag und in die Nutzdaten der Datei (alles im Datenbereich). Ein Ordner ist vom Eintrag im Dateisystem einer Datei sehr ähnlich. Wo bei einer Datei über den 1. Cluster eine Cluster-Chain für die eigentlichen Daten der Datei beginnt, wird bei einem Ordner so eine Cluster-Chain für weitere Datei/Ordner Einträge verkettet. Ein Ordner bietet pro Sektor maximal 16 Einträge (16*32=512). [Bearbeiten] Siehe auch
[Bearbeiten] WeblinksWeitere Projekte mit FAT MMC/SD Karten: |