FatFS簡介


1.1 簡介

  隨着信息技術的發展,當今社會的信息量越來越大,以往由單片機構成的系統簡單地對
存儲媒介按地址、按字節的讀/寫已經不能滿足人們實際應用的需要,於是利用文件系統對
存儲媒介進行管理成了今后單片機系統的一個發展方向。目前常用的文件系統主要有微軟的
FATl2、FATl6、FAT32、NTFS 以及Linux 系統下的EXT2 和EXT3 等。由於微軟Windows
的廣泛應用,在當前的消費類電子產品中,用得最多的還是FAT 文件系統,如U 盤、MP3、
MP4 和數碼相機等,所以找到一款容易移植和使用、占用硬件資源相對較小而功能又強大
的FAT 開源文件系統,對於單片機系統設計者來說是很重要的。

  FatFs Module 是一種完全免費開源的FAT 文件系統模塊,專門為小型的嵌入式系統而
設計。它完全用標准C 語言編寫,且完全獨立於I/O 層,可以移植到 8051、PIC、AVR、SH、
Z80、H8 和ARM 等系列單片機上且只需做簡單的修改。它支持FATl2、FATl6 和FAT32,
支持多個存儲媒介,有獨立的緩沖區,可以對多個文件進行讀/寫。

  FatFs Module 有個簡化版本Tiny-FatFs,它跟完全版FatFs 不同之處主要有兩點:

(1) 占用內存更少,只要1 KB RAM; 

(2) 1 次僅支持 1 個存儲介質。

完全版FatFs 和Tiny-FatFs 的用法一樣,僅僅是包含不同的頭文件,本文主要以完全版
講解FatFs 的使用。

1.2 特性

(1)Windows 兼容的FAT 文件系統;
(2)平台無關,容易移植;
(3)代碼量小;
(4)多種配置選項:
   支持多卷(物理驅動器或分區);
   多個ANSI/OEM 代碼頁包括DBCS;
   支持長文件名,ANSI/OEM 或Unicode;
   支持RTOS;
   支持多種扇區大小;
   只讀、最小化的API 和I/O 緩沖區等。

1.3 應用

FatFs Module 一開始就是為了能在不同的單片機上使用而設計的,所以具有良好的層次
結構,如圖 1.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 提供的底層接口,它包括存儲媒介讀/寫
接口Disk I/O 和供給文件創建修改時間的實時時鍾。

  本文講解時移植硬件平台為ZLG 公司的SmartCortexM3-1700 和普通U 盤。LPC1768
是一款32 位 Cortex-M3 內核的單片機,具有多達64 KB 的SRAM、512 KB 的內部Flash 和
豐富的外設。軟件平台是Keil 集成開發環境。

1.3.1 FatFs 軟件包中相關文件

1. 平台無關

(1)ffconf.h FatFs 模塊配置文件

(2)ff.h FatFs 和應用模塊公用的包含文件

(3)ff.c FatFs 模塊

(4)diskio.h FatFs and disk I/O 模塊公用的包含文件

(5)integer.h 數據類型定義

(6)option 可選的外部功能

2. 平台相關(不屬於 FatFs 需要由用戶提供)

(1)diskio.c FatFs 與disk I/O 模塊接口層文件

1.3.2 FatFs 應用范圍

支持FAT12、FAT16 和FAT32;
可打開的文件:無限制,依賴於有效的存儲器;
支持最多 10 個卷;
文件大小:與FAT 類型有關(upto 4G-1 bytes);
卷大小:與FAT 類型有關(upto 2T bytes on 512 bytes/sector);
簇大小:與FAT 類型有關(upto 64K bytes on 512 bytes/sector);
扇區大小:與FAT 類型有關(upto 4K bytes)。

FatFs 模塊在移植時需先注意以下兩點:

•ANSI C

FatFs 模塊是用ANSI C 編寫的中間件,只要編譯器遵循ANSI C,它都是平台無關的。

•整型大小

FatFs 假定 char/short/long 的長度為8/16/32 位,而int 為 16 位或 32 位,這些相應的定
義位於integer.h 文件。這在大多數的編譯器上都不會是問題,但是當與預定義的內容發生沖
突時,需要用戶注意。

1.3.3 FatFs 配置

文件系統的配置項都在ffconf.h 文件之中。

(1) _FS_TINY :這個選項在R0.07 版本之中開始出現,在之前的版本都是以獨立的C

文件出現,現在通過一個宏來修改使用起來更方便;決定在文件數據傳輸中使用哪種扇區緩沖區 
(2) _FS_MINIMIZE、_FS_READONLY、_USE_STRFUNC、_USE_MKFS、
_USE_FORWARD 這些宏是用來對文件系統進行裁剪的,下面的 1.3.4 小節中有詳細介紹;
(3) _CODE_PAGE :本選項用於設置語言碼的類型,對應的字庫可以在網上下載

(4) _USE_LFN :取值為0~3,主要用於長文件名的支持及緩沖區的動態分配:
0:不支持長文件名;
1:支持長文件名存儲的靜態分配,一般是存儲在BSS 段;
2:支持長文件名存儲的動態分配,存儲在棧上;
3:支持長文件名存儲的動態分配,存儲在堆上。
(5) _MAX_LFN :可存儲長文件的最大長度,其值一般為(12~255),但是緩沖區一
般占(_MAX_LFN + 1) * 2 bytes;
(6) _LFN_UNICODE :為1 時才支持unicode 碼;
(7) _FS_RPATH :R0.08a 版本改動配置項,取值范圍0~2:
0:去除相對路徑支持和函數;
1:開啟相對路徑並且開啟f_chdrive()和 f_chdir()兩個函數;
2:在1 的基礎上添加f_getcwd()函數。

(8) _VOLUMES :支持的邏輯設備數目;
(9) _MAX_SS :扇區緩沖的最大值,其值一般為512;
(10) _MULTI_PARTITION :定義為1 時,支持磁盤多個分區;
(11) _USE_ERASE :R0.08a 新加入的配置項,設置為 1 時,支持扇區擦除;
(12) _WORD_ACCESS :如果定義為1,則可以使用word 訪問;
(13) _FS_REENTRANT :定義為1 時,文件系統支持重入,但是需要加上跟操作系統
信號量相關的幾個函數,函數在 syscall.c 文件中;
(14) _FS_SHARE :文件支持的共享數目。

  FatFs 只要求提供FatFs 模塊所必需的底層磁盤I/O 函數,如果存在一個可工作的目標磁
盤模塊,你僅需將編寫的新函數附加到FatFs 模塊上,如果沒有,則需要提供其它磁盤模塊
或者從頭編寫底層驅動。FatFs 中所有定義的函數並不總是必需的,例如,在只讀配置模式
下,磁盤寫函數是不需要的。表 1.1 顯示了FatFs 的函數需要依賴於配置選項。

 

1.3.4 FatFs API 函數選擇

  通過配置選項對API 函數進行選擇(剪裁)以減小模塊代碼大小

1.3.5 路徑名格式

  FatFs 模塊上使用的路徑名格式類似於DOS/Windows 下的文件名,格式如下:

"[drive#:][/]directory/file"

  FatFs 模塊支持長文件名 (LFN)和DOS 8.3 文件名 (SFN)。當使能LFN 特性時 (_USE
_LFN > 0),可以使用長文件名,子目錄用‘\ ’或者‘/ ’隔開,這與DOS/Windows API 函
數接口是相同的方式,不同的是邏輯驅動器用數字帶一個冒號來指定的。當一個驅動器號被
忽略時,默認為驅動器0 或者當前驅動器。控制字符(\0~\x1F )被認為是路徑名的末尾。
首位或中間嵌入的空格是合法的,當配置為LFN 時被看作是名字的一部分,配置為非LFN
時被視為路徑名的末尾。空格和點號被忽略。

  默認配置下(_FS_RPATH == 0 ),FatFs 沒有一個像操作系統面向文件系統的當前目錄
的概念。卷上的所有對象總是以根目錄下的完整路徑名來指定,不允許點目錄名。標題分隔
符’/’被忽略,它可以存在或省略,默然的驅動器號為0。

  當使能相對路徑時(_FS_RPATH == 1 ),如果存在標題分隔符,指定的路徑是指相對
於根目錄,如果沒有標題分隔符,指定目錄是指相對於用f_chdir 函數設置的當前目錄,路
徑名中允許使用點名稱。默認的驅動器是用 f_chdrive 函數設定的當前驅動器。

1.3.6 關於長文件名

FatFs 從0.07 版本開始支持長文件名(LFN)。在調用文件函數時,一個文件的兩個文
件名(SFN 與LFN)是通用的,除了f_readdir 函數。支持長文件特性將需要一個額外的工
作緩沖區,此緩沖區的大小可以通過設置_MAX_LFN 來以可用的內存大小相符。因為長文
件名可長達255 個字符,因此_MAX_LFN 應該設置為255 來支持全特性的LFN 選項。當工
作緩沖區的大小容不下給出的文件名時文件函數就會因為FR_INVALID_NAME 而調用失
敗。

當使能LFN,模塊增加的大小由編碼頁(Code Page)類型決定。日語、中文與韓國語擁有成千上萬的字詞,因
需要一個巨大的OEM-Unicode 雙向轉換表,模塊的大小將大大的增大。

注:FAT 文件系統的LFN 特性是微軟公司的專利。當在商用產品上使用時,根據最終目的的不同可

能需要獲得微軟的許可證。

 1.3.7 重入

對不同卷的文件操作總是可以同時地工作,而與重入設置無關。而對於同一個卷的重入
訪問可以通過使能_FS_REENTRANT 選項。此時,在 ff.c 中的與平台相關的鎖定函數必須
為每個RTOS 重新編寫。如果一個文件函數調用時其訪問的卷正被另一個線程使用,則此
訪問將阻塞直到該卷解鎖。如果等待時間超過了_TIMEOUT 毫秒,則函數將因FR_TIMEOUT
而終止。某些RTOS 可能不支持超時操作。

f_mount 與f_mkfs 函數是個例外,這些函數對於同一個卷不會重入。當使用這些函數時,
其它線程必須關閉此卷中相應的文件,避免對此卷的訪問。

注意此部分描述的是FatFs 自身的重入,與底層磁盤I/O 的重入無關。

1.3.8 執行有效的文件訪問

  為了在小型的嵌入式系統中得到優秀的讀寫效率,應用程序程序員需要可考慮FatFs 究
竟做了什么。磁盤中的數據是通過下面的方式來被f_read 函數傳送。

  文件I/O 緩沖區(file I/O buffer)表示一個將被讀/寫數據的扇區的緩沖區。扇區緩沖區
可以是每個文件對象私有的,或者是文件系統共享的,緩沖區配置選項_FS_TINY 決定在文
件數據傳輸中使用哪種扇區緩沖區。當選擇小緩沖區(1),數據內存的使用量將降低到每
個文件對象 512 字節。在這種情況下,FatFs 只使用一個扇區緩沖區來進行文件數據傳輸以
及FAT/ 目錄訪問。配置為小緩沖區的缺點是:每次文件數據傳輸時FAT 數據緩沖都會丟失
而必須從一個簇的邊界開始重新載入數據。不過從其體面的表現與少內存消耗這方面來考
慮,這對於多數的應用也是合適的。

  使用扇區對齊的方式來進行讀寫訪問可以避免緩沖區數據傳輸,並且讀寫效率將被
提升。除了效率以外,在tiny 配置的情況下FAT 快速緩存數據在文件數據傳輸時不會刷新,
所以可以用小內存消耗來達到非tiny 配置相同的性能。

1.3.9 臨界區

當對FAT 文件系統的寫操作由於意外而中斷,如突然斷電,不正確的磁盤移除或不可
恢復的磁盤錯誤,FAT 結構可能被毀壞。

1.3.10 FatFs 的其它特性和新進展

(1) 支持並發操作;

在多任務操作系統中,各個任務是並發的。當它們要同時訪問文件系統時,先要獲得同
步對象。比如在uCOS 中,可以采用互斥信號量來同步。在f_mount()時,創建同步對象,
在check_mount()和validate()函數調用時,先申請同步對象,若是其它任務在使用文件系統,
則在同步對象上等待。任務完成后,再釋放同步對象。這個功能與操作系統的任務同步特性
相關,以后如果要使用這個特性的話在詳細分析。

(2) 支持文件的共享打開(主要是多次以讀的方式打開);

這是FatFs 作者在3 月份新上傳的R008 Rev1 版本里新增加的功能:在ffconf.h 中增加
了_FS_SHARE 共享數目定義。在 ff.h 增加了:文件共享信息結構體定義,並在文件系統結
構體中使用,在ff.c 中增加了5 個函數。

(3) 支持文件的快速定位;

內存中划一塊緩沖區用於存儲 文件的簇鏈映射圖,以方便查找簇鏈。稍微閱讀了以下
源代碼,其實現方法是這樣的:當給出參數 ofs == CREATE_LINKMAP 的時候,在tbl 所指
向的內存區域建立新的簇鏈映射。

表的第一項是整個映射表的長度,以后每兩項為一對:前者存儲相鄰簇的數目,后者存
儲相鄰簇的起始簇號。舉個例子,某個文件占據 5、6、7、8、15、16、17 共 7 個簇,則需
要兩對表項。分別是(4,5)和(3,15)兩項。以后就可以利用該簇鏈映射圖實現文件的
快速定位了,不用沿着簇鏈一項一項找下去,最后實現定位。

(4) 支持長文件名緩沖區的動態分配;
(5) 添加函數 f_getcwd();
(6) 添加_USE_ERASE ;

將以前的 auto_mount()改成了現在的chk_mounted()添加部分功能使文件系統更適合多
邏輯設備數目。

1.3.11 程序移植

移植FatFs 主要分為三步:

(1) 數據類型:在integer.h 里面去定義好數據的類型。這里需要了解你用的編譯器的數
據類型,並根據編譯器定義好數據類型。
(2) 配置:打開 ffconf.h (我用的FatFs,不是Tiny,可以在此頭文件中進行定義),文
件系統的配置裁剪等均在此頭文件中進行定義配置。
(3) 函數編寫:打開diskio.c,進行底層驅動編寫,實際上需要編寫6 個接口函數,如
圖1.6 所示。

1.3.12 diskio.c函數編寫

1、disk_initialize

初始化磁盤驅動器 

2、disk_status

返回當前磁盤驅動器的狀態 

3、disk_read 

從磁盤驅動器上讀取扇區

4、disk_write 

向磁盤寫入一個或多個扇區 

5、disk_ioctl 

控制設備指定特性和除了讀/寫外的雜項功能

6、get_fattime 

獲取當前時間

1.3.13 FatFS軟件包提供的API函數

 1、f_mount:注冊/注銷一個工作區

2、f_open:打開/創建一個文件

3、f_close:關閉一個文件

4、f_read:讀文件

5、f_write:寫文件

6、f_lseek:移動讀/寫指針,擴展文件大小

7、f_truncate:截斷文件大小

8、f_sync:刷新緩沖區

9、f_opendir:打開一個目錄

10、f_readdir:讀取目錄

11、f_getfree:獲取空閑簇

12、f_stat:獲取文件狀態

13、f_mkdir:創建一個新目錄

14、f_unlink:刪除一個文件

15、f_chmod:改變一個文件或目錄的屬性

16、f_utime:改變一個文件或目錄的時間戳

17、f_rename:重命名一個對象

18、f_mkfs:格式化

19、f_forward:讀取文件數據轉移到數據流設備

20、f_chdir:改變驅動器的當前目錄

21、f_chdrive:改變當前驅動器

22、f_getcwd:檢索當前目錄

23、f_gets:從文件中讀取字符串

24、f_putc:從文件中寫一個字符

25、f_puts:往文件中寫一個字符串

26、f_printf:往文件中寫入格式化字符串

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM