標籤:顯示 過程 格式 版本 rgb pac 檔案大小 官方 控制
本文使用的FatFs版本為:V0.12b(2016年9月4發布)
1.如何移植1.1首要考慮FatFs模組移植基於以下假設條件:
- ANSI C: 編譯器應遵循ANSI C。FatFs模組是以ANSI C(C89標準)語言編寫的中介軟體軟體,它不依賴任何硬體平台,只要相應的編譯器支援ANSI C。
- 整形類型大小: FatFs模組假設char/short/long類型變數大小為8/16/32位、假設int類型變數為16或32位。這些內容定義在檔案integer.h中,對大多數編譯器而言,預設的定義都不會有什麼問題。如果與當前的定義有衝突,你必須在這個檔案中小心的解決掉。
1.2系統組織圖圖1-1給出了嵌入式系統FatFs模組典型的關係依賴圖。圖中假設使用SPI介面訪問SD卡,藍色地區表示FatFs模組,注意FatFs模組並不包含也從不關心綠色地區的底層磁碟IO層。對於使用SPI訪問SD卡的應用,FatFs官網提供的常式中,有使用硬體SPI和類比SPI的常式。
圖1-1:FatFs關係依賴圖如果只有一個磁碟裝置,並且使用FatFs提供的磁碟介面,則不需要其它模組,只管編寫應用程式即可,1-2(a)所示。如果使用多種不同介面,則需要編寫另外一層軟體,用來在磁碟機和FatFs之間翻譯命令和資料流,1-2(b)所示。
注意圖1-2中灰色部分屬於底層磁碟I/O層,FatFs從來不關心這一層是如何?的!
圖1-2:單個裝置和多個裝置系統1.3移植必須實現的函數
僅需要提供FatFs模組需要的底層磁碟I/O函數,其它的均不是必須的。大部分函數不是必須的,例如,磁碟寫函數在配置為唯讀模式時就不是必須的。表1-1給出函數是否需要與配置選項的關係。
表1-1:移植時需要的函數列表
2.限制
- 支援的檔案系統類型:FAT12、FAT16、FAT32(r0.0)和exFAT(r1.0,從版本R0.12開始支援)
- 開啟的檔案數目:無限制(取決於可用記憶體)
- 卷數量:最大為10
- 卷大小:最大為2TB(512位元組/扇區)
- 單個檔案大小:FAT卷最大為4GB,exFAT卷幾乎無限制(理論16*1024*1024TB)
- 簇大小:FAT卷最大為128扇區,exFAT卷最大為16MB
- 扇區大小:512、1024、2048、4096位元組
什麼是exFAT?
exFAT(Extended File Allocation Table File System,擴充FAT)是Microsoft在Windows Embeded 5.0以及以上版本中引入的一種適合於快閃記憶體的檔案系統,為瞭解決FAT32檔案系統不支援大於等於4GB的單個檔案而推出。
卷、簇和扇區?
卷(邏輯磁碟機)是檔案系統為管理物理磁碟而提出的。一個物理磁碟可以有多個卷,多個物理磁碟也可以映射到1個卷上。我們常說將硬碟分為4個區,對於檔案系統而言,實際上它就要管理4個卷。
簇可以簡單的理解為是一組扇區,是檔案系統管理磁碟資料區的最小單位,一個檔案即便是0位元組,也一定會佔用一個簇。當格式化磁碟時,會有“配置單位大小”選項,預設選擇為4096位元組,這個大小就是簇大小。
扇區是物理磁碟的最小單位,在製造時大小已經確定,對於隨身碟、SD卡,一般為512位元組。
3.記憶體使用量量記憶體使用量量大小取決於配置選項,表3-1顯示了在特定配置下的ROM和RAM使用方式(FatFs官方網站上有更多的平台供參考,這裡截取了其中的常用平台)。在此之前,先來瞭解一下表3-1會遇到的配置選項和縮寫。
在表3-1中:
- V表示宏_VOLUMES定義的值(卷的個數);
- F表示開啟的檔案數。
- 宏_FS_READONLY表示讀寫限制,0表示讀/寫(R/W),1表示唯讀(R/O);
- 宏_FS_MINIMIZE用於函數裁剪,0表示全功能版(Full),3為最小功能(Min);
- 宏_FS_TINY用於模式配置,0表示正常模式,1表示微型模式。
表3-1:不同平台、不同配置下,FatFs模組ROM和RAM消耗參考
4.功能裁剪表4-1列出了FatFs的所有API函數以及函數在不同配置下的裁剪情況。表4-1:API函數和配置宏關係
5.長檔名FatFs模組從版本0.07開始支援長檔名。除了函數f_readdir函數外,FatFs模組的其它函數對短檔案名稱(SFN)和長檔名(LFN)是透明的。預設情況下,長檔名被禁止。要使能長檔名,需要設定宏_USE_LFN為1、2或3,並且需要向項目中增加檔案option/unicode.c。LFN需要一些額外的緩衝,緩衝的大小通過宏_MAX_LFN來設定。長檔名最多可能需要255個字元,所以要完全符合長檔名的特性,則至少需要分配255位元組的緩衝區。如果分配的緩衝區不足以放下檔案名稱,則檔案函數會返回一個FR_INVALID_NAME的錯誤值。當使能了長檔名特性並且使能了可重新進入特性(宏_FS_REENTRANT==1),_USE_LFN必須設定為2或3。在這種情況下,檔案函數訪問的檔案名稱工作區緩衝位域棧或堆中。工作緩衝區佔用(_MAX_LFN+1)*2位元組,如果使能exFAT檔案系統,需要再增加608位元組緩衝。
表5-1列出了在Cortex-M3硬體平台、GCC編譯器環境,使用長檔名時不同內碼錶增加的ROM大小。
當LFN特性被使能,ROM大小的增長取決於所用的內碼錶。上表顯示了使用LFN特性後幾種內碼錶對應的ROM增長大小。當使用日文、中文和漢語時,會有成千上萬的字元。不幸的是,它們需要一個巨大的OEM-Unicode雙向轉換表,這會使得模組的大小大幅度的增加,就像表中所給出的資料所示。因此,FatFs的雙位元組字元集的長檔名特性對於大多數的8位微控制器是不現實的。(這也是為什麼作者在很長的時間內都沒有興趣實現LFN特性的原因)。
註:FAT檔案系統中的長檔名特性微軟的專利。當在一個商業應用中使能LFN時,可能需要向微軟申請許可。
6.Unicode API預設情況下,FatFs的API函數使用ANSI/OEM代碼集,即使在使能長檔名的情況下也是如此。但是FatFs也可以切換到Unicode代碼集,只需要_LFN_UNICODE==1。使用ANSI/OEM代碼集時字串資料型別使用char,使用Unicode代碼集時,字串資料型別使用WCHAR(UTF-16)。《FatFs路徑名稱規則》一文提供了關於Unicode更詳細的資訊。
7.exFAT檔案系統exFAT(Microsoft‘s Extended File Allocation Table)檔案系統是微軟在廣泛使用的嵌入式作業系統中為替換FAT檔案系統而開發的。它已經被SDA(SD卡協會)所採納並推薦使用者在高容量SD卡(>32G)中使用。因此exFAT即將成為抽取式存放裝置器的標準檔案系統。
對於FAT32系統來說,單個檔案被限制到最大4GB,但exFAT檔案系統單個檔案大小可以超過256TB!此外相對於FAT檔案系統,exFAT檔案系統在檔案系統開銷、特別是檔案分配延時上都有降低,能夠改善檔案寫效率。但是,當前FatFs版本軟體也存在一個問題,就是在檔案寫入扇區非對齊時不如FAT檔案系統輸送量大。可以使用f_expand函數預先分配一個連續塊來避免這個問題。
注意exFAT屬於微軟專利!FatFs模組的exFAT功能是根據US. Pat. App. Pub. No. 2009/0164440 A1來實現的。可以通過配置宏使能或禁用exFAT功能。當在商業產品上使能exFAT功能後,需要向微軟申請許可。
特別注意,使能exFAT後,不再相容C89,因為需要64位整形類型。
8.可重新進入性不同卷上的檔案操作總是可重新進入的(使能長檔名並且使用靜態工作緩衝區除外),並且可以同時工作。相同卷上的檔案操作是不可重新進入的,但是也可以通過配置_FS_REENTRANT選項使用線程保護。在這種情況下,需要OS的同步對象控制函數,必須增加函數ff_cre_syncobj、ff_del_syncobj、ff_req_grant和ff_rel_grant到工程。
當卷被某個任務使用時,這時如果另外一個任務調用檔案函數,那麼訪問會被阻塞等待,直到任務離開檔案函數。如果等待超過由宏_TIMEOUT定義的時間,檔案函數調用會終止,並返回FR_TIMEOUT。逾時特性在某些RTOS下可能不被支援。
函數f_mount、f_mkfs和f_fdisk是一個例外。這些卷管理函數在同一個卷或物理磁碟上始終是不可重新進入的。當使用這些函數,其它任務要避免訪問此卷。
註:這個段落只是描述FatFs模組本身的可重新進入性,不假定底層磁碟I/O模組具有可重新進入性。
9.重複的訪問檔案(Duplicated File Access)預設情況下,FatFs不支援以讀/寫方式重複開啟檔案,允許以唯讀方式重複開啟檔案。在寫入模式下禁止重複開啟檔案,禁止重新命名、刪除已經開啟的檔案,否則該卷上的FAT結構體會崩潰。還有,目前的目錄也不能被刪除。
檔案鎖控制可以通過宏_FS_LOCK > 1使能。這個宏定義的值表示在檔案鎖控制下,多少檔案、子目錄可以同時開啟。在這種情況下,任何對開啟對象的非法操作(比如移除、重新命名)會被拒絕並返回FR_LOCKED錯誤碼,函數f_open和f_opendir是一個特例,它們執行失敗返回FR_TOO_MANY_OPEN_FILES錯誤碼。
10. 高效能檔案訪問在小型嵌入式系統中,為了獲得更好的讀寫檔案效能,應用程式編程應該考慮如何處理以合乎FatFs模組的特性。f_read函數讀取磁碟上的檔案資料按照中的序列:
圖10-1:讀資料,扇區未對齊(小塊資料) 圖10-2:讀資料,扇區未對齊(大塊資料) 圖10-3:讀資料,扇區對齊檔案I/O緩衝區用來讀寫部分扇區資料。檔案I/O緩衝區可以是每個檔案對象都有的私人扇區緩衝,也可以是共用整個檔案系統對象下的扇區緩衝。宏_FS_TINY用來確定檔案I/O緩衝區是使用檔案對象緩衝還是使用檔案系統對象緩衝。當_FS_TINY==1時,表示使用微型模式,檔案I/O緩衝區共用檔案系統對象緩衝,檔案資料轉送和FAT/目錄訪問都使用檔案系統快取。這樣每個檔案對象可以減少_MAX_SS個位元組資料記憶體。這種小記憶體配置的缺點是:緩衝在檔案I/O緩衝區的FAT資料在檔案資料轉送時將會丟失,並且在每一個簇的邊界都要重新載入(意味著更長的執行時間)。 無論如何,這適合於大多數的應用場合,只需少量記憶體消耗就能獲得不錯的效能。
圖10-1描述了檔案當中未對齊扇中的部分扇區資料通過檔案I/O緩衝進行傳送過程。大塊資料傳送見圖10-2,圖10-2中的中間部分的一個或多個扇區資料傳送直接使用了應用程式緩衝。圖10-3描述了按扇區對齊的資料傳送。在這種情況下,檔案I/O緩衝不使用。直接傳送,通過disk_read函數一次最大程度的讀取盡量多的扇區範圍,但是多扇區資料轉送從不越過簇邊界,即使它們是連續的。
因此,盡量在讀寫時保證扇區對齊,避免傳輸快取資料,這樣可以改善讀寫效能。除了這個外,使用扇區對齊讀寫,在配置成小記憶體模式下,在檔案傳送時,不會沖刷掉緩衝的FAT資料,這樣就可以獲得和正常模式下同樣的效能同時又具有小的記憶體消耗。
11. 使用Flash儲存空間的注意事項使用Flash儲存空間時,例如SDC和CFC,為了獲得最大寫效能,必須考慮它們的特性。
11.1 使用多扇區寫 圖11-1:多扇區/單扇區對比使用Flash儲存空間時,一個扇區一個扇區的寫入最影響寫入資料的吞吐率。如果每次能寫入多個扇區,會大大提高寫入資料的吞吐率,11-1所示。儲存空間介面時鐘越快,影響越大,並且通常吞吐率會增大10倍以上。圖11-2顯示這種關係,在儲存空間介面速率相同的情況下,比如使用8GB SDHC類型的SD卡,每次寫16K(32扇區)比每次寫100位元組(1扇區)吞吐率高了38.8倍。寫事件的次數會影響儲存空間的壽命,當使用小資料區塊時,可能會多次訪問同一扇區,比如每次寫入100位元組,會寫5~6次才能將一個扇區寫滿,因此從保護儲存空間使用壽命上考慮,也要儘可能的使用大塊資料。
圖11-2:讀寫吞吐率與寫入塊大小、儲存空間介面速率關係因此應用程式應該儘可能將資料群組成一個大資料區塊再進行寫入操作。理想的寫入方式是每次寫入是以扇區對齊的,並且寫入資料大小等於扇區的倍數,最好是等於簇大小。當然,應用程式層到介質層必須要支援多扇區寫特性,可是多數開源磁碟驅動缺少這塊。
註:Fatfs模組和它的常式磁碟驅動支援多扇區讀寫。
12.強制擦除儲存空間當通過f_unlink函數移除一個檔案時,FatFs會在FAT表中把檔案佔用的簇資料空間標記為"空",但是並不會對包含檔案資料的扇區做任何擦除操作,所以檔案資料仍然存在著。如果要在移除檔案時將檔案資料強制移除,儲存空間上的空閑塊會增加。這樣,在下次向這個資料區塊寫資料時,就可以跳過內部擦除操作。這樣可能會提高寫入效能。要使能這個特性,設定_USE_TRIM為1。註:這個特性是Flash儲存空間內部處理常式所期望的。大多數應用並不需要這個特性,並且當移除大檔案時,f_unlink函數可能會花費很長時間。
13.臨界區寫FAT卷時,如果因為意外故障導致寫操作被中斷,比如突然斷電、錯誤的移除磁碟以及不可恢複的磁碟錯誤,可能會導致FAT結構體崩潰。圖13-1和圖13-2說明FatFs應用程式的臨界區。
圖13-1:長臨界區 圖13-2::最小化的臨界區上述紅色地區代碼執行時被意外終止,正在執行的對象更改可能會丟失。當上述黃色地區代碼執行時被意外終止,下面列出的一個或多個可能會發生:
- 正在改寫的檔案資料被損壞
- 添加的檔案恢複到初始狀態
- 丟失建立的檔案
- 新建立的檔案或者覆寫的內容丟失
- 由於丟失簇鏈,磁碟效能下降
如果以唯讀模式開啟檔案,是不會出現上述情況的。為了使資料丟失風險最小化,臨界區應儘可能的短,適當的使用f_sync函數可以縮短臨界區,13-2所示的那樣。
FatFs模組系統應用指南