⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fat16.c

📁 杭州立宇泰豪华型44B0开发板
💻 C
📖 第 1 页 / 共 3 页
字号:
#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 + -