FATSingleOpt
fat 

所属分类:处理器开发
开发工具: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 ... ...

近期下载者

相关文件


收藏者