?? fat16.c
字號:
//還原Sectorbuffer的數據
memcpy(SectorBuffer,ClusterBuffer[page],BytesPerSector);//保持Sectorbuffer作為cache內容保持不變!!
//Erase_Cluster(block);
SD_EraseBlock_00(block);//寫入之前,擦除當前簇;
for(i=0;i<SectorsPerCluster;i++)//一扇區接一扇區寫入
{
for(j=0;j<255;j++);//延時
//WritePage(block,i,ClusterBuffer[i]);
SD_WriteBlock1(block,i,ClusterBuffer[i]);
}
//沒有檢驗
}
// 扇區與簇的對應關系:
// 扇區 簇
// 512 2
// 520 3
// 528 4
// 536 5
// .............
WORD SectorNum2ClusterNum(DWORD SectorNum) //扇區數 換算成 簇數
{
return (WORD)((SectorNum - FirstDataSector) / SectorsPerCluster + 2);//NOTE:NO MBR!!!
}
DWORD ClusterNum2SectorNum(WORD ClusterNum) //簇數 換算成 扇區數
{
return FirstDataSector + (ClusterNum - 2) * SectorsPerCluster;//NOTE:NO MBR!!!
}
// return the first sector number of dir content .
// 0xffffffff indicate failed.//從目錄區中取得一個目錄項
int AllocDir(DWORD ParentDirSectorNum, DIRENTRY* new_dir, _FILE * fp)
{
BYTE* Cache;
DIRENTRY *dir;
DWORD i;
WORD PrevCluster;
WORD Cluster;
DWORD DirSectorNum = ParentDirSectorNum;
//if(dirname == NULL)// *Cache
//return 1;
if(ParentDirSectorNum == FirstDirSector)//在根目錄區
{
for(i=0; i<RootDirCount * sizeof(DIRENTRY) / BytesPerSector; i++)
{
Cache = GetSectorData(DirSectorNum);
if(Cache == NULL)
return 2;
for(dir = (DIRENTRY *)Cache; (BYTE*)dir < Cache + BytesPerSector; dir++)
{
if(dir->deName[0] == '\0' || dir->deName[0] == 0xe5)
{
memcpy((BYTE *)dir, (BYTE *)new_dir, sizeof(DIRENTRY)); //將新的目錄信息寫入
Flush();//更新disk中該扇區,將該根目錄區內容重寫,只改變了一個目錄信息,其他不變
if(fp)//更新文件信息
{
fp->DirSectorNum = DirSectorNum;//當前目錄項所在的扇區地址
fp->DirIndex = ((BYTE*)dir - Cache) / sizeof(DIRENTRY);//計算目錄索引,即該扇區中第x個目錄項
memcpy((BYTE *)(&fp->dir), (BYTE *)new_dir, sizeof(DIRENTRY));//新的目錄信息寫到文件結構中
}
return 0;//操作成功,退出
}
}
DirSectorNum++;//下一個根目錄扇區
}
// root dir have no room.
return 3;
}
else//不在根目錄區
{
Cluster = SectorNum2ClusterNum(DirSectorNum);//
while(Cluster != 0xffff)
{
for(i=0; i< SectorsPerCluster; i++)//在整個簇中搜索
{
Cache = GetSectorData(DirSectorNum);
if(Cache == NULL)
return 2;
for(dir = (DIRENTRY *)Cache; (BYTE*)dir < Cache + BytesPerSector; dir++)
{
if(dir->deName[0] == '\0' || dir->deName[0] == 0xe5)
{
memcpy((BYTE *)dir, (BYTE *)new_dir, sizeof(DIRENTRY));
Flush();
if(fp)
{
fp->DirSectorNum = DirSectorNum;
fp->DirIndex = ((BYTE*)dir - Cache) / sizeof(DIRENTRY);//計算目錄索引,即該扇區中第x個目錄項
memcpy((BYTE *)(&fp->dir),(BYTE *)new_dir, sizeof(DIRENTRY));
}
return 0;
}
}
DirSectorNum++;//下一個扇區
}
//搜索完當前簇,沒有空的目錄項
PrevCluster = Cluster;//從FAT表中找出下一簇
Cluster = GetNextClusterNum(Cluster);
DirSectorNum = ClusterNum2SectorNum(Cluster);//刷新目錄扇區
}
//且這已經是最后一個簇
//
// we have to extend this parent dir room.
//
Cluster = AllocCluster(PrevCluster);//利用FAT表獲得一個空簇
if(Cluster == 0xffff)//沒有空簇
return 4;
DirSectorNum = ClusterNum2SectorNum(Cluster);//空簇做新的目錄扇區地址
Cache = GetSectorData(DirSectorNum);
if(Cache == NULL)
return 2;
dir = (DIRENTRY *)Cache;
memcpy((BYTE *)dir, (BYTE *)new_dir, sizeof(DIRENTRY));
Flush();
if(fp)
{
fp->DirSectorNum = DirSectorNum;
fp->DirIndex = ((BYTE*)dir - Cache) / sizeof(DIRENTRY);
memcpy((BYTE *)(&fp->dir), (BYTE *)new_dir, sizeof(DIRENTRY));
}
return 0;
}
return 5;
}
int DeleteDir(_FILE *file)
{
BYTE* Cache;
DIRENTRY *dir;
Cache = GetSectorData(file->DirSectorNum);//文件在目錄區的扇區地址
if(Cache == NULL)
return 1;
dir = (DIRENTRY *)Cache;
dir += file->DirIndex;//目錄的索引號
dir->deName[0] = 0xe5;//做刪除標記
Flush();
return 0;
}
// helper functions
// NULL indicate failed.
// Valid format is full path: \[8.3\]*DIR_Name檢驗文件路徑字符串是否合法
// limits:
// length < 80 && !(special char)
char* get_valid_format(const char *fullpath)
{
static char static_path[512];
char* p=static_path;
char path[80];
char* ppath = path;
int dir_len_count; //count dir len.
int i;
if(fullpath == NULL || strlen(fullpath) >=80 || *fullpath != '\\')//第一個字符不是‘\’
return NULL;
if(strlen(fullpath) > 1 && fullpath[strlen(fullpath)-1] =='\\')//最后一個字符是‘\’
return NULL;
strcpy(path, fullpath);
//strupr(path);
memset(p, 0, 512); //將P指向的512字節清為0,內存空間初始化
for(;;)
{
switch(*ppath)
{
case 0x00://結束符
{
if(dir_len_count != 0) // prev is not '\\'
{
for(i=0; i<(11 - dir_len_count); i++)//未滿11字節,用blank填滿
{
*p = 0x20;
p++;
}
}
}
return static_path;//返回整個字符串
case '\\':
{
if(p != static_path) // this is not the first '\\'
{
if(dir_len_count == 0)// more than one '\\'
return NULL;
for(i=0; i<(11 - dir_len_count); i++)
{
*p = 0x20;
p++;
}
}
*p = '\\';
p++;
ppath++;
dir_len_count =0;
continue;
}
break;
case '.':
{
if(dir_len_count > 8 || dir_len_count ==0) // '\\.' check
return NULL;
if(ppath[1] == '.' || ppath[1] == '\\') // more than one '.' or '.\\' check
return NULL;
for(i=0; i<(8 - dir_len_count); i++)
{
*p = 0x20;
p++;
}
dir_len_count =8;
ppath++;
continue;
}
break;
case 0x22://非法字符
case 0x2A:
case 0x2B:
case 0x2C:
case 0x2F:
case 0x3A:
case 0x3B:
case 0x3C:
case 0x3D:
case 0x3E:
case 0x3F:
case 0x5B:
case 0x5D:
case 0x7C:
return NULL;
default:
{
if(*ppath < 0x20)
return NULL;
}
break;
}
*p = *ppath;
dir_len_count ++;
if(dir_len_count > 11)
return NULL;
p++;
ppath++;
}
return static_path;
}
//11個字符,其中8個字符為文件名,3個字符為文件后綴
void unformat_name(char * filename, const unsigned char dirname[11])
{
int i;
int j;
memset(filename, 0, 13);
for(i=0; i<8; i++)
{
if(dirname[i] != 0x20)
filename[i] = dirname[i];
else
break;
}
if(dirname[8] != 0x20)
{
filename[i] = '.';
j = i + 1;
for(i=8; i<11; i++,j++)
{
if(dirname[i] != 0x20)
filename[j] = dirname[i];
else
break;
}
}
}
//在所給的sector內尋找與dirname名稱相同的項目
DWORD SectorSearch(DWORD Sector, const char dirname[11], _FILE *file)
{
BYTE* Cache;
DIRENTRY *dir;
unsigned int j;
Cache = GetSectorData(Sector);//取得一個扇區的數據,
if(Cache == NULL) //返回的是指向數據存放數組SectorBuffer的指針
return 0xffffffff;
dir = (DIRENTRY *)Cache;
for(j=0; (dir->deName[0] != '\0') && (j< BytesPerSector / sizeof(DIRENTRY)); j++)//不是空的目錄項,在整個扇區搜索
{
if(memcmp((const char*)dir->deName, dirname, 11) == 0 && (!(dir->deAttributes & ATTR_VOLUME)))// not volumn id or long name entry.
//如果目錄名/文件名相同,且不是卷標項目
{
if(file != NULL)
{
memset((BYTE *)file, 0, sizeof(_FILE));
file->DirSectorNum = Sector;
file->DirIndex = j;
memcpy((BYTE *)(&file->dir), (BYTE *)dir, sizeof(DIRENTRY));
}
return ClusterNum2SectorNum(dir->deStartCluster);//返回該目錄/文件的起始簇號
}
dir++;
}
return 0xffffffff;
}
int FlieList(const char *File_Extension)
{
BYTE* Cache;
DIRENTRY *dir;
char deName[9]={0,0,0,0,0,0,0,0,0};
char deExtension[4]={0,0,0,0};
unsigned int i,k,j=1;
unsigned int Sector_num = 480;
Cache = GetSectorData(Sector_num);//取得一個根目錄扇區的數據,
if(Cache == NULL)
return 0xffffffff;
dir = (DIRENTRY *)Cache;
while(dir->deName[0] != '\0')
{
for(i=0; (dir->deName[0] != '\0') && i<16; i++)
{
memcpy(deName, (char *)dir->deName, 8);
memcpy(deExtension, (char *)dir->deExtension, 3);
if ( (strcmp(File_Extension, deExtension)==0 || strcmp(File_Extension, "ALL") == 0) && dir->deName[0] != 0xe5 )
{
memcpy(FileName_All[j], (char *)dir, 11);
Uart_Printf("%2d--->%s.%s size:%dk\n",j,deName,deExtension,dir->deFileSize/1024);
j++;
}
dir++;
}
if(dir->deName[0] == '\0') break;
Sector_num++;
Cache = GetSectorData(Sector_num);
}
}
//在所給sector內尋找未被刪除且不是卷標項的目錄項,記錄項目名稱
int SectorGet(DWORD Sector, FatGet *fat_get)
{
BYTE* Cache;
DIRENTRY *dir;
unsigned int j;
Cache = GetSectorData(Sector);
if(Cache == NULL)
return 1;
dir = (DIRENTRY *)Cache;
dir += fat_get->DirIndex;
for(j=fat_get->DirIndex; (dir->deName[0] != '\0') && (j< BytesPerSector / sizeof(DIRENTRY)); j++)
{
if(dir->deName[0] != 0xe5 && (!(dir->deAttributes & ATTR_VOLUME)))// not volumn id or long name entry.
{
fat_get->DirSectorNum = Sector;
fat_get->DirIndex = j + 1;
unformat_name(fat_get->filename, dir->deName);
return 0;
}
dir++;
}
return 2;
}
//在根目錄區或者數據區尋找是否有與dirname名稱相同的項目
// return the first sector number of dir/file entry.
// 0xffffffff indicate failed.
DWORD fat_search(DWORD Sector, const char dirname[11], _FILE *file)
{
unsigned int i;
WORD Cluster;
DWORD FirstSectorOfFile;
//if(dirname == NULL)
//return 0xffffffff;
if(Sector == FirstDirSector)//指定根目錄
{
for(i=0; i<(RootDirCount * sizeof(DIRENTRY) / BytesPerSector); i++)//在整個根目錄區尋找
{
FirstSectorOfFile = SectorSearch(Sector++, dirname, file);//尋找與dirname名稱相同的目錄/文件
if(FirstSectorOfFile != 0xffffffff) //返回目錄/文件的第一簇
return FirstSectorOfFile;
}
}
else
{
Cluster = SectorNum2ClusterNum(Sector);//非根目錄
// because arg Sector is the first sector of parent dir content,
// so it is the first sector of the cluster.
/*
i = (Sector - FirstDataSector) % Bpb.SecPerClus;
if(i != 0)
{
for(; i< Bpb.SecPerClus; i++)
{
FirstSectorOfFile = SectorSearch(Sector++, dirname, file);
if(FirstSectorOfFile != 0xffffffff)
return FirstSectorOfFile;
}
Cluster = GetNextClusterNum(Cluster);
Sector = ClusterNum2SectorNum(Cluster);
}*/
while(Cluster != 0xffff)//不是最后一簇
{
for(i=0; i< SectorsPerCluster; i++)
{
FirstSectorOfFile = SectorSearch(Sector++, dirname, file);//尋找名稱相同的目錄/文件項
if(FirstSectorOfFile != 0xffffffff)
return FirstSectorOfFile;
}
Cluster = GetNextClusterNum(Cluster);
Sector = ClusterNum2SectorNum(Cluster);
}
}
return 0xffffffff;//找不到
}
//定位文件,即在根目錄區查找到它的第一級目錄,在下一個簇查找到它的第二級目錄……,直到最終定位文件。
// return the first sector number of dir/file content.
// 0xffffffff indicate failed.
// if path is root dir, file arg is ignore.
DWORD fat_locate(const char *path, _FILE *file)
{
DWORD Sector = FirstDirSector;
char *p;
p = get_valid_format(path);//判斷是否合法
if(p == NULL)
return 0xffffffff;
// locate first sub dir.
p++;//忽略第一個‘\’
// locate next sub dir(s).
for(;;)
{
if(*p == NULL)
return Sector;
Sector = fat_search(Sector, p, file);//在根目錄區尋找是否有與P同名的目錄/文件項
if(Sector == 0xffffffff)
return 0xffffffff;
p+=12;
}
// we never go here.
return 0xffffffff;
}
//獲得當前的系統時間
void fat_datetime(FatDateTime *fatdatetime)
{
int year,month,day,weekday,hour,min,sec;
WORD pdate = fatdatetime->Date;
WORD ptm = fatdatetime->Time;
if(rBCDYEAR == 0x99)
year = 0x1999;
else
year = 0x2000 + rBCDYEAR;
month=rBCDMON;
day=rBCDDAY;
weekday=rBCDDATE;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -