FatFs中文介紹和移植方法
——————————————一下為轉載—————————————————————-
下面是我做的一些中文解釋。大家可以到原網站獲取更多的資訊。
英文原文:FatFs is a generic file system module to implement the FAT file system to small embedded systems. The FatFs is written in compliance with ANSI C, therefore it is independent of hardware architecture. It can be incorporated into cheap microcontrollers, such as 8051, PIC, AVR, SH, Z80, H8, ARM and etc…, without any change.
中文譯文:
FatFs是一個通用的檔案系統模組,以小的嵌入式系統的FAT檔案系統。 FatFs的程式設計遵守的ANSI C格式語法標準,因此,它是具有獨立於硬體架構。 在不做任何改變就可以被移植到常用的微控制器中,如8051, PIC, AVR, SH, Z80, H8, ARM等。
FatFs 特點
分離緩衝的FAT結構和每一個檔案,適合快速訪問多個檔案。
支援多個驅動器和分割槽。
支援FAT12 , FAT16和FAT32 。
支援8.3格式的檔名(LFN不支援)
支援兩個分割槽規則: Fdisk和超級軟盤。
優化8/16-bit微控制器。
應用介面
FatFs /微型FatFs模組提供下列功能。
f_mount – 登記或登出一個工作領域
f_open -開啟或建立檔案
f_close – 關閉一個檔案
f_read – 讀檔案
f_write – 寫檔案
f_lseek -移動檔案讀/寫指標
f_truncate – 截斷檔案
f_sync – 重新整理快取的資料
f_opendir – 開啟一個目錄
f_readdir – 閱讀目錄專案
f_getfree -獲取免費叢集
f_stat – 獲取檔案狀態
f_mkdir – 建立一個目錄
f_unlink – 刪除檔案或目錄
f_chmod – 更改屬性
f_utime – 變更時間戳記
f_rename -重新命名/移動檔案或目錄
f_mkfs – 建立一個檔案系統的驅動器
f_forward -轉發檔案資料流直接
fgets – 讀一個字串
fputc – 寫一個字元
fputs – 寫一個字串
fprintf – 寫格式化字串
Disk I/O Interface
disk_initialize -初始化的磁碟驅動器
disk_status – 獲取磁碟狀態
disk_read – 讀部門(星期日)
disk_write – 收件部門(星期日)
disk_ioctl – 控制裝置依賴功能
get_fattime – 獲取當前時間
一種易於移植和使用的檔案系統FatFs Moule
引 言
隨著資訊科技的發展,當今社會的資訊量越來越大,以往由微控制器構成的系統簡單地對儲存媒介按地址、按位元組的讀/寫已經不滿足人們實際應用的需要,於是利用檔案系統對儲存媒介進行管理成了今後微控制器系統的一個發展方向。目前常用的檔案系統主要有微軟的FATl2、FATl6、FAT32、NTFS,以及Linux系統下的EXT2、EXT3等。由於微軟Windows的廣泛應用,在當前的消費類電子產品中,用得最多的還是FAT檔案系統,如U盤、MP3、MP4、數碼相機等,所以找到一款容易移植和使用、佔用硬體資源相對較小而功能又強大的FAT開原始檔系統,對於微控制器系統設計者來說是很重要的。
FatFs Module是一種完全免費開源的FAT檔案系統模組,專門為小型的嵌入式系統而設計。它完全用標準C語言編寫,所以具有良好的硬體平臺獨立性,可以移植到8051、PIC、AVR、SH、Z80、H8、ARM等系列微控制器上而只需做簡單的修改。它支援FATl2、FATl6和FAT32,支援多個儲存媒介;有獨立的緩衝區,可以對多個檔案進行讀/寫,並特別對8位微控制器和16位微控制器做了優化。FatFs Module有個簡化版本Tiny—FatFs,它跟完全版FatFs的不同之處主要有兩點:
①佔用記憶體更少,只要1 KB RAM;
②1次僅支援1個儲存介。
FatFs和Tiny—FatFs的用法一樣,僅僅是包含不同的標頭檔案即可,非常方便,本文主要介紹Tiny-FatFs.
1 Tiny-FatFs
1.1 移植前的準備
FatFs Module一開始就是為了能在不同的微控制器上使用而設計的,所以具有良好的層次結構,如圖1所示。最頂層是應用層,使用者無需理會FatFs Module的內部結構和複雜的FAT協議,只需要呼叫FatFs Module提供給使用者的一系列應用介面函式,如f_open,f_read,f_write、f_close等,就可以像在PC上讀/寫檔案那樣簡單。
中間層FatFs Module實現了FAT檔案讀/寫協議。FatFs Module的完全版提供的是ff.c、ff.h,簡化版Tiny—FatFs提供的是tff.c、tff.h。除非有必要,使用者一般不用修改,使用時將需要版本的標頭檔案直接包含進去即可。
需要使用者編寫移植程式碼的是FatFs Module提供的底層介面,它包括儲存媒介讀/寫介面DiskIO和供給檔案建立修改時間的實時時鐘。
本移植硬體平臺使用型號為ATmegal28的AVR微控制器和SD卡。ATmegal28是一種8位RISC微控制器,具有多達4 KB的RAM、128 KB的內部Flash和豐富的外設。軟體平臺是WINAVR,具有程式碼優化能力強和完全免費的優點。
1.2 移植步驟
1.2.1 編寫SPI和SD卡介面程式碼
本文使用SD卡的SPI通訊模式。SD卡的DI接MOSI,DO接MISO,CS接SS。這就需要ATmegal28提供SPI讀/寫介面程式碼,主要包括初始化、讀和寫。SPI初始化包括SPI相關暫存器的初始化和相關I/O口的初始化。將ATmega 128的SPI配置成主機模式、資料高位先傳、時鐘速率為二分之一系統時鐘等。程式碼如下:
SPCR=(O<<SPIE)|
(1<<SPE)|
(O<<DORD) |
(1<<MSTR)|
(O<<CPOL) |
(O<<CPHA)|
(O<<SPR1) |
(O<<SPRO);
SPSR|=(1<<SPI2X);
接著配置I/O口的輸入/輸出。MOSI腳和Ss腳配置成輸出,MISO腳配置成輸入。然後,就可以進行讀/寫了。
讀1個位元組的SPI介面程式碼:
static BYTE rcvr_spi(void){
SPDR=OxFF;
loop_until_bit_is_set(SPSR,SPIF);
return SPDR;
}
寫1個位元組的SPI介面程式碼:
static void xmit_spi(BYTE dat){
SPDR=dat;
loop_until_bit_is_set(SPSR,SPIF)
}
在具備SPI讀/寫介面的基礎上編寫SD卡介面程式碼,需要編寫3個基本介面函式:
①向SD卡傳送1條命令:
Static BYTE send-cmd(BYTE cmd,DWORD arg);
②向SD卡傳送1個數據包:
Static BOOL xmit—datablock(const BYTE *buff,BYTE token);
③從SD卡接收1個數據包:
static BCK]L rcvr-datablock(BYTE*buff,UINT btr);
1.2.2 編寫DiskIO
編寫好儲存媒介的介面程式碼後,就可以編寫DiskIO了,DiskIO結構如圖2所示。
Tiny—FatFs的移植實際上需要編寫6個介面函式,分別是:
①DSTATUS disk_initialize(BYTE drv);
儲存媒介初始化函式。由於儲存媒介是SD卡,所以實際上是對SD卡的初始化。drv是儲存媒介號碼,由於Tinv—FatFs只支援一個儲存媒介,所以drv應恆為0。執行無誤返回0,錯誤返回非0。
②DSTATUS disk_status(BYTE drV);
狀態檢測函式。檢測是否支援當前的儲存媒介,對Tinv—FatFs來說,只要drv為0,就認為支援,然後返回0。
③DRESULT disk_read(BYTE drv,BYTE*buff,DWORD sector,BYTE.count);
讀扇區函式。在SD卡讀介面函式的基礎上編寫,*buff儲存已經讀取的資料,sector是開始讀的起始扇區,count是需要讀的扇區數。1個扇區512個位元組。執行無誤返回O,錯誤返回非0。
④DRESULT disk_write(BYTE drv,const BYTE*buff,DWORD sector,BYTE count);
寫扇區函式。在SD卡寫介面函式的基礎上編寫,*buff儲存要寫入的資料,sector是開始寫的起始扇區count是需要寫的扇區數。1個扇區512個位元組。執行無誤返回0,錯誤返回非0。
⑤DRESULT disk_ioctl(BYTE drv,BYTE ctrl,VoiI*buff);
儲存媒介控制函式。ctrl是控制程式碼,*buff儲存或接收控制資料。可以在此函式裡編寫自己需要的功能程式碼,比如獲得儲存媒介的大小、檢測儲存媒介的上電與否儲存媒介的扇區數等。如果是簡單的應用,也可以不用編寫,返回O即可。
⑥DWORD get_fattime(Void);
實時時鐘函式。返回一個32位無符號整數,時鐘資訊包含在這32位中,如下所示:
bit31:25 年(O..127)從1980年到現在的年數
bit24:21 月(1…12)
bit20:16 日(1..31)
bitl5.1] 時(O..23)
bitl0:5 分(O..59)
bit4:0 秒/2(0..29)
如果用不到實時時鐘,也可以簡單地返回一個數。正確編寫完DiskIO,移植工作也就基本完成了,接下來的工作就是對Tiny—FatFs進行配置。
2 Tiny—FatFs的配置
Tiny—FatFs是一款可配置可裁減的檔案系統,使用者可以選擇自己需要的功能。Tiny—FatFs總共有5個檔案,分別是tff.c、tff.h、diskio.c、diskio.h和integer.h。tff_c和integer.h一般不用改動,前面的移植工作主要更改的是diskio.c,而配置Tiny—FatFs則主要修改tff.h和diskio.h。
在diskio.h中,使用者可以根據需要使能disk—write或disk_ioctl。以下程式碼使能disk_write和disk_ioctl:
#define—READONLY 0
#define—USE_IOCTL 1
在tff.h中,使用者可以根據需要對整個檔案系統進行全面的配置:
①#define_MCU_ENDIAN。有1和2兩個值可設,預設情況下設1,以獲得較好的系統性能。如果微控制器是大端模式或者設為1時系統執行不正常,則必須設為2。
②#define_FS_READONLY。設為1時將使能只讀操作,程式編譯時將檔案系統中涉及寫的操作全部去掉,以節省空間。
③#define_FS_MINIMIZE。有0、1、2、3四個選項可設。設0表示可以使用全部Tiny-FatFs提供的使用者函式;設1將禁用f_stat、f_getfree、f_unlink、f_mkdir、f_chmod和f_rename;設2將在1的基礎上禁用f_opendir和f_readdir;設3將在1和2的基礎上再禁用f_lseek。使用者可以根據需要進行裁減,以節省空間。
④#define_FAT32。設1時將支援FAT32。
⑤#define_USE_FSINFO。設1時提供FAT32的磁碟資訊支援。
⑥#define_USE_SJIS。設1時支援Shift-JIS碼,一般設0。
⑦#define_USE_NTFLAG。設1時將對檔名大小寫敏感。3 TINY-FatFs 的讀/寫測試
Tiny-FatFs的功能很強大,提供了豐富而易於使用的使用者介面函式,如圖3所示。
Tiny—FatFs的功能很全,本文僅測試f_mount、f_open、f_read、f_write和f_close五個函式來讀一個3.4 MB的檔案和寫一個1MB的檔案,檔名分別為testl.dat和test2.dat。主要程式碼如下:
經過實際測試,在微控制器系統時鐘為11.059 2 MHz下讀一個3.4 MB檔案耗時約20 s,平均約170 KB/s;寫一個1 MB檔案耗時約6s,平均約166 KB/s,在資源有限的微控制器系統下這個讀/寫速度是相當令人滿意的。綜上所述,FatFs Module具有容易移植、功能強大和易於使用的優點,適用於小型嵌入式系統;又是完全的免費和開源,也可以用於教育科研及其商業用途。