?? fat.c
字號:
#include "fat.h"
#include "sd.h" //存儲設備的扇區(qū)讀寫驅(qū)動,這里是SD卡
#include "string.h"
//全局變量定義
struct direntry idata temp_rec;
INT8 temp_dir_name[13];
UINT32 temp_dir_cluster;
UINT32 temp_last_cluster;
UINT8 FAT32_Buffer[512]; //扇區(qū)數(shù)據(jù)讀寫緩沖區(qū),由外部提供
extern struct FAT32_Init_Arg *pArg; //初始化參數(shù)結(jié)構(gòu)體指針,用以指向某一存儲設備的初始化參數(shù)結(jié)構(gòu)體,由外部提供
unsigned char (*pRS)(unsigned long,unsigned char *); //指向?qū)嶋H存儲設備的讀扇區(qū)函數(shù)的函數(shù)指針,用以實現(xiàn)對設備的支持
unsigned char (*pWS)(unsigned long,unsigned char *); //指向?qū)嶋H存儲設備的寫扇區(qū)函數(shù)的函數(shù)指針,用以實現(xiàn)對設備的支持
extern unsigned char Dev_No;
/******************************************************************
- 功能描述:FAT的存儲設備底層驅(qū)動接口,讀取存儲設備的addr扇區(qū)的
512個字節(jié)的數(shù)據(jù)放入buf數(shù)據(jù)緩沖區(qū)中
- 隸屬模塊:FAT文件系統(tǒng)模塊
- 函數(shù)屬性:內(nèi)部(用于與存儲設備的底層驅(qū)動對接)
- 參數(shù)說明:addr:扇區(qū)地址
buf:指向數(shù)據(jù)緩沖區(qū)
- 返回說明:0表示讀取扇區(qū)成功,否則失敗
- 注:這里加入了天狼星精華板上的三種存儲設備,即SD卡(有效)、U盤、
CF卡通過在程序中動態(tài)的切換不同的設備驅(qū)動,從而實現(xiàn)多設備(即同
時對多種存儲設備進行操作,比如從SD卡拷貝文件到U盤等等),不同
驅(qū)動的切換,只需要在程序中改變Dev_No這個全局變量的值即可
******************************************************************/
UINT8 FAT32_ReadSector(UINT32 addr,UINT8 *buf)
{
switch(Dev_No)
{
case SDCARD:
pRS=SD_Read_Sector;
break;
case UDISK:
//pRS=CH375_Read_Sector;
break;
case CFCARD:
//pRS=CF_Read_Sector;
//無
break;
case OTHER:
//無
break;
}
return (*pRS)(addr,buf); //替換成實際存儲器的扇區(qū)讀函數(shù),這里是SD卡扇區(qū)讀函數(shù)
}
/******************************************************************
- 功能描述:FAT的存儲設備底層驅(qū)動接口,將buf數(shù)據(jù)緩沖區(qū)中的512個
字節(jié)的數(shù)據(jù)寫入到存儲設備的addr扇區(qū)中
- 隸屬模塊:FAT文件系統(tǒng)模塊
- 函數(shù)屬性:內(nèi)部(用于與存儲設備的底層驅(qū)動對接)
- 參數(shù)說明:addr:扇區(qū)地址
buf:指向數(shù)據(jù)緩沖區(qū)
- 返回說明:0表示讀取扇區(qū)成功,否則失敗
- 注:略
******************************************************************/
UINT8 FAT32_WriteSector(UINT32 addr,UINT8 *buf)
{
switch(Dev_No)
{
case SDCARD:
pWS=SD_Write_Sector;
break;
case UDISK:
//pWS=CH375_Write_Sector;
break;
case CFCARD:
//pWS=CF_Write_Sector;
//無
break;
case OTHER:
//無
break;
}
return (*pWS)(addr,buf); //替換成實際存儲器的扇區(qū)寫函數(shù),這里是SD卡扇區(qū)寫函數(shù)
}
/******************************************************************
- 功能描述:小端轉(zhuǎn)大端,即LittleEndian車BigEndian
- 隸屬模塊:FAT文件系統(tǒng)模塊
- 函數(shù)屬性:內(nèi)部
- 參數(shù)說明:dat:指向要轉(zhuǎn)為大端的字節(jié)序列
len:要轉(zhuǎn)為大端的字節(jié)序列長度
- 返回說明:轉(zhuǎn)為大端模式后,字節(jié)序列所表達的數(shù)據(jù)
- 注:比如:小端模式的 0x33 0x22 0x11 0x00 (低字節(jié)在前)
轉(zhuǎn)為大端模式后為 0x00 0x11 0x22 0x33 (高字節(jié)在前)
所表達的數(shù)值為 0x00112233
(CISC的CPU通常是小端的,所以FAT32也設計為小端,而單片機
這種RISC的CPU,通常來說都是大端的,所以需要這個函數(shù)將字
節(jié)的存放次序進行調(diào)整,才能得到正確的數(shù)值)
******************************************************************/
UINT32 LE2BE(UINT8 *dat,UINT8 len)
{
UINT32 temp=0;
UINT32 fact=1;
UINT8 i=0;
for(i=0;i<len;i++)
{
temp+=dat[i]*fact; //將各字節(jié)乘以相應的權(quán)值后累加
fact*=256; //更新權(quán)值
}
return temp;
}
/******************************************************************
- 功能描述:將小字字符轉(zhuǎn)為大寫
- 隸屬模塊:FAT文件系統(tǒng)模塊
- 函數(shù)屬性:內(nèi)部
- 參數(shù)說明:c:要轉(zhuǎn)換為大寫的字符
- 返回說明:要轉(zhuǎn)換的字節(jié)的相應的大寫字符
- 注:只對小寫字符有效,如果不是a~z的小寫字符,將直接返回
******************************************************************/
INT8 L2U(INT8 c)
{
if(c>='a' && c<='z') return c+'A'-'a';
else return c;
}
/******************************************************************
- 功能描述:讀取0扇區(qū),檢測有沒有MBR(主引導記錄)
- 隸屬模塊:FAT文件系統(tǒng)模塊
- 函數(shù)屬性:內(nèi)部
- 參數(shù)說明:無
- 返回說明:1表示檢測到MBR,0表示沒有檢測到MBR
- 注:有些存儲設備格式化為FAT32以后,沒有MBR,則0扇區(qū)就是DBR
如果有MBR,就需要對其進行解析,以得到DBR的扇區(qū)位置,同時MBR中
還含分區(qū)、分區(qū)容量等信息
******************************************************************/
UINT8 FAT32_is_MBR()
{
UINT8 result;
FAT32_ReadSector(0,FAT32_Buffer);
if(FAT32_Buffer[0]!=0xeb)
{
result=1;
}
else
{
result=0;
}
return result;
}
/***********************************************************************
- 功能描述:得到DBR所在的扇區(qū)號(如果沒有MBR,則DBR就在0扇區(qū))
- 隸屬模塊:FAT文件系統(tǒng)模塊
- 函數(shù)屬性:內(nèi)部
- 參數(shù)說明:無
- 返回說明:DBR的扇區(qū)地址
- 注:DBR中包含了很多有用的參數(shù)信息,因此正確定位DBR扇區(qū)的位置,是極為
重要的,后面將有專門的函數(shù)對DBR進行解析,正確解析DBR是實現(xiàn)FAT32的
基礎(chǔ)
***********************************************************************/
UINT16 FAT32_Find_DBR()
{
UINT16 sec_dbr;
FAT32_ReadSector(0,FAT32_Buffer);
if(FAT32_Buffer[0]!=0xeb)
{
sec_dbr=LE2BE(((((struct PartSector *)(FAT32_Buffer))->Part[0]).StartLBA),4);
}
else
{
sec_dbr=0;
}
return sec_dbr;
}
/***********************************************************************
- 功能描述:獲取分區(qū)的總?cè)萘? - 隸屬模塊:FAT文件系統(tǒng)模塊
- 函數(shù)屬性:外部,使用戶使用
- 參數(shù)說明:無
- 返回說明:分區(qū)容量值,單位為字節(jié)
- 注:這里得到的總?cè)萘渴荈AT32分區(qū)的容量,一定小于實際的物理容量
***********************************************************************/
UINT32 FAT32_Get_Total_Size()
{
UINT32 temp;
FAT32_ReadSector(pArg->BPB_Sector_No,FAT32_Buffer);
FAT32_ReadSector(pArg->BPB_Sector_No,FAT32_Buffer);
temp=((LE2BE((((struct FAT32_BPB *)(FAT32_Buffer))->BPB_TotSec32),4)))*pArg->BytesPerSector;
return temp;
}
/***********************************************************************
- 功能描述:讀取FSInfo獲取最近的一個可用空閑簇
- 隸屬模塊:FAT文件系統(tǒng)模塊
- 函數(shù)屬性:內(nèi)部
- 參數(shù)說明:無
- 返回說明:最近的一個可用空閑簇
- 注:FAT32中的FSInfo扇區(qū)(絕對1扇區(qū))中記錄了最近的一個可用空閑簇
***********************************************************************/
UINT32 Search_Last_Usable_Cluster()
{
FAT32_ReadSector(1+pArg->BPB_Sector_No,FAT32_Buffer);
return LE2BE(((struct FSInfo *)FAT32_Buffer)->Last_Cluster,4);
}
/***********************************************************************
- 功能描述:FAT32文件系統(tǒng)初始化
- 隸屬模塊:FAT文件系統(tǒng)模塊
- 函數(shù)屬性:外部,使用戶使用
- 參數(shù)說明:FAT32_Init_Arg類型的結(jié)構(gòu)體指針,用于裝載一些重要的參數(shù)信息,
以備后面使用
- 返回說明:無
- 注:在使用znFAT前,這個函數(shù)是必須先被調(diào)用的,將很多參數(shù)信息裝入到
arg指向的結(jié)構(gòu)體中,比如扇區(qū)大小、根目錄的位置、FAT表大小等等。
這些參數(shù)絕大部分是來自于DBR的BPB中,因此此函數(shù)主要在作對DBR的參數(shù)解析
***********************************************************************/
void FAT32_Init()
{
struct FAT32_BPB *bpb;
bpb=(struct FAT32_BPB *)(FAT32_Buffer); //將數(shù)據(jù)緩沖區(qū)指針轉(zhuǎn)為struct FAT32_BPB 型指針
pArg->DEV_No=Dev_No; //裝入設備號
pArg->BPB_Sector_No =FAT32_Find_DBR(); //FAT32_FindBPB()可以返回BPB所在的扇區(qū)號
pArg->BPB_Sector_No =FAT32_Find_DBR(); //FAT32_FindBPB()可以返回BPB所在的扇區(qū)號
pArg->Total_Size =FAT32_Get_Total_Size(); //FAT32_Get_Total_Size()可以返回磁盤的總?cè)萘浚瑔挝皇亲止?jié)
pArg->Total_Size =FAT32_Get_Total_Size(); //FAT32_Get_Total_Size()可以返回磁盤的總?cè)萘浚瑔挝皇钦?
pArg->FATsectors =LE2BE((bpb->BPB_FATSz32) ,4);//裝入FAT表占用的扇區(qū)數(shù)到FATsectors中
pArg->FirstDirClust =LE2BE((bpb->BPB_RootClus) ,4);//裝入根目錄簇號到FirstDirClust中
pArg->BytesPerSector =LE2BE((bpb->BPB_BytesPerSec),2);//裝入每扇區(qū)字節(jié)數(shù)到BytesPerSector中
pArg->SectorsPerClust =LE2BE((bpb->BPB_SecPerClus) ,1);//裝入每簇扇區(qū)數(shù)到SectorsPerClust 中
pArg->FirstFATSector =LE2BE((bpb->BPB_RsvdSecCnt) ,2)+pArg->BPB_Sector_No;//裝入第一個FAT表扇區(qū)號到FirstFATSector 中
pArg->FirstDirSector =(pArg->FirstFATSector)+(bpb->BPB_NumFATs[0])*(pArg->FATsectors); //裝入第一個目錄扇區(qū)到FirstDirSector中
temp_last_cluster=Search_Last_Usable_Cluster();
}
/***********************************************************************
- 功能描述:獲取剩余容量
- 隸屬模塊:FAT文件系統(tǒng)模塊
- 函數(shù)屬性:外部,使用戶使用
- 參數(shù)說明:無
- 返回說明:剩余容量,單位字節(jié)
- 注:從FSInfo中讀取空閑簇數(shù),而從計算得到剩余的容量,單位字節(jié)
***********************************************************************/
UINT32 FAT32_Get_Remain_Cap()
{
FAT32_ReadSector(1+pArg->BPB_Sector_No,FAT32_Buffer);
if(((struct FSInfo *)FAT32_Buffer)->Free_Cluster[0]==0xff
&& ((struct FSInfo *)FAT32_Buffer)->Free_Cluster[1]==0xff
&& ((struct FSInfo *)FAT32_Buffer)->Free_Cluster[2]==0xff
&& ((struct FSInfo *)FAT32_Buffer)->Free_Cluster[3]==0xff)
return pArg->Total_Size;
else
return LE2BE(((struct FSInfo *)FAT32_Buffer)->Free_Cluster,4)*pArg->SectorsPerClust*pArg->BytesPerSector;
}
/***********************************************************************
- 功能描述:更新FSInfo中的可用空閑簇的數(shù)量
- 隸屬模塊:FAT文件系統(tǒng)模塊
- 函數(shù)屬性:內(nèi)部
- 參數(shù)說明:PlusOrMinus:可用空閑簇數(shù)加1或減1
- 返回說明:無
- 注:創(chuàng)建文件、追加數(shù)據(jù)、刪除文件等操作都可能會使可用的空閑簇數(shù)變化
要及時更新
***********************************************************************/
void FAT32_Update_FSInfo_Free_Clu(UINT32 PlusOrMinus)
{
UINT32 Free_Clu=0;
FAT32_ReadSector(1+pArg->BPB_Sector_No,FAT32_Buffer);
Free_Clu=(FAT32_Get_Remain_Cap())/(pArg->SectorsPerClust*pArg->BytesPerSector);
if(PlusOrMinus) Free_Clu++;
else Free_Clu--;
((struct FSInfo *)FAT32_Buffer)->Free_Cluster[0]=((unsigned char *)&Free_Clu)[3];
((struct FSInfo *)FAT32_Buffer)->Free_Cluster[1]=((unsigned char *)&Free_Clu)[2];
((struct FSInfo *)FAT32_Buffer)->Free_Cluster[2]=((unsigned char *)&Free_Clu)[1];
((struct FSInfo *)FAT32_Buffer)->Free_Cluster[3]=((unsigned char *)&Free_Clu)[0];
FAT32_WriteSector(1+pArg->BPB_Sector_No,FAT32_Buffer);
}
/***********************************************************************
- 功能描述:更新FSInfo中的下一個可用空閑簇的簇號
- 隸屬模塊:FAT文件系統(tǒng)模塊
- 函數(shù)屬性:內(nèi)部
- 參數(shù)說明:Last_Clu:將要更新到FSInfo中的下一個可用空閑簇的簇號
- 返回說明:無
- 注:FSInfo中的下一個可用空閑簇號可以給文件系統(tǒng)一個參考,直接告訴文件系統(tǒng)
下一個可用的空閑簇在什么地方
***********************************************************************/
void FAT32_Update_FSInfo_Last_Clu(UINT32 Last_Clu)
{
FAT32_ReadSector(1+pArg->BPB_Sector_No,FAT32_Buffer);
((struct FSInfo *)FAT32_Buffer)->Last_Cluster[0]=((unsigned char *)&Last_Clu)[3];
((struct FSInfo *)FAT32_Buffer)->Last_Cluster[1]=((unsigned char *)&Last_Clu)[2];
((struct FSInfo *)FAT32_Buffer)->Last_Cluster[2]=((unsigned char *)&Last_Clu)[1];
((struct FSInfo *)FAT32_Buffer)->Last_Cluster[3]=((unsigned char *)&Last_Clu)[0];
FAT32_WriteSector(1+pArg->BPB_Sector_No,FAT32_Buffer);
}
/***********************************************************************
- 功能描述:獲得下一個簇的簇號
- 隸屬模塊:FAT文件系統(tǒng)模塊
- 函數(shù)屬性:內(nèi)部
- 參數(shù)說明:LastCluster:基準簇號
- 返回說明:LastClutster的下一簇的簇號
- 注:獲得下一簇的簇號,就是憑借FAT表中所記錄的簇鏈關(guān)系來實現(xiàn)的
***********************************************************************/
UINT32 FAT32_GetNextCluster(UINT32 LastCluster)
{
UINT32 temp;
struct FAT32_FAT *pFAT;
struct FAT32_FAT_Item *pFAT_Item;
temp=((LastCluster/128)+pArg->FirstFATSector);
FAT32_ReadSector(temp,FAT32_Buffer);
pFAT=(struct FAT32_FAT *)FAT32_Buffer;
pFAT_Item=&((pFAT->Items)[LastCluster%128]);
return LE2BE((UINT8 *)pFAT_Item,4);
}
/***********************************************************************
- 功能描述:比較目錄名
- 隸屬模塊:FAT文件系統(tǒng)模塊
- 函數(shù)屬性:內(nèi)部
- 參數(shù)說明:a:指向目錄名1的指針
b:指向目錄名2的指針
- 返回說明:如果兩個目錄名相同就返回1,否則為0
***********************************************************************/
UINT8 Compare_Dir_Name(INT8 *a,INT8 *b)
{
UINT8 i;
for(i=0;i<8;i++)
{
if(a[i]!=b[i]) return 0;
}
return 1;
}
/***********************************************************************
- 功能描述:文件名匹配(支持帶*?通配符的文件名的匹配)
- 隸屬模塊:FAT文件系統(tǒng)模塊
- 函數(shù)屬性:內(nèi)部
- 參數(shù)說明:pat:源文件名,可以含*或?通配符 如 *.txt 或 A?.mp3等等
name:目標文件名
- 返回說明:如果兩個文件名匹配就返回1,否則為0
- 注:關(guān)于通配文件名匹配,有這樣的例子,比如 A*.txt 與 ABC.txt是匹配的
同時與 ABCDE.txt也是匹配的。此功能在文件枚舉中將會用到,用來匹配
文件名符合一定條件的文件
***********************************************************************/
UINT8 FilenameMatch(INT8 *pat,INT8 *name)
{
INT16 match,ndone;
INT8 *cpp,*cpn;
cpp=pat;
cpn=name;
match=1;
ndone=1;
while(ndone)
{
switch (*cpp)
{
case '*':
cpp++;
cpn=strchr(cpn,*cpp);
if(cpn==NULL)
{
cpn=name;
while(*cpn) cpn++;
}
break;
case '?':
cpp++;
cpn++;
break;
case 0:
if(*cpn!=0)
match=0;
ndone=0;
break;
default:
if((*cpp)==(*cpn))
{
cpp++;
cpn++;
}
else
{
match=0;
ndone=0;
}
break;
}
}
return(match);
}
/***********************************************************************
- 功能描述:FAT32的文件目錄項的文件名字段(8個字節(jié)),轉(zhuǎn)為普通的文件名
如:ABC MP3 將轉(zhuǎn)為 ABC.MP3
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -