文章目錄
- 前言
- 編寫目的
- 術語和縮寫詞
- 方案選擇
- 一、Littlefs介紹
- 二、Littlefs搭建步驟
- 1.設備樹構建
- 2.自動掛載流程(二選一)
- 2.1設備樹啟用自動掛載
- 2.2 在 littlefs_fs.c 中,設備樹宏會被展開
- 2.3 模塊注冊初始化
- 2.4 初始化階段
- 2.4.1注冊Littlefs文件系統到總文件系統
- 2.4.2 檢查自動掛載標志
- 2.5 掛載函數調用
- 3.手動掛載流程(二選一)
- 3.1設備樹注釋自動掛載
- 3.2 外部聲明掛載結構
- 3.3 基礎方式掛載
- 4. 基礎應用
- 總結
前言
編寫目的
?本文檔旨在為開發者介紹Littlef’s文件系統相關配置使用指南。通過本文檔,開發者可以了解系統支持的文件系統類型、文件系統的掛載與使用方法、文件操作接口以及文件系統相關的配置選項,幫助開發者在嵌入式環境中高效、安全地使用文件系統功能,實現數據的持久化存儲和管理。
術語和縮寫詞
術語和縮寫詞 | 解釋 |
---|---|
文件系統 | 用于組織和存儲數據的方法,管理文件的創建、讀取、寫入、刪除等操作,提供數據持久化存儲能力 |
littlefs | 為閃存設計的輕量級文件系統,具有掉電保護和磨損均衡功能,適用于資源受限的嵌入式設備 |
fatfs | 一種廣泛使用的文件系統格式,兼容性好,支持長文件名,適用于SD卡、U盤等可移動存儲設備 |
方案選擇
?Zephyr 操作系統支持 fatfs 和 littlefs,因為 SPINAND 存在壞塊,而 littlefs 支持壞塊管理,所以選擇 littlefs 作為外部NAND-Flash文件系統。
一、Littlefs介紹
請參考優秀博客:
Little介紹
單片機移植操作
二、Littlefs搭建步驟
Littlefs系統原函數文件路徑:zephyr/subsys/fs/littlefs_fs.c
該文件作用說明:
- LittleFS 文件系統驅動原函數實現
- 雙存儲后端支持
- 設備樹驅動的自動掛載(若設備樹啟動:autonount屬性)
- 內存管理和線程安全
- 通過 SYS_INIT 在系統啟動時自動初始化(注冊文件系統框架)
1.設備樹構建
/ {fstab {compatible = "zephyr,fstab";lfs1: lfs1 {compatible = "zephyr,fstab,littlefs"; //標識符read-size = <1>; // 數據塊讀取的最小大小,所有讀取都將是此值的倍數prog-size = <16>; // 數據塊寫入的最小大小,所有寫入都將是此值的倍數cache-size = <256>; //緩存的大小,必須是 flash page size 的倍數lookahead-size = <32>; //lookahead 緩沖區大小,必須是8的倍數block-cycles = <512>; //用于動態磨損均衡,將數據移動到另一個塊之前的擦除次數partition = <&lfs1_partition>; //掛載分區mount-point = "/lfs1"; //掛載點automount; //啟用自動掛載(自動:littlefs_fs.c掛載。手動:fs_mount函數掛載)};};
};&flash0 {partitions {compatible = "fixed-partitions";#address-cells = <1>;#size-cells = <1>;/* Use second half of flash for the filesystem. */lfs1_partition: partition@100000 {label = "storage";reg = <0x100000 DT_SIZE_K(1024)>;};};
};
易錯點:若重復掛載會返回錯誤
可使用**fs_statvfs()**檢查后再掛載。
2.自動掛載流程(二選一)
2.1設備樹啟用自動掛載
fstab {compatible = "zephyr,fstab";lfs1: lfs1 {.......automount; // 啟用自動掛載.......};
};
2.2 在 littlefs_fs.c 中,設備樹宏會被展開
//匹配設備樹:
#define DT_DRV_COMPAT zephyr_fstab_littlefs
// DT_INST_FOREACH_STATUS_OKAY(DEFINE_FS) 展開為:
#define DEFINE_FS(inst) \
static struct fs_littlefs fs_data_0 = { \.cfg = { \.read_size = 1, \.prog_size = 16, \.cache_size = 256, \.lookahead_size = 32, \.read_buffer = read_buffer_0, \.prog_buffer = prog_buffer_0, \.lookahead_buffer = lookahead_buffer_0, \}, \
}; \
struct fs_mount_t z_fsmp_lfs1 = { \.type = FS_LITTLEFS, \.mnt_point = "/lfs1", \.fs_data = &fs_data_0, \.storage_dev = (void *)0, \.flags = FS_MOUNT_FLAG_AUTOMOUNT, \
};
2.3 模塊注冊初始化
// 文件系統初始化優先級:CONFIG_FILE_SYSTEM_INIT_PRIORITY
// littlefs_fs.c 中的 SYS_INIT 宏
SYS_INIT(littlefs_init, POST_KERNEL, CONFIG_FILE_SYSTEM_INIT_PRIORITY);// 系統啟動時自動調用 littlefs_init()
2.4 初始化階段
2.4.1注冊Littlefs文件系統到總文件系統
// 注冊 LittleFS 文件系統驅動int rc = fs_register(FS_LITTLEFS, &littlefs_fs);if (rc != 0) {LOG_ERR("Failed to register LittleFS driver: %d", rc);return rc;}
2.4.2 檢查自動掛載標志
if ((mp->flags & FS_MOUNT_FLAG_AUTOMOUNT) != 0) {// 執行自動掛載int rc = fs_mount(mp);if (rc < 0) {LOG_ERR("Automount %s failed: %d", mp->mnt_point, rc);} else {LOG_INF("Automount %s succeeded", mp->mnt_point);}}// 如果沒有 automount 標志,直接返回,不執行掛載
2.5 掛載函數調用
int fs_mount(struct fs_mount_t *mp)
{......// 檢查是否已經掛載if (mp->fs != NULL) {return -EBUSY; // 已經掛載}// 調用文件系統特定的掛載函數int rc = fs->mount(mp);if (rc == 0) {// 5. 掛載成功,更新掛載點信息mp->fs = fs;mp->mountp_len = strlen(mp->mnt_point);}.......
}
3.手動掛載流程(二選一)
3.1設備樹注釋自動掛載
fstab {compatible = "zephyr,fstab";lfs1: lfs1 {.......//automount; //注釋關閉掉.......};
};
3.2 外部聲明掛載結構
// 在應用程序中聲明外部掛載結構
FS_FSTAB_DECLARE_ENTRY(FS_PARTITION_NODE);
// 展開為:extern struct fs_mount_t z_fsmp_lfs1;
3.3 基礎方式掛載
#include <zephyr/fs/fs.h>
#include <zephyr/fs/littlefs.h>void basic_mount_example(void)
{// 1. 獲取掛載結構指針struct fs_mount_t *mp = &FS_FSTAB_ENTRY(FS_PARTITION_NODE);// 2. 執行掛載int rc = fs_mount(mp);if (rc < 0) {printk("Mount failed: %d\n", rc);return;}printk("Mount succeeded at %s\n", mp->mnt_point);
}
4. 基礎應用
簡化版Demo:
/** 最簡 LittleFS 測試*/#include <stdio.h>
#include <zephyr/kernel.h>
#include <zephyr/fs/fs.h>
#include <zephyr/fs/littlefs.h>int main(void)
{struct fs_file_t file;char buffer[64];int res;printk("Simple LittleFS Test\n");// 掛載文件系統FS_LITTLEFS_DECLARE_DEFAULT_CONFIG(storage);static struct fs_mount_t lfs_mount = {.type = FS_LITTLEFS,.fs_data = &storage,.storage_dev = (void *)FIXED_PARTITION_ID(storage_partition),.mnt_point = "/lfs",};res = fs_mount(&lfs_mount);if (res != 0) {printk("Mount failed: %d\n", res);return 0;}printk("Mounted successfully\n");// 寫入文件fs_file_t_init(&file);res = fs_open(&file, "/lfs/hello.txt", FS_O_CREATE | FS_O_WRITE);if (res == 0) {fs_write(&file, "Hello LittleFS!", 15);fs_close(&file);printk("File written\n");}// 讀取文件res = fs_open(&file, "/lfs/hello.txt", FS_O_READ);if (res == 0) {res = fs_read(&file, buffer, sizeof(buffer) - 1);if (res > 0) {buffer[res] = '\0';printk("Read: %s\n", buffer);}fs_close(&file);}// 卸載fs_unmount(&lfs_mount);printk("Test completed\n");return 0;
}
更完善Demo請參考官方Littlefs例程:Littlefs_demo
總結
無論使用自動掛載還是使用手動掛載,Littlefs_Moudle都會在啟動階段進行初始化。手動掛載具有搭配(條件掛載、錯誤處理、狀態檢測、性能監控的優勢),提供了更大的靈活性和控制力,具體可通過Shell進行測試與體驗。