###############################################
# Willkommen bei Holgi's kleinem ATMega-DOS ! #
###############################################
24.05.2004
CompactFlash (CF) werden hier im 8 Bit Microcontroller Modus betrieben.
Die Ansteuerung hat nichts mit Festplatten zu tun. Die FAT-Routinen zum
lesen/schreiben von Dateien könnte man aber übernehmen.
Neu hinzugekommen sind Routinen für die Ansteuerung von MultiMedia- (MMC)
und SecureDigital- (SD) Cards im SPI Modus. SD-Cards wurden aber noch nicht
getestet !
Alles was ab hier zu CF gesagt wird gilt auch für MMC/SD.
Wer wissen möchte wie schnell das ganze arbeitet findet in den Unterverzeichnissen
jeweils eine Datei readme.txt mit unverbindlichen Messungen ;)
###################
# Zur Geschichte: #
###################
Ziel des Projektes war es CompactFlash mit einem Microcontroller
zu lesen und zu schreiben weil ein 512kB Flash Eprom wie 29F040 manchmal
auch noch zu klein ist. Außerdem sollte eine einfache Möglichkeit her die
Daten auch mit dem PC zu lesen oder zu schreiben. Also am besten ein
FAT-Filesystem. Kann man mit jedem billigen CF-Reader lesen und
schreiben.
Beim Microcontroller sollte möglichst kein externes RAM zum Einsatz
kommen. Das ist ganz gut gelungen. 1.2kB für ein Dateisystem ohne
FAT-Buffer und 1.7kB mit FAT-Buffer passt noch gut in einen ATMega32.
Programmspeicherbedarf mit ALLEN Funktionen bisher unter 10kB (5k Worte).
Da die Routinen in C geschrieben sind dürfte es nicht all zu schwer
sein das ganze auch auf 8051 (dann externes RAM) oder anderen Micro-
controllern zum laufen zu bringen. PIC's sind da leider keine gute
Wahl weil man wegen des RAM Bankings maximal 256 Byte RAM am Stück
bekommt. Das dürfte recht kompliziert werden.
Hier eine Übersicht welche Funktionen man zur Zeit benutzen kann
ohne das man sich erst in FAT-Dateisysteme einarbeiten muss.
unsigned char GetDriveInformation(void);
unsigned char fopen(char *name, unsigned char flag);
unsigned int fread(unsigned char *buf, unsigned int numbytes);
unsigned int fwrite(unsigned char *buf, unsigned int numbytes);
void fflush(void);
void fclose(void);
unsigned char chdir(char *name);
unsigned char mkdir(char *name);
unsigned char remove(char *name);
unsigned char FindName(char *name);
unsigned char ReadFileRaw(char *name);
Namen und Parameter sind so weit wie möglich an die DOS Funktionen
angelehnt die man auch vom PC her kennt. Es gibt allerdings
Unterschiede und Einschränkungen. Siehe unten.
Zuerst einmal: Was geht nicht !
===============================
Lange Dateinamen werden nicht unterstützt. Sie stören aber nicht
und können bearbeitet werden wenn man den DOS Namen der Datei kennt.
Mehrere Dateien gleichzeitig öffnen geht NICHT.
Eine Datei kann nur zum lesen ODER schreiben geöffnet werden.
Man kann eine Datei nicht zum schreiben öffnen und
alte Daten überschreiben. Es wird IMMER hinten drangehängt.
Formatieren geht natürlich nicht.
Verzeichnisse löschen geht nicht.
Noch kein fseek() Befehl vorhanden.
Es wird keine Kopie von der FAT angelegt. Scandisk meckert da !
Man kann nur mit der ersten Partition arbeiten.
Es gibt keine Laufwerksnamen wie C:
Pfadangaben in Dateinamen sind nicht erlaubt. Man kann mit chdir()
aber schrittweise in mehrere Unterverzeichnisse wechseln.
Was geht ?
==========
Das Programm unterstützt FAT12,FAT16 und FAT32 Dateisysteme.
Man kann Dateien lesen und neue Dateien erstellen.
Daten an vorhandene Dateien dranhängen. Dateien löschen.
Man kann neue Verzeichnisse erstellen. Auch in Unterverzeichnissen.
Man kann in Verzeichnisse wechseln und alle oben genannten Funktionen
darin ausführen.
Alle Routinen arbeiten auch mit einer fragmentierten FAT !
RAM Speicherbedarf
==================
Ohne FATBuffer ca. 1,2kB RAM Bedarf
Mit FATBuffer ca. 1,7kB RAM Bedarf
!! Also nur für die größeren ATMega ab ATMega32 !!!
Ohne FAT-Buffer ist nur für reine Lesesysteme empfehlenswert.
Schreiben sollte man damit nicht. Siehe unten. Beim lesen kommt
man auch ohne FAT Buffer auf gute Geschwindigkeiten.
Schreiben ohne FAT Buffer
=========================
Schreiben ohne FAT Buffer ist keine gute Idee. Erstens kommt
man nicht richtig auf Geschwindigkeit wenn die FAT fragmentiert
ist, zweitens wird die FAT zu oft beschrieben. Das verkürzt die
Lebensdauer des CF um einiges.
Beispiele CF mit unfragmentierter FAT ganz vollschreiben:
16 MB CF mit FAT12 3900 Cluster
Schreiben mit FAT-Buffer 39 FAT Schreibzyklen.
Schreiben ohne FAT-Buffer 7815 FAT Schreibzyklen.
32 MB CF mit FAT16 15569 Cluster
Schreiben mit FAT-Buffer 121 FAT Schreibzyklen.
Schreiben ohne FAT-Buffer 31137 FAT Schreibzyklen.
Ein 32MB CF hat z.B. 61 FAT Sektoren. Jeder Sektor wird ohne FAT Buffer
also ca. 510 mal beschrieben. Es gibt CF wo jeder Sektor nur 10000
mal beschrieben werden darf ! Das heißt aber nicht das der CF nach
20 Versuchen kaputt ist. CF haben eine Sektorreserve für häufig
beschriebene Sektoren. Sektoren werden AUTOMATISCH ersetzt wenn sie
nicht mehr beschreibbar sind. Der CF ist erst kaputt wenn diese Reserve
verbraucht ist. Moderne CF haben >100000 garantierte Schreibzyklen
pro Sektor. Muß man mal ins Datenblatt sehen. Für solche CF kann man
wenn es nicht auf Geschwindigkeit ankommt auf den FAT Buffer verzichten.
Probleme beim schreiben von Daten
=================================
Beim schreiben darf man die Schaltung nicht einfach ausschalten bzw.
den CF rausziehen bevor nicht fclose() aufgerufen wurde. Die Dateigröße
stimmt dann nicht oder es gehen Cluster verloren weil sie noch nicht
in die FAT eingetragen wurden. Der Grund dafür ist das für Daten und
für die FAT immer ein kompletter Sektor im Speicher gehalten wird.
Diese Sektorbuffer werden nur geschrieben wenn neue Daten in einem
anderen Sektor liegen. Nur so kann man Schreibzugriffe auf den CF
minimieren und seine Lebensdauer wirklich ausnutzen.
Es gibt ein paar Möglichkeiten das Problem zu umgehen. 100% sicher
sind die z.B. bei Stromausfall aber nicht. Win oder Linux gehts da
auch nicht anders :)
1. Datei gelegentlich mal mit fclose() schließen und neu öffnen
2. fflush() in größeren Zeitabständen aufrufen. NICHT im Sekunden-
takt. Ein Tag hat 86400 Sekunden. Eher so alle 10 Minuten.
3. fflush() aufrufen wenn eine vorgegebene Datenmenge erreicht ist.
4. Einen Eingang vorsehen der dazu dient fclose() aufzurufen wenn
ein Schalter geschlossen wird. Die sicherste Methode.
//###################################################################
//###################################################################
// Beschreibung der DOS Funktionen
//###################################################################
//###################################################################
Hier die Beschreibungen zu den wichtigsten Funktionen die man benutzen
kann. Um die anderen muß man sich nur Gedanken machen wenn man selbst
Erweiterungen programmieren möchte.
//###################################################################
// unsigned char GetDriveInformation(void)
//###################################################################
Funktion: Diese Funktion ist die wichtigste. Sie ermittelt alle
Daten zum CF wie Anzahl Sektoren, Anzahl Cluster und
was für ein Filesystem auf dem CF ist (FAT12,FAT16,FAT32),
wo sich das RootDirectory befindet und vieles mehr.
Ohne diese Informationen können weder Daten vom CF gelesen
noch darauf geschrieben werden.
Diese Funktion MUSS vor allen anderen Funktionen aufgerufen
werden !
Parameter: keine
Rückgabe: F_OK wenn ein CF gefunden wurde
F_ERROR wenn kein CF gefunden wurde.
Dann auf keinen Fall weitermachen !
//###################################################################
// unsigned char fopen(char *name, unsigned char