diff --git a/avr/usbload/Makefile b/avr/usbload/Makefile index 48fe1b2..5a50dfb 100644 --- a/avr/usbload/Makefile +++ b/avr/usbload/Makefile @@ -33,7 +33,7 @@ ifeq ($(DEBUG),1) OBJECTS = usbdrv/usbdrv.o usbdrv/usbdrvasm.o usbdrv/oddebug.o \ main.o usb_bulk.o uart.o fifo.o sram.o crc.o debug.o \ dump.o timer.o watchdog.o rle.c loader.o info.o shared_memory.o \ - command.o testing.o + command.o mmc.o fat.o file.o testing.o else LDFLAGS = -Wl,-u CFLAGS = -Iusbdrv -I. -DDEBUG_LEVEL=0 -DNO_DEBUG -DNO_INFO diff --git a/avr/usbload/fat.c b/avr/usbload/fat.c new file mode 100755 index 0000000..d7d3308 --- /dev/null +++ b/avr/usbload/fat.c @@ -0,0 +1,664 @@ + +#include +#include + +#include "fat.h" +#include "file.h" +#include "hardware.h" + + struct Fat fat; // wichtige daten/variablen der fat + struct File file; // wichtige dateibezogene daten/variablen + +#if (write==1) +//*************************************************************************************************************** +// schreibt sektor nummer:sec auf die karte (puffer:sector) !! +// setzt bufferFlag=0 da puffer nicht dirty sein kann nach schreiben ! +//*************************************************************************************************************** +unsigned char fat_writeSector(unsigned long int sec){ + + fat.bufferDirty=0; // buffer kann nicht dirty sein weil wird geschrieben + 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) ! +// *************************************************************************************************************** +unsigned long int fat_clustToSec(unsigned long int clust){ + + return (fat.dataDirSec+2+((clust-2) * fat.secPerClust)); // errechnet den 1. sektor der sektoren des clusters +} + +// *************************************************************************************************************** +// umrechnung sektor auf cluster (nicht die position im cluster selber!!) +// *************************************************************************************************************** +unsigned long int fat_secToClust(unsigned long int sec){ + + return ((sec-fat.dataDirSec-2+2*fat.secPerClust)/fat.secPerClust); // umkerhrfunktion von fat_clustToSec +} + + +//*************************************************************************************************************** +// läd sektor:sec auf puffer:sector zum bearbeiten im ram ! +// setzt currentSectorNr auf richtigen wert (also den sektor der gepuffert ist). es wird geprüft +// ob der gepufferte sektor geändert wurde, wenn ja muss erst geschrieben werden, um diese daten nicht zu verlieren ! +//*************************************************************************************************************** +unsigned char fat_loadSector(unsigned long int sec){ + + if(sec!=fat.currentSectorNr){ // nachladen nötig + #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 + fat.currentSectorNr=sec; // aktualisiert sektor nummer (nummer des gepufferten sektors) + return(0); + } + + else return(0); // alles ok, daten sind schon da (sec==fat.currentSectorNr) + + return(1); // fehler +} + + + + + + + +// datei lesen funktionen: + +// fat_loadSector -> 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){ + 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. + + 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]; + + 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 , 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 + if(0==strncmp((char*)file.name,name,10)){ // zeile r ist gesuchte + file.row=r; // zeile sichern. + return(0); + } + r++; + }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). +// 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 char s=0; // sektoren des clusters. + unsigned int i; + 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). + } + } + s++; // sektoren des clusters ++ weil einen geprüft. + }while(s 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). + + unsigned char i=1; + do{ + fat_writeSector(fat.currentSectorNr+i); // löschen des cluster (überschreibt mit 0x00), wichtig bei ffls, + i++; + }while(i>16; // 1. low von cluster + *bytesOfSec++=(cluster&0xff000000)>>24; // high byte + + *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 + + *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 ! +} + + +//*************************************************************************************************************** +// 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(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); + +} + + #endif + + + + + +// 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 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 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) + } + } + + // 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 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; + } + } + + return(0); // neuladen des fat sektors, in dem oneCluster ist nötig !! +} + + +//*************************************************************************************************************** +// 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 !! +//*************************************************************************************************************** +unsigned char fat_getClustersInRow(unsigned long int offsetCluster,unsigned char emptyOrFirst){ + + 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; +} + + + #if (write==1) +//*************************************************************************************************************** +// bekommt cluster übergeben !!! +// verkettet ab newOffsetCluster, cluster in einer reihe bis length (ist nötig zu berechnen ob schon ein neuer cluster angefangen wurde). +// es ist wegen der fragmentierung der fat nötig, sich den letzten bekannten cluster zu merken, +// damit man bei weiteren cluster in einer reihe die alten cluster noch dazu verketten kann (so sind lücken im verketten möglich). +//*************************************************************************************************************** +unsigned char fat_setClusterChain(unsigned long int newOffsetCluster,unsigned int length){ + + if(length==0){ // nur ein bis zu einem sektor geschrieben ? + fat_setCluster(newOffsetCluster,0xfffffff); + return 1; + } + + unsigned int i=0; + unsigned int tmp_length=length/fat.secPerClust; // anzahl der cluster zum verketten + if( 0 != length % fat.secPerClust ) tmp_length+=1; // wenn z.b. ein sektor mehr beschrieben wurde muss ein ganzer cluster mehr verkettet werden + + fat_setCluster(file.lastCluster,newOffsetCluster); // ende der chain setzen + + do{ + fat_setCluster( newOffsetCluster+i , newOffsetCluster+i+1 ); // verketten der cluster der neuen kette + i++; + }while( i < tmp_length ); + + i--; // damit ende cluster richtig gesetzt wird + + fat_setCluster(newOffsetCluster+i,0xfffffff); // ende der chain setzen + file.lastCluster=newOffsetCluster+i; // ende cluster der kette updaten + fat_writeSector(fat.currentSectorNr); + + return 0; +} + + +//*************************************************************************************************************** +// 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 char *bytesOfSec; + + // FAT 16**************FAT 16 + if(fat.fatType==16){ + 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); + } + } + + // 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 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); + } + } + + + 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. +//*************************************************************************************************************** +void fat_delClusterChain(unsigned long int startCluster){ + + unsigned long int 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); +} + +#endif + + +//*************************************************************************************************************** +// 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 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 + + 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.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]; + + 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]; + + 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 + + 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.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); + } + + + 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){ + + 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,fat.sector)){ + + 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]; + + 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); +} + +#if (smallFileSys==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 +// VORSICHT es werden keine Prüfungen gemacht ! +// ***************************************************************************************************************** +char * fat_str(char *str){ + + unsigned char i; + unsigned char j=0; + unsigned char c; + char tmp[12]; // tmp string zum einfacheren umwandeln + + strcpy(tmp,str); + + for(i=0;i<11;i++)str[i]=' '; // als vorbereitung alles mit leerzeichen füllen + str[11]='\0'; + + i=0; + + do{ + c=toupper(tmp[j]); + if(c=='\0')return str; + if(c!='.')str[i]=c; + else i=7; + i++; + j++; + }while(i<12); + + return str; + +} + +#endif + diff --git a/avr/usbload/fat.h b/avr/usbload/fat.h new file mode 100755 index 0000000..93c35e3 --- /dev/null +++ b/avr/usbload/fat.h @@ -0,0 +1,79 @@ + +#ifndef _FAT_H + + #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) !! + + // 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_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 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 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); + + + //####################################################################################################################### + // 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 + 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 endSectors; + 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 + }file; + +#endif + + + + + + diff --git a/avr/usbload/file.c b/avr/usbload/file.c new file mode 100755 index 0000000..bddf53c --- /dev/null +++ b/avr/usbload/file.c @@ -0,0 +1,409 @@ + +#include +#include + +#include "hardware.h" +#include "fat.h" +#include "file.h" + +//******************************************************************************************************************************* +// 2 möglichkeiten beim öffnen, datei existiert oder muss angelegt werden +//******************************************************************************************************************************* +unsigned char ffopen(char name[]){ + + 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 + 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 + return 2; + } + #endif +} + + +//******************************************************************************************************************************* +// 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) +//******************************************************************************************************************************* +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 + + fat_writeSector(fat.currentSectorNr); // abschließendes schreiben ! + } + + 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.seek=0; + return(0); +} + + + +// ******************************************************************************************************************************* +// 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. +// ******************************************************************************************************************************* +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 + + 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 ! **/ + + 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 +} + + + + + #if (smallFileSys==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); + } + } + }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(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.... + 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 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 + + 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 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 + } + + } + + + return(1); // fehler, nicht gefunden? +} +#endif + + +//******************************************************************************************************************************* +// liest 512 bytes aus dem puffer fat.sector. dann werden neue 512 bytes der datei geladen, sind nicht genügend verkettete +// sektoren in einer reihe bekannt, wird in der fat nachgeschaut. dann werden weiter bekannte nachgeladen... +//******************************************************************************************************************************* +inline unsigned char ffread(void){ + + 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.. + } + 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 ! ) +} + + +#if (write==1) +//******************************************************************************************************************************* +// 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 +//******************************************************************************************************************************* +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 GESCHRIEBEN ( 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**/ + 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. + } + } +} + + +// ******************************************************************************************************************************* +// schreibt string auf karte, siehe ffwrite() +// ******************************************************************************************************************************* +inline void ffwrites(const char *s ){ + while (*s) ffwrite(*s++); + } +#endif + + + + + + + + diff --git a/avr/usbload/file.h b/avr/usbload/file.h new file mode 100755 index 0000000..749db53 --- /dev/null +++ b/avr/usbload/file.h @@ -0,0 +1,34 @@ + + + +#ifndef _FILE_H + + #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 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 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 + + //####################################################################################################################### + + + +#endif + + + + diff --git a/avr/usbload/hardware.h b/avr/usbload/hardware.h new file mode 100755 index 0000000..69785d9 --- /dev/null +++ b/avr/usbload/hardware.h @@ -0,0 +1,12 @@ + +#ifndef _HARDWARE_H +/* +hier sind die beiden hardware abhängigen bibliotheken zu includen ! +welchen umfang diese haben müssen (an funktionen), muss man in den bibliotheken nachsehen. +*/ + #define _HARDWARE_H + #include "uart.h" + #include "mmc.h" + +#endif + diff --git a/avr/usbload/main.c b/avr/usbload/main.c index 26fdc60..513bfc6 100644 --- a/avr/usbload/main.c +++ b/avr/usbload/main.c @@ -317,6 +317,7 @@ int main(void) info("Sytem start\n"); system_init(); + test_sdcard(); #if 0 test_read_write(); test_bulk_read_write(); diff --git a/avr/usbload/mmc.c b/avr/usbload/mmc.c new file mode 100755 index 0000000..c5efbad --- /dev/null +++ b/avr/usbload/mmc.c @@ -0,0 +1,249 @@ +/*####################################################################################### +Connect AVR to MMC/SD + +Copyright (C) 2004 Ulrich Radig + +Bei Fragen und Verbesserungen wendet euch per EMail an + +mail@ulrichradig.de + +oder im Forum meiner Web Page : www.ulrichradig.de + +Dieses Programm ist freie Software. Sie k�nnen es unter den Bedingungen der +GNU General Public License, wie von der Free Software Foundation ver�ffentlicht, +weitergeben und/oder modifizieren, entweder gem�� Version 2 der Lizenz oder +(nach Ihrer Option) jeder sp�teren Version. + +Die Ver�ffentlichung dieses Programms erfolgt in der Hoffnung, +da� es Ihnen von Nutzen sein wird, aber OHNE IRGENDEINE GARANTIE, +sogar ohne die implizite Garantie der MARKTREIFE oder der VERWENDBARKEIT +F�R EINEN BESTIMMTEN ZWECK. Details finden Sie in der GNU General Public License. + +Sie sollten eine Kopie der GNU General Public License zusammen mit diesem +Programm erhalten haben. +Falls nicht, schreiben Sie an die Free Software Foundation, +Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. +#######################################################################################*/ + +#include + +#include "mmc.h" + + +//############################################################################ +//Routine zur Initialisierung der MMC/SD-Karte (SPI-MODE) +unsigned char mmc_init (){ + unsigned int Timeout = 0; + unsigned char a; + unsigned char b; + //Konfiguration des Ports an der die MMC/SD-Karte angeschlossen wurde + MMC_Direction_REG &=~(1< 200){ + MMC_Disable(); + return(1); //Abbruch bei Commando1 (Return Code1) + } + } + //Sendet Commando CMD1 an MMC/SD-Karte + Timeout = 0; + CMD[0] = 0x41;//Commando 1 + CMD[5] = 0xFF; + while( mmc_write_command (CMD) !=0){ + if (Timeout++ > 400){ + MMC_Disable(); + return(2); //Abbruch bei Commando2 (Return Code2) + } + } + + //SPI Bus auf max Geschwindigkeit + SPCR &= ~((1< 500){ + break; //Abbruch da die MMC/SD-Karte nicht Antwortet + } + } + return(tmp); +} + +//############################################################################ +//Routine zum Empfangen eines Bytes von der MMC-Karte +unsigned char mmc_read_byte (void){ + + //unsigned char Byte = 0; + + SPDR = 0xff; + while(!(SPSR & (1<>24 ); + cmd[2] = ((addr & 0x00FF0000) >>16 ); + cmd[3] = ((addr & 0x0000FF00) >>8 ); + + //Sendet Commando cmd24 an MMC/SD-Karte (Write 1 Block/512 Bytes) + tmp = mmc_write_command (cmd); + if (tmp != 0) + { + return(tmp); + } + + //Wartet einen Moment und sendet einen Clock an die MMC/SD-Karte + for (a=0;a<100;a++) + { + mmc_read_byte(); + } + + //Sendet Start Byte an MMC/SD-Karte + mmc_write_byte(0xFE); + + //Schreiben des Bolcks (512Bytes) auf MMC/SD-Karte + for (i=0;i<512;i++) + { + mmc_write_byte(*Buffer++); + } + + //CRC-Byte schreiben + mmc_write_byte(0xFF); //Schreibt Dummy CRC + mmc_write_byte(0xFF); //CRC Code wird nicht benutzt + + //Fehler beim schreiben? (Data Response XXX00101 = OK) + if((mmc_read_byte()&0x1F) != 0x05) return(1); + + //Wartet auf MMC/SD-Karte Bussy + while (mmc_read_byte() != 0xff){}; + + //set MMC_Chip_Select to high (MMC/SD-Karte Inaktiv) + MMC_Disable(); + +return(0); +} + +//############################################################################ +//Routine zum lesen des CID Registers von der MMC/SD-Karte (16Bytes) +void mmc_read_block(unsigned char *cmd,unsigned char *Buffer,unsigned int Bytes){ + //Sendet Commando cmd an MMC/SD-Karte + unsigned int a; + if (mmc_write_command (cmd) != 0) + { + return; + } + + //Wartet auf Start Byte von der MMC/SD-Karte (FEh/Start Byte) + + while (mmc_read_byte() != 0xfe){}; + + //Lesen des Bolcks (normal 512Bytes) von MMC/SD-Karte + for (a=0;a>24 ); + cmd[2] = ((addr & 0x00FF0000) >>16 ); + cmd[3] = ((addr & 0x0000FF00) >>8 ); + + mmc_read_block(cmd,Buffer,512); + + return(0); +} + + diff --git a/avr/usbload/mmc.h b/avr/usbload/mmc.h new file mode 100755 index 0000000..833f036 --- /dev/null +++ b/avr/usbload/mmc.h @@ -0,0 +1,36 @@ +/*####################################################################################### +Connect ARM to MMC/SD + +Copyright (C) 2004 Ulrich Radig +#######################################################################################*/ + + +#ifndef _MMC_H + #define _MMC_H + + #define MMC_Write PORTB //Port an der die MMC/SD-Karte angeschlossen ist also des SPI + #define MMC_Read PINB + #define MMC_Direction_REG DDRB + + + #define SPI_DI 6 //Port Pin an dem Data Output der MMC/SD-Karte angeschlossen ist + #define SPI_DO 5 //Port Pin an dem Data Input der MMC/SD-Karte angeschlossen ist + #define SPI_Clock 7 //Port Pin an dem die Clock der MMC/SD-Karte angeschlossen ist (clk) + #define MMC_Chip_Select 4 //Port Pin an dem Chip Select der MMC/SD-Karte angeschlossen ist + #define SPI_SS 4 //Nicht Benutz mu� aber definiert werden + + + extern unsigned char mmc_read_byte(void); + extern void mmc_write_byte(unsigned char); + extern void mmc_read_block(unsigned char *,unsigned char *,unsigned in); + extern unsigned char mmc_init(void); + extern unsigned char mmc_read_sector (unsigned long,unsigned char *); + extern unsigned char mmc_write_sector (unsigned long,unsigned char *); + extern unsigned char mmc_write_command (unsigned char *); + + #define MMC_Disable() MMC_Write|= (1< +#include #include #include @@ -32,6 +33,14 @@ #include "crc.h" #include "info.h" +#include "mmc.h" +#include "fat.h" +#include "file.h" + + + + + void test_read_write() { @@ -104,3 +113,55 @@ void test_crc() test_non_zero_memory(0x000000, 0x10000); } + +void test_sdcard(void){ + + + while (mmc_init() !=0){ //ist der Rückgabewert ungleich NULL ist ein Fehler aufgetreten + printf("no sdcard\n"); + } + + + if (fat_initfat()){ + printf("fatinit ok\n"); + } else { + printf("fatinit failed\n"); + return; + } + + char datei[12]="test.txt"; // hier muss platz für 11 zeichen sein (8.3), da fat_str diesen string benutzt !! + fat_str(datei); // wandelt "test.txt" in das fat format 8.3 der form: "TEST TXT" muss immer dieses Format haben, auch ordner !! + + // 0.) ______________löschen von dateien/ordnern (ordner rekursiv)____________________________________________ + ffrm( datei ); // löschen der datei/ordner falls vorhanden + + // 1.) ______________anlegen und schreiben____________________________________________________________________ + /* öffnet datei, wenn nicht vorhanden, legt ffopen datei an (rückgabewert = 1 datei existiert, also nur öffnen, 2 = angelegt). */ + ffopen( datei ); + + /* schreibt string */ + ffwrites((char*)"Hallo Datei :)"); + // neue zeile in der datei + ffwrite(0x0D); + ffwrite(0x0A); + + /* schließt datei */ + ffclose(); + + // 2.)________________ändern von vorhandenen daten in dateien__________________________________________________ + ffopen( datei ); // siehe oben... + ffseek(12); // spult in datei auf position 12 vor (fängt immer bei 0 an zu zählen !) + ffwrite(';'); // schreibt dann ab position 12 (überschreibt daten der datei, hier nur 1 zeichen) + ffclose(); // schließt datei + + // 3.)________________lesen von dateien_________________________________________________________________________ + ffopen( datei ); // siehe oben... + unsigned long int seek=file.length; // eine variable setzen und runterzählen bis 0 geht am schnellsten ! + do{ + printf(ffread()); // liest ein zeichen und gibt es über uart aus ! + }while(--seek); // liest solange bytes da sind (von datei länge bis 0) + ffclose(); // schließt datei + + +} + diff --git a/avr/usbload/testing.h b/avr/usbload/testing.h index e4c85b2..bca60a3 100644 --- a/avr/usbload/testing.h +++ b/avr/usbload/testing.h @@ -27,5 +27,6 @@ void test_read_write(); void test_bulk_read_write(); void test_non_zero_memory(uint32_t bottom_addr, uint32_t top_addr); void test_crc(); +void test_sdcard(); #endif