?? fat16.c
字號:
#include <string.h>
#include "fat16.h"
#include "..\Target\44blib.h"
#include "..\Target\44b.h"
#define SEEK_SET 0
#define SEEK_CUR 1
#define SEEK_END 2
#define DISK_32M 32
#define DISK_16M 16
#define DISK_1M 1
#define DEBUG_FAT 1
#define FAT_SIZEOFWORD 8*256
//請注意每個扇區實際為528個字節,最后還有16個字節
BYTE SectorBuffer[512]; //SectorBuffer
BYTE SectorSpare[16];//Nandflash的備用區,防止sectorbuffer與clusterbuffer沖突
BYTE ClusterBuffer[32][512];//ClusterBuffer
WORD FatCache[FAT_SIZEOFWORD];
//unsigned char *SectorBuffer = (unsigned char *) SECTOR_BUFFER1_ADDR;//暫放sector的512字節空間
//unsigned char *LongNameBuffer = (unsigned char *) LONGNAME_BUFFER_ADDR;//暫放長文件名的字節空間
//unsigned char *DirNameBuffer = (unsigned char *) DIRNAME_BUFFER_ADDR;//暫放路徑名的字節空間
extern unsigned char Erase_Cluster(unsigned int cluster);
extern void ReadPage(unsigned int block,unsigned int page,unsigned char *pPage);
extern int WritePage(unsigned int block,unsigned int page,U8 *pPage);
//--------------該函數用于將磁盤格式化----------------------------//
int fat_format(unsigned char Media,unsigned char Sizeofdisk_M,unsigned char FilesysType)
{
//PARTSECTOR *partsector;
//PARTRECORD *partrecord;
int i,j,fatsec,temp,blocknum;
BOOTSECTOR50 *bootsector;
BPB50 *bpb;
EXTBOOT *ext;
const CHAR *litai_str="-LiTai- ";
const CHAR *armsys_str="ARMSYS44B0 ";
const CHAR *fat16_str="FAT16 ";
blocknum=((Sizeofdisk_M<<20)>>9)>>5;
/* for(i=0;i<blocknum;i++){
if(!(Erase_Cluster(i)))
{
Uart_Printf("\nErase Nand-flash failed!%d block,it can be omitted.",i);
//return 0;
}
for(j=0;j<255;j++);
}
Uart_Printf("\nErase Nand-flash successfully!");*/
for(i=0;i<512;i++)
SectorBuffer[i]=0xff;
if(Media==NAND_FLASH_Drv)//對Nand-flash進行格式化
{
//第0個扇區為DBR
bootsector = (BOOTSECTOR50 *)SectorBuffer;
bpb = (BPB50 *)(bootsector->bsBPB);
ext = (EXTBOOT *)(bootsector->bsExt);
bootsector->bsJump[0] = 0xeb;
bootsector->bsJump[1] = 0x03;
bootsector->bsJump[2] = 0x90;
for(i=0;i<7;i++)
bootsector->bsOemName[i] = *litai_str++;
bootsector->bsOemName[7]='\0';
bootsector->bsBootSectSig0 = BOOTSIG0;
bootsector->bsBootSectSig1 = BOOTSIG1;
bpb->bpbBytesPerSec = 512;
bpb->bpbSecPerClust = 32;
if(FilesysType==PART_TYPE_FAT12||FilesysType==PART_TYPE_DOSFAT16
||FilesysType==PART_TYPE_FAT16||FilesysType==PART_TYPE_FAT16LBA)
bpb->bpbResSectors = 1;
else if(FilesysType==PART_TYPE_FAT32||FilesysType==PART_TYPE_FAT32LBA)
bpb->bpbResSectors = 32;
bpb->bpbFATs = 2;
bpb->bpbRootDirEnts = ((bpb->bpbSecPerClust)-1-(Sizeofdisk_M >> 1)) << 4;
bpb->bpbSectors = Sizeofdisk_M << 11;
bpb->bpbMedia = 0xf0;//必須與FAT[0]一致。
fatsec = bpb->bpbFATsecs = Sizeofdisk_M >> 2;
bpb->bpbSecPerTrack = 0;
bpb->bpbHeads = 0;
bpb->bpbHiddenSecs = 0;
bpb->bpbHugeSectors = Sizeofdisk_M << 11;
ext->exDriveNumber = 0x80;
ext->exReserved1 = 0;
ext->exBootSignature = EXBOOTSIG;
ext->exVolumeID = 0x88331446;
for(i=0;i<10;i++)
ext->exVolumeLabel[i] = *armsys_str++;
ext->exVolumeLabel[10]='\0';
for(i=0;i<7;i++)
ext->exFileSysType[i] = *fat16_str++;
ext->exFileSysType[8]='\0';
memcpy(ClusterBuffer[0],SectorBuffer,512);
//第1個扇區開始是FAT及FAT備份區
for(i=0;i<512;i++)
SectorBuffer[i]=0x00;
for(i=1;i<(fatsec*2+1);i++)
memcpy(ClusterBuffer[i],SectorBuffer,512);
ClusterBuffer[1][0]=0xf0;//0xf8?
ClusterBuffer[1][1]=0xff;
ClusterBuffer[1][2]=0xff;
ClusterBuffer[1][3]=0xff;
ClusterBuffer[fatsec+1][0]=0xf0;//0xf8?
ClusterBuffer[fatsec+1][1]=0xff;
ClusterBuffer[fatsec+1][2]=0xff;
ClusterBuffer[fatsec+1][3]=0xff;
//從第fatsec*2+1個扇區開始,是根目錄區,到簇的最后,應該清零
for(i=fatsec*2+1;i<32;i++)
memcpy(ClusterBuffer[i],SectorBuffer,512);
for(i=0;i<32;i++)//一扇區接一扇區寫入
{
for(j=0;j<255;j++);//延時
temp=WritePage(0,i,ClusterBuffer[i]);
if(temp==0)
{
Uart_Printf("\nFormat Nand-flash failed!");
return 0;
}
}
Uart_Printf("\nFormat Nand-flash Successfully!\n");
return 1;
}
return 0;
}
//PARTRECORD PartInfo;
unsigned char Fat32Enabled;
unsigned int FirstDataSector;
unsigned int BytesPerSector;
unsigned int FATsectors;
unsigned int SectorsPerCluster;
unsigned int FirstFATSector;
unsigned int FirstDirSector;
unsigned int FileSize;
unsigned int FatInCache = 0;
DWORD RootDirSectors; // Numbers of sectors occupied by Root Directory.
DWORD RootDirCount;
//--------------該函數主要用于從已有的存儲介質中獲得文件系統信息------------------//
unsigned char fatInit(void)
{
BOOTSECTOR50 *bootsector;
BPB50 *bpb;
EXTBOOT *ext;
int i,j;
for(j=0;j<255;j++);
ReadPage(0,0,SectorBuffer);
bootsector = (BOOTSECTOR50 *)SectorBuffer;
bpb = (BPB50 *)(bootsector->bsBPB);
ext = (EXTBOOT *)(bootsector->bsExt);
// setup global disk constants
FirstDataSector = 0;//PartInfo.prStartLBA;
if(bpb->bpbFATsecs)
{
// bpbFATsecs is non-zero and is therefore valid
FirstDirSector = bpb->bpbResSectors + bpb->bpbFATs * bpb->bpbFATsecs;
//FAT12,16 =1 =2(2份FAT,其中1份為備份)×每一份FAT所占用的sector數
}
SectorsPerCluster = bpb->bpbSecPerClust;//每cluster的sector數目
BytesPerSector = bpb->bpbBytesPerSec;//每sector的字節數
FirstFATSector = bpb->bpbResSectors + 0;//PartInfo.prStartLBA;//FAT區的起始地址
FATsectors = bpb->bpbFATsecs;
FirstDataSector = FirstDirSector+((bpb->bpbRootDirEnts)>>4);
RootDirCount = bpb->bpbRootDirEnts;
RootDirSectors = (RootDirCount*32)>>9;
#ifdef DEBUG_FAT
Uart_Printf("\nOEM name : %s",(char *)(bootsector->bsOemName));
//Uart_Printf("\nFirst sector : %4x",PartInfo.prStartLBA);
//Uart_Printf("\nSize : %4x",PartInfo.prSize);
Uart_Printf("\nbytes per sector : %4d",bpb->bpbBytesPerSec);
Uart_Printf("\nsectors per cluster : %4d",bpb->bpbSecPerClust);
Uart_Printf("\nreserved sectors: %4d",bpb->bpbResSectors);
Uart_Printf("\nRootDir Entrys : %4d",bpb->bpbRootDirEnts);
Uart_Printf("\nTolSectors : %4d",bpb->bpbSectors);
Uart_Printf("\nFatSectors : %4d",bpb->bpbFATsecs);
//Uart_Printf("\nBigFatSectors : %4x",bpb->bpbBigFATsecs);
Uart_Printf("\nNumber of Fats : %4d",bpb->bpbFATs);
Uart_Printf("\nFirst Fat Sector: %4d",FirstFATSector);
Uart_Printf("\nFirst Dir sector: %4d",FirstDirSector);
Uart_Printf("\nFirst Data Sect : %4d",FirstDataSector);
//Uart_Printf("\nVolNumber : %x",(unsigned int)(ext->exVolumeID));
Uart_Printf("\nVolumeLabel : %s\n",(char *)(ext->exVolumeLabel));
#endif
for(i=0;i<FATsectors;i++)
{
ReadPage(0,i+1,SectorBuffer);
for(j=0;j<256;j++)
{
FatCache[i*256+j] = SectorBuffer[j*2] + (SectorBuffer[j*2+1] << 8);
}
}
return 0;
}
//一個測試程序
void fat16_Nandflash_test(void)
{
int x,result,i;
char buff[]="fangajfdklsafjasfa;lfs;l";
char buff1[]="hzlitai elec. CO.,Ltd.";
if(fat_format(NAND_FLASH_Drv,DISK_16M,PART_TYPE_FAT16))
{
fatInit();
result=fat_mkdir("\\abcde");
x = fat_creat("\\abcde\\fang123.txt", 0x27);//0x27:txt file?
//Uart_Printf("\nfat_creat's file handle=%d",x);
fat_write(x, buff, 20);//將buff中10個字節內容寫入文件x
fat_write(x, buff1, 10);
fat_lseek(x, 0, SEEK_SET);
memset(buff, 0, sizeof(buff));
Uart_Printf("\nfat_read buff=");
fat_read(x, buff, 30);
for(i=0;i<30;i++)
Uart_Printf("%c",buff[i]);
fat_close(x);
x=fat_open("\\abcde\\fang123.txt");
Uart_Printf("\nfat_open's result=%d",x);
Uart_Printf("\nfat_read buff=");
fat_read(x, buff, 15);
for(i=0;i<15;i++)
Uart_Printf("%c",buff[i]);
fat_close(x);
result=fat_rename("\\abcde\\fang123.txt", "fang321.txt");
Uart_Printf("\nfat_rename's result=%d",x);
x=fat_open("\\abcde\\fang321.txt");
Uart_Printf("\nfat_open's result=%d",result);
Uart_Printf("\nfat_read buff=",result);
fat_read(x, buff, 20);
for(i=0;i<20;i++)
Uart_Printf("%c",buff[i]);
result=fat_remove("\\abcde\\fang321.txt");
Uart_Printf("\nfat_remove's result=%d",result);
x=fat_open("\\abcde\\fang321.txt");
Uart_Printf("\nfat_open's result=%d",x);
//result=fat_rename("\\abcde\\", "abcd12");
//Uart_Printf("\nfat_rename's result=%d",result);
result=fat_rmdir("\\abcde");
Uart_Printf("\nfat_rmdir's result=%d\n",result);
}
}
void FlushFAT()
{
int i,j;
ReadPage(0,0,SectorBuffer);
memcpy(ClusterBuffer[0], SectorBuffer, BytesPerSector); //backup Sector0
for(i=FirstDirSector;i<SectorsPerCluster;i++)
{
ReadPage(0,i,SectorBuffer);
memcpy(ClusterBuffer[i],SectorBuffer,BytesPerSector);
}
for(i=0;i<FATsectors;i++)
{
for(j=0;j<256;j++)
{
SectorBuffer[j*2]=(FatCache[i*256+j])%256;
SectorBuffer[j*2+1]=(FatCache[i*256+j])>>8;
}
memcpy(ClusterBuffer[i+FirstFATSector],SectorBuffer,BytesPerSector);
}
for(i=0;i<FATsectors;i++)//backup FAT field
{
for(j=0;j<256;j++)
{
SectorBuffer[j*2]=(FatCache[i*256+j])%256;
SectorBuffer[j*2+1]=(FatCache[i*256+j])>>8;
}
memcpy(ClusterBuffer[i+FirstFATSector+FATsectors],SectorBuffer,BytesPerSector);
}
Erase_Cluster(0);//寫入之前,擦除當前簇;
for(i=0;i<SectorsPerCluster;i++)//一扇區接一扇區寫入
{
for(j=0;j<255;j++);//延時
WritePage(0,i,ClusterBuffer[i]);
}
}
//The sector number of the first sector of that cluster.
//FirstSectorofCluster = ((N – 2) * BPB_SecPerClus) + FirstDataSector;
//Because No MBR,so: clust-1!
unsigned long FirstSectorofCluster(unsigned long clust)//數據存放的cluster轉為sector
{
return ((clust-1) * SectorsPerCluster + FirstDataSector);
}
// alloc a free cluster. policy is searching from prev cluster number, if no free cluster till end of fat, then search from head of fat.
// return a cluster number. 0xffff indicate faild, disk overflow.
// argument 0 : no prev cluster.
WORD AllocCluster(WORD PrevClusterNum)
{
static WORD LastAllocClusterNum=0;
WORD i;
if(LastAllocClusterNum == 0)
LastAllocClusterNum = PrevClusterNum;
for(i = LastAllocClusterNum; i < BytesPerSector * FATsectors / sizeof(WORD); i++)
{
if(FatCache[i] == 0)//此簇為空簇
{
FatCache[i] = 0xffff; // flag with 0xffff, this is the last cluster.
LastAllocClusterNum = i;
//chain this cluster to prev one.
if(PrevClusterNum != 0)
FatCache[PrevClusterNum] = LastAllocClusterNum;
//FlushFAT();//更新FAT表
return LastAllocClusterNum;//返回簇號
}
}
// we have to search from head of fat
for(i = 2; i < BytesPerSector * FATsectors / sizeof(WORD); i++)
{
if(FatCache[i] == 0)
{
FatCache[i] = 0xffff; // flag with 0xffff, this is the last cluster.
LastAllocClusterNum = i;
//chain this cluster to prev one.
if(PrevClusterNum != 0)
FatCache[PrevClusterNum] = LastAllocClusterNum;
//FlushFAT();//更新FAT表
return LastAllocClusterNum;
}
}
return 0xffff;
}
//return next cluster num,
//0xffff indicate no next cluster.
//Note! : this function will dirty cache!
WORD GetNextClusterNum(WORD ClusterNum)
{
return FatCache[ClusterNum];
}
// free cluster chain.此函數應當是用于依次釋放fat鏈時
// argument 0 : no prev cluster.
void FreeCluster(WORD StartClusterNum)//何時更新disk中的FAT表?
{
WORD Cluster;
WORD NextCluster;
Cluster = StartClusterNum;
while(Cluster != 0xffff)
{
NextCluster = FatCache[Cluster];
FatCache[Cluster] = 0x0000;
Cluster = NextCluster;
}
//FlushFAT();//更新FAT表
}
DWORD CurrentCacheSector;
//Read a special sector into disk cache.
//NULL indicate failed.
BYTE* GetSectorData(DWORD StartSector)//LBA
{
unsigned int block;
unsigned int page;
if((CurrentCacheSector == StartSector) && (StartSector != 0))
return SectorBuffer;
block=StartSector/0x20;
page=StartSector%0x20;
ReadPage(block,page,SectorBuffer);
CurrentCacheSector = StartSector;
return SectorBuffer;
}
void Flush()
{
//memcpy(&((BYTE*)MemDisk)[CurrentCacheSector * Bpb.BytsPerSec], SectorCache, 512);
int i,j;
unsigned int block;
unsigned int page;
block=CurrentCacheSector/0x20;
page =CurrentCacheSector%0x20;
memcpy(ClusterBuffer[page],SectorBuffer, BytesPerSector);
if(page==0)
{
for(i=1;i<SectorsPerCluster;i++){
ReadPage(block,i,SectorBuffer);
memcpy(ClusterBuffer[i], SectorBuffer, BytesPerSector);
}
}
else
{
for(i=0;i<page-1;i++)
{
ReadPage(block,i,SectorBuffer);
memcpy(ClusterBuffer[i], SectorBuffer, BytesPerSector);
}
for(i=page+1;i< SectorsPerCluster;i++)
{
ReadPage(block,i,SectorBuffer);
memcpy(ClusterBuffer[i], SectorBuffer, BytesPerSector);
}
}
memcpy(SectorBuffer,ClusterBuffer[page],BytesPerSector);//保持Sectorbuffer作為cache內容保持不變!!
Erase_Cluster(block);//寫入之前,擦除當前簇;
for(i=0;i<SectorsPerCluster;i++)//一扇區接一扇區寫入
{
for(j=0;j<255;j++);//延時
WritePage(block,i,ClusterBuffer[i]);
}
//沒有檢驗
}
WORD SectorNum2ClusterNum(DWORD SectorNum)
{
return (WORD)((SectorNum - FirstDataSector) / SectorsPerCluster + 1);//NOTE:NO MBR!!!
}
DWORD ClusterNum2SectorNum(WORD ClusterNum)
{
return FirstDataSector + (ClusterNum - 1) * 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)
//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);
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
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -