add mmc layer
This commit is contained in:
parent
dbff180a91
commit
2132b572ff
@ -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
664
avr/usbload/fat.c
Executable 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
79
avr/usbload/fat.h
Executable 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
409
avr/usbload/file.c
Executable 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
34
avr/usbload/file.h
Executable 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
12
avr/usbload/hardware.h
Executable 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
|
||||
|
||||
@ -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
249
avr/usbload/mmc.c
Executable 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
36
avr/usbload/mmc.h
Executable 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
|
||||
@ -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();
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user