📄 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 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="ARMSys2004 ";
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 + -