FATSingleOpt
所属分类:处理器开发
开发工具:C/C++
文件大小:95KB
下载次数:4
上传日期:2011-03-02 20:49:52
上 传 者:
majzlik
说明: MCU Fat AVR with MMC card support
文件列表:
Vs1001_Play (0, 2006-10-30)
Vs1001_Play\buttons.txt (185, 2006-09-07)
Vs1001_Play\_gcc.bat (69, 2005-07-29)
Vs1001_Play\_gcc2.bat (56, 2006-06-21)
Vs1001_Play\makefile (3157, 2007-04-26)
Vs1001_Play\mydefs.h (3114, 2007-04-15)
Vs1001_Play\protos.h (522, 2006-06-23)
Vs1001_Play\main.c (4784, 2007-02-03)
Vs1001_Play\buttons.c (6083, 2006-11-12)
Vs1001_Play\rc5.h (13618, 2007-04-15)
Vs1001_Play\rc5.c (5166, 2006-11-04)
Vs1001_Play\buttons.h (1696, 2006-11-12)
Vs1001_Play\display.c (3537, 2006-11-12)
Vs1001_Play\display.h (671, 2006-09-01)
Vs1001_Play\playmp3.c (3971, 2006-11-12)
Vs1001_Play\playmp3.h (477, 2006-11-12)
Vs1001_Play\vs1001.c (9641, 2007-04-15)
Vs1001_Play\vs1001.h (8901, 2006-10-28)
Vs1001_Play\dosdefs.h (2103, 2007-02-21)
Vs1001_Play\printf.c (5425, 2007-04-26)
Vs1001_Play\printf.h (707, 2005-07-29)
_doxygen.bat (63, 2007-02-07)
compact.c (8105, 2007-04-15)
compact.h (3950, 2007-02-03)
dir.c (21296, 2007-02-21)
dir.h (1225, 2007-02-23)
dos.c (19696, 2007-03-16)
dos.h (6473, 2007-04-15)
doxygen.conf (52753, 2007-02-20)
drivefree.c (2424, 2007-02-20)
drivefree.h (757, 2007-02-18)
dumpsect.c (1027, 2006-09-09)
dumpsect.h (173, 2005-08-18)
fat.c (26058, 2007-04-25)
fat.h (10839, 2007-04-15)
find_x.c (3793, 2007-02-21)
find_x.h (1830, 2007-02-18)
lcd.c (10325, 2007-04-15)
lcd.h (2481, 2007-02-01)
... ...
###############################################
# Willkommen bei Holgi's kleinem ATMega-DOS ! #
###############################################
################################################################################
# Nachbau und Benutzung auf eigene Gefahr !
#
# Vor dem ersten Versuch folgende Dinge kontrollieren:
# Im makefile nachsehen welcher Prozessor eingestellt ist.
# In mydefs.h den Prozessortakt richtig einstellen.
# In media.h das Medium (CF/SD/MMC) auswhlen.
# In dosdefs.h alle gewünschten DOS Routinen de-/aktivieren.
################################################################################
Viel Spa damit
hk@holger-klabunde.de
http://www.holger-klabunde.de/index.html
24.09.2006
################################################################################
# Warnung: DOS legt die Daten in Partitionstabelle,Bootsektor,Verzeichnissen
# und FAT im LITTLE ENDIAN Format ab. Wer z.B. KEIL C51 benutzt
# muss diese Daten beim lesen erst in BIG ENDIAN umrechnen.
# Beim schreiben muss wieder ins LITTLE ENDIAN Format umgerechnet
# werden, sonst kann DOS nichts mehr lesen.
################################################################################
Mein ATMega-DOS ist nur für Prozessoren ab 1kB RAM geeignet. Ein FAT-Buffer kann
nur ab 2kB RAM benutzt werden ! ATMega8 hat zwar genügend RAM, aber evtl. nicht
ausreichend Flash für ALLE Routinen !
Mit AT90Sxxxx AVR's oder ATMega8515 arbeiten diese Routinen nicht !
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 knnte man aber übernehmen.
Neu hinzugekommen sind Routinen für die Ansteuerung von MultiMedia- (MMC)
und SecureDigital- (SD) Cards im SPI Modus.
Das meiste was hier zu CF gesagt wird gilt auch für MMC/SD.
Wer wissen mchte wie schnell das ganze arbeitet findet in den
Unterverzeichnissen der Testprogramme jeweils eine Datei readme.txt
mit unverbindlichen Messungen ;)
Und ein ganz wichtiger Tip: Halte die Kabel kurz ! Nicht mehr als 10cm.
Bei meinen MMC war bereits bei 18cm NICHTS mehr zu machen.
CF brauchen unbedingt Pullups am Datenport. Ohne interne Pullups vom
ATMega ging fast gar nichts. Bei langen Kabeln knnte es erforderlich
sein externe Pullups um 10k am Datenport anzuschliessen.
Das Programm erwartet das ein CF/MMC/SD vorhanden ist ! Ich bekam schon
Rückmeldungen das nichts angezeigt wird wenn z.B. kein MMC angeschlossen
ist, und man einige Schleifen mit Timeouts versehen sollte damit doch noch
eine Meldung kommt. Wozu ? Das macht das Programm nur langsamer. Es war nie
dazu vorgesehen OHNE CF/MMC/SD zu funktionieren ;)
CF/MMC/SD knnen NICHT im laufenden Programm eingesteckt oder rausgezogen werden !
Bitte die Schaltung deaktivieren bevor du das machst.
###################
# Zur Geschichte: #
###################
Ziel des Projektes war es moderne Speichermedien mit einem Microcontroller
zu lesen und zu schreiben weil ein 512kB Flash Eprom wie 29F040 manchmal
noch zu klein ist. Flash Eproms brauchen auch zu viele Pins für die
Ansteuerung. Die sind in der Schaltung oft nicht frei.
Auerdem sollte eine einfache Mglichkeit her die Daten auch mit dem PC zu
lesen oder zu schreiben. Also am besten ein FAT-Filesystem. Kann man mit
jedem billigen CF/MMC/SD-Reader lesen und schreiben.
Beim Microcontroller sollte mglichst kein externes RAM zum Einsatz
kommen. Das ist ganz gut gelungen. 0.7kB für ein Dateisystem ohne
FAT-Buffer und 1.2kB mit FAT-Buffer passt noch gut in einen ATMega32.
Programmspeicherbedarf mit ALLEN Funktionen bisher unter 12kB (6k 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. PIC16 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. Bei PIC18 siehts besser aus.
Hier eine bersicht welche Funktionen man zur Zeit benutzen kann
ohne das man sich erst in FAT-Dateisysteme einarbeiten muss. Von
den anderen Funktionen sollte man besser die Finger weglassen !
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);
unsigned int Fputc(unsigned char buf);
unsigned char Fgetc(void);
unsigned long Filelength(void);
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);
unsigned char Findfirst(void);
unsigned char Findnext(void);
Namen und Parameter sind so weit wie mglich an die DOS Funktionen
angelehnt die man auch vom PC her kennt. Es gibt allerdings
Unterschiede und Einschrnkungen. Siehe unten.
Zuerst einmal: Was geht nicht !
===============================
Lange Dateinamen lesen wird zum Teil unterstützt. Siehe Findfirst() und Findnext()
Mehrere Dateien gleichzeitig ffnen geht NICHT.
Es kann immer nur EINE Datei geffnet und bearbeitet werden.
Eine Datei kann nur zum lesen ODER schreiben geffnet werden.
Man kann eine Datei nicht zum schreiben ffnen und
alte Daten überschreiben. Es wird IMMER hinten drangehngt.
Formatieren geht natürlich nicht.
Verzeichnisse lschen 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.
Man kann den CF nicht aus der laufenden Schaltung rausziehen bzw.
einen CF reinstecken.
Was geht ?
==========
Das Programm unterstützt FAT12,FAT16 und FAT32 Dateisysteme.
Man kann Dateien lesen und neue Dateien erstellen.
Daten an vorhandene Dateien dranhngen. Dateien lschen.
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. 0,7kB RAM Bedarf
Mit FATBuffer ca. 1,2kB RAM Bedarf
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.
Wenn man lange Dateinamen von Findfirst()/Findnext() bekommen
mchte kommen noch einmal 256 Byte RAM dazu. Man kann den Wert
_MAX_NAME in find_x.h aber auch kleiner machen, z.B. ***. Wenn
der Name lnger ist wird er einfach hinten abgeschnitten.
Probleme beim schreiben von Daten
=================================
Beim schreiben darf man die Schaltung nicht einfach ausschalten bzw.
den CF rausziehen bevor nicht Fclose() aufgerufen wurde. Die Dateigre
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 Mglichkeiten 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() schlieen und neu ffnen
2. Fflush() in greren Zeitabstnden aufrufen. NICHT im Sekunden-
takt. Ein Tag hat 8***00 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.
Aber bedenke: Ohne Notstromversorgung ist der Daten-GAU fast unvermeidlich !
Ein Watchdog Reset kann einem auch den Tag (die Daten) verderben.
//###################################################################
//###################################################################
// 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 mchte.
//###################################################################
// 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 knnen weder Daten vom CF gelesen
noch darauf geschrieben werden.
Diese Funktion MUSS vor allen anderen Funktionen aufgerufen
werden !
Bei MMC/SD-Karten mu MMC_IO_Init(); vor GetDriveInformation();
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 !
Irgend etwas stimmt dann mit der Hardware nicht oder das
Kabel ist einfach zu lang. Eventuell ist der CF gar nicht
mit FAT formatiert ! Oder mit einem FAT das nicht den MS
Vorgaben entspricht.
//###################################################################
// unsigned char Fopen(char *name, unsigned char flag)
//###################################################################
Funktion: ffnet eine Datei zum lesen ODER schreiben
Parameter: "name" ist der DOS 8.3 Name der zu ffnenden Datei
"flag" F_READ Datei zum lesen ffnen
"flag" F_WRITE Datei zum schreiben ffnen
Rückgabe: F_OK wenn die Datei geffnet werden konnte.
F_ERROR wenn die Datei nicht geffnet werden konnte
oder bereits eine Datei offen ist.
Wenn F_WRITE benutzt wird und die Datei noch nicht
existiert, wird versucht eine neue Datei anzulegen.
Wenn die Datei bereits existiert wird an ihr ENDE
vorgespult um Daten anzuhngen. Es ist nicht vorgesehen
alte Daten zu überschreiben.
Das aktuelle Verzeichnis wird automatisch vergrert wenn
keine Eintrge mehr frei sind. Das geht bei FAT12 und FAT16
nicht wenn man sich im RootVerzeichnis befindet. Die Anzahl
der Eintrge ist fest vom Dateisystem vorgegeben.
Wer mehr als 512 Dateien anlegen will MUSS bei FAT12 und
FAT16 in einem Unterverzeichnis arbeiten !
//###################################################################
// void Fclose(void)
//###################################################################
Funktion: Schliet eine offene Datei
Parameter: keine
Rückgabe: keine
Bei FileFlag F_WRITE wird der Inhalt des Datei-Sektorbuffers
geschrieben. Dazu wird Fflush() aufgerufen. Falls ein
FAT-Write-Buffer verwendet wird, wird dieser auf den CF
geschrieben. Auch das passiert in Fflush().
Der Verzeichniseintrag der Datei wird mit der zuletzt
ermittelten Dateigre aufgefrischt.
Eine offene Datei muss AUF JEDEN FALL mit Fclose() geschlossen
werden. Tut man dies nicht kann das zu einem kompletten
Datenverlust führen.
Wer eine Uhr in seinem System hat knnte mit einer Funktion
, z.B. getclock(); , in UpdateFileEntry() auch Uhrzeit und
Datum des letzten Schreibzugriffes speichern.
//###################################################################
// unsigned int Fread(unsigned char *buf, unsigned int numbytes)
//###################################################################
Funktion: Liest eine bestimmte Anzahl Bytes aus einer Datei in einen
Puffer
Parameter: "buf" Zeiger auf den Puffer wo die Daten rein sollen
"numbytes" Anzahl der Bytes die gelesen werden sollen
Rückgabe: Anzahl der Bytes die gelesen wurden
Beispiel: 11 Bytes lesen
unsigned char inbuff[10];
unsigned char by;
unsigned int readbytes;
if(Fopen("mydata.dat",F_READ)==F_OK)
{
readbytes=Fread(inbuff,10);
readbytes=Fread(&by,1); // Achte auf das & vor by !
Fclose();
}
Wenn das Dateiende erreicht ist liefert Fread() die Anzahl
bis zum Dateiende gelesener Bytes oder einfach eine 0.
//###################################################################
// unsigned int Fwrite(unsigned char *buf, unsigned int numbytes)
//###################################################################
Funktion: Schreibt eine bestimmte Anzahl Bytes aus einem Puffer in
eine Datei
Parameter: "buf" Zeiger auf den Puffer der die Daten enthlt
"numbytes" Anzahl der Bytes die geschrieben werden sollen
Rückgabe: Anzahl der Bytes die geschrieben wurden
Beispiel:
unsigned char outbuff[10];
unsigned char by;
unsigned int written;
for(by=0; by<10; by++) outbuff[by]=by;
if(Fopen("mydata.dat",F_WRITE)==F_OK)
{
written=Fwrite("Hello World",11);
written=Fwrite(outbuff,10);
written=Fwrite(&by,1); // Achte auf das & vor by !
Fclose();
}
Wenn Fwrite() nicht die Anzahl Bytes zurückliefert die
geschrieben werden sollten, dann ist der CF voll !
//###################################################################
// void Fflush(void)
//###################################################################
Parameter: keine
Rückgabe: keine
Fflush() ruft man auf wenn alle gesammelten Daten sofort
auf den CF geschrieben werden sollen OHNE die Datei zu
schlieen.
Der Inhalt des Sektorbuffers wird geschrieben. Falls ein
FAT-Write-Buffer verwendet wird, wird dieser auf den CF
geschrieben. Der Verzeichniseintrag der Datei wird mit der
zuletzt ermittelten Dateigre aufgefrischt.
Wer eine Uhr in seinem System hat knnte mit einer Funktion
, z.B. getclock(); , in UpdateFileEntry() auch Uhrzeit und
Datum des letzten Schreibzugriffes speichern.
//###################################################################
// unsigned long Filelength(void)
//###################################################################
Parameter: keine
Rückgabe: Die Dateigre.
Ist als Macro in DOS.H definiert und entspricht FileSize.
FileSize hat nur dann einen gültigen Wert wenn eine Datei
mit Fopen() geffnet wurde !
//###################################################################
// unsigned char Chdir(char *name)
//###################################################################
Funktion: In ein Unter- oder ein hheres Verzeichnis wechseln
Parameter: Der DOS 8.3 Verzeichnisname z.B. Chdir("tmp");
Rückgabe: F_OK wenn das Verzeichnis gefunden wurde,
F_ERROR wenn das Verzeichnis nicht gefunden wurde.
Man kann immer nur eine Verzeichnistiefe zur Zeit wechseln.
Wenn man in "tmp/test" wechseln mchte mu Chdir()
zweimal aufgerufen werden:
Chdir("tmp");
Chdir("test");
Wenn man eine Verzeichnistiefe zurück mchte ruft
man einfach Chdir(".."); auf.
Chdir("/"); wechselt ins RootVerzeichnis.
Chdir() arbeitet NICHT wenn eine Datei offen ist !
//###################################################################
// unsigned char Mkdir(char *name)
//###################################################################
Funktion: Ein neues Verzeichnis erzeugen
Parameter: Der DOS 8.3 Verzeichnisname z.B. Mkdir("tmp");
Rückgabe: F_OK wenn das Verzeichnis erstellt werden konnte oder
bereits existiert.
F_ERROR wenn das Verzeichnis nicht erstellt werden konnte.
Mkdir() arbeitet NICHT wenn eine Datei offen ist !
//###################################################################
// unsigned char Remove(char *name)
//###################################################################
Funktion: Lscht eine Datei
Parameter: Der DOS 8.3 Dateiname z.B. Remove("tmp");
Rückgabe: F_OK wenn die Datei gelscht wurde (oder gar nicht existierte ;),
F_ERROR wenn die Datei nicht gelscht wurde.
Remove() arbeitet NICHT wenn eine Datei offen ist !
Remove() lscht keine Verzeichnisse.
Remove() bearbeitet die Eintrge von langen Dateinamen
nicht wenn die Datei einen langen Dateinamen hatte ! Nur
der Eintrag für den DOS-Namen wird entfernt. Es knnte sein
das es dann Probleme beim lesen des CF mit dem PC gibt.
Remove() ist eine Killer-Routine. Sie scheint zu
funktionieren, falls es aber noch Bugs gibt knnten da eine
Menge Daten verschwinden !
//###################################################################
// unsigned char Findfirst(void)
//###################################################################
Funktion: Findet den ersten Datei- oder Verzeichniseintrag im
aktuellen Verzeichnis.
Parameter: Keine
Rückgabe: 0 wenn kein Verzeichnis und keine Datei gefunden wurde.
1 wenn ein Verzeichnis oder eine Datei gefunden wurde.
Findfirst() und Findnext() benutzen eine globale Struktur ffblk
struct FindFile
{
unsigned char ff_attr; // Attribut Datei oder Verzeichnis
unsigned long ff_fsize; // Dateigre, 0 bei Verzeichnissen
char ff_name[13]; // 8.3 DOS Dateiname mit '.' und \0 am Ende
#ifdef USE_FINDLONG
char ff_longname[_MAX_NAME]; // The very long filename.
#endif
unsigned int newposition; // Finger weg !
unsigned int lastposition; // Position der gefundenen Datei/Verzeichnis
// Zhlt auch ".", ".." mit ! Also Vorsicht.
};
struct FindFile ffblk;
Findfirst() und Findnext() braucht man wenn man die Datei- oder
Verzeichnisnamen auf dem Laufwerk nicht kennt. Mit diesen beiden
Befehlen kann man DIR/LS Befehle bauen oder auch nach bestimmten
Dateitype ... ...
近期下载者:
相关文件:
收藏者: