📄 fat.c
字号:
#include "Fat.h"
#include "UART.h"
#include "SD.h"
#include <stdlib.h>
#define debug 0
#define List_DirFile_EN 1
unsigned char BUFFER[512] = {0};
//////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////
volatile struct
{
unsigned int unknown: 1;
unsigned int isFat16: 1;
unsigned int isFat32: 1;
unsigned int isDir: 1; //当前目录下指定的是目录
unsigned int isFile: 1; //当前目录下指定的是文件
}Flags;
unsigned short BytesPerSector=0; //每扇区字节数
unsigned char SectorsPerCluster=0; //每簇扇区数
unsigned int StartSector=0; //分区起始扇区地址,即DBR_LBA
unsigned int FATSector=0; //文件分配表(FAT)起始扇区地址
unsigned int RootDirCluster=0; //根目录所在簇号
unsigned int RootDirSector=0; //根目录起始扇区地址
unsigned int DataSector=0; //数据区起始扇区地址
unsigned int TotalSectors=0; //分区总容量
unsigned int FAT_Size=0; //文件分配表(FAT)大小
unsigned int RootDir_Size=0; //根目录大小,Fat32时为0
unsigned int Data_Size=0; //数据区大小
#define ClusterToSector(N) ((N - 2) * SectorsPerCluster + DataSector) //簇号 -> 扇区号
unsigned int DirCluster=0; //当前目录所在簇号,用于表识当前活动的目录
unsigned int DirFileCluster=0; //当前目录下指定的文件或子目录所在簇号,用于表识即将打开的文件或子目录
unsigned int DirFile_Size=0; //当前目录下指定的文件或子目录的大小
//////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------
//初始化文件系统信息
//-----------------------------------------------------------------------
int Fat_Init(void)
{
DBR *dbr;
BPB *bpb;
DPT *PartInfo;
#if debug
unsigned int i;
#endif
Uart_Printf(0,"Now,Start to Init FileSystem.\n");
// 读MBR结构
ReadS(0,(unsigned int *)BUFFER,512);
#if debug
Uart_Printf(0,"MBR is \n");
for(i=0;i<32;i++)
Uart_Printf(0,"0x%2x 0x%2x 0x%2x 0x%2x 0x%2x 0x%2x 0x%2x 0x%2x 0x%2x 0x%2x 0x%2x 0x%2x 0x%2x 0x%2x 0x%2x 0x%2x\n",BUFFER[0+i*16],BUFFER[1+i*16],BUFFER[2+i*16],BUFFER[3+i*16],BUFFER[4+i*16],BUFFER[5+i*16],BUFFER[6+i*16],BUFFER[7+i*16],BUFFER[8+i*16],BUFFER[9+i*16],BUFFER[10+i*16],BUFFER[11+i*16],BUFFER[12+i*16],BUFFER[13+i*16],BUFFER[14+i*16],BUFFER[15+i*16]);
#endif
// 读取第0分区表信息,并分析
PartInfo = ((DPT *)(((MBR *)BUFFER)->psPart + 16 * 0)); //指向第0分区表项
switch (PartInfo->prPartType)//查询该分区文件系统类型
{
case PART_TYPE_FAT12:
case PART_TYPE_DOSFAT16:
case PART_TYPE_FAT16:
case PART_TYPE_FAT16LBA:
Flags.isFat16 = 1; //该分区为Fat16
Flags.isFat32 = 0;
Flags.unknown = 0;
break;
case PART_TYPE_FAT32LBA:
case PART_TYPE_FAT32:
Flags.isFat16 = 0;
Flags.isFat32 = 1; //该分区为Fat32
Flags.unknown = 0;
break;
case PART_TYPE_UNKNOWN:
default:
Flags.isFat16 = 0;
Flags.isFat32 = 0;
Flags.unknown = 1; //无法识别该分区
break;
}
//TotalSectors = PartInfo->prSize; //分区容量
StartSector = PartInfo->prStartLBA; //分区起始扇区地址
// 读分区引导扇区
// 引导扇区号在PartInfo.prStartLBA中
ReadS(StartSector,(unsigned int *)BUFFER,512);
#if debug
Uart_Printf(0,"StartSector is \n");
for(i=0;i<32;i++)
Uart_Printf(0,"0x%2x 0x%2x 0x%2x 0x%2x 0x%2x 0x%2x 0x%2x 0x%2x 0x%2x 0x%2x 0x%2x 0x%2x 0x%2x 0x%2x 0x%2x 0x%2x\n",BUFFER[0+i*16],BUFFER[1+i*16],BUFFER[2+i*16],BUFFER[3+i*16],BUFFER[4+i*16],BUFFER[5+i*16],BUFFER[6+i*16],BUFFER[7+i*16],BUFFER[8+i*16],BUFFER[9+i*16],BUFFER[10+i*16],BUFFER[11+i*16],BUFFER[12+i*16],BUFFER[13+i*16],BUFFER[14+i*16],BUFFER[15+i*16]);
#endif
dbr = (DBR *) BUFFER; //调整指针
bpb = (BPB *) dbr->bsBPB; //调整指针
BytesPerSector = bpb->bpbBytesPerSec; //每扇区字节数
SectorsPerCluster = bpb->bpbSecPerClust; //每簇扇区数
FATSector = bpb->bpbResSectors + StartSector; //文件分配表(FAT)起始扇区地址
if(Flags.isFat16)
{
TotalSectors = bpb->bpbSmallSectors; //分区容量
FAT_Size = bpb->bpbFATs * bpb->bpbFATsecs; //文件分配表(FAT)大小
RootDirCluster = 1; //根目录簇号
}
if(Flags.isFat32)
{
TotalSectors = bpb->bpbHugeSectors; //分区容量
FAT_Size = bpb->bpbFATs * bpb->bpbBigFATsecs; //文件分配表(FAT)大小
RootDirCluster = bpb->bpbRootClust; //根目录簇号
}
DirCluster = RootDirCluster; //初始当前活动目录为根目录
RootDir_Size = ((bpb->bpbRootDirEnts * 32) + (BytesPerSector - 1)) / BytesPerSector; //根目录大小
RootDirSector = FATSector + FAT_Size; //根目录起始扇区地址
Data_Size = TotalSectors - (bpb->bpbResSectors + FAT_Size + RootDir_Size); //数据区大小
DataSector = RootDirSector + RootDir_Size; //数据区起始扇区地址
#if debug
if(Flags.isFat16) Uart_Printf(0,"It is Fat16.\n");
if(Flags.isFat32) Uart_Printf(0,"It is Fat32.\n");
Uart_Printf(0,"TotalSectors = %d\n",TotalSectors);
Uart_Printf(0,"StartSector = %d\n",StartSector);
Uart_Printf(0,"BytesPerSector = %d\n",BytesPerSector);
Uart_Printf(0,"SectorsPerCluster = %d\n",SectorsPerCluster);
Uart_Printf(0,"FATSector = %d\n",FATSector);
Uart_Printf(0,"FAT_Size = %d\n",FAT_Size);
Uart_Printf(0,"RootDirCluster = %d\n",RootDirCluster);
Uart_Printf(0,"RootDirSector = %d\n",RootDirSector);
Uart_Printf(0,"RootDir_Size = %d\n",RootDir_Size);
Uart_Printf(0,"DataSector = %d\n",DataSector);
Uart_Printf(0,"Data_Size = %d\n",Data_Size);
//厂商标志和OS版本号
Uart_Printf(0,"The OEMName is %s\n",dbr->bsOEMName);
//显示磁盘容量
Uart_Printf(0,"The SDCard'Size is %d Bits\n",TotalSectors<<9);
Uart_Printf(0,"############################################\n");
#endif
return 1;
}
//////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------
//在FAT表中查询下一个簇所在扇区号
//-----------------------------------------------------------------------
unsigned int FatNextCluster(unsigned int cluster)
{
unsigned int nextCluster;
unsigned int fatMask;
unsigned int fatOffset;
unsigned int sector;
unsigned int offset;
#if debug
unsigned int i;
#endif
if(Flags.isFat16)
{
// 一个表项为2bytes(16 bits)
fatOffset = cluster << 1;
// 设置 FAT16 bit mask
fatMask = FAT16_MASK;
}
if(Flags.isFat32)
{
// 一个表项为4bytes(32 bits)
fatOffset = cluster << 2;
// 设置 FAT32 bit mask
fatMask = FAT32_MASK;
}
//计算FAT扇区号
sector = FATSector + (fatOffset / BytesPerSector);
//计算FAT扇区号中表项的偏移地址
offset = fatOffset % BytesPerSector;
#if debug
Uart_Printf(0,"The Cluster Sector is %d\n",sector);
Uart_Printf(0,"The Cluster Offset is %d\n",offset);
#endif
ReadS(sector,(unsigned int *)BUFFER,512);
#if debug
Uart_Printf(0,"Cluster is \n");
for(i=0;i<32;i++)
Uart_Printf(0,"0x%2x 0x%2x 0x%2x 0x%2x 0x%2x 0x%2x 0x%2x 0x%2x 0x%2x 0x%2x 0x%2x 0x%2x 0x%2x 0x%2x 0x%2x 0x%2x\n",BUFFER[0+i*16],BUFFER[1+i*16],BUFFER[2+i*16],BUFFER[3+i*16],BUFFER[4+i*16],BUFFER[5+i*16],BUFFER[6+i*16],BUFFER[7+i*16],BUFFER[8+i*16],BUFFER[9+i*16],BUFFER[10+i*16],BUFFER[11+i*16],BUFFER[12+i*16],BUFFER[13+i*16],BUFFER[14+i*16],BUFFER[15+i*16]);
#endif
// 读取下一个簇号
if(Flags.isFat16)
{
//nextCluster = (*((unsigned int*) &((char*)BUFFER)[offset])) & fatMask;
nextCluster = (unsigned int)(*(unsigned short*)&(((FAT *)BUFFER)->Item[offset])) & fatMask;
}
if(Flags.isFat32)
{
//nextCluster = (*((unsigned int*) &((char*)BUFFER)[offset])) & fatMask;
nextCluster = *(unsigned int*)&(((FAT *)BUFFER)->Item[offset]) & fatMask;
}
// 是否文件的结束簇
if (nextCluster == (CLUST_EOFE & fatMask))
nextCluster = 0;
#if debug
Uart_Printf(0,"The Current Cluster is %d\n",cluster);
Uart_Printf(0,"The Next Cluster is %d\n",nextCluster);
Uart_Printf(0,"############################################\n");
#endif
return nextCluster;
}
//////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------
//
//-----------------------------------------------------------------------
#if List_DirFile_EN
void List_DirFile(void)
{
unsigned char i,j,k;
unsigned int kk;
DirFile *dirfile;
kk = DirCluster; //当前目录所在簇号
while(1)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -