//###################################################################################################### FAT - File - System // ************************************************************************************************************************** // * Das FAT - File - System Benutzung: * // * ----------------------------------- * // * Zunächst muss die SD-Karte initialisiert werden: * // * char = mmc_init(); Rückgabewert 0 = OK / 1 = Fehler * // * * // * Jetzt muss das FAT-File-System initialiesiert werden: * // * char = fat_initfat(); Rückgabewert 0 = OK / 1 = Fehler * // * * // * Jede Aktion auf eine Datei kann nur erfolgen, wenn diese mit einer bestimmten Option * // * geöffnet wurde: * // * Datei erstellen & schreiben: * // * char = ffopen('w',"DATEINAME"); Rückgabewert 0 = OK / 1 = Datei bereits vorhanden * // * (kein Schreiben möglich) * // * Datei öffnen & Text anhängen: * // * char = ffopen('a',"DATEINAME"); Rückgabewert 0 = OK / 1 = Datei nicht vorhanden * // * (kein Schreiben möglich) * // * Datei öffnen & lesen: * // * char = ffopen('r',"DATEINAME"); Rückgabewert 0 = OK / 1 = Datei nicht vorhanden * // * (kein Lesen möglich) * // * (DATEINAME muss ein 8.3 Format haben -> z.B. "NEU TXT") * // * ( 12345678123 ) * // * Je nach Öffnungsoption kann man nun: * // * In die Datei schreiben: * // * ffwrite(text[i]); (unsigned char text[9]="DU DA!\n\r";) * // * * // * Aus der Datei lesen: * // * char = ffread(); (ffread liest ein Byte und setzt den "Curser") * // * (automatisch auf das nächste Zeichen ) * // * * // * Ist die gewünsche Aktion beendet, muss die Datei wieder geschlossen werden. Dies geschied mit: * // * ffclose(); * // * * // * Dateien können auch gelöscht werden: * // * char = ffrm("DATEINAME"); Rückgabewert 0 = OK (Datei gelöscht) * // * / 1 = Fehler * // * (Die Datei muss geschlossen sein ( ffclose(); )) * // ************************************************************************************************************************** //******************************************************************************************************************************* // öffnet EINE datei zum lesen/schreiben/anhĂ€ngen. // datei optionen: lesen(1),schreiben/erstellen(2),anhĂ€ngen(3). //******************************************************************************************************************************* unsigned char ffopen(unsigned char option,unsigned char name[]){ unsigned long int end,start,c; unsigned char s; // datei lesen ******************************************************************************* if(option=='r' && file_flag==0){ // option; dateioperation frei. if(0==fat_loadFileDataFromDir(name)){ // lĂ€d datei infos aus dem direktory (wechselbar mit ffcd). bufferClusterChain(file.firstCluster); // puffert die ersten ccSize(anzahl) cluster der datei. if(0==fat_loadSector( fat_clustToSec(file.firstCluster) )){ // lĂ€t die ersten 512 bytes der datei auf puffer:sector. seek=file.length; // init von seek, noch keine bytes gelesen. cntSecOfClust=1; // 1.sektor von cluster geladen. ccPointer++; // zeiger++ weil 1. cluster schon geladen. bytesOfSec=§or[0]; // zeiger auf erstes byte, der datei-bytes. file_flag=1; // 1==file read. return(0); // alles ok. } } } // datei schreiben *************************************************************************** if(option=='w' && file_flag==0){ // option; dateioperation frei. if(0==fat_loadFileDataFromDir(name))return (1); // prĂŒft ob datei im dir vorhanden, wenn ja, abbruch ! currentCluster=fat_getFreeCluster(0); // holt neuen freien cluster. fat_setCluster(currentCluster,0x0fffffff);// fat16/32 cluster chain ende setzen. strcpy((char*)file.name,(char*)name); // fĂŒllen des file struct, zum abschließenden schreiben. file.firstCluster=currentCluster; // 1. cluster der datei. file.attrib=32; // file.row wird in der funktion fat_getFreeRowOfDir geschrieben !! file.length=0; // zĂ€hlt geschriebene bytes. cntSecOfClust=1; // noch kein sektor geschrieben. cntOfBytes=0; // zĂ€hlt geschriebene bytes eines sektors. file_flag=2; // schreiben flag. mmc_write_atAddr_start(fat_clustToSec(file.firstCluster));// teilt karte die aktuelle schreib adresse mit return (0); // alles OK ! } // datei anhĂ€ngen *************************************************************************** if(option=='a' && file_flag==0){ // option; dateioperation frei. if(0==fat_loadFileDataFromDir(name)){ // prĂŒft ob datei im dir vorhanden, wenn nicht, abbruch ! end=file.firstCluster; // variablen, wegen verketteten clustern... start=end; while(!((end==0xfffffff&&fat.fatType==32)||(end==0xffff&&fat.fatType==16))){ // solange bis ende cluster chain start=end; end=fat_getNextCluster(end); } // TODO einfachere methode finden den gewĂŒnschten sektor zu bestimmen !! end = file.length/fat.bytsPerSec; // end wird hier neu verwendet ! c = end/fat.secPerClust; s = (unsigned char)end-(c*fat.secPerClust); // s ist sektor des clusters. fat_loadSector(fat_clustToSec(start)+s); // lĂ€d 1. sektor des letzten clusters der datei. bytesOfSec=§or[0]; // zeigt auf erstes byte des geladenen sektors. cntSecOfClust = s+1; mmc_write_atAddr_start(fat_clustToSec(start)+s); // teilt karte die adresse mit, ab der nun geschrieben wird. // da man immer 512 bytes in folge schreiben muss, wird hier der inhalt der schon da ist nochmal auf die karte geschrieben, // beim schreiben eines sektors (wo nur wenig geĂ€ndert wurde) passiert nichts anderes... for(cntOfBytes=0;cntOfBytes<(file.length%512);cntOfBytes++)mmc_write_byte(*bytesOfSec++); file_flag=3; cntSecOfClust=1; return (0); // alles OK ! } else return (1); } return(1); //fehler? } //******************************************************************************************************************************* // gibt ffopen wieder frei. regelt wenn zum schreiben/anhĂ€ngen geöffnet war. // da immer 512 bytes komplett zur karte geschrieben werden mĂŒssen, muss noch der rest des sektors, // der nicht genutzt wurde (beim schreiben/anhĂ€ngen) voll gemacht werden !! // erst wenn datei geschlossen wird, wird wenn zum schreiben/erstellen geöffnet wird die datei informationen geschrieben, // bis hier werden nur die daten geschrieben ! //******************************************************************************************************************************* unsigned char ffclose(void){ unsigned int j; unsigned long int i; if(file_flag>1){ // war zum schreiben/anhĂ€ngen geöffnet j=file.length%512; // errechnet stelle ab der mit 0 ĂŒberschrieben werden muss while(j<512){ mmc_write_byte(0x00); // beschreibt ungenutzte bytes mit 0x00 j++; } mmc_write_atAddr_end(); // abschluss, schreiben eines blocks if(file_flag==2)fat_makeFileEntry(file.name,file.attrib,file.firstCluster,file.length); // macht datei eintrag im aktuellen verzeichniss if(file_flag==3){ i=file.length; // muss gesichert werden, wird sonst von der karte geladen und verĂ€ndert ! strcpy((char*)kb_buffer,(char*)file.name);// muss gesichert werden, wird sonst von der karte geladen und verĂ€ndert ! fat_loadFileDataFromDir(kb_buffer); // lĂ€d sektor, des datei eintrags, und lĂ€d daten auf struct file! file.length=i; fat_makeRowDataEntry(file.row,file.name,0x20,file.firstCluster,file.length); // macht eintrag im puffer fat_writeSector(fat.currentSectorNr); // schreibt puffer auf karte } } file_flag=0; cntSecOfClust=0; seek=0; cntOfBytes=0; return(0); } //***************************************************************************************PhysFS**************************************** // wechselt verzeichniss. start immer im root Dir. // MUSS in das direktory gewechselt werden, in dem die datei zum lesen/schreiben ist ! //******************************************************************************************************************************* unsigned char ffcd(unsigned char name[]){ if(0==fat_cd(name))return(0); return(1); } //******************************************************************************************************************************* // zeigt reihen eines clusters an, wird fĂŒr ffls benötigt ! // es wird ab dem start sektor start_sec, der dazugehörige cluster angezeigt. geprĂŒft wird ob es ein richtiger // eintrag in der reihe ist (nicht gelöscht, nicht frei usw). die sektoren des clusters werden nachgeladen. // die dateien werden mit namen und datei grĂ¶ĂŸe angezeigt. //******************************************************************************************************************************* void lsRowsOfClust (unsigned long int start_sec){ unsigned char row; // reihen unsigned char sec=0; // sektoren do{ fat_loadSector(start_sec + sec); for(row=0;row<16;row++){ // geht durch reihen des sektors fat_loadRowOfSector(row); if((file.attrib==0x20||file.attrib==0x10) && (file.name[0]!=0xE5&&file.name[0]!=0x00)){ //uputs((char*)file.name); //uputs(" "); ltoa(file.length,(char*)kb_buffer); //uputs((char*)kb_buffer); // printf("%lu",file.length); //uputs("\n\r"); } } sec++; }while(sec=0){ // gibt es einen eintrag davor ? if(sector[(file.row<<5)-21]==0x0f)sector[(file.row<<5)-32]=0xE5; // langer datei eintag auch gelöscht. } bufferDirty=1; // eintrag in puffer gemacht. fat_delClusterChain(file.firstCluster); // löscht die zu der datei gehörige cluster-chain aus der fat. return(0); } //TODO noch nicht optimal. zu viele schreib vorgĂ€nge beim löschen von datei eintrĂ€gen. bis zu 16/sektor ! else{ // ist ordner, rekursiv löschen !! sector[file.row<<5]=0xE5; // löscht dir eintrag if((file.row-1)>=0){ // gibt es einen eintrag davor (langer datei eintrag)? if(sector[(file.row<<5)-21]==0x0f)sector[(file.row<<5)-32]=0xE5; // langer datei eintag auch gelöscht } bufferDirty=1; // puffer eintrag gemacht parent=fat.dir; // der ordner in dem der zu löschende ordner ist. own=file.firstCluster; // der 1. cluster des ordners der zu löschen ist. clustsOfDir=file.firstCluster; // die "cluster" des zu löschenden ordners cntSecOfClust=0; // 0 sektoren bearbeitet do{ // geht durch cluster des dirs fat_loadSector(fat_clustToSec(clustsOfDir)); // sektor des dirs laden do{ // geht durch sektoren des clusters do{ // geht durch reihen des sektors fat_loadRowOfSector(i); if(file.attrib!=0x10 && file.attrib!=0x00 && file.name[0]!=0xE5){ // ist kein ordner,noch nicht gelöscht, kein freier eintrag sector[i<<5]=0xE5; // erster eintrag der reihe als gelöscht markiert bufferDirty=1; // puffer eintrag gemacht if(file.attrib==0x20){ // ist datei! fat_delClusterChain(file.firstCluster); // ist datei, dann cluster-chain der datei löschen fat_loadSector(fat_clustToSec(clustsOfDir)+cntSecOfClust); // sektor neu laden, weil löschen der chain, den puffer nutzt. } } if(file.attrib==0x10&&file.name[0]=='.'){ // "." oder ".." eintrag erkannt, löschen ! sector[i<<5]=0xE5; // eintrag als gelöscht markiert bufferDirty=1; // puffer eintrag gemacht } if(file.attrib==0x10&&file.name[0]!='.'&&file.name[0]!=0xE5){ // ordner erkannt. löschen und rein wechseln ! sector[i<<5]=0xE5; // dir eintrag als gelöscht markiert bufferDirty=1; // puffer eintrag gemacht fat_loadSector(fat_clustToSec(file.firstCluster)); // sektor des dirs laden clustsOfDir=file.firstCluster; // eigenes dir ist file.firstCluster own=file.firstCluster; // eigener start cluster/dir fat_loadRowOfSector(1); // ".." laden um parent zu bestimmen parent=file.firstCluster; // parent sichern. cntSecOfClust=0; // init von gelesenen sektoren und reihen ! i=0; continue; } if(file.name[0]==0x00){ // ende des dirs erreicht, wenn nicht voll !! if(parent==fat.dir){ // erfolgreich alles gelöscht fat_delClusterChain(own); // cluster chain des ordners löschen return(0); } fat_delClusterChain(own); // cluster chain des ordners löschen clustsOfDir=parent; // parent ist jetzt wieder arbeisverzeichniss. own=parent; // arbeitsverzeichniss setzten fat_loadSector(fat_clustToSec(own)); // sektor des dirs laden fat_loadRowOfSector(1); // ".." laden um parent zu bestimmen parent=file.firstCluster; // parent sichern. cntSecOfClust=0; // init von gelesenen sektoren und reihen ! i=0; continue; } i++; }while(i<16); // geht durch reihen des sektors. i=0; // neuer sektor -> reihen von vorne. cntSecOfClust++; fat_loadSector(fat_clustToSec(clustsOfDir)+cntSecOfClust); // lĂ€d sektoren des clusters nach }while(cntSecOfClust sektoren von vorne. clustsOfDir=fat_getNextCluster(clustsOfDir); // sucht neuen cluster der cluster-chain. }while(!((clustsOfDir==0xfffffff&&fat.fatType==32)||(clustsOfDir==0xffff&&fat.fatType==16))); // geht durch cluster des dirs. fat_delClusterChain(own); // hier landet man, wenn der ordner voll war !! } } return(1); // fehler } // ******************************************************************************************************************************* // erstellt einen dir eintrag im aktuellen verzeichniss (geht nur wenn keine lese/schreib usw. vorgĂ€nge). // prĂŒft ob es den den dir-namen:name schon gibt, dann wird nichts angelegt. // wenn ok, dann wird ein freier cluster gesucht, als ende markiert, der eintrag ins dir geschrieben. // dann wird der cluster des dirs aufbereitet. der erste sektor des clusters enthĂ€lt den "." und ".." eintrag. // der "." hat den 1. cluster des eigenen dirs. der ".." eintrag ist der 1. cluster des parent dirs. // ein dir wird immer mit 0x00 initialisiert ! also alle sektoren des clsters ( bis auf . und .. eintrĂ€ge)! // ******************************************************************************************************************************* unsigned char ffmkdir(unsigned char name[]){ unsigned char i; unsigned char* TEMP = ". "; unsigned char* TEMP1= ".. "; if(0==fat_loadFileDataFromDir(name)||file_flag!=0)return (1); // prĂŒft ob dirname im dir schon vorhanden, wenn ja, abbruch ! currentCluster=fat_getFreeCluster(0); // holt neuen freien cluster. fat_setCluster(currentCluster,0x0fffffff); // fat16/32 cluster chain ende setzen. fat_makeFileEntry(name,0x10,currentCluster,0); // macht dir eintrag im aktuellen verzeichniss // aufbereiten des neuen dir clusters ! fat_markSector00(); // löschen des sektors (nur im puffer). fat_makeRowDataEntry(0,TEMP,0x10,currentCluster,0); // macht "." eintrag des dirs // fat_makeRowDataEntry(0,". ",0x10,currentCluster,0); // macht "." eintrag des dirs // fat_makeRowDataEntry(1,".. ",0x10,fat.dir,0); // macht ".." eintrag des dirs fat_makeRowDataEntry(1,TEMP1,0x10,fat.dir,0); // macht ".." eintrag des dirs fat_writeSector(fat_clustToSec(currentCluster)); // schreibt eintrĂ€ge auf karte ! fat_markSector00(); // löschen des sektors (nur im puffer). for(i=1;i1){ // prĂŒft ob datei operation w oder a. mmc_write_byte(c); // c auf karte schreiben cntOfBytes++; // zĂ€hler fĂŒr geschriebene bytes eines sekors file.length++; // geschriebene bytes erhöhen if(cntOfBytes==512){ // SEKTOR GESCHRIEBEN ( 2 möglichkeiten ab hier !) mmc_write_atAddr_end(); // abschluss schreiben eines sektors cntOfBytes=0; // init des zĂ€hlers if(cntSecOfClust fat_loadRowOfSector -> fat_loadFileDataFromCluster -> fat_loadFileDataFromDir -> fat_loadFileDataFromDir -> fat_cd "daten chain" //*************************************************************************************************************** // lĂ€d die reihe:row des gepufferten sektors auf das struct:file. dort stehen dann // alle wichgigen daten wie: 1.cluster,lĂ€nge bei dateien, name des eintrags, reihen nummer (im sektor), attribut use... //*************************************************************************************************************** unsigned char fat_loadRowOfSector(unsigned int row){ void *firstCluster=&file.firstCluster; // void pointer auf datei erster cluster,zum schreiben von einzel bytes auf 4 byte variable. void *length=&file.length; // void pointer auf datei lĂ€nge, zum schreiben von einzel bytes auf 4 byte variable. unsigned char i; // zĂ€hler im sektor(32byte zĂ€hler). row=row<<5; // multipliziert mit 32 um immer auf zeilen anfang zu kommen (zeile 0=0,zeile 1=32,zeile 2=62 usw) . bytesOfSec=§or[row]; // byte zeiger auf puffer:sector. for(i=0;i<11;i++)file.name[i]=*bytesOfSec++; // datei name, ersten 10 bytes vom 32 byte eintrag. file.attrib=*bytesOfSec; // datei attribut, byte 11. *(unsigned char*)firstCluster++=sector[row+26]; // datei erster cluster , byte von klein nach hoch: 26,27,20,21 . *(unsigned char*)firstCluster++=sector[row+27]; // hier nicht mit bytesOfSec pointer, weil man hin und her springen, *(unsigned char*)firstCluster++=sector[row+20]; // mĂŒsste.. *(unsigned char*)firstCluster++=sector[row+21]; bytesOfSec+=17; *(unsigned char*)length++=*bytesOfSec++; // datei lĂ€nge, bytes 28,29,30,31. *(unsigned char*)length++=*bytesOfSec++; *(unsigned char*)length++=*bytesOfSec++; *(unsigned char*)length++=*bytesOfSec++; return(0); } //*************************************************************************************************************** // geht reihen weise durch sektoren des clusters mit dem startsektor:sec, und sucht nach der datei mit dem // namen:name. es werden die einzelnen sektoren nachgeladen auf puffer:sector vor dem bearbeiten. // wird die datei in dem cluster gefunden ist return 0 , sonst return1. //*************************************************************************************************************** unsigned char fat_loadFileDataFromCluster(unsigned long int sec , unsigned char name[]){ unsigned char r; unsigned char s=0; do{ // sektoren des clusters prĂŒfen if(0==fat_loadSector(sec+s)){ // lĂ€d den sektor:sec auf den puffer:sector for(r=0;r<16;r++){ // zĂ€hlt zeilennummer (16(zeilen) * 32(spalten) == 512 bytes des sektors) fat_loadRowOfSector(r) ; // zeile 0-15 auf struct:file laden if(0==strncmp((char*)file.name,(char*)name,10)){ // zeile r ist gesuchte file.row=r; // zeile sichern. return(0); } } } s++; }while(s fat_getFreeRowOfDir -> fat_makeRowDataEntry -> fat_makeFileEntry -> fat_writeSector -> eintrag gemacht !! // *************************************************************************************************************** // sucht leeren eintrag (zeile) im cluster mit dem startsektor:secStart. // wird dort kein freier eintrag gefunden ist return (1). // wird ein freier eintrag gefunden, ist die position der freien reihe auf file.row abzulesen und return (0). // der sektor mit der freien reihe ist auf dem puffer:sector gepuffert. // **************************************************************************************************************** unsigned char fat_getFreeRowOfCluster(unsigned long secStart){ unsigned int i; // 1. zeichen einer reihe, eine sektors, eines clusters. unsigned char s=0; // sektoren des clusters. do{ file.row=0; // neuer sektor(oder 1.sektor), reihen von vorne. if(0==fat_loadSector(secStart+s)){ // lĂ€d sektor auf puffer:buffer.dSector, setzt buffer.currentDatSector. for(i=0;i<512;i=i+32){ // zĂ€hlt durch zeilen (0-15). if(sector[i]==0x00||sector[i]==0xE5)return(0); // prĂŒft auf freihen eintrag (leer oder gelöscht == OK!). file.row++; // zĂ€hlt reihe hoch (nĂ€chste reihe im sektor). } } s++; // sektoren des clusters ++ weil einen geprĂŒft. }while(s neuer cluster nötig. dir=fat_getFreeCluster(start); // muss neuen freien cluster suchen (benutzt puffer:sector). fat_setCluster(start,dir); // cluster-chain mit neuem verketten (benutzt puffer:sector). fat_setCluster(dir,0x0fffffff); // cluster-chain ende markieren (benutzt puffer:sector). fat_loadSector(fat_clustToSec(dir)); // lĂ€d neuen cluster (wenn bufferFlag==1 schreibt vorher alten cluster) !! fat_markSector00(); // löschen des sektors (nur im puffer) (benutzt puffer:sector). for(i=1;i11&&i<20)*bytesOfSec=0x01; //nulle nicht nötige felder ! if(i>21&&i<26)*bytesOfSec=0x01; //nulle nicht nötige felder ! if(i==20){ // 1. cluster der datei byte 20/21 und 26/27 = 4 bytes *bytesOfSec++=(cluster&0x00ff0000)>>16; // 1. low *bytesOfSec=(cluster&0xff000000)>>24; // high byte i++; } if(i==26){ *bytesOfSec++=(cluster&0x000000ff); // low byte *bytesOfSec=(cluster&0x0000ff00)>>8; // 2. low i++; } if(i==28){ //datei lĂ€nge (4 bytes) vLength=&length; *bytesOfSec++ =*(unsigned char*)vLength++; // low *bytesOfSec++ =*(unsigned char*)vLength++; // 1. hi *bytesOfSec++ =*(unsigned char*)vLength++; // 2. hi *bytesOfSec =*(unsigned char*)vLength; // hi return (0); // alles ok, eintrag angelegt !! } bytesOfSec++; } return (1); //fehler (datei nicht gefunden, oder fehler beim lesen) } //*************************************************************************************************************** // macht den datei eintrag im jetzigen verzeichniss (fat.dir). // file.row enthĂ€lt die reihen nummer des leeren eintrags, der vorher gesucht wurde, auf puffer:sector ist der gewĂŒnschte // sektor gepuffert. fĂŒr fat16 im root dir muss andere funktion genutzt werden, als fat_getFreeRowOfDir (durchsucht nur dirs). // fat.rootDir enthĂ€lt bei fat32 den start cluster des directory, bei fat16 den 1. sektor des rootDir bereichs! //*************************************************************************************************************** unsigned char fat_makeFileEntry(unsigned char name[],unsigned char attrib,unsigned long int cluster,unsigned long int length){ unsigned int s; // zĂ€hler fĂŒr root dir sektoren fat16 if(fat.dir==0&&fat.fatType==32)fat_getFreeRowOfDir(fat.rootDir); // IM ROOT DIR (fat32) else if(fat.dir==0 && fat.fatType==16){ // IM ROOT DIR (fat16) for(s=0;s<(unsigned int)(fat.dataDirSec+2-fat.rootDir);s++){ // zĂ€hlt durch RootDir sektoren (errechnet anzahl rootDir sektoren). if(0==fat_getFreeRowOfCluster(fat.rootDir+s))break; // geht durch sektoren des root dir. } } else fat_getFreeRowOfDir(fat.dir); // NICHT ROOT DIR fat_makeRowDataEntry(file.row,name,attrib,cluster,length); // macht file eintrag im puffer fat_writeSector(fat.currentSectorNr); // schreibt file daten auf karte return(0); } // fat funktionen: //*************************************************************************************************************** // sucht nötige folge Cluster aus der fat ! // erster daten cluster = 2, ende einer cluster chain 0xFFFF (fat16) oder 0xFFFFFFF, 0xFFFFFF8 (fat32), // stelle des clusters in der fat, hat als wert, den nĂ€chsten cluster. (1:1 gemapt)! //*************************************************************************************************************** unsigned long int fat_getNextCluster(unsigned long int oneCluster){ unsigned long int i,j; void *vi; // FAT 16**************FAT 16 if(fat.fatType==16){ // i=oneCluster/256 i=oneCluster>>8;; // errechnet den sektor der fat in dem oneCluster ist (rundet immer ab) // j=(oneCluster-256*i)*2 == 2*oneCluster-512*i j=(oneCluster<<1)-(i<<9); // errechnet das low byte von oneCluster in dem ausgelesenen sektor der fat (high und low byte enthalten den folge cluster) if(0==fat_loadSector(i+fat.fatSec)){ // ob neu laden nötig wird von fat_loadSector geprĂŒft i=0; vi=&i; // zeiger auf i bytesOfSec=§or[j]; // zeiger auf puffer *(unsigned char*)vi++=*bytesOfSec++; // setzen low byte von i, aus puffer *(unsigned char*)vi++=*bytesOfSec++; // setzen von höherem byte in i, aus puffer return i; // gibt neuen cluster zurĂŒck (oder 0xffff) } } // FAT 32**************FAT 32 else{ // i=oneCluster/128 i=oneCluster>>7; // errechnet den sektor der fat in dem oneCluster ist (rundet immer ab) // j=(oneCluster-128*i)*4 == oneCluster*4-512*i j=(oneCluster<<2)-(i<<9); // errechnet das low byte von oneCluster in dem ausgelesenen sektor der fat (high und low byte enthalten den folge cluster) if(0==fat_loadSector(i+fat.fatSec)){ // ob neu laden nötig wird von fat_loadSector geprĂŒft vi=&i; bytesOfSec=§or[j]; *(unsigned char*)vi++=*bytesOfSec++; *(unsigned char*)vi++=*bytesOfSec++; *(unsigned char*)vi++=*bytesOfSec++; *(unsigned char*)vi++=*bytesOfSec++; return i; } } return(0); // neuladen des fat sektors, in dem oneCluster ist nötig !! } //*************************************************************************************************************** // sucht freien cluster in der fat ab dem offsetCluster (also offsetCluster+1). //*************************************************************************************************************** unsigned long int fat_getFreeCluster(unsigned long int offsetCluster){ do{ offsetCluster++; // cluster nummer }while(fat_getNextCluster(offsetCluster)); // freier cluster gefunden (return 0, weil inhalt des clusters 0) return offsetCluster; } //*************************************************************************************************************** // setzt den cluster inhalt. errechnet den sektor der fat in dem cluster ist, errechnet das low byte von // cluster und setzt dann byteweise den inhalt:content. // prĂŒft ob buffer dirty (zu setztender cluster nicht in jetzt gepuffertem). // prĂŒfung erfolgt in fat_loadSector, dann wird alter vorher geschrieben, sonst gehen dort daten verloren !! //*************************************************************************************************************** unsigned char fat_setCluster(unsigned long int cluster, unsigned long int content){ unsigned long int i,j; void *vc; // FAT 16**************FAT 16 if(fat.fatType==16){ // i=cluster/256 i=cluster>>8; // errechnet den sektor der fat in dem cluster ist (rundet immer ab) // j=(cluster-256*i)*2 == 2*cluster-512*i j=(cluster<<1)-(i<<9); // errechnet das low byte von cluster in dem ausgelesenen sektor der fat if(0==fat_loadSector(i+fat.fatSec)){ // neu laden (fat_loadSector prĂŒft ob schon gepuffert) // printf("\n\rfat_setClust: %lu-> %lu",cluster,content); bytesOfSec=§or[j]; // init des zeigers auf low byte vc=&content; // init des zeigers auf content *bytesOfSec++=*(unsigned char*)vc++; // setzen von 2 byte.. *bytesOfSec++=*(unsigned char*)vc++; bufferDirty=1; // zeigt an, dass im aktuellen sector geschrieben wurde return (0); } } // FAT 32**************FAT 32 else{ // i=cluster/128 i=cluster>>7; // errechnet den sektor der fat in dem cluster ist (rundet immer ab) // j=(cluster-128*i)*4 == cluster*4-512*i j=(cluster<<2)-(i<<9); // errechnet das low byte von cluster in dem ausgelesenen sektor der fat if(0==fat_loadSector(i+fat.fatSec)){ // neu laden (fat_loadSector prĂŒft ob schon gepuffert) // printf("\n\rfat_setClust: %lu-> %lu",cluster,content); bytesOfSec=§or[j]; // init des zeigers auf low byte vc=&content; // init des zeigers auf content *bytesOfSec++=*(unsigned char*)vc++; // setzen von 4 byte.... *bytesOfSec++=*(unsigned char*)vc++; *bytesOfSec++=*(unsigned char*)vc++; *bytesOfSec++=*(unsigned char*)vc++; bufferDirty=1; // zeigt an, dass im aktuellen sector geschrieben wurde return (0); } } return(1); // neuladen des fat sektors, in dem oneCluster ist, nötig !! } //*************************************************************************************************************** // löscht cluster chain, beginnend ab dem startCluster. // sucht cluster, setzt inhalt usw.. abschließend noch den cluster-chain ende markierten cluster löschen. //*************************************************************************************************************** unsigned char fat_delClusterChain(unsigned long int startCluster){ unsigned long int nextCluster; nextCluster=startCluster; // tmp variable, wegen verketteter cluster.. do{ startCluster=nextCluster; nextCluster=fat_getNextCluster(startCluster); fat_setCluster(startCluster,0x00000000); }while(!((nextCluster==0xfffffff&&fat.fatType==32)||(nextCluster==0xffff&&fat.fatType==16))); fat_writeSector(fat.currentSectorNr); return(0); } //*************************************************************************************************************** // Initialisiert die Fat(16/32) daten, wie: root directory sektor, daten sektor, fat sektor... // siehe auch Fatgen103.pdf. ist NICHT auf performance optimiert! // byte/sector, byte/cluster, anzahl der fats, sector/fat ... (halt alle wichtigen daten zum lesen ders datei systems!) //*****************************************************************<********************************************** unsigned char fat_loadFatData(unsigned long int sec){ // offset,size unsigned int rootEntCnt; // 17,2 // umbedingt mal nachsehen ! unsigned int fatSz16; // 22,2 sectors occupied by one fat16 unsigned long int fatSz32; // 36,4 sectors occupied by one fat32 void *vFatSz32; void *rootDir; if(0==mmc_read_sector(sec,sector)){ // lesen von fat sector und bestimmen der wichtigen berreiche fat.secPerClust=sector[13]; // fat.secPerClust, 13 only (power of 2) fat.bytsPerSec=sector[12]; // bytesPerSec, 12 high nibble 11 low nibble fat.bytsPerSec=fat.bytsPerSec<<8; fat.bytsPerSec+=sector[11]; fat.fatSec=sector[15]; // resvdSecCnt, 15 high nibble 14 low nibble fat.fatSec=fat.fatSec<<8; fat.fatSec+=sector[14]; rootEntCnt=sector[18]; // rootEntCnt, 18 high nibble 17 low nibble rootEntCnt=rootEntCnt<<8; rootEntCnt+=sector[17]; fatSz16=sector[23]; // fatSz16, 23 high nibble 22 low nibble fatSz16=fatSz16<<8; fatSz16+=sector[22]; fat.rootDir = (((rootEntCnt <<5) + fat.bytsPerSec) / fat.bytsPerSec)-1; // ist 0 bei fat 32, sonst der root dir sektor if(fat.rootDir==0){ // FAT32 spezifisch (die prĂŒfung so, ist nicht spezifikation konform !). vFatSz32=&fatSz32; // void pointer auf fatSz32 zum schreiben von 4 bytes *(unsigned char*)vFatSz32++=sector[36]; // lowest byte *(unsigned char*)vFatSz32++=sector[37]; // 1. higher byte *(unsigned char*)vFatSz32++=sector[38]; // 2. higher byte *(unsigned char*)vFatSz32=sector[39]; // high byte rootDir=&fat.rootDir; // void pointer auf fat.rootDir zum schreiben von 4 bytes. *(unsigned char*)rootDir++=sector[44]; // lowest byte *(unsigned char*)rootDir++=sector[45]; // 1. higher byte *(unsigned char*)rootDir++=sector[46]; // 2. higher byte *(unsigned char*)rootDir=sector[47]; // high byte fat.dataDirSec = fat.fatSec + (fatSz32 * sector[16]); // data sector (beginnt mit cluster 2) fat.dir=0; // dir auf 0==root dir, sonst 1. Cluster des dir fat.dataDirSec-=2; // zeigt auf 1. cluster fat.fatType=32; // fat typ fat.dataDirSec+=sec; // addiert den startsektor auf (umrechnung von absolut auf real) fat.fatSec+=sec; // addiert den startsektor auf } else{ // FAT16 spezifisch fat.dataDirSec = fat.fatSec + (fatSz16 * sector[16]) + fat.rootDir; // data sektor (beginnt mit cluster 2) fat.rootDir=fat.dataDirSec-fat.rootDir; // root dir sektor, da nicht im datenbereich(cluster) fat.dataDirSec-=2; // zeigt auf 1. cluster fat.dataDirSec+=sec; // addiert den startsektor auf (umrechnung von absolut auf real) fat.fatSec+=sec; // addiert den startsektor auf " fat.rootDir+=sec; // addiert den startsektor auf " fat.dir=0; // dir auf '0'==root dir, sonst 1.Cluster des dir fat.fatType=16; // fat typ } return (0); } return (1); // sector nicht gelesen, fat nicht initialisiert!! } //************************************************************************************************<<*************** // int fat sucht den 1. cluster des dateisystems (fat16/32) auch VBR genannt, // wenn superfloppy==0 wird der MBR ausgelesen um an VBR zu kommen. //************************************************************************************************<<*************** unsigned char fat_initfat(void){ void *vSecOfFirstPartition; unsigned long int secOfFirstPartition=0; // ist 1. sektor der 1. partition aus dem MBR if(superfloppy==0){ // ist partitioniert if(0==mmc_read_sector(0,sector)){ vSecOfFirstPartition=&secOfFirstPartition; *(unsigned char*)vSecOfFirstPartition++=sector[454]; *(unsigned char*)vSecOfFirstPartition++=sector[455]; *(unsigned char*)vSecOfFirstPartition++=sector[456]; *(unsigned char*)vSecOfFirstPartition++=sector[457]; return fat_loadFatData(secOfFirstPartition); // lĂ€d fat daten aus dem 1. sektor der patition } } else { return fat_loadFatData(secOfFirstPartition); // ist nicht partitioniert, lĂ€d fat daten aus sektor 0 } return (1); }