diff --git a/avr/usbload/fat.c b/avr/usbload/fat.c index d7d3308..a1defdf 100755 --- a/avr/usbload/fat.c +++ b/avr/usbload/fat.c @@ -6,10 +6,12 @@ #include "file.h" #include "hardware.h" - struct Fat fat; // wichtige daten/variablen der fat - struct File file; // wichtige dateibezogene daten/variablen +struct Fat fat; // wichtige daten/variablen der fat +struct File file; // wichtige dateibezogene daten/variablen + + +#if (WRITE==1) -#if (write==1) //*************************************************************************************************************** // schreibt sektor nummer:sec auf die karte (puffer:sector) !! // setzt bufferFlag=0 da puffer nicht dirty sein kann nach schreiben ! @@ -20,25 +22,9 @@ unsigned char fat_writeSector(unsigned long int sec){ return(mmc_write_sector(sec,fat.sector)); // schreiben von sektor puffer } -//*************************************************************************************************************** -// markiert sector komplett mit 0x00 (nur den gepufferten) -// wenn neuer direktory cluster verkettet wird, muss er mit 0x00 initialisiert werden (alle felder) -//*************************************************************************************************************** -void fat_markSector00(void){ - - fat.currentSectorNr=0; // geladener sektor wird hier geändert ! - unsigned int i=512; - - do{ - fat.sector[i]=0x00; //schreibt puffer sector voll mit 0x00==leer - }while(--i); - -} - #endif - // *************************************************************************************************************** // umrechnung cluster auf 1.sektor des clusters (möglicherweise mehrere sektoren/cluster) ! // *************************************************************************************************************** @@ -64,7 +50,7 @@ unsigned long int fat_secToClust(unsigned long int sec){ unsigned char fat_loadSector(unsigned long int sec){ if(sec!=fat.currentSectorNr){ // nachladen nötig - #if (write==1) + #if (WRITE==1) if(fat.bufferDirty==1) fat_writeSector(fat.currentSectorNr); // puffer diry, also vorher schreiben #endif mmc_read_sector(sec,fat.sector); // neuen sektor laden @@ -92,26 +78,25 @@ unsigned char fat_loadSector(unsigned long int sec){ // 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){ - unsigned char i; - + + unsigned char i; row=row<<5; // multipliziert mit 32 um immer auf zeilen anfang zu kommen (zeile 0=0,zeile 1=32,zeile 2=62 usw). - - void *firstCluster=&file.firstCluster; // void pointer auf file.firstCluster,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. + + void *vsector; // void, damit man schoen umbiegen kann :) - for(i=0;i<11;i++) file.name[i]=fat.sector[row+i]; // datei name, ersten 10 bytes vom 32 byte eintrag. + for(i=0;i<11;i++) + file.name[i]=fat.sector[row+i]; // datei name, ersten 10 bytes vom 32 byte eintrag. file.attrib=fat.sector[row+11]; // datei attribut, byte 11. - - *(unsigned char*)firstCluster++=fat.sector[row+26]; // datei erster cluster , byte von klein nach hoch: 26,27,20,21 . - *(unsigned char*)firstCluster++=fat.sector[row+27]; // hier nicht mit bytesOfSec pointer, weil man hin und her springen, - *(unsigned char*)firstCluster++=fat.sector[row+20]; // müsste.. - *(unsigned char*)firstCluster++=fat.sector[row+21]; - *(unsigned char*)length++=fat.sector[row+28]; // datei länge, bytes 28,29,30,31. - *(unsigned char*)length++=fat.sector[row+29]; - *(unsigned char*)length++=fat.sector[row+30]; - *(unsigned char*)length++=fat.sector[row+31]; + vsector=&fat.sector[row+26]; // low word von fist.cluster + file.firstCluster=*(unsigned short*)vsector; + + vsector=&fat.sector[row+20]; // high word von first.cluster + file.firstCluster|=(*(unsigned short*)vsector)<<16; + + vsector=&fat.sector[row+28]; // 4 byte von file.length + file.length=*(unsigned long int*)vsector; return(0); } @@ -127,22 +112,26 @@ unsigned char fat_loadFileDataFromCluster(unsigned long int sec , char name[]){ unsigned char r; unsigned char s=0; - do{ // sektoren des clusters prüfen - r=0; // neuer sektor, dann reihen von 0 an. - if(0==fat_loadSector(sec+s)){ // läd den sektor:sec auf den puffer:sector - do{ // reihen des sektors prüfen - fat_loadRowOfSector(r); // zeile 0-15 auf struct:file laden + do{ // sektoren des clusters prüfen + r=0; // neuer sektor, dann reihen von 0 an. + mmc_read_sector(sec+s,fat.sector); // läd den sektor sec auf den puffer fat.sector + fat.currentSectorNr=sec+s; // setzen des aktuellen sektors + do{ // reihen des sektors prüfen + fat_loadRowOfSector(r); // zeile 0-15 auf struct file laden + if(file.name[0]==0){ // wenn man auf erste 0 stößt müsste der rest auch leer sein! + file.row=r; // zeile sichern. + return(1); + } if(0==strncmp((char*)file.name,name,10)){ // zeile r ist gesuchte - file.row=r; // zeile sichern. + file.row=r; // zeile sichern. return(0); } r++; - }while(r<16); // zählt zeilennummer (16(zeilen) * 32(spalten) == 512 bytes des sektors) - } + }while(r<16); // zählt zeilennummer (16(zeilen) * 32(spalten) == 512 bytes des sektors) 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). @@ -211,19 +203,20 @@ unsigned char fat_cd(char name[]){ // **************************************************************************************************************** unsigned char fat_getFreeRowOfCluster(unsigned long secStart){ - unsigned char s=0; // sektoren des clusters. - unsigned int i; + unsigned int b; // zum durchgenen der sektor bytes + 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(fat.sector[i]==0x00||fat.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). + file.row=0; // neuer sektor(oder 1.sektor), reihen von vorne. + if(0==fat_loadSector(secStart+s)){ // laed sektor auf puffer fat.sector + for(b=0;b<512;b=b+32){ // zaehlt durch zeilen (0-15). + if(fat.sector[b]==0x00||fat.sector[b]==0xE5)return(0); // prueft auf freihen eintrag (leer oder geloescht == 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. + } // wenn aus schleife raus, kein freier eintrag da -> neuer cluster nötig. - fat_getClustersInRow(2,0); // sucht freie cluster in einer reihe - dir=fat.startSectors; // 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). + dir=fat_secToClust(fat.startSectors); // dir ist jetzt neuer cluster zum verketten ! + fat_setCluster(start,dir); // cluster-chain mit neuem cluster verketten + fat_setCluster(dir,0x0fffffff); // cluster-chain ende markieren - unsigned char i=1; + //es muessen neue gesucht werden, weil der bekannte aus file.c ja grade verkettet wurden. datei eintrag passte nicht mehr ins dir... + fat_getFreeClustersInRow(2); // neue freie cluster suchen, für datei. + file.firstCluster=fat_secToClust(fat.startSectors); // 1. cluster der datei + file.lastCluster=fat_secToClust(fat.endSectors); // letzter bekannter cluster der datei + + fat.currentSectorNr=fat_clustToSec(dir); // setzen des richtigen sektors, also auf den 1. der neu verketteten + + unsigned int j=511; + do{ + fat.sector[j]=0x00; //schreibt puffer fat.sector voll mit 0x00==leer + }while(j--); + + unsigned char i=1; // ab 1 weil der 1.sektor des clusters eh noch beschrieben wird... do{ fat_writeSector(fat.currentSectorNr+i); // löschen des cluster (überschreibt mit 0x00), wichtig bei ffls, i++; - }while(i>16;// low word von cluster - *bytesOfSec++=(cluster&0x00ff0000)>>16; // 1. low von cluster - *bytesOfSec++=(cluster&0xff000000)>>24; // high byte + vsector=&fat.sector[row+22]; + *(unsigned long int*)vsector=0x01010101; // unnoetige felder beschreiben - *bytesOfSec++=0x01; // nicht nötige felder beschreiben - *bytesOfSec++=0x01; // nicht nötige felder beschreiben - *bytesOfSec++=0x01; // nicht nötige felder beschreiben - *bytesOfSec++=0x01; // nicht nötige felder beschreiben - - *bytesOfSec++=(cluster&0x000000ff); // low byte von cluster - *bytesOfSec++=(cluster&0x0000ff00)>>8; // 2. low + vsector=&fat.sector[row+26]; + *(unsigned short*)vsector=(cluster&0x0000ffff); // high word von cluster - *bytesOfSec++ =*(unsigned char*)vLength++; // low von länge - *bytesOfSec++ =*(unsigned char*)vLength++; // 1. hi - *bytesOfSec++ =*(unsigned char*)vLength++; // 2. hi - *bytesOfSec++ =*(unsigned char*)vLength; // hi - - return (0); // eintrag in puffer gemacht ! + vsector=&fat.sector[row+28]; + *(unsigned long int*)vsector=length; // laenge } @@ -311,28 +307,25 @@ unsigned char fat_makeRowDataEntry(unsigned int row,char name[],unsigned char at // 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(char name[],unsigned char attrib,unsigned long int cluster,unsigned long int length){ +void fat_makeFileEntry(char name[],unsigned char attrib,unsigned long int length){ - unsigned int s; // zähler für root dir sektoren fat16 + 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. + if(0==fat_getFreeRowOfCluster(fat.rootDir+s))break; // geht durch sektoren des root dir. } } - else fat_getFreeRowOfDir(fat.dir); // NICHT ROOT DIR + else fat_getFreeRowOfDir(fat.dir); // NICHT ROOT DIR fat32/fat16 - 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_makeRowDataEntry(file.row,name,attrib,file.firstCluster,length); // schreibt file eintrag auf puffer + fat_writeSector(fat.currentSectorNr); // schreibt puffer auf karte } - #endif +#endif @@ -347,121 +340,96 @@ unsigned char fat_makeFileEntry(char name[],unsigned char attrib,unsigned long i //*************************************************************************************************************** unsigned long int fat_getNextCluster(unsigned long int oneCluster){ - unsigned char *bytesOfSec; - // FAT 16**************FAT 16 if(fat.fatType==16){ - unsigned long int i=oneCluster>>8;; // (i=oneCluster/256)errechnet den sektor der fat in dem oneCluster ist (rundet immer ab) + unsigned long int i=oneCluster>>8;; // (i=oneCluster/256)errechnet den sektor der fat in dem oneCluster ist (rundet immer ab) unsigned long int j=(oneCluster<<1)-(i<<9); // (j=(oneCluster-256*i)*2 == 2*oneCluster-512*i)errechnet das low byte von oneCluster - if(0==fat_loadSector(i+fat.fatSec)){ // ob neu laden nötig, wird von fat_loadSector geprüft - i=0; - void *vi=&i; // zeiger auf i - bytesOfSec=&fat.sector[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) + if(0==fat_loadSector(i+fat.fatSec)){ // ob neu laden nötig, wird von fat_loadSector geprüft + void *bytesOfSec=&fat.sector[j]; // zeiger auf puffer + return *(unsigned short*)bytesOfSec; // da der ram auch little endian ist, kann einfach gecastet werden und gut :) } } // FAT 32**************FAT 32 else{ - unsigned long int i=oneCluster>>7; // (i=oneCluster/128)errechnet den sektor der fat in dem oneCluster ist (rundet immer ab) + unsigned long int i=oneCluster>>7; // (i=oneCluster/128)errechnet den sektor der fat in dem oneCluster ist (rundet immer ab) unsigned long int j=(oneCluster<<2)-(i<<9); // (j=(oneCluster-128*i)*4 == oneCluster*4-512*i)errechnet das low byte von oneCluster if(0==fat_loadSector(i+fat.fatSec)){ // ob neu laden nötig wird von fat_loadSector geprüft - void *vi=&i; - bytesOfSec=&fat.sector[j]; - *(unsigned char*)vi++=*bytesOfSec++; - *(unsigned char*)vi++=*bytesOfSec++; - *(unsigned char*)vi++=*bytesOfSec++; - *(unsigned char*)vi++=*bytesOfSec++; - return i; + void *bytesOfSec=&fat.sector[j]; // zeiger auf puffer + return *(unsigned long int*)bytesOfSec; // da der ram auch little endian ist, kann einfach gecastet werden und gut :) } - } + } - return(0); // neuladen des fat sektors, in dem oneCluster ist nötig !! + return(0); } //*************************************************************************************************************** -// sucht freie sektoren oder verkettete in einer reihe ! -// das flag emptyOrFirst sagt ob freie oder verkettete gesucht werden. offsetCluster ist einmal der cluster ab dem -// freie gesucht werden oder der erste cluster der datei. beide male enthält fat.startSectors den ersten sektor der -// reihe und fat.cntSectors die anzahl der sektoren in einer reihe! -// [ fat.startSectors , fat.startSectors+fat.cntSectors ] = anzahl der sektoren !! +// sucht verkettete cluster einer datei, die in einer reihe liegen. worst case: nur ein cluster. +// sieht in der fat ab dem cluster offsetCluster nach. sucht die anzahl von MAX_CLUSTERS_IN_ROW, +// am stück,falls möglich. prüft ob der cluster neben offsetCluster dazu gehört... +// setzt dann fat.endSectors und fat.startSectors. das -1 weil z.b. [95,98] = {95,96,97,98} = 4 sektoren //*************************************************************************************************************** -unsigned char fat_getClustersInRow(unsigned long int offsetCluster,unsigned char emptyOrFirst){ +void fat_getFatChainClustersInRow(unsigned long int offsetCluster){ - unsigned char i; // variable für anzahl der zu suchenden sektoren - - if(0==emptyOrFirst){ /** SUCHEN von freien sektoren (max 255 am stück) **/ - i=1; - offsetCluster--; // ernidrigen, da dann inklusive diesem cluster gesucht wird - do{ // suche des 1. freien - offsetCluster++; // cluster nummer - }while(fat_getNextCluster(offsetCluster)); // freier cluster gefunden, returnwert=0 -> abbruch - fat.startSectors=fat_clustToSec(offsetCluster); // setzen des startsektors der freien sektoren (umrechnen von cluster zu sektoren) - fat.endSectors=fat.startSectors; - do{ // suche der nächsten freien - if(0==fat_getNextCluster(offsetCluster+i) ) fat.endSectors+=fat.secPerClust; // zählen der zusammenhängenden sektoren - else break; // cluster daneben ist nicht frei - i++; - }while(i<255); - fat.endSectors+=fat.secPerClust; - } - - else{ /** SUCHEN von verketteten sektoren der datei (max 255 am stück) **/ - i=0; - fat.startSectors=fat_clustToSec(offsetCluster); // setzen des 1. sektors der datei - fat.endSectors=fat.startSectors; - do{ - if( (offsetCluster+1+i)==fat_getNextCluster(offsetCluster+i) ) fat.endSectors+=fat.secPerClust; // zählen der zusammenhängenden sektoren - else { - file.lastCluster=offsetCluster+i; // cluster daneben gehört nicht dazu, somit ist offset+i der letzte bekannte - break; - } - i++; - }while(i<255); - fat.endSectors+=fat.secPerClust; - } - - return 0; + unsigned int i=0; + fat.startSectors=fat_clustToSec(offsetCluster); // setzen des 1. sektors der datei + fat.endSectors=fat.startSectors; + do{ + if( (offsetCluster+1+i)==fat_getNextCluster(offsetCluster+i) ) fat.endSectors+=fat.secPerClust; // zählen der zusammenhängenden sektoren + else { + file.lastCluster=offsetCluster+i; // cluster daneben gehört nicht dazu, somit ist offset+i der letzte bekannte + break; + } + }while(i++>8; // (i=cluster/256)errechnet den sektor der fat in dem cluster ist (rundet immer ab) + unsigned long int i=cluster>>8; // (i=cluster/256)errechnet den sektor der fat in dem cluster ist (rundet immer ab) unsigned long int j=(cluster<<1)-(i<<9); // (j=(cluster-256*i)*2 == 2*cluster-512*i)errechnet das low byte von cluster if(0==fat_loadSector(i+fat.fatSec)){ // neu laden (fat_loadSector prüft ob schon gepuffert) - bytesOfSec=&fat.sector[j]; // init des zeigers auf low byte - void *vc=&content; // init des zeigers auf content - *bytesOfSec++=*(unsigned char*)vc++; // setzen von 2 byte.. - *bytesOfSec++=*(unsigned char*)vc++; - fat.bufferDirty=1; // zeigt an, dass im aktuellen sector geschrieben wurde - return (0); + void *bytesOfSec=&fat.sector[j]; // init des zeigers auf unterste adresse + *(unsigned short*)bytesOfSec=content;// weil ram auch little endian geht das so :) + fat.bufferDirty=1; // zeigt an, dass im aktuellen sector geschrieben wurde } } // FAT 32**************FAT 32 else{ - unsigned long int i=cluster>>7; // (i=cluster/128)errechnet den sektor der fat in dem cluster ist (rundet immer ab) + unsigned long int i=cluster>>7; // (i=cluster/128)errechnet den sektor der fat in dem cluster ist (rundet immer ab) unsigned long int j=(cluster<<2)-(i<<9); //(j=(cluster-128*i)*4 == cluster*4-512*i)errechnet das low byte von cluster - if(0==fat_loadSector(i+fat.fatSec)){ // neu laden (fat_loadSector prüft ob schon gepuffert) - bytesOfSec=&fat.sector[j]; // init des zeigers auf low byte - void *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++; - fat.bufferDirty=1; // zeigt an, dass im aktuellen sector geschrieben wurde - return (0); + if(0==fat_loadSector(i+fat.fatSec)){ // neu laden (fat_loadSector prüft ob schon gepuffert) + void *bytesOfSec=&fat.sector[j]; // init des zeigers auf unterste adresse + *(unsigned long int*)bytesOfSec=content; // weil ram auch little endian geht das so :) + fat.bufferDirty=1; // zeigt an, dass im aktuellen sector geschrieben wurde } } - - - return(1); // neuladen des fat sektors, in dem oneCluster ist, nötig !! } @@ -538,59 +493,53 @@ void fat_delClusterChain(unsigned long int startCluster){ //*****************************************************************<********************************************** unsigned char fat_loadFatData(unsigned long int sec){ - // offset,size + // offset,size unsigned int rootEntCnt; // 17,2 größe die eine fat belegt - unsigned int fatSz16; // 22,2 sectors occupied by one fat16 - unsigned long int fatSz32; // 36,4 sectors occupied by one fat32 + unsigned int fatSz16; // 22,2 sectors occupied by one fat16 + unsigned long int fatSz32; // 36,4 sectors occupied by one fat32 + + void *vsector; if(0==mmc_read_sector(sec,fat.sector)){ // lesen von fat sector und bestimmen der wichtigen berreiche - fat.bufferDirty = 0; // init wert des flags + fat.bufferDirty = 0; // init wert des flags fat.secPerClust=fat.sector[13]; // fat.secPerClust, 13 only (power of 2) - fat.fatSec=fat.sector[15]; // resvdSecCnt->1.fat sektor, 15 high nibble 14 low nibble - fat.fatSec=fat.fatSec<<8; - fat.fatSec+=fat.sector[14]; + vsector=&fat.sector[14]; + fat.fatSec=*(unsigned short*)vsector; - rootEntCnt=fat.sector[18]; // rootEntCnt, 18 high nibble 17 low nibble - rootEntCnt=rootEntCnt<<8; - rootEntCnt+=fat.sector[17]; - - fatSz16=fat.sector[23]; // fatSz16, 23 high nibble 22 low nibble - fatSz16=fatSz16<<8; - fatSz16+=fat.sector[22]; + vsector=&fat.sector[17]; + rootEntCnt=*(unsigned short*)vsector; - fat.rootDir = (((rootEntCnt <<5) + 512) /512)-1; // ist 0 bei fat 32, sonst der root dir sektor + vsector=&fat.sector[22]; + fatSz16=*(unsigned short*)vsector; + + fat.rootDir = (((rootEntCnt <<5) + 512) /512)-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 !). - void *vFatSz32=&fatSz32; // void pointer auf fatSz32 zum schreiben von 4 bytes - *(unsigned char*)vFatSz32++=fat.sector[36]; // lowest byte - *(unsigned char*)vFatSz32++=fat.sector[37]; // 1. higher byte - *(unsigned char*)vFatSz32++=fat.sector[38]; // 2. higher byte - *(unsigned char*)vFatSz32=fat.sector[39]; // high byte - void *rootDir=&fat.rootDir; // void pointer auf fat.rootDir zum schreiben von 4 bytes. - *(unsigned char*)rootDir++=fat.sector[44]; // lowest byte - *(unsigned char*)rootDir++=fat.sector[45]; // 1. higher byte - *(unsigned char*)rootDir++=fat.sector[46]; // 2. higher byte - *(unsigned char*)rootDir=fat.sector[47]; // high byte + vsector=&fat.sector[36]; + fatSz32=*(unsigned long int *)vsector; - fat.dataDirSec = fat.fatSec + (fatSz32 * fat.sector[16]); // data sector (beginnt mit cluster 2) - fat.fatType=32; // fat typ + vsector=&fat.sector[44]; + fat.rootDir=*(unsigned long int *)vsector; + + fat.dataDirSec = fat.fatSec + (fatSz32 * fat.sector[16]); // data sector (beginnt mit cluster 2) + fat.fatType=32; // fat typ } else{ // FAT16 spezifisch fat.dataDirSec = fat.fatSec + (fatSz16 * fat.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.rootDir+=sec; // addiert den startsektor auf " - fat.fatType=16; // fat typ + fat.rootDir+=sec; // addiert den startsektor auf " + fat.fatType=16; // fat typ } - fat.fatSec+=sec; // addiert den startsektor auf - fat.dataDirSec+=sec; // addiert den startsektor auf (umrechnung von absolut auf real) - fat.dataDirSec-=2; // zeigt auf 1. cluster - fat.dir=0; // dir auf '0'==root dir, sonst 1.Cluster des dir + fat.fatSec+=sec; // addiert den startsektor auf + fat.dataDirSec+=sec; // addiert den startsektor auf (umrechnung von absolut auf real) + fat.dataDirSec-=2; // zeigt auf 1. cluster + fat.dir=0; // dir auf '0'==root dir, sonst 1.Cluster des dir return (0); } @@ -601,33 +550,28 @@ unsigned char fat_loadFatData(unsigned long int sec){ //************************************************************************************************<<*************** // 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){ - unsigned long int secOfFirstPartition=0; // ist 1. sektor der 1. partition aus dem MBR + unsigned long int secOfFirstPartition=0; // ist 1. sektor der 1. partition aus dem MBR + + if(0==mmc_read_sector(0,fat.sector)){ - if(superfloppy==0){ // ist partitioniert - if(0==mmc_read_sector(0,fat.sector)){ + void *vsector=&fat.sector[454]; //startsektor bestimmen + secOfFirstPartition=*(unsigned long int*)vsector; - void *vSecOfFirstPartition=&secOfFirstPartition; - *(unsigned char*)vSecOfFirstPartition++=fat.sector[454]; - *(unsigned char*)vSecOfFirstPartition++=fat.sector[455]; - *(unsigned char*)vSecOfFirstPartition++=fat.sector[456]; - *(unsigned char*)vSecOfFirstPartition++=fat.sector[457]; + //prüfung ob man schon im VBR gelesen hat (0x6964654d = "Medi") + if(secOfFirstPartition==0x6964654d) return fat_loadFatData(0); //ist superfloppy - 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 - } + else {return fat_loadFatData(secOfFirstPartition);} // ist partitioniert... + } return (1); } -#if (smallFileSys==0) + +#if (SMALL_FILE_SYSTEM==0) + // ***************************************************************************************************************** // bereitet str so auf, dass man es auf die mmc/sd karte schreiben kann. // wandelt z.b. "t.txt" -> "T TXT" oder "main.c" in "MAIN C " => also immer 8.3 und upper case letter diff --git a/avr/usbload/fat.h b/avr/usbload/fat.h index 93c35e3..d05aa3b 100755 --- a/avr/usbload/fat.h +++ b/avr/usbload/fat.h @@ -3,71 +3,68 @@ #define _FAT_H - //####################################################################################################################### - // WICHTIGE SCHLATER: -> hier kann die code größe angepasst werden, zu lasten der funktionalität ! - #define smallFileSys 0 // wenn 1 dann ist kleines file system, wenn 0 dann komplette file unterstützung ! - #define write 1 // wenn 1 dann ist write an, wenn 0 dann read only ! - - /** ===> hier MUSS eingestellt werden ob die karte partitioniert ist oder nicht ! <====**/ - #define superfloppy 0 // wenn 0 ist partitioniert, wenn 1 ist unpartitioniert (superfloppy) !! + // ************************************************************************************************************************** + // WICHTIGE SCHLATER: -> hier kann die code größe angepasst werden, zu lasten der funktionalität ! + #define SMALL_FILE_SYSTEM 0 // wenn 1 dann ist kleines file system, wenn 0 dann komplette file unterstützung ! + #define WRITE 1 // wenn 1 dann ist write an, wenn 0 dann read only ! + #define OVER_WRITE 1 // wenn 1 dann kann ffwrite dateien überschreiben (nicht performant), wenn 0 dann nur normales schreiben ! + #define MAX_CLUSTERS_IN_ROW 256 // gibt an wie viele cluster am stück ohne fat lookup geschrieben bzw gelesen werden können, wenn die fat nicht fragmentiert ist ! // 1. fat_getFreeRowOfCluster -> fat_getFreeRowOfDir -> fat_makeRowDataEntry -> fat_makeFileEntry -> fat_writeSector "eintrag gemacht !!" // 2. fat_loadSector -> fat_loadRowOfSector -> fat_loadFileDataFromCluster -> fat_loadFileDataFromDir (-> fat_cd) "daten chain" - //####################################################################################################################### + // ************************************************************************************************************************** // funktionen - //extern unsigned long int fat_getFreeCluster(unsigned long int offsetCluster); // sucht leeren fat cluster aus der fat extern unsigned long int fat_clustToSec(unsigned long int); // rechnet cluster zu 1. sektor des clusters um extern unsigned long int fat_secToClust(unsigned long int sec); // rechnet sektor zu cluster um! extern unsigned long int fat_getNextCluster(unsigned long int oneCluster); // fat auf nächsten, verketteten cluster durchsuchen extern unsigned char fat_initfat(void); // initalisierung (durchsucht MBR oder nicht) extern unsigned char fat_writeSector(unsigned long int sec); // schreibt sektor auf karte - extern unsigned char fat_setCluster(unsigned long int cluster, unsigned long int content); // setzt cluster inhalt in der fat + extern void fat_setCluster(unsigned long int cluster, unsigned long int content); // setzt cluster inhalt in der fat extern void fat_delClusterChain(unsigned long int startCluster); // löscht cluster-chain in der fat - extern unsigned char fat_getFreeRowOfDir(unsigned long int dir); // durchsucht directory nach feiem eintrag - extern unsigned char fat_makeFileEntry(char name[],unsigned char attrib,unsigned long int cluster,unsigned long int length); + extern void fat_getFreeRowOfDir(unsigned long int dir); // durchsucht directory nach feiem eintrag + extern void fat_makeFileEntry(char name[],unsigned char attrib,unsigned long int length); extern unsigned char fat_loadSector(unsigned long int sec); // läd übergebenen absoluten sektor extern unsigned char fat_loadFileDataFromDir(char name[]); // durchsucht das aktuelle directory extern unsigned char fat_cd(char *); // wechselt directory (start im rootDir) extern unsigned char fat_loadFatData(unsigned long int); // läd fat daten extern unsigned char fat_getFreeRowOfCluster(unsigned long secStart);// durchsucht cluster nach freiem eintrag - extern unsigned char fat_getClustersInRow(unsigned long int offsetCluster,unsigned char emptyOrFirst); // holt zusammenhängende cluster - extern unsigned char fat_makeRowDataEntry(unsigned int row,char name[],unsigned char attrib,unsigned long int cluster,unsigned long int length); + extern void fat_getFreeClustersInRow(unsigned long int offsetCluster); // sucht zusammenhängende freie cluster aus der fat + extern void fat_getFatChainClustersInRow(unsigned long int offsetCluster); // sucht fat-chain cluster die zusammenhängen + extern void fat_makeRowDataEntry(unsigned int row,char name[],unsigned char attrib,unsigned long int cluster,unsigned long int length); extern unsigned char fat_loadRowOfSector(unsigned int); // läd reihe des geladen sektors auf struct:file extern unsigned char fat_loadFileDataFromCluster(unsigned long int sec , char name[]); // durchsucht die reihen des geladenen sektors - extern void fat_markSector00(void); // markiert puffer:sector mit 0x00 - extern unsigned char fat_setClusterChain(unsigned long int newOffsetCluster,unsigned int length); - extern char * fat_str(char *str); + extern void fat_setClusterChain(unsigned long int newOffsetCluster,unsigned int length); + extern char *fat_str(char *str); // wandelt einen string so, dass er der fat konvention entspricht ! - //####################################################################################################################### + // ************************************************************************************************************************** // variablen - extern struct Fat{ // fat daten (1.cluster, root-dir, dir usw.) - unsigned char sector[512]; // der puffer für sektoren ! - unsigned char bufferDirty; // puffer wurde beschrieben, sector muss geschrieben werden bevor er neu geladen wird - unsigned long int currentSectorNr; // aktuell geladener Sektor (in sector) //beschleunigt wenn z.b 2* 512 byte puffer vorhanden, oder bei fat operationen im gleichen sektor - unsigned long int dir; // Direktory zeiger rootDir=='0' sonst(1.Cluster des dir; start auf root) - unsigned long int rootDir; // Sektor(f16)/Cluster(f32) nr root directory + extern struct Fat{ // fat daten (1.cluster, root-dir, dir usw.) + unsigned char sector[512]; // der puffer für sektoren ! + unsigned char bufferDirty; // puffer wurde beschrieben, sector muss geschrieben werden bevor er neu geladen wird + unsigned long int currentSectorNr;// aktuell geladener Sektor (in sector) //beschleunigt wenn z.b 2* 512 byte puffer vorhanden, oder bei fat operationen im gleichen sektor + unsigned long int dir; // Direktory zeiger rootDir=='0' sonst(1.Cluster des dir; start auf root) + unsigned long int rootDir; // Sektor(f16)/Cluster(f32) nr root directory unsigned long int dataDirSec; // Sektor nr data area unsigned long int fatSec; // Sektor nr fat area - unsigned long int startSectors; // der erste sektor in einer reihe (freie oder verkettete) + unsigned long int startSectors; // der erste sektor in einer reihe (freie oder verkettete) unsigned long int endSectors; - unsigned char secPerClust; // anzahl der sektoren pro cluster - unsigned char fatType; // fat16 oder fat32 (16 oder 32) - + unsigned char secPerClust; // anzahl der sektoren pro cluster + unsigned char fatType; // fat16 oder fat32 (16 oder 32) }fat; - extern struct File{ // datei infos (32 bytes lang- 16 bei 512 bytesPerSec) - unsigned int cntOfBytes; // -nicht direkt aus dem dateisystem- zäht geschriebene bytes eines sektors - unsigned char name[13]; // 0,10 datei Name.ext (8.3 = max 11)(MUSS unsigned char weil E5) - unsigned char attrib; // 11,1 datei Attribut: 8=value name, 32=datei, 16=Verzeichniss, 15=linux kleingeschrieben eintrag - unsigned char row; // reihe im sektor in der die datei infos stehen (reihe 0-15) - unsigned long int firstCluster; // 20,2 /26,2 datei 1.cluster hi,low(möglicherweise der einzige) (4-byte) - unsigned long int length; // 28,4 datei Länge (4-byte) - unsigned long int lastCluster; // -nicht direkt aus dem dateisystem- letzter cluster der ersten kette - unsigned long int seek; // schreib position in der datei + extern struct File{ // datei infos + unsigned int cntOfBytes; // -nicht direkt aus dem dateisystem- zäht geschriebene bytes eines sektors + unsigned char name[13]; // 0,10 datei Name.ext (8.3 = max 11)(MUSS unsigned char weil E5) + unsigned char attrib; // 11,1 datei Attribut: 8=value name, 32=datei, 16=Verzeichniss, 15=linux kleingeschrieben eintrag + unsigned char row; // reihe im sektor in der die datei infos stehen (reihe 0-15) + unsigned long int firstCluster; // 20,2 /26,2 datei 1.cluster hi,low(möglicherweise der einzige) (4-byte) + unsigned long int length; // 28,4 datei Länge (4-byte) + unsigned long int lastCluster; // -nicht direkt aus dem dateisystem- letzter cluster der ersten kette + unsigned long int seek; // schreib position in der datei }file; #endif diff --git a/avr/usbload/file.c b/avr/usbload/file.c index bddf53c..4f56c04 100755 --- a/avr/usbload/file.c +++ b/avr/usbload/file.c @@ -1,33 +1,43 @@ - #include #include +#include #include "hardware.h" #include "fat.h" #include "file.h" + + //******************************************************************************************************************************* -// 2 möglichkeiten beim öffnen, datei existiert oder muss angelegt werden +// 2 möglichkeiten beim öffnen, datei existiert(return 1) oder muss angelegt werden(return 2) +// zuerst wird geprüft ob es die datei im verzeichniss gibt. danach wird entschieden, ob die datei geöffnet wird oder angelegt. +// -beim offnen werden die bekannten cluster gesucht maximal MAX_CLUSTERS_IN_ROW in reihe. dann wird der 1. sektor der datei auf +// den puffer fat.sector geladen. jetzt kann man ffread lesen... +// -beim anlegen werden freie cluster gesucht, maximal MAX_CLUSTERS_IN_ROW in reihe. dann wird das struct file gefüllt. +// danach wird der dateieintrag gemacht(auf karte). dort wird auch geprüft ob genügend platz im aktuellen verzeichniss existiert. +// möglicherweise wird der 1. cluster der datei nochmal geändert. jetzt ist der erste frei sektor bekannt und es kann geschrieben werden. //******************************************************************************************************************************* unsigned char ffopen(char name[]){ - unsigned char file_flag=fat_loadFileDataFromDir(name); //prüfung ob datei vorhanden und evetuelles laden des file struct - + unsigned char file_flag=fat_loadFileDataFromDir(name); //prüfung ob datei vorhanden und evetuelles laden des file struct + if( file_flag==0 ){ /** Datei existiert, anlegen nicht nötig! **/ - fat_getClustersInRow( file.firstCluster,1 ); // cluster chain suchen - fat_loadSector( fat_clustToSec(file.firstCluster) ); // lät die ersten 512 bytes der datei auf puffer:sector. - file.lastCluster=file.firstCluster; // setzen des arbeis clusters + fat_getFatChainClustersInRow( file.firstCluster ); // verkettete cluster aus der fat-chain suchen. + fat_loadSector( fat_clustToSec(file.firstCluster) ); // lät die ersten 512 bytes der datei auf puffer:sector. + file.lastCluster=fat_secToClust(fat.endSectors); // letzter bekannter cluster der datei return 1; } - #if (write==1) - else{ /** Datei existiert nicht, also anlegen ! (nur wenn schreiben option an ist)**/ - fat_getClustersInRow(3,0); // leere cluster suchen - strcpy((char*)file.name,(char*)name); // --- füllen des file struct, zum abschließenden schreiben. - file.firstCluster=fat_secToClust(fat.startSectors); // 1. cluster der datei. - file.lastCluster=file.firstCluster; // letzter bekannter cluster der datei - file.attrib=32; // --- file.row wird in der funktion fat_getFreeRowOfDir geschrieben !! - fat_makeFileEntry((char *)file.name,file.attrib,file.firstCluster,0); // DATEI ANLEGEN - fat.currentSectorNr=fat_clustToSec(file.firstCluster); // setzen des ersten sektors + + #if (WRITE==1) // anlegen ist schreiben ! + else{ /** Datei existiert nicht, also anlegen ! (nur wenn schreiben option an ist)**/ + fat_getFreeClustersInRow(2); // leere cluster suchen, ab cluster 2. + strcpy((char*)file.name,(char*)name); // --- füllen des file struct, zum abschließenden schreiben. + file.firstCluster=fat_secToClust(fat.startSectors); // 1. cluster der datei + file.lastCluster=file.firstCluster;//fat_secToClust(fat.endSectors); // letzter bekannter cluster der datei + file.attrib=32; // --- file.row wird in der funktion fat_getFreeRowOfDir geschrieben !! + file.length=0; // damit da nix drin steht ^^ + fat_makeFileEntry((char *)file.name,file.attrib,0); // DATEI ANLEGEN auf karte + fat.currentSectorNr=fat_clustToSec(file.firstCluster); // setzen des ersten sektors return 2; } #endif @@ -35,122 +45,126 @@ unsigned char ffopen(char name[]){ //******************************************************************************************************************************* -// schließt die datei operation ab. eigentlich nur nötig wenn geschrieben wurde. -// es gibt 2 möglichkeiten : -// 1. die datei wird geschlossen und man war innerhalb der datei größe, dann muss nur der daten sektor geschrieben werden. -// 2. die datei wird geschlossen und es wurde über die alte datei länge hinaus geschrieben. -// der zweite fall ist komplizierter, weil ermittelt werden muss wie viele sektoren neu beschrieben wurden um diese zu verketten -// und die neue datei länge zu ermitteln. abschließend wird entweder (fall 1) nur der daten sektor geschrieben, oder -// der aktuallisierte datei eintrag (von setClusterChain wird ggf der dirty sector puffer geschrieben) +// schließt die datei operation ab. eigentlich nur nötig wenn geschrieben wurde. es gibt 2 möglichkeiten : +// 1. die datei wird geschlossen und es wurde über die alte datei länge hinaus geschrieben. +// 2. die datei wird geschlossen und man war innerhalb der datei größe, dann muss nur der aktuelle sektor geschrieben werden. +// der erste fall ist komplizierter, weil ermittelt werden muss wie viele sektoren neu beschrieben wurden um diese zu verketten +// und die neue datei länge muss ermitt weden. abschließend wird entweder (fall 2) nur der aktuelle sektor geschrieben, oder +// der aktuallisierte datei eintrag und die cluster (diese werden verkettet, siehe fileUpdate() ). //******************************************************************************************************************************* unsigned char ffclose(void){ - #if (write==1) - /** 2 möglichkeiten beim schließen !! (lesend spielt keine rolle) **/ - if( file.length < (file.seek+file.cntOfBytes) ){ /** 1.) es wurde über die alte datei größe hinaus geschrieben **/ - unsigned int comp_cntOfBytes=file.cntOfBytes; // sicher nötig wegen schleife... - while( comp_cntOfBytes < 512 ){ // sektor ist beschrieben worden, daher nötigenfalls mit 00 füllen - fat.sector[comp_cntOfBytes]=0x00; // beschreibt ungenutzte bytes mit 0x00 - comp_cntOfBytes++; - } - - char name[13]; // zum sichern des dateinamens - unsigned long int save_length = file.cntOfBytes + file.seek; // muss gesichert werden, wird sonst von der karte geladen und verändert ! - strcpy(name,(char *)file.name); // muss gesichert werden, wird sonst von der karte geladen und verändert ! - - fat_setClusterChain(fat_secToClust(fat.startSectors),fat.currentSectorNr - fat.startSectors); // verketten der geschriebenen cluster - fat_loadFileDataFromDir(name); // läd sektor, des datei eintrags, und läd daten von karte auf struct file! - fat_makeRowDataEntry(file.row,name,32,file.firstCluster,save_length); // macht eintrag im puffer + #if (WRITE==1) /** 2 möglichkeiten beim schließen !! (lesend spielt keine rolle, nichts muss geupdatet werden) **/ - fat_writeSector(fat.currentSectorNr); // abschließendes schreiben ! - } + if( file.length < (file.seek+file.cntOfBytes) ) fileUpdate(); /** 1.) es wurde über die alte datei größe hinaus geschrieben **/ + + else if( fat.bufferDirty==1) fat_writeSector( fat.currentSectorNr ); /** 2.) nicht über alte datei länge hinaus **/ - else if( fat.bufferDirty==1) fat_writeSector( fat.currentSectorNr ); /** 2.) nicht über alte datei länge hinaus **/ #endif - file.cntOfBytes=0; // init der nötigen zähler + file.cntOfBytes=0; // init werte der nötigen zähler file.seek=0; return(0); } +// ******************************************************************************************************************************* +// updatet datei eintrag auf der karte und verkettet die dazugehörigen fat cluster. +// füllt den aktuell beschriebenen sektor mit 0x00, da sonst die datei nicht richtig angezeigt wird. +// darf nur während schreibe operationen aufgerufen werden ! +// ******************************************************************************************************************************* +void fileUpdate(void){ + + unsigned int comp_cntOfBytes=file.cntOfBytes; // sicher nötig wegen schleife... + while( comp_cntOfBytes < 512 ){ // sektor ist beschrieben worden, daher nötigenfalls mit 00 füllen + fat.sector[comp_cntOfBytes]=0x00; // beschreibt ungenutzte bytes mit 0x00 + comp_cntOfBytes++; + } + char name[13]; // zum sichern des dateinamens + unsigned long int save_length = file.cntOfBytes + file.seek; // muss gesichert werden, wird sonst von der karte geladen und verändert ! + strcpy(name,(char *)file.name); // muss gesichert werden, wird sonst von der karte geladen und verändert ! + + fat_setClusterChain(fat_secToClust(fat.startSectors),fat_secToClust(fat.currentSectorNr)); // verketten der geschriebenen cluster + fat_loadFileDataFromDir(name); // läd sektor, des datei eintrags, und läd daten von karte auf struct file! + fat_makeRowDataEntry(file.row,name,32,file.firstCluster,save_length); // macht eintrag im puffer + + fat_writeSector(fat.currentSectorNr); +} // ******************************************************************************************************************************* -// offset byte wird übergeben. es wird durch die sektoren der datei gespult, bis der sektor mit dem offset byte erreicht ist, -// dann wird der sektor geladen und der zähler für die bytes eines sektors gesetzt. wenn das byte nicht in den sektoren ist, -// die vorgeladen wurden, müssen noch weitere sektoren der datei gesucht werden. +// offset byte wird übergeben. es wird durch die sektoren der datei gespult (gerechnet), bis der sektor mit dem offset byte erreicht +// ist, dann wird der sektor geladen und der zähler für die bytes eines sektors gesetzt. wenn das byte nicht in den sektoren ist, +// die "vorgesucht" wurden, müssen noch weitere sektoren der datei gesucht werden (sec > fat.endSectors). // ******************************************************************************************************************************* -void ffseek(unsigned long int offset){ - - fat_getClustersInRow(file.firstCluster,1); // suchen von anfang der cluster chain aus ! - unsigned long int sec=fat.startSectors; // setzen des 1. sektors der neu gesuchten // sektor variable zum durchgehen durch die sektoren +void ffseek(unsigned long int offset){ + + #if (OVER_WRITE==1) // man muss den dateieintrag updaten, um die daten zu retten !! + if( file.seek > file.length ) fileUpdate(); // fat verketten und datei update auf der karte ! + #endif - do{ /** 3 möglichkeiten ab hier ! **/ - if(offset>=512){ /** 1. offset ist in nächstem sektor **/ - sec++; // da byte nicht in diesem sektor ist, muss hochgezählt werden - offset-=512; // ein sektor weniger in dem das byte sein kann - file.seek+=512; // file.seek update, damit bei ffclose() die richtige file.length herauskommt - } - else break; /** 2. sektor in dem offset ist, ist gefunden ! **/ + fat_getFatChainClustersInRow(file.firstCluster); // suchen von anfang der cluster chain aus ! + unsigned long int sec=fat.startSectors; // sektor variable zum durchgehen durch die sektoren + file.seek=0; // weil auch von anfang an der chain gesucht wird mit 0 initialisiert - if ( sec == fat.endSectors ){ /** 3. es müssen mehr sektoren der datei gesucht werden **/ - fat_getClustersInRow(fat_getNextCluster( file.lastCluster ),1 ); // nachladen von clustern in der chain - sec=fat.startSectors; // setzen des 1. sektors der neu gesuchten - } - - }while(1); - - file.lastCluster=fat_secToClust(sec); // letzter bekannter cluster der datei - fat_loadSector(sec); // sektor mit offset byte laden - file.cntOfBytes = offset % 512; // setzen des lese zählers + while(offset>=512){ /** suchen des sektors in dem offset ist **/ + sec++; // da byte nicht in diesem sektor ist, muss hochgezählt werden + offset-=512; // ein sektor weniger in dem das byte sein kann + file.seek+=512; // file.seek update, damit bei ffclose() die richtige file.length herauskommt + if ( sec > fat.endSectors ){ // es müssen mehr sektoren der datei gesucht werden + fat_getFatChainClustersInRow(fat_getNextCluster( file.lastCluster ) ); // nachladen von clustern in der chain + sec=fat.startSectors; // setzen des 1. sektors der neu geladenen, zum weitersuchen ! + } + } + file.lastCluster=fat_secToClust(fat.endSectors); // letzter bekannter cluster der datei + fat_loadSector(sec); // sektor mit offset byte laden + file.cntOfBytes = offset; // setzen des lese zählers } - #if (smallFileSys==0) +#if (SMALL_FILE_SYSTEM==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(char name[]){ return(fat_cd(name)); } -//******************************************************************************************************************************* +// ******************************************************************************************************************************* // 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); // sektoren des clusters laden for(row=0;row<16;row++){ // geht durch reihen des sektors fat_loadRowOfSector(row); // reihe eines sektors (auf dem puffer) laden - if((file.attrib==0x20||file.attrib==0x10) && (file.name[0]!=0xE5&&file.name[0]!=0x00)){ - printf("%s %li\n",file.name, file.length); + if( (file.attrib==0x20||file.attrib==0x10) && (file.name[0]!=0xE5 && file.name[0]!=0x00) ){ + printf("Name:%s Size:%li\n",file.name,file.length ); } } }while(++sec=0){ // gibt es einen eintrag davor ? - if(fat.sector[(file.row<<5)-21]==0x0f)fat.sector[(file.row<<5)-32]=0xE5; // langer datei eintag auch gelöscht. - } - fat.bufferDirty=1; // eintrag in puffer gemacht. + if(file.attrib!=0x10){ // ist datei. + fat.sector[file.row<<5]=0xE5; // datei gelöscht markieren (file.row*32, damit man auf reihen anfang kommt) + if((file.row-1)>=0){ // gibt es einen eintrag davor ? + if(fat.sector[(file.row<<5)-21]==0x0f)fat.sector[(file.row<<5)-32]=0xE5; // langer datei eintag auch gelöscht. + } + fat.bufferDirty=1; // eintrag in puffer gemacht. if(0==fat_getNextCluster(file.firstCluster)) return(0); // 1.cluster ist leer ?!? 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. max bis zu 16/sektor ! - else{ // ist ordner, rekursiv löschen !! - #ifndef __AVR_ATmega8__ // mega8 zu klein für die funktionalität.... + else{ // ist ordner, dann rekursiv löschen !! + #ifndef __AVR_ATmega8__ // mega8 zu klein für die funktionalität.... unsigned long int parent; unsigned long int own; unsigned long int clustsOfDir; // um durch die cluster chain eines dirs zu gehen. - unsigned long int cntSecOfClust=0; + unsigned char cntSecOfClust=0; unsigned char i=0; - fat.sector[file.row<<5]=0xE5; // löscht dir eintrag - if((file.row-1)>=0){ // gibt es einen eintrag davor (langer datei eintrag)? - if(fat.sector[(file.row<<5)-21]==0x0f)fat.sector[(file.row<<5)-32]=0xE5; // langer datei eintag auch gelöscht - } - fat.bufferDirty=1; // puffer eintrag gemacht + fat.sector[file.row<<5]=0xE5; // löscht dir eintrag + if((file.row-1)>=0){ // gibt es einen eintrag davor (langer datei eintrag)? + if(fat.sector[(file.row<<5)-21]==0x0f)fat.sector[(file.row<<5)-32]=0xE5; // langer datei eintag auch gelöscht + } + fat.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 + + 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 + fat.sector[i<<5]=0xE5; // erster eintrag der reihe als gelöscht markiert + fat.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 ! + fat.sector[i<<5]=0xE5; // eintrag als gelöscht markiert + fat.bufferDirty=1; // puffer eintrag gemacht + } + + if(file.attrib==0x10 && file.name[0]!='.' && file.name[0]!=0xE5 && file.name[0]!=0){ // ordner erkannt ! + fat.sector[i<<5]=0xE5; // dir eintrag als gelöscht markiert + fat.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. - 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 - - 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 - fat.sector[i<<5]=0xE5; // erster eintrag der reihe als gelöscht markiert - fat.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 ! - fat.sector[i<<5]=0xE5; // eintrag als gelöscht markiert - fat.bufferDirty=1; // puffer eintrag gemacht - } - - if(file.attrib==0x10&&file.name[0]!='.'&&file.name[0]!=0xe5&&file.name[0]!=0){ // ordner erkannt ! - fat.sector[i<<5]=0xE5; // dir eintrag als gelöscht markiert - fat.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 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 (auf cluster "ebene")!! - #endif + cntSecOfClust=0; // neuer cluster -> 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 (auf cluster "ebene")!! + #endif } } @@ -338,6 +355,7 @@ unsigned char ffrm(char name[]){ return(1); // fehler, nicht gefunden? } + #endif @@ -347,50 +365,85 @@ unsigned char ffrm(char name[]){ //******************************************************************************************************************************* inline unsigned char ffread(void){ - if(file.cntOfBytes==512){ /** EINEN SEKTOR GLESEN (ab hier 2 möglichkeiten !) **/ + if(file.cntOfBytes==512){ /** EINEN SEKTOR GLESEN (ab hier 2 möglichkeiten !) **/ file.cntOfBytes=0; // byte zähler zurück setzen - if( fat.currentSectorNr == fat.endSectors-1 ){ /** 1.) nötig mehr sektoren der chain zu laden (mit ein bisschen glück nur alle 512*500=256000 bytes)**/ - fat_getClustersInRow(fat_getNextCluster(fat_secToClust( fat.endSectors-1) ),1); // nachladen von clustern in der chain - fat.currentSectorNr=fat.startSectors-1; // setzen des nächsten sektors um weiter lesen zu können.. + if( fat.currentSectorNr == fat.endSectors ){ /** 1.) nötig mehr sektoren der chain zu laden (mit ein bisschen glück nur alle 512*MAX_CLUSTERS_IN_ROW bytes)**/ + fat_getFatChainClustersInRow(fat_getNextCluster(fat_secToClust( fat.endSectors) )); // nachladen von clustern in der chain + fat.currentSectorNr=fat.startSectors-1; // setzen des nächsten sektors um weiter lesen zu können.. } fat_loadSector(fat.currentSectorNr+1); /** 2.) die bekannten in einer reihe reichen noch.(nur alle 512 bytes)**/ } - return fat.sector[file.cntOfBytes++]; // rückgabe, byte des sektors (NACH rückgabe erhöhen von zähler ! ) + return fat.sector[file.cntOfBytes++]; // rückgabe, byte des sektors (NACH rückgabe erhöhen von zähler ! ) } -#if (write==1) +#if (WRITE==1) +#if (OVER_WRITE==0) // nicht überschreibende write funktion + //******************************************************************************************************************************* // schreibt 512 byte blöcke auf den puffer fat.sector. dann wird dieser auf die karte geschrieben. wenn genügend feie -// sektoren zum beschreiben bekannt sind, muss nicht in der fat nachgeschaut werden. sollten nicht genügend zusammenhängende -// sektoren bekannt sein, werden die alten verkettet und neue gesucht (ist nötig sich den letzten bekannten zu merken -> file.lastCluster). -// es wird geprüft ob eine datei überschrieben wird (dann werden keine neuen sektoren verkettet), oder ob man über das -// dateiende hinaus schreibt. wichtige variabeln: fat.startSectors/fat.endSectors, fat.currentSectorNr und file.cntOfBytes +// sektoren zum beschreiben bekannt sind(datenmenge zu groß), muss nicht in der fat nachgeschaut werden. sollten nicht genügend +// zusammenhängende sektoren bekannt sein, werden die alten verkettet und neue gesucht. es ist nötig sich den letzten bekannten +// einer kette zu merken -> file.lastCluster, um auch nicht zusammenhängende cluster verketten zu können (fat_setClusterChain macht das)! //******************************************************************************************************************************* inline void ffwrite(unsigned char c){ fat.sector[file.cntOfBytes++]=c; // schreiben des chars auf den puffer sector und zähler erhöhen (pre-increment) - fat.bufferDirty=1; // puffer dirty weil geschrieben und noch nicht auf karte. + fat.bufferDirty=1; // puffer dirty weil geschrieben und noch nicht auf karte. - if( file.cntOfBytes==512 ){ /** SEKTOR GESCHRIEBEN ( 2 möglichkeiten ab hier !) **/ + if( file.cntOfBytes==512 ){ /** SEKTOR VOLL ( 2 möglichkeiten ab hier !) **/ file.cntOfBytes=0; // rücksetzen des sektor byte zählers - mmc_write_sector(fat.currentSectorNr++,fat.sector); /** 1.) vollen sektor auf karte schreiben und hochzählen von sektoren**/ + mmc_write_sector(fat.currentSectorNr,fat.sector); /** 1.) vollen sektor auf karte schreiben **/ fat.bufferDirty=0; // puffer jetzt clear, weil grade alles geschrieben. - file.seek+=512; // position in der datei erhöhen, weil grade 512 bytes geschrieben - - if( fat.currentSectorNr==fat.endSectors ){ /** 2.) es ist nötig, neue freie zu suchen und die alten zu verketten (mit ein bischen glück nur alle 512*500 bytes) **/ - unsigned char flag=1; - if( file.seek>file.length ){ // außerhalb der datei !! - fat_setClusterChain(fat_secToClust(fat.startSectors),fat.endSectors-fat.startSectors); // verketten der beschriebenen - flag=0; - } - fat_getClustersInRow(file.lastCluster,flag); // suchen der neuen sektoren. - fat.currentSectorNr=fat.startSectors; // setzen des 1. sektors der neuen reihe zum schreiben. - } + file.seek+=512; // position in der datei erhöhen, weil grade 512 bytes geschrieben + if( fat.currentSectorNr==fat.endSectors ){ /** 2.) es ist nötig, neue freie zu suchen und die alten zu verketten (mit ein bischen glück nur alle 512*MAX_CLUSTERS_IN_ROW bytes) **/ + fat_setClusterChain( fat_secToClust(fat.startSectors) , fat_secToClust(fat.endSectors) ); // verketten der beschriebenen + fat_getFreeClustersInRow(file.lastCluster); // suchen von leeren sektoren. + fat.currentSectorNr=fat.startSectors-1; // setzen des 1. sektors der neuen reihe zum schreiben. + } + fat.currentSectorNr++; // nächsten sektor zum beschreiben. } } +#endif + +#if (OVER_WRITE==1) // überschreibende write funktion, nicht performant, weil immer auch noch ein sektor geladen werden muss + +//******************************************************************************************************************************* +// schreibt 512 byte blöcke auf den puffer fat.sector. dann wird dieser auf die karte geschrieben. wenn genügend feie +// sektoren zum beschreiben bekannt sind, muss nicht in der fat nachgeschaut werden. sollten nicht genügend zusammenhängende +// sektoren bekannt sein(datenmenge zu groß), werden die alten verkettet und neue gesucht. es ist nötig sich den letzten bekannten einer +// kette zu merken -> file.lastCluster, um auch nicht zusammenhängende cluster verketten zu können (fat_setClusterChain macht das)! +// es ist beim überschreiben nötig, die schon beschriebenen sektoren der datei zu laden, damit man die richtigen daten +// hat. das ist blöd, weil so ein daten overhead von 50% entsteht. da lesen aber schneller als schreiben geht, verliert man nicht 50% an geschwindigkeit. +//******************************************************************************************************************************* +inline void ffwrite(unsigned char c){ + + fat.sector[file.cntOfBytes++]=c; // schreiben des chars auf den puffer sector und zähler erhöhen (pre-increment) + fat.bufferDirty=1; // puffer dirty weil geschrieben und noch nicht auf karte. + + if( file.cntOfBytes==512 ){ /** SEKTOR VOLL ( 2 möglichkeiten ab hier !) **/ + file.cntOfBytes=0; // rücksetzen des sektor byte zählers. + mmc_write_sector(fat.currentSectorNr,fat.sector); /** 1.) vollen sektor auf karte schreiben**/ + fat.bufferDirty=0; // puffer jetzt clear, weil grade alles geschrieben. + file.seek+=512; // position in der datei erhöhen, weil grade 512 bytes geschrieben. + if( fat.currentSectorNr==fat.endSectors ){ /** 2.) es ist nötig, neue freie zu suchen und die alten zu verketten (mit ein bischen glück nur alle 512*MAX_CLUSTERS_IN_ROW bytes) **/ + if( file.seek > file.length ){ // außerhalb der datei !! + fat_setClusterChain( fat_secToClust(fat.startSectors) , fat_secToClust(fat.endSectors) ); // verketten der beschriebenen. + fat_getFreeClustersInRow( file.lastCluster ); // neue leere sektoren benötigt, also suchen. + } + else { + fat_getFatChainClustersInRow( fat_getNextCluster(file.lastCluster) ); // noch innerhalb der datei, deshlab verkettete suchen. + } + fat.currentSectorNr=fat.startSectors-1; // setzen des 1. sektors der neuen reihe zum schreiben. + } + fat.currentSectorNr++; // nächsten sektor zum beschreiben. + mmc_read_sector(fat.currentSectorNr,fat.sector); // wegen überschreiben, muss der zu beschreibende sektor geladen werden... + } +} + +#endif // ******************************************************************************************************************************* // schreibt string auf karte, siehe ffwrite() @@ -398,6 +451,7 @@ inline void ffwrite(unsigned char c){ inline void ffwrites(const char *s ){ while (*s) ffwrite(*s++); } + #endif diff --git a/avr/usbload/file.h b/avr/usbload/file.h index 749db53..c8388f2 100755 --- a/avr/usbload/file.h +++ b/avr/usbload/file.h @@ -5,25 +5,26 @@ #define _FILE_H - //####################################################################################################################### + // ************************************************************************************************************************** // funktionen extern inline unsigned char ffread(void); // liest byte-weise aus der datei (puffert immer 512 bytes zwischen) - extern inline void ffwrite(unsigned char c); // schreibt ein byte in die geöffnete datei - extern inline void ffwrites(const char *s ); // schreibt string auf karte + extern inline void ffwrite(unsigned char c); // schreibt ein byte in die geöffnete datei + extern inline void ffwrites(const char *s ); // schreibt string auf karte extern unsigned char ffopen(char name[]); // kann immer nur 1 datei bearbeiten. - extern unsigned char ffclose(void); // muss aufgerufen werden bevor neue datei bearbeitet wird. + extern unsigned char ffclose(void); // muss aufgerufen werden bevor neue datei bearbeitet wird. - extern void ffseek(unsigned long int offset); // setzt zeiger:bytesOfSec auf position in der geöffneten datei. - extern unsigned char ffcd(char name[]); // wechselt direktory - extern unsigned char ffls(void); // zeigt direktory inhalt an - extern unsigned char ffcdLower(void); // geht ein direktory zurück, also cd.. (parent direktory) - extern unsigned char ffrm(char name[]); // löscht datei aus aktuellem verzeichniss. - extern unsigned char ffmkdir(char name[]); // legt ordner in aktuellem verzeichniss an. - void lsRowsOfClust (unsigned long int start_sec); // zeigt reihen eines clusters an, ab start_sec + extern void ffseek(unsigned long int offset); // setzt zeiger:bytesOfSec auf position in der geöffneten datei. + extern unsigned char ffcd(char name[]); // wechselt direktory + extern void ffls(void); // zeigt direktory inhalt an + extern unsigned char ffcdLower(void); // geht ein direktory zurück, also cd.. (parent direktory) + extern unsigned char ffrm(char name[]); // löscht datei aus aktuellem verzeichniss. + extern void ffmkdir(char name[]); // legt ordner in aktuellem verzeichniss an. + void lsRowsOfClust (unsigned long int start_sec); // zeigt reihen eines clusters an, ab start_sec + void fileUpdate(void); // updatet datei eintrag auf karte - //####################################################################################################################### + // **************************************************************************************************************************// ####################################################################################################################### diff --git a/avr/usbload/loader.c b/avr/usbload/loader.c index 310419f..1710683 100644 --- a/avr/usbload/loader.c +++ b/avr/usbload/loader.c @@ -1,6 +1,6 @@ /* File: main.smc -Time: Thu, 06 Aug 2009 20:01:38 +Time: Sun, 09 Aug 2009 11:41:19 */ #include #include diff --git a/avr/usbload/mmc.c b/avr/usbload/mmc.c index 4678a25..7ab85ef 100755 --- a/avr/usbload/mmc.c +++ b/avr/usbload/mmc.c @@ -26,16 +26,18 @@ Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. #######################################################################################*/ #include -#include + #include "mmc.h" +#include //############################################################################ //Routine zur Initialisierung der MMC/SD-Karte (SPI-MODE) -unsigned char mmc_init (){ - unsigned int Timeout = 0; +unsigned char mmc_init (void){ + unsigned char a; - unsigned char b; + unsigned int Timeout = 0; + //Konfiguration des Ports an der die MMC/SD-Karte angeschlossen wurde MMC_Direction_REG &=~(1< 200){ + _delay_us(100); + if (Timeout++ > 200){ MMC_Disable(); - printf("fail1\n"); return(1); //Abbruch bei Commando1 (Return Code1) } } @@ -74,7 +80,6 @@ unsigned char mmc_init (){ while( mmc_write_command (CMD) !=0){ if (Timeout++ > 400){ MMC_Disable(); - printf("fail2\n"); return(2); //Abbruch bei Commando2 (Return Code2) } } @@ -92,9 +97,10 @@ unsigned char mmc_init (){ //############################################################################ //Sendet ein Commando an die MMC/SD-Karte unsigned char mmc_write_command (unsigned char *cmd){ + unsigned char a; unsigned char tmp = 0xff; unsigned int Timeout = 0; - unsigned char a; + //set MMC_Chip_Select to high (MMC/SD-Karte Inaktiv) MMC_Disable(); @@ -121,23 +127,17 @@ unsigned char mmc_write_command (unsigned char *cmd){ //############################################################################ //Routine zum Empfangen eines Bytes von der MMC-Karte -unsigned char mmc_read_byte (void){ - - //unsigned char Byte = 0; - +unsigned char mmc_read_byte (void){ SPDR = 0xff; - while(!(SPSR & (1<