參考博文: 博文很長,但是實際要操作的步驟沒幾下。
http://m.elecfans.com/article/730878.html 為了防止幾年后文章鏈接找不到,我把文章復制過來了
/************************轉載注明出處 http://m.elecfans.com/article/730878.html Start**************************************************/
本應用筆記介紹了 RT-Thread 文件系統的基本知識和使用方法,幫助開發者更好地使用 RT-Thread 文件系統。並給出了在正點原子 STM32F429-apollo 開發板上驗證的代碼示例。
本文的目的和結構
本文的目的和背景
第一次接觸 RT-Thread 文件系統的開發者可能覺得 RT-Thread 文件系統過於復雜,不知道該從何入手。想要在項目中使用文件系統,卻不知道該怎么做。產生這種印象的原因是對 RT-Thread DFS 框架沒有足夠的了解,如果理解了 DFS 框架,在使用 RT-Thread 文件系統時就可以得心應手了。
為了能讓開發者清楚地理解 RT-Thread DFS 框架的概念,學會使用 RT-Thread 文件系統。本應用筆記將一步步深入介紹 RT-Thread DFS 框架的相關知識以及實現原理。通過演示 shell 命令和使用示例的方式來操作文件系統,讓開發者能夠學會 RT-Thread 文件系統的使用方法。
本文的結構
本應用筆記將從以下三個方面來介紹 RT-Thread 文件系統:
RT-Thread DFS 框架
RT-Thread 文件系統的移植
RT-Thread 文件系統的使用
問題闡述
本應用筆記將圍繞下面幾個問題來介紹RT-Thread 文件系統。
如何移植各種類型的文件系統?
如何對文件系統進行操作?
如何在文件系統中對文件和文件夾進行操作?
想要解決這些問題,就要了解 RT-Thread DFS 框架。下面我們就通過 DFS 框架一步一步地將文件系統使用起來。
問題的解決
DFS 框架介紹
RT-Thread 的文件系統采用了三層結構,這種結構就是 RT-Thread DFS 框架。
下圖為 RT-Thread 文件系統結構圖 :
DFS 框架的最頂層是一套面向嵌入式系統,專門優化過的設備虛擬文件系統 POSIX 文件接口,中間層是各種文件系統的實現,最底層是各類存儲設備驅動。
DFS 框架的來源
RT-Thread 為了能夠支持各種文件系統,設計了這樣一個 DFS 框架,各個層次獨立實現,提高了操作系統的可擴展性。使用 DFS 框架可以使得各種文件系統經過簡單的修改即可匹配到這個框架上,降低了文件系統移植難度,讓 開發者有更多的文件系統類型可供選擇。
DFS 框架各層次說明
頂層:POSIX 文件接口層
這一層是給開發者使用的接口函數層,開發者使用這一層提供的 POSIX 文件接口進行文件的相關操作,不用關心文件系統是如何實現的,也不用關心數據是存放在哪個存儲器中。
中間層:文件系統實現層
中間層是各種具體文件系統的實現,這里所說文件系統指各種不同類型的文件系統,比如 ELM FatFS、RomFS、devfs、Yaffs2、Uffs2 等。需要知道的是,不同的文件系統類型是獨立於存儲設備驅動而實現的。因此,想要正確地使用這些文件系統,需要把底層存儲設備的驅動接口和文件系統對接起來。
底層:存儲設備驅動層
這一層是存儲設備驅動層,具體的功能是初始化存儲設備並向上層提供存儲設備的驅動接口。存儲設備的類型可能是 SPI Flash,SD卡 等。
文件系統的移植
本次演示使用正點原子開發板 STM32F429-Apollo ,選擇的文件系統類型是 elm FatFS 。由於 RT-Thread 自帶了這個文件系統,所以移植工作較為簡單,只需要通過 env 工具對系統進行合適的配置既可。其他 RT-Thread 支持的文件系統,移植過程也是類似的,只需要對系統進行合適的配置即可使用。
准備工程
下載 RT-Thread 源碼 。
env 工具
移植過程介紹
文件系統的移植主要包括下面幾個方面:
開啟/配置 DFS 框架
開啟/配置 指定的文件系統
確保開發板上的存儲設備驅動正常工作
通過 env 工具可以方便地開啟文件系統,將所需的文件系統類型添加到工程中。
對存儲設備進行功能測試,可以確保存儲設備驅動是正常工作的。驅動程序的穩定工作是文件系統正常使用的基礎。
文件系統的配置
使用 env 工具進入 rt-thread\bsp\stm32f429-apollo 目錄,在命令行中輸入 menuconfig 命令進入配置界面。
在 menuconfig 配置界面依次選擇 RT-Thread Components → Device virtual file system,如下圖所示:
下面介紹 DFS 的配置項:
Using device virtual file system : 使用設備虛擬文件系統,即 RT-Thread 文件系統。
Using working directory : 打開這個選項,在 finsh/msh 中就可以使用基於當前工作目錄的相對路徑。
The maximal number of mounted file system : 最大掛載文件系統的數量。
The maximal number of file system type : 最大支持文件系統類型的數量。
The maximal number of opened files : 打開文件的最大數量。
Enable elm-chan fatfs : 使用 elm-chan FatFs。
elm-chan’s FatFs, Generic FAT Filesystem Module : elm-chan 文件系統的配置項。
Using devfs for device objects : 開啟 devfs 文件系統。
Enable BSD socket operated by file system API : 使 BSD socket 可以使用文件系統的 API 來管理,比如讀寫操作和 select/poll 的 POSIX API 調用。
Enable ReadOnly file system on flash : 在 Flash 上使用只讀文件系統。
Enable RAM file system : 使用 RAM 文件系統。
Enable UFFS file system: Ultra-low-cost Flash File System :使用 UFFS。
Enable JFFS2 file system : 使用 JFFS2 文件系統。
Using NFS v3 client file system :使用 NFS 文件系統。
進入到 DFS 的配置界面,開啟下圖所示的選項,就可以將 FatFS 添加到系統中。如圖所示:
這里需要注意的是還需要進入到 elm-chan's FatFs, Generic FAT Filesystem Module 選項中修改關於長文件名支持的選項,否則在后面使用文件系統的過程中,創建的文件或者文件夾的名稱不能超過 8 個字符。修改方式如下圖所示:
因為要使用一些 C 庫函數,所以需要打開 libc 功能:
保存選項后即可退出,此時 elm FatFS 已經添加到項目中 。
存儲設備初始化
開啟 SPI 設備驅動
DFS 框架的文件系統實現層需要存儲設備驅動層提供驅動接口用於對接,本次使用的存儲設備為 SPI Flash,底層設備初始化過程可以參考 《SPI 設備應用筆記》 。
重新打開 menuconfig 配置界面,在 RT-Thread Components → Device Drivers 界面中選中 Using SPI Bus/Device device drivers 以及 Using Serial Flash Universal Driver 選項,如下圖所示:
為了方便地使用 shell 命令,我們在 RT-Thread Components → Command shell 選項中開啟 Using module shell 選項,如下圖所示:
保存選項並退出,在 env 中輸入命令 scons --target=mdk5 -s 生成 mdk5 工程,編譯並下載程序。
檢查存儲設備驅動
在 stm32f429-apollo 開發板上 SPI Flash 掛在了 SPI5 總線上,對應的 SPI Device的設備名為 spi50。在終端輸入 list_device 命令可以看到名為 spi50 的設備類型為SPI Device,就說明 SPI 設備添加成功。如果沒有出現相應的設備,則需要檢查驅動程序,查找錯誤。
為了確保該驅動工作正常,可以使用 sf 命令對該設備做 benchmark 測試。該功能由 sfud組件提供,可以通過檢查存儲設備的讀、寫和擦除功能來判斷存儲設備的驅動程序是否正常。 如果像下圖一樣提示成功,所示則認為該驅動工作正常。如果無法通過測試,則需要檢查驅動程序,使用邏輯分析儀對存儲設備的接口波形進行分析。測試過程如下圖:
創建存儲設備
由於只有塊設備類型的設備才能和文件系統對接,所以需要根據 SPI Device 找到 SPI Flash 設備,並創建與其對應的 Block Device。
這里需要使用到萬能 SPI Flash 驅動庫:SFUD ,RT-Thread 已經集成了該組件,在上面的配置過程中我們已經開啟這個功能。此時只需要使用 SFUD 提供的rt_sfud_flash_probe 函數即可。該函數將執行如下操作:
根據名為 spi50 的 SPI Device 設備找到對應的 Flash 存儲設備。
初始化 Flash 設備。
在 Flash 存儲設備上創建名為 W25Q256 的 Block Device。
如果開啟了組件自動初始化功能,該函數會被自動執行,否則需要手動調用運行。
static int rt_hw_spi_flash_with_sfud_init(void) { if (RT_NULL == rt_sfud_flash_probe("W25Q256", "spi50")) { return RT_ERROR; }; return RT_EOK; } INIT_COMPONENT_EXPORT(rt_hw_spi_flash_with_sfud_init)
在終端輸入 list_device 命令如果看到名為 W25Q256 的設備類型為 Block Device,這說明塊設備已經創建成功,如果失敗則需要對 spi50 設備進行檢查。
如下圖所示:
獲得可以用於掛載的塊類型設備,那么移植的工作就算完成了。
文件系統的使用
文件系統的初始化
RT-Thread 文件系統初始化過程一般按以下流程來進行:
初始化 DFS 框架
初始化具體文件系統
初始化存儲設備
下面我們按照這樣的順序來逐步講解文件系統的初始化過程:
DFS 框架的初始化
DFS 框架的初始化主要是對內部數據結構以及資源的初始化。這一過程包括初始化文件系統必須的數據表,以及互斥鎖。該功能由如下函數完成。如果開啟了組件自動初始化功能,該函數會被自動執行,否則需要手動調用運行。
中間層文件系統的初始化
這一步的初始化主要是將 elm FatFS 的操作函數注冊到 DFS 框架中。該功能由如下函數完成。如果開啟了組件自動初始化功能,該函數會被自動執行,否則需要手動調用運行。
存儲設備的初始化
存儲設備的初始化可以參考 《創建存儲設備》章節。
創建文件系統
第一次使用 SPI Flash 作為文件系統地存儲設備時,如果我們直接重啟開發板來掛載文件系統,就會看到 spi flash mount to /spi failed! 的提示。這是因為此時在 SPI Flash 中還沒有創建相應類型的文件系統,這就用到了創建文件系統 shell 命令:mkfs。
mkfs 命令的功能是在指定的存儲設備上創建指定類型的文件系統。使用格式為:mkfs [-t type] device 。第一次掛載文件系統前需要使用 mkfs 命令在存儲設備上創建相應的文件系統,否則就會掛載失敗。如果要在 W25Q256 設備上創建 elm 類型的文件系統,就可以使用 mkfs -t elm W25Q256 命令,使用方法如下圖:
文件系統創建完成后需要重啟設備。
文件系統的掛載
文件系統的掛載指的是將文件系統和具體的存儲設備關聯起來,並掛載到某個掛載點,這個掛載點即為這個文件系統的根目錄。在下面的示例中,我們將 elm FatFS 文件系統和名為 W25Q256的存儲設備關聯起來,並且掛載到 /spi 文件夾中。(這里可以掛載到 /spi 文件夾的原因是stm32f429-apollo BSP 的文件系統根目錄已經掛載了 RomFS,並且已經創建了 /spi 文件夾。如果沒有特殊情況,文件系統可以直接掛載到根目錄 / 上。)
掛載文件系統的操作由 dfs_mount() 函數完成,dfs_mount() 函數的參數分別為:塊設備名、文件系統掛載點路徑、掛載文件系統類型、讀寫標志位以及文件系統的私有數據,使用方法如下圖所示:
經過了上面的創建文件系統操作,我們重啟開發板(會自動重新執行掛載函數),就可以成功地掛載文件系統了。可以看到提示 spi flash mount to /spi ! 。這時再次使用list_device 命令可以看到 W25Q256 設備已經被掛載成功。如下圖所示:
到這一步為止,文件系統已經初始化完成,接下來可以對文件和目錄進行操作了。
文件與目錄操作 shell 命令
在這一小節介紹關於文件和目錄操作常用的 shell 命令:
ls 功能:顯示文件和目錄的信息,示例如下圖:
cd 功能:切換到指定工作目錄,示例如下圖:
cp 功能:copy 文件,示例如下圖:
rm 功能:刪除文件或目錄,示例如下圖:
mv 功能:將文件移動位置或者改名,示例如下圖:
echo 功能:將指定內容寫入文件:
cat 功能:展示文件的內容,示例如下圖:
pwd 功能:打印出當前目錄地址,示例如下圖:
mkdir 功能:創建文件夾,示例如下圖:
文件操作示例
本節以創建文件夾操作為例,介紹如何使用 RT-Thread 文件系統 Sample 來對文件系統進行操作。
在 menuconfig 配置界面依次選擇 RT-Thread online packages → miscellaneous packages → filesystem sample options,選中 [filesystem] mkdir 選項,如下圖所示:
保存並退出后,使用 pkgs --update 命令更新軟件包,然后使用 scons --target=mdk5 -s 命令重新生成工程。可以看到該 Sample 已經添加到工程中:
這里需要注意的是由於我們文件系統的根目錄掛載了 RomFS,不可修改,所以我們不能直接在根目錄創建文件夾。因此,我們需要對程序進行簡單的修改,如下圖所示:
重新編譯后下載運行,在 msh 中可以使用 mkdir_sample_init 命令來創建 web 文件夾,效果如下圖所示:
此時切換到 /spi 文件夾中可以看到 web 文件夾已經被創建。
文件系統提供的 Sample 還有openfile、readwrite、stat、rename、opendir、readdir 、tell_seek_dir,大家可以用上面的方法來使用這些功能。
常見問題
(1)發現文件名或者文件夾名稱顯示不正常怎么辦?
檢查是否開啟了長文件名支持,可以參考本應用筆記《文件系統的配置》章節。
(2)文件系統初始化失敗怎么辦?
檢查文件系統配置項目中的允許掛載的文件系統類型和數量是否充足。
(3)創建文件系統 mkfs 命令失敗怎么辦?
檢查存儲設備是否存在,如果存在檢查設備驅動是否可以通過功能測試,如果不能通過,則檢查驅動錯誤。
檢查 libc 功能是否開啟,參見 《文件系統的配置》章節。
(4)文件系統掛載失敗怎么辦?
檢查指定的掛載路徑是否存在。文件系統可以直接掛載到根目錄(“/”),但是如果想要掛載到其他路徑上,如 (“/sdcard”)。需要確保(“/sdcard”)路徑是存在的,否則需要先在根目錄創建 sdcard 文件夾才能掛載成功。
檢查是否在存儲設備上創建了文件系統,如果存儲設備上沒有文件系統,需要使用 mkfs 命令在存儲器上創建文件系統。
(5)SFUD 探測不到 Flash 所使用的具體型號怎么辦?
檢查硬件引腳設置錯誤
SPI 設備是否已經注冊
SPI 設備是否已經掛載到總線
檢查在 RT-Thread Components → Device Drivers -> Using SPI Bus/Device device drivers -> Using Serial Flash Universal Driver 菜單下的 Using auto probe flash JEDEC SFDP parameter 和 Using defined supported flash chip information table 配置項是否選中,如果沒有選中那么需要開啟這兩個選項。配置圖可參考 《開啟 SPI 設備驅動》 章節。
如果開啟了上面的選項仍然無法識別存儲設備,那么可以在 SFUD 項目中提出 issues。
(6)elm FatFS 的最大扇區大小該如何設置?
根據所使用的存儲設備的不同,也會有些不一樣,一般根據 Flash 設備的要求可以設置為 4K,也就是填寫 4096。
一般常見的 TF 卡和 SD 卡的扇區大小設置為 512。
(7)存儲設備的 benchmark 測試耗時過長是怎么回事?
可對比 system tick 為 1000 時的 benchmark 測試數據 和本次測試所需的時長,如果耗時差距過大,則可以認為測試工作運行不正常。
檢查系統 tick 的設置,因為一些延時操作會根據 tick 時間來決定,所以需要根據系統情況來設置合適的 system tick 值。如果系統的 system tick 值不低於 1000,則需要使用邏輯分析儀檢查波形確定通信速率正常。
(8)SPI Flash 實現 elmfat 文件系統,如何保留部分扇區不被文件系統使用?
可以使用 RT-Thread 提供的 partition 工具軟件包為整個存儲設備創建多個塊設備,為創建的多個塊設備分配不同的功能即可。
(9)測試文件系統過程中程序卡住了怎么辦?
嘗試使用調試器或者打印一些必要的調試信息,確定程序卡住的位置再提出問題。
(10)如何一步步檢查文件系統出現的問題?
可以采用從底層到上層的方法來逐步排查問題。
首先檢查存儲設備是否注冊成功,功能是否正常。
檢查存儲設備中是否創建了文件系統。
檢查指定文件系統類型是否注冊到 DFS 框架,經常要檢查允許的文件系統類型和數量是否足夠。
檢查 DFS 是否初始化成功,這一步的初始化操作是純軟件的,因此出錯的可能性不高。需要注意的是如果開啟了組件自動初始化,就無需再次手動初始化。
/*******************************************http://m.elecfans.com/article/730878.html OVER***********************************************************************************************/
我的實操
Last --- 補充:
針對上述博文的注意事項:
留下的疑問: 1.mkfs -t elm W25Q256 這句shell對應的內部代碼是哪些呢 ???
2.為什么要重新上電板子,執行ls等文件系統命令才生效呢?
為什么不是執行 “ mkfs -t elm W25Q256 ” 這句shell后就即時生效呢????????
elm是啥玩意兒?
elm就是fat接入dfs的連接件。由於fat文件系統不是針對RT-Thread的,RT-Thread作者也沒有修改出一套RT-Thread專用的文件系統源碼。
所有就有了elm這一層,可以看作是"RT-Thread下的fat文件系統"(封裝fat操作並提供底層硬件操作回調)。
相關優秀博文
https://blog.csdn.net/OHRadiance/article/details/50807386 RT-Thread文件系統(dfs)淺析
https://blog.csdn.net/flydream0/article/details/8841770 rt-thread組件之elmfat文件系統淺析
https://blog.csdn.net/flydream0/article/details/54411630 elm FatFs文件系統移植總結
https://blog.csdn.net/flydream0/article/details/8838192 rt-thread組件之dfs文件架構淺析
--------尚待閱讀源碼
.