?? znfat.c
字號:
#include "znfat.h"
#include "sd.h" //存儲設備的扇區讀寫驅動,這里是SD卡
//#include "ch375.h" //存儲設備的扇區讀寫驅動,這里是U盤
//#include "cf.h"
#include "string.h"
/*******************************************************
+-----------------------------------------+
|振南電子 原創程序模塊 znFAT文件系統 5.18 |
+-----------------------------------------+
此源碼版權屬 振南 全權享有,如欲引用,敬請署名并告知
嚴禁隨意用于商業目的,違者必究,后果自負
振南電子
->產品網站 http://www.znmcu.cn/
->產品網店 http://shop.znmcu.cn/
->產品咨詢 QQ:987582714
MSN:yzn07@126.com
WW:yzn07
說明:znFAT經多方測試,確保其正確性與穩定性,請放心使用,
如有bug敬請告知,謝謝!!
********************************************************/
//全局變量定義
struct direntry temp_rec;
INT8 temp_dir_name[13];
UINT32 temp_dir_cluster;
UINT32 temp_last_cluster;
UINT8 xdata znFAT_Buffer[512]; //扇區數據讀寫緩沖區,由外部提供
/******************************************************************
- 功能描述:znFAT的存儲設備初始化函數
- 隸屬模塊:znFAT文件系統模塊
- 函數屬性:外部(用于對存儲設備進行初始化)
- 參數說明:無
- 返回說明:無
- 注:在調znFAT其它函數之前,必須先對存儲設備進行成功的初始化。
******************************************************************/
void znFAT_Device_Init()
{
SD_Reset();
SD_Init();
}
/******************************************************************
- 功能描述:znFAT的存儲設備底層驅動接口,讀取存儲設備的addr扇區的
512個字節的數據放入buf數據緩沖區中
- 隸屬模塊:znFAT文件系統模塊
- 函數屬性:內部(用于與存儲設備的底層驅動對接)
- 參數說明:addr:扇區地址
buf:指向數據緩沖區的指針
- 返回說明:0表示讀取扇區成功,否則失敗
- 注:這里加入了天狼星精華板上的三種存儲設備,即SD卡(有效)、U盤、
CF卡通過在程序中動態的切換不同的設備驅動,從而實現多設備(即同
時對多種存儲設備進行操作,比如從SD卡拷貝文件到U盤等等),不同
驅動的切換,只需要在程序中改變Dev_No這個全局變量的值即可
******************************************************************/
UINT8 znFAT_ReadSector(UINT32 addr,UINT8 *buf)
{
switch(Dev_No) //由Dev_No來決定所使用的存儲設備驅動
{
case SDCARD:
return SD_Read_Sector(addr,buf);
break;
case UDISK:
//return CH375_Read_Sector(addr,buf);
break;
case CFCARD:
//return CF_Read_Sector(addr,buf);
break;
case OTHER:
//return XXX_Read_Sector(addr,buf);
break;
}
}
/******************************************************************
- 功能描述:znFAT的存儲設備底層驅動接口,將buf數據緩沖區中的512個
字節的數據寫入到存儲設備的addr扇區中
- 隸屬模塊:znFAT文件系統模塊
- 函數屬性:內部(用于與存儲設備的底層驅動對接)
- 參數說明:addr:扇區地址
buf:指向數據緩沖區
- 返回說明:0表示讀取扇區成功,否則失敗
- 注:略
******************************************************************/
UINT8 znFAT_WriteSector(UINT32 addr,UINT8 *buf)
{
switch(Dev_No) //由Dev_No來決定所使用的存儲設備驅動
{
case SDCARD:
return SD_Write_Sector(addr,buf);
break;
case UDISK:
//return CH375_Write_Sector(addr,buf);
break;
case CFCARD:
//return CF_WriteSector(addr,buf);
break;
case OTHER:
//return XXX_Write_Sector(addr,buf);
break;
}
}
/******************************************************************
- 功能描述:小端轉大端,即LittleEndian車BigEndian
- 隸屬模塊:znFAT文件系統模塊
- 函數屬性:內部
- 參數說明:dat:指向要轉為大端的字節序列
len:要轉為大端的字節序列長度
- 返回說明:轉為大端模式后,字節序列所表達的數據
- 注:比如:小端模式的 0x33 0x22 0x11 0x00 (低字節在前)
轉為大端模式后為 0x00 0x11 0x22 0x33 (高字節在前)
所表達的數值為 0x00112233
(CISC的CPU通常是小端的,所以znFAT也設計為小端,而單片機
這種RISC的CPU,通常來說都是大端的,所以需要這個函數將字
節的存放次序進行調整,才能得到正確的數值)
******************************************************************/
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; //將各字節乘以相應的權值后累加
fact*=256; //更新權值
}
return temp;
}
//-----------------------------------
/**************************************************************************
- 功能描述:清空某個簇的所有扇區,填充0
- 隸屬模塊:znFAT文件系統模塊
- 函數屬性:內部
- 參數說明:cluster:要清空的簇的簇號
- 返回說明:無
**************************************************************************/
#ifdef ZNFAT_EMPTY_CLUSTER
void znFAT_Empty_Cluster(UINT32 Cluster)
{
UINT32 iSec;
UINT16 i;
for(i=0;i<pArg->BytesPerSector;i++)
{
znFAT_Buffer[i]=0;
}
for(iSec=SOC(Cluster);iSec<SOC(Cluster)+pArg->SectorsPerClust;iSec++)
{
znFAT_WriteSector(iSec,znFAT_Buffer);
}
}
#endif
/***********************************************************************
- 功能描述:獲取剩余容量
- 隸屬模塊:znFAT文件系統模塊
- 函數屬性:外部,使用戶使用
- 參數說明:無
- 返回說明:剩余容量,單位字節
- 注:從FSInfo中讀取空閑簇數,而從計算得到剩余的容量,單位字節
***********************************************************************/
#ifdef znFAT_GET_REMAIN_CAP
UINT32 znFAT_Get_Remain_Cap(void)
{
znFAT_ReadSector(1+pArg->BPB_Sector_No,znFAT_Buffer);
if(((struct FSInfo *)znFAT_Buffer)->Free_Cluster[0]==0xff
&& ((struct FSInfo *)znFAT_Buffer)->Free_Cluster[1]==0xff
&& ((struct FSInfo *)znFAT_Buffer)->Free_Cluster[2]==0xff
&& ((struct FSInfo *)znFAT_Buffer)->Free_Cluster[3]==0xff)
return pArg->Total_Size;
else
return LE2BE(((struct FSInfo *)znFAT_Buffer)->Free_Cluster,4)*pArg->SectorsPerClust*pArg->BytesPerSector;
}
#endif
//--------------------------------------------
/******************************************************************
- 功能描述:將小字字符轉為大寫
- 隸屬模塊:znFAT文件系統模塊
- 函數屬性:內部
- 參數說明:c:要轉換為大寫的字符
- 返回說明:要轉換的字節的相應的大寫字符
- 注:只對小寫字符有效,如果不是a~z的小寫字符,將直接返回
******************************************************************/
INT8 L2U(INT8 c)
{
if(c>='a' && c<='z') return c+'A'-'a';
else return c;
}
/***********************************************************************
- 功能描述:得到DBR所在的扇區號(如果沒有MBR,則DBR就在0扇區)
- 隸屬模塊:znFAT文件系統模塊
- 函數屬性:內部
- 參數說明:無
- 返回說明:DBR的扇區地址
- 注:DBR中包含了很多有用的參數信息,因此正確定位DBR扇區的位置,是極為
重要的,后面將有專門的函數對DBR進行解析,正確解析DBR是實現znFAT的
基礎
***********************************************************************/
UINT16 znFAT_Find_DBR(void)
{
UINT16 sec_dbr;
znFAT_ReadSector(0,znFAT_Buffer);
if(znFAT_Buffer[0]!=0xeb)
{
sec_dbr=LE2BE(((((struct PartSector *)(znFAT_Buffer))->Part[0]).StartLBA),4);
}
else
{
sec_dbr=0;
}
return sec_dbr;
}
/***********************************************************************
- 功能描述:獲取分區的總容量
- 隸屬模塊:znFAT文件系統模塊
- 函數屬性:外部,使用戶使用
- 參數說明:無
- 返回說明:分區容量值,單位為字節
- 注:這里得到的總容量是znFAT分區的容量,一定小于實際的物理容量
***********************************************************************/
#ifdef ZNFAT_GET_TOTAL_SIZE
UINT32 znFAT_Get_Total_Size(void)
{
return pArg->Total_Size;
}
#endif
/***********************************************************************
- 功能描述:讀取FSInfo獲取最近的一個可用空閑簇
- 隸屬模塊:znFAT文件系統模塊
- 函數屬性:內部
- 參數說明:無
- 返回說明:最近的一個可用空閑簇
- 注:znFAT中的FSInfo扇區(絕對1扇區)中記錄了最近的一個可用空閑簇
***********************************************************************/
UINT32 Search_Last_Usable_Cluster(void)
{
znFAT_ReadSector(1+pArg->BPB_Sector_No,znFAT_Buffer);
return LE2BE(((struct FSInfo *)znFAT_Buffer)->Last_Cluster,4);
}
/***********************************************************************
- 功能描述:znFAT文件系統初始化
- 隸屬模塊:znFAT文件系統模塊
- 函數屬性:外部,使用戶使用
- 參數說明:znFAT_Init_Arg類型的結構體指針,用于裝載一些重要的參數信息,
以備后面使用
- 返回說明:無
- 注:在使用znFAT前,這個函數是必須先被調用的,將很多參數信息裝入到
arg指向的結構體中,比如扇區大小、根目錄的位置、FAT表大小等等。
這些參數絕大部分是來自于DBR的BPB中,因此此函數主要在作對DBR的參數解析
***********************************************************************/
void znFAT_Init(void)
{
struct znFAT_BPB *bpb;
bpb=(struct znFAT_BPB *)(znFAT_Buffer); //將數據緩沖區指針轉為struct znFAT_BPB 型指針
pArg->DEV_No=Dev_No; //裝入設備號
pArg->BPB_Sector_No =znFAT_Find_DBR(); //znFAT_FindBPB()可以返回BPB所在的扇區號
znFAT_ReadSector(pArg->BPB_Sector_No,znFAT_Buffer);
pArg->FATsectors =LE2BE((bpb->BPB_FATSz32) ,4);//裝入FAT表占用的扇區數到FATsectors中
pArg->FirstDirClust =LE2BE((bpb->BPB_RootClus) ,4);//裝入根目錄簇號到FirstDirClust中
pArg->BytesPerSector =LE2BE((bpb->BPB_BytesPerSec),2);//裝入每扇區字節數到BytesPerSector中
pArg->SectorsPerClust =LE2BE((bpb->BPB_SecPerClus) ,1);//裝入每簇扇區數到SectorsPerClust 中
pArg->FirstFATSector =LE2BE((bpb->BPB_RsvdSecCnt) ,2)+pArg->BPB_Sector_No;//裝入第一個FAT表扇區號到FirstFATSector 中
pArg->FirstDirSector =(pArg->FirstFATSector)+(bpb->BPB_NumFATs[0])*(pArg->FATsectors); //裝入第一個目錄扇區到FirstDirSector中
pArg->Total_Size =LE2BE((bpb->BPB_TotSec32),4)*pArg->BytesPerSector; //磁盤的總容量,單位是字節
temp_last_cluster=Search_Last_Usable_Cluster();
}
/***********************************************************************
- 功能描述:更新FSInfo中的可用空閑簇的數量
- 隸屬模塊:znFAT文件系統模塊
- 函數屬性:內部
- 參數說明:PlusOrMinus:可用空閑簇數加1或減1
- 返回說明:無
- 注:創建文件、追加數據、刪除文件等操作都可能會使可用的空閑簇數變化
要及時更新
***********************************************************************/
#ifdef ZNFAT_UPDATE_FSINFO_FREE_CLU
void znFAT_Update_FSInfo_Free_Clu(UINT32 PlusOrMinus)
{
UINT32 Free_Clu=0;
znFAT_ReadSector(1+pArg->BPB_Sector_No,znFAT_Buffer);
Free_Clu=(znFAT_Get_Remain_Cap())/(pArg->SectorsPerClust*pArg->BytesPerSector);
if(PlusOrMinus) Free_Clu++;
else Free_Clu--;
((struct FSInfo *)znFAT_Buffer)->Free_Cluster[0]=Free_Clu&0x000000ff;//((UINT8 *)&Free_Clu)[0];
((struct FSInfo *)znFAT_Buffer)->Free_Cluster[1]=(Free_Clu&0x0000ff00)>>8;//((UINT8 *)&Free_Clu)[1];
((struct FSInfo *)znFAT_Buffer)->Free_Cluster[2]=(Free_Clu&0x00ff0000)>>16;//((UINT8 *)&Free_Clu)[2];
((struct FSInfo *)znFAT_Buffer)->Free_Cluster[3]=(Free_Clu&0xff000000)>>24;//((UINT8 *)&Free_Clu)[3];
znFAT_WriteSector(1+pArg->BPB_Sector_No,znFAT_Buffer);
}
#endif
/***********************************************************************
- 功能描述:更新FSInfo中的下一個可用空閑簇的簇號
- 隸屬模塊:znFAT文件系統模塊
- 函數屬性:內部
- 參數說明:Last_Clu:將要更新到FSInfo中的下一個可用空閑簇的簇號
- 返回說明:無
- 注:FSInfo中的下一個可用空閑簇號可以給文件系統一個參考,直接告訴文件系統
下一個可用的空閑簇在什么地方
***********************************************************************/
#ifdef ZNFAT_UPDATE_FSINFO_LAST_CLU
void znFAT_Update_FSInfo_Last_Clu(UINT32 Last_Clu)
{
znFAT_ReadSector(1+pArg->BPB_Sector_No,znFAT_Buffer);
((struct FSInfo *)znFAT_Buffer)->Last_Cluster[0]=Last_Clu&0x000000ff;//((UINT8 *)&Last_Clu)[0];
((struct FSInfo *)znFAT_Buffer)->Last_Cluster[1]=(Last_Clu&0x0000ff00)>>8;//((UINT8 *)&Last_Clu)[1];
((struct FSInfo *)znFAT_Buffer)->Last_Cluster[2]=(Last_Clu&0x00ff0000)>>16;//((UINT8 *)&Last_Clu)[2];
((struct FSInfo *)znFAT_Buffer)->Last_Cluster[3]=(Last_Clu&0xff000000)>>24;//((UINT8 *)&Last_Clu)[3];
znFAT_WriteSector(1+pArg->BPB_Sector_No,znFAT_Buffer);
}
#endif
/***********************************************************************
- 功能描述:獲得下一個簇的簇號
- 隸屬模塊:znFAT文件系統模塊
- 函數屬性:內部
- 參數說明:LastCluster:基準簇號
- 返回說明:LastClutster的下一簇的簇號
- 注:獲得下一簇的簇號,就是憑借FAT表中所記錄的簇鏈關系來實現的
***********************************************************************/
#ifdef ZNFAT_GETNEXTCLUSTER
UINT32 znFAT_GetNextCluster(UINT32 LastCluster)
{
UINT32 temp;
struct znFAT_FAT *pFAT;
struct znFAT_FAT_Item *pFAT_Item;
temp=((LastCluster/128)+pArg->FirstFATSector);
znFAT_ReadSector(temp,znFAT_Buffer);
pFAT=(struct znFAT_FAT *)znFAT_Buffer;
pFAT_Item=&((pFAT->Items)[LastCluster%128]);
return LE2BE((UINT8 *)pFAT_Item,4);
}
#endif
/***********************************************************************
- 功能描述:比較目錄名
- 隸屬模塊:znFAT文件系統模塊
- 函數屬性:內部
- 參數說明:a:指向目錄名1的指針
b:指向目錄名2的指針
- 返回說明:如果兩個目錄名相同就返回1,否則為0
***********************************************************************/
#ifdef COMPARE_DIR_NAME
UINT8 Compare_Dir_Name(CONST INT8 *a,CONST INT8 *b)
{
UINT8 i;
for(i=0;i<8;i++)
{
if(a[i]!=b[i]) return 0;
}
return 1;
}
#endif
/***********************************************************************
- 功能描述:文件名匹配(支持帶*?通配符的文件名的匹配)
- 隸屬模塊:znFAT文件系統模塊
- 函數屬性:內部
- 參數說明:pat:源文件名,可以含*或?通配符 如 *.txt 或 A?.mp3等等
name:目標文件名
- 返回說明:如果兩個文件名匹配就返回1,否則為0
- 注:關于通配文件名匹配,有這樣的例子,比如 A*.txt 與 ABC.txt是匹配的
同時與 ABCDE.txt也是匹配的。此功能在文件枚舉中將會用到,用來匹配
文件名符合一定條件的文件
***********************************************************************/
#ifdef FILENAMEMATCH
UINT8 FilenameMatch(INT8 *pat,INT8 *name)
{
UINT8 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;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -