📄 fat.c
字号:
#include "config.h"
uint8 FAT_ReadBlock(uint32 LBA);
uint8 FAT_WriteBlock(uint32 LBA);
uint8 IsEqual(void* A, void* B, uint8 Size);
void ReadBPB(void);
uint32 ClusConvLBA(uint16 ClusID);
uint16 FAT_ReadFAT(uint16 Index);
uint8 GetFileID(uint8 Name[11], DIR* ID);
static uint8 BUFFER[512];
static FileSystemInfo Info;
static FATFileIndex FileIndex;
//********************************************************************************************
//初始化驱动,建立必要数据结构
//void FAT_Init(void);
//********************************************************************************************
void FAT_Init(void) {
ReadBPB();
}
//********************************************************************************************
//读一个扇区
//********************************************************************************************
uint8 FAT_ReadBlock(uint32 LBA) {
return(MMC_Read_Sector(LBA , BUFFER));
}
//********************************************************************************************
//写一个扇区
//********************************************************************************************
uint8 FAT_WriteBlock(uint32 LBA)
{
return(MMC_Write_Sector(LBA, BUFFER));
}
uint8 IsEqual(void* A, void* B, uint8 Size)
{
uint8 i, *a = A, *b = B;
for(i = 0; i < Size; i++)
if(*a++!= *b++)
return FALSE;
return TRUE;
}
//********************************************************************************************
//读取BPB数据结构
//static void ReadBPB(void)
//********************************************************************************************
void ReadBPB(void)
{
FAT_BPB* BPB = (FAT_BPB*)BUFFER;
FAT_ReadBlock(0);
//缓存相关参数
Info.BPB_SecPerClus = BPB->BPB_SecPerClus;
Info.BPB_RsvdSecCnt = BPB->BPB_RsvdSecCnt;
Info.BPB_NumFATs = BPB->BPB_NumFATs;
Info.BPB_RootEntCnt = BPB->BPB_RootEntCnt;
Info.BPB_TotSec16 = BPB->BPB_TotSec16;
Info.BPB_FATSz16 = BPB->BPB_FATSz16;
Info.BPB_HiddSec = BPB->BPB_HiddSec;
Info.DirStartSec = Info.BPB_RsvdSecCnt + Info.BPB_NumFATs * Info.BPB_FATSz16; //获取根目录开始扇区号
Info.DataStartSec = Info.DirStartSec + Info.BPB_RootEntCnt * 32 / 512; //获取数据区开始扇区号
Info.DirSecCount = Info.BPB_RootEntCnt * 32 / 512; //目录项占用的扇区数
}
//********************************************************************************************
//获取一个簇的开始扇区
//********************************************************************************************
uint32 ClusConvLBA(uint16 ClusID)
{
return Info.DataStartSec + Info.BPB_SecPerClus * (ClusID - 2);
}
//********************************************************************************************
//读取文件分配表的指定项
//********************************************************************************************
uint16 FAT_ReadFAT(uint16 Index)
{
uint16 *RAM = (uint16*)BUFFER;
FAT_ReadBlock(Info.BPB_RsvdSecCnt + Index / 256);
return RAM[Index % 256];
}
//********************************************************************************************
//获得和文件名对应的目录项
//********************************************************************************************
uint8 GetFileID(uint8 * Name, DIR* ID)
{
uint16 DirSecCut, DirStart, i, m;
DirSecCut = Info.DirSecCount; //目录占扇区总数
DirStart = Info.DirStartSec; //目录开始扇区
for(i = 0; i < DirSecCut; i++)
{
if(!FAT_ReadBlock(DirStart + i))
{
break;
}
for(m = 0; m <16; m++)
{
// if(IsEqual(Name, &((DIR*)&BUFFER[m * 32])->FileName, 11))
if(IsEqual(Name, &BUFFER[m * 32], 11))
{
*ID = *((DIR*)&BUFFER[m * 32]);
return TRUE;
}
}
}
return FALSE;
}
//********************************************************************************************
//打开指定文件
//********************************************************************************************
uint32 FAT_FileOpen(uint8 * Name, uint32 Start)
{
uint16 BytePerClus, ClusNum;
DIR FileDir;
BytePerClus = Info.BPB_SecPerClus * 512; // 每簇的字节数
if (!GetFileID(Name, &FileDir))
{
return FALSE;
}
//计算开始位置所在簇的簇号
ClusNum = Start / BytePerClus;
FileIndex.ClusID = FileDir.Start;
for(FileIndex.i = 0; FileIndex.i < ClusNum; FileIndex.i++)
FileIndex.ClusID = FAT_ReadFAT(FileIndex.ClusID);
FileIndex.i = (Start % BytePerClus) / 512; //开始位置所在扇区簇内偏移
FileIndex.m = (Start % BytePerClus) % 512; //开始位置扇区内偏移
FileIndex.LBA = ClusConvLBA(FileIndex.ClusID) + FileIndex.i; //开始位置所在的扇区号
FAT_ReadBlock(FileIndex.LBA); //预读取一个扇区的内容
return (FileDir.Size);
}
//********************************************************************************************
//读取文件的数据
//********************************************************************************************
uint16 FAT_FileRead(uint32 Length, void* Data)
{
uint8 *data = Data;
goto FAT_FileRead_Start;
while(1)
{
FileIndex.ClusID = FAT_ReadFAT(FileIndex.ClusID); //下一簇簇号
if (FileIndex.ClusID==0xFFFF)
{
return FALSE; //文件结束
}
FileIndex.LBA = ClusConvLBA(FileIndex.ClusID); //簇的开始扇区号
FileIndex.i = 0; //簇内扇区偏移
while(FileIndex.i < Info.BPB_SecPerClus)
{
FAT_ReadBlock(FileIndex.LBA); //读当前簇
FileIndex.m = 0; //当前扇区内的数据偏移
FAT_FileRead_Start:
while(FileIndex.m < 512)
{
*data++ = BUFFER[FileIndex.m];
FileIndex.m++;
//如果读取完成就退出
if(--Length == 0)
{
return (FileIndex.m);
}
}
FileIndex.LBA++; //下一扇区号
FileIndex.i++;
}
}
return FALSE;
}
//********************************************************************************************
//写文件的数据
//********************************************************************************************
void FAT_FileWrite(uint32 Length, void* Data) {
uint8 *data = Data;
goto FAT_FileWrite_Start;
while(1) {
FileIndex.ClusID = FAT_ReadFAT(FileIndex.ClusID); //下一簇簇号
FileIndex.LBA = ClusConvLBA(FileIndex.ClusID);
FileIndex.i = 0;
while(FileIndex.i < Info.BPB_SecPerClus) {
FAT_ReadBlock(FileIndex.LBA);
FileIndex.m = 0;
FAT_FileWrite_Start:
while(FileIndex.m < 512) {
BUFFER[FileIndex.m] = *data++;
FileIndex.m++;
//如果读取完成就退出
if(--Length == 0) {
FAT_WriteBlock(FileIndex.LBA); //回写扇区
return;
}
}
FAT_WriteBlock(FileIndex.LBA++); //回写扇区,指针下移
FileIndex.i++;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -