add mmc layer

This commit is contained in:
David Voswinkel 2009-08-08 16:43:51 +02:00
parent dbff180a91
commit 2132b572ff
12 changed files with 1548 additions and 2 deletions

View File

@ -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

664
avr/usbload/fat.c Executable file
View File

@ -0,0 +1,664 @@
#include <ctype.h>
#include <string.h>
#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.secPerClust); // geht durch sektoren des clusters
return (1); // fehler (datei nicht gefunden, oder fehler beim lesen)
}
//***************************************************************************************************************
// wenn dir == 0 dann wird das root direktory durchsucht, wenn nicht wird der ordner cluster-chain gefolgt, um
// die datei zu finden. es wird das komplette directory in dem man sich befindet durchsucht.
// bei fat16 wird der rootDir berreich durchsucht, bei fat32 die cluster chain des rootDir.
//***************************************************************************************************************
unsigned char fat_loadFileDataFromDir(char name[]){
unsigned int s;
if(fat.dir==0 && fat.fatType==16){ // IM ROOTDIR. 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_loadFileDataFromCluster(fat.rootDir+s,name))return(0); // sucht die datei, wenn da, läd daten (1.cluster usw)
}
}
else {
unsigned long int i;
if(fat.dir==0 && fat.fatType==32)i=fat.rootDir; // IM ROOTDIR. fat32
else i=fat.dir; // NICHT ROOTDIR
while(!((i==0xfffffff&&fat.fatType==32)||(i==0xffff&&fat.fatType==16))){ // prüft ob weitere sektoren zum lesen da sind (fat32||fat16)
if(0==fat_loadFileDataFromCluster(fat_clustToSec(i),name))return(0); // lät die daten der datei auf struct:file. datei gefunden (umrechnung auf absoluten sektor)
i=fat_getNextCluster(i); // liest nächsten cluster des dir-eintrags (unterverzeichniss größer 16 einträge)
}
}
return(1); // datei/verzeichniss nicht gefunden
}
#if (smallFileSys==0)
//***************************************************************************************************************
// start immer im root Dir. start in root dir (dir==0).
// es MUSS in das direktory gewechselt werden, in dem die datei zum lesen/anhängen ist (außer root, da startet mann)!
//***************************************************************************************************************
unsigned char fat_cd(char name[]){
if(name[0]==0){ // ZUM ROOTDIR FAT16/32
fat.dir=0; // root dir
return(0);
}
if(0==fat_loadFileDataFromDir(name)){ // NICHT ROOTDIR (fat16/32)
fat.dir=file.firstCluster; // zeigt auf 1.cluster des dir (fat16/32)
return(0);
}
return(1); // dir nicht gewechselt (nicht da?) !!
}
#endif
#if (write==1)
// datei anlegen funktionen :
//fat_getFreeRowOfCluster -> 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<fat.secPerClust); // geht die sektoren des clusters durch (möglicherweise auch nur 1. sektor).
return (1); // nicht gefunden in diesem cluster (== nicht OK!).
}
// ***************************************************************************************************************
// sucht leeren eintrag (zeile) im directory mit dem startcluster:dir.
// geht die cluster chain des direktories durch. dabei werden auch alle sektoren der cluster geprüft.
// wird dort kein freier eintrag gefunden, wird ein neuer leerer cluster gesucht, verkettet und der
// 1. sektor des freien clusters geladen. die reihe wird auf den ersten eintrag gesetzt, da frei.
// anhand der reihe kann man nun den direktory eintrag vornehmen, und auf die karte schreiben.
// ****************************************************************************************************************
unsigned char fat_getFreeRowOfDir(unsigned long int dir){
unsigned long int start=dir;
// solange bis ende cluster chain.
while( !((dir==0xfffffff&&fat.fatType==32)||(dir==0xffff&&fat.fatType==16)) ){
if(0==fat_getFreeRowOfCluster(fat_clustToSec(dir)))return(0); // freien eintrag in clustern, des dir gefunden !!
start=dir;
dir=fat_getNextCluster(dir);
} // 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).
unsigned char i=1;
do{
fat_writeSector(fat.currentSectorNr+i); // löschen des cluster (überschreibt mit 0x00), wichtig bei ffls,
i++;
}while(i<fat.secPerClust);
file.row=0; // erste reihe frei, weil grad neuen cluster verkettet.
return(0); // keinen freien platz in clustern, des dir gefunden, aber neuen cluster verkettet.
}
//***************************************************************************************************************
// erstellt 32 byte eintrag einer datei, oder verzeichnisses im puffer:sector.
// erstellt eintrag in reihe:row, mit namen:name usw... !!
// muss noch auf die karte geschrieben werden ! nicht optimiert auf geschwindigkeit.
//***************************************************************************************************************
unsigned char fat_makeRowDataEntry(unsigned int row,char name[],unsigned char attrib,unsigned long int cluster,unsigned long int length){
fat.bufferDirty=1; // puffer beschrieben, also neue daten darin(vor lesen muss geschrieben werden)
row=row<<5; // multipliziert mit 32 um immer auf zeilen anfang zu kommen (zeile 0=0,zeile 1=32,zeile 2=62 ... zeile 15=480)
unsigned char i; // byte zähler in reihe von sektor (32byte eintrag)
unsigned char *bytesOfSec=&fat.sector[row]; // zeiger auf sector bytes
void *vLength=&length; // zeiger auf länge (übergebener 4 byte parameter)
for(i=0;i<11;i++) *bytesOfSec++=name[i];// namen schreiben
*bytesOfSec++=attrib; // attrib schreiben
for(i=12;i<20;i++)*bytesOfSec++=0x01; // nicht nötige felder beschreiben
*bytesOfSec++=(cluster&0x00ff0000)>>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

79
avr/usbload/fat.h Executable file
View File

@ -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

409
avr/usbload/file.c Executable file
View File

@ -0,0 +1,409 @@
#include <string.h>
#include <stdlib.h>
#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<fat.secPerClust);
}
//*******************************************************************************************************************************
// zeigt inhalt eines direktory an.
// unterscheidung ob man sich im rootDir befindet nötig, weil bei fat16 im root dir eine bestimmt anzahl sektoren durchsucht
// werden müssen und bei fat32 ab einem start cluster ! ruft lsRowsOfClust auf um cluster/sektoren anzuzeigen.
//*******************************************************************************************************************************
unsigned char ffls(void){
unsigned long int clust; // cluster
unsigned int s; // fat16 root dir sektoren
if(fat.dir==0 && fat.fatType==16){ // IM ROOTDIR. fat16
for(s=0;s<(unsigned int)(fat.dataDirSec+2-fat.rootDir);s++){ // zählt durch RootDir sektoren (errechnet anzahl rootDir sektoren).
lsRowsOfClust(fat.rootDir+s); // zeigt reihen eines root dir clust an
}
}
else {
if(fat.dir==0 && fat.fatType==32)clust=fat.rootDir; // IM ROOTDIR. fat32
else clust=fat.dir; // NICHT ROOT DIR
while( !((clust==0xfffffff&&fat.fatType==32)||(clust==0xffff&&fat.fatType==16)) ){ // prüft ob weitere sektoren zum lesen da sind (fat32||fat16)
lsRowsOfClust(fat_clustToSec(clust)); // zeigt reihen des clusters an
clust=fat_getNextCluster(clust); // liest nächsten cluster des dir-eintrags
}
}
return(0);
}
//*******************************************************************************************************************************
// wechselt in das parent verzeichniss (ein verzeichniss zurück !)
// die variable fat.dir enthält den start cluster des direktory in dem man sich grade befindet, anhand diesem,
// kann der "." bzw ".." eintrag im ersten sektor des direktory ausgelesen und das parent direktory bestimmt werden.
//*******************************************************************************************************************************
unsigned char ffcdLower(void){
if(fat.dir==0)return(1); // im root dir, man kann nicht höher !
fat_loadSector(fat_clustToSec(fat.dir)); // läd 1. sektor des aktuellen direktory.
fat_loadRowOfSector(1); // ".." eintrag (parent dir) ist 0 wenn parent == root
fat.dir=file.firstCluster; // dir setzen
return(0);
}
// *******************************************************************************************************************************
// erstellt einen dir eintrag im aktuellen verzeichniss (geht nur wenn keine lese/schreib usw. vorgänge).
// prüft ob es den den dir-namen:name schon gibt, dann wird nichts angelegt.
// wenn ok, dann wird ein freier cluster gesucht, als ende markiert, der eintrag ins dir geschrieben.
// dann wird der cluster des dirs aufbereitet. der erste sektor des clusters enthält den "." und ".." eintrag.
// der "." hat den 1. cluster des eigenen dirs. der ".." eintrag ist der 1. cluster des parent dirs.
// ein dir wird immer mit 0x00 initialisiert ! also alle sektoren des clsters ( bis auf . und .. einträge)!
// *******************************************************************************************************************************
unsigned char ffmkdir(char name[]){
#ifndef __AVR_ATmega8__
unsigned char i;
if(0==fat_loadFileDataFromDir(name))return (1); // prüft ob dirname im dir schon vorhanden, wenn ja, abbruch !
fat_getClustersInRow(2,0); // holt neue freie cluster, ab cluster 2 ...
fat_setCluster(fat_secToClust(fat.startSectors),0x0fffffff); // fat16/32 cluster chain ende setzen. (neuer ordner in fat)
fat_makeFileEntry(name,0x10,fat_secToClust(fat.startSectors),0); // macht dir eintrag im aktuellen verzeichniss (legt ordner im partent verzeichniss an)
// aufbereiten des neuen dir clusters !
fat_markSector00(); // löschen des sektors (nur im puffer)./**/
// fat_makeRowDataEntry(0,(char *)str_p(PSTR(". ")),0x10,fat_secToClust(fat.currentSectorNr),0); // macht "." eintrag des dirs
// fat_makeRowDataEntry(1,(char *)str_p(PSTR(".. ")),0x10,fat.dir,0); // macht ".." eintrag des dirs
fat_makeRowDataEntry(0,". ",0x10,fat_secToClust(fat.currentSectorNr),0); // macht "." eintrag des dirs
fat_makeRowDataEntry(1,".. ",0x10,fat.dir,0); // macht ".." eintrag des dirs
fat_writeSector(fat_clustToSec(fat.startSectors)); // schreibt einträge auf karte !
fat_markSector00(); // löschen des sektors (nur im puffer).
for(i=1;i<fat.secPerClust;i++){ // ein dir cluster muss mit 0x00 initialisiert werden !
fat_writeSector(fat.startSectors+i); // löschen des cluster (überschreibt mit 0x00), wichtig bei ffls!
}
#endif
return(0);
}
#endif
#if (write==1)
//*******************************************************************************************************************************
// löscht datei aus aktuellem verzeichniss, wenn es die datei gibt.
// löscht dateien und ordner rekursiv !
//*******************************************************************************************************************************
unsigned char ffrm(char name[]){
if(0==fat_loadFileDataFromDir(name)){ // datei/ordner gibt es
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....
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<fat.secPerClust); // geht durch sektoren des clusters.
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
}
}
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

34
avr/usbload/file.h Executable file
View File

@ -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

12
avr/usbload/hardware.h Executable file
View File

@ -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

View File

@ -317,6 +317,7 @@ int main(void)
info("Sytem start\n");
system_init();
test_sdcard();
#if 0
test_read_write();
test_bulk_read_write();

249
avr/usbload/mmc.c Executable file
View File

@ -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<EFBFBD>nnen es unter den Bedingungen der
GNU General Public License, wie von der Free Software Foundation ver<EFBFBD>ffentlicht,
weitergeben und/oder modifizieren, entweder gem<EFBFBD><EFBFBD> Version 2 der Lizenz oder
(nach Ihrer Option) jeder sp<EFBFBD>teren Version.
Die Ver<EFBFBD>ffentlichung dieses Programms erfolgt in der Hoffnung,
da<EFBFBD> es Ihnen von Nutzen sein wird, aber OHNE IRGENDEINE GARANTIE,
sogar ohne die implizite Garantie der MARKTREIFE oder der VERWENDBARKEIT
F<EFBFBD>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 <avr/io.h>
#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<<SPI_DI); //Setzen von Pin MMC_DI auf Input
MMC_Direction_REG |= (1<<SPI_Clock); //Setzen von Pin MMC_Clock auf Output
MMC_Direction_REG |= (1<<SPI_DO); //Setzen von Pin MMC_DO auf Output
MMC_Direction_REG |= (1<<MMC_Chip_Select);//Setzen von Pin MMC_Chip_Select auf Output
MMC_Direction_REG |= (1<<SPI_SS);
MMC_Write |= (1<<MMC_Chip_Select); //Setzt den Pin MMC_Chip_Select auf High Pegel
for(a=0;a<200;a++){
nop();
}; //Wartet eine kurze Zeit
//Aktiviren des SPI - Bus, Clock = Idel LOW
//SPI Clock teilen durch 128
SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0)|(1<<SPR1); //Enable SPI, SPI in Master Mode
//SPSR = (0<<SPI2X);
//Initialisiere MMC/SD-Karte in den SPI-Mode
for (b = 0;b<0x0f;b++){ //Sendet min 74+ Clocks an die MMC/SD-Karte
mmc_write_byte(0xff);
}
//Sendet Commando CMD0 an MMC/SD-Karte
unsigned char CMD[] = {0x40,0x00,0x00,0x00,0x00,0x95};
while(mmc_write_command (CMD) !=1){
if (Timeout++ > 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<<SPR0) | (1<<SPR1));
SPSR = SPSR|(1<<SPI2X);
//set MMC_Chip_Select to high (MMC/SD-Karte Inaktiv)
MMC_Disable();
return(0);
}
//############################################################################
//Sendet ein Commando an die MMC/SD-Karte
unsigned char mmc_write_command (unsigned char *cmd){
unsigned char tmp = 0xff;
unsigned int Timeout = 0;
unsigned char a;
//set MMC_Chip_Select to high (MMC/SD-Karte Inaktiv)
MMC_Disable();
//sendet 8 Clock Impulse
mmc_write_byte(0xFF);
//set MMC_Chip_Select to low (MMC/SD-Karte Aktiv)
MMC_Enable();
//sendet 6 Byte Commando
for (a = 0;a<0x06;a++){
mmc_write_byte(*cmd++);
}
//Wartet auf ein gültige Antwort von der MMC/SD-Karte
while (tmp == 0xff){
tmp = mmc_read_byte();
if (Timeout++ > 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<<SPIF))){};
//Byte = SPDR;
return (SPDR);
}
//############################################################################
//Routine zum Senden eines Bytes zur MMC-Karte
void mmc_write_byte (unsigned char Byte){
SPDR = Byte; //Sendet ein Byte
while(!(SPSR & (1<<SPIF))){ //Wartet bis Byte gesendet wurde
}
}
//############################################################################
//Routine zum schreiben eines Blocks(512Byte) auf die MMC/SD-Karte
unsigned char mmc_write_sector (unsigned long addr,unsigned char *Buffer){
unsigned char tmp;
//Commando 24 zum schreiben eines Blocks auf die MMC/SD - Karte
unsigned char cmd[] = {0x58,0x00,0x00,0x00,0x00,0xFF};
unsigned char a;
unsigned int i;
/*Die Adressierung der MMC/SD-Karte wird in Bytes angegeben,
addr wird von Blocks zu Bytes umgerechnet danach werden
diese in das Commando eingef<EFBFBD>gt*/
addr = addr << 9; //addr = addr * 512
cmd[1] = ((addr & 0xFF000000) >>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<Bytes;a++)
{
*Buffer++ = mmc_read_byte();
}
//CRC-Byte auslesen
mmc_read_byte();//CRC - Byte wird nicht ausgewertet
mmc_read_byte();//CRC - Byte wird nicht ausgewertet
//set MMC_Chip_Select to high (MMC/SD-Karte Inaktiv)
MMC_Disable();
return;
}
//############################################################################
//Routine zum lesen eines Blocks(512Byte) von der MMC/SD-Karte
unsigned char mmc_read_sector (unsigned long addr,unsigned char *Buffer){
//Commando 16 zum lesen eines Blocks von der MMC/SD - Karte
unsigned char cmd[] = {0x51,0x00,0x00,0x00,0x00,0xFF};
/*Die Adressierung der MMC/SD-Karte wird in Bytes angegeben,
addr wird von Blocks zu Bytes umgerechnet danach werden
diese in das Commando eingef<EFBFBD>gt*/
addr = addr << 9; //addr = addr * 512
cmd[1] = ((addr & 0xFF000000) >>24 );
cmd[2] = ((addr & 0x00FF0000) >>16 );
cmd[3] = ((addr & 0x0000FF00) >>8 );
mmc_read_block(cmd,Buffer,512);
return(0);
}

36
avr/usbload/mmc.h Executable file
View File

@ -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<6D> 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<<MMC_Chip_Select);
#define MMC_Enable() MMC_Write&=~(1<<MMC_Chip_Select);
#define nop() __asm__ __volatile__ ("nop" ::)
#endif

View File

@ -103,7 +103,7 @@ void shared_memory_write(uint8_t cmd, uint8_t value)
shared_memory_scratchpad_tx_restore();
shared_memory_irq_restore();
//sram_bulk_addr_restore();
sram_bulk_addr_restore();
}

View File

@ -22,6 +22,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <util/delay.h>
@ -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
}

View File

@ -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