1.簡介
LittleFS是一個小型的Flash文件系統(tǒng),它結(jié)合日志結(jié)構(gòu)(log-structured)文件系統(tǒng)和COW(copy-on-write)文件系統(tǒng)的思想,以日志結(jié)構(gòu)存儲元數(shù)據(jù),以COW結(jié)構(gòu)存儲數(shù)據(jù)。這種特殊的存儲方式,使LittleFS具有強(qiáng)大的掉電恢復(fù)能力(power-loss resilience)。分配COW數(shù)據(jù)塊時LittleFS采用了名為統(tǒng)計(jì)損耗均衡的動態(tài)損耗均衡算法,使Flash設(shè)備的壽命得到有效保障。同時LittleFS針對資源緊缺的小型設(shè)備進(jìn)行設(shè)計(jì),具有極其有限的ROM和RAM占用,并且所有RAM的使用都通過一個可配置的固定大小緩沖區(qū)進(jìn)行分配,不會隨文件系統(tǒng)的擴(kuò)大占據(jù)更多的系統(tǒng)資源。當(dāng)在一個資源非常緊缺的小型設(shè)備上,尋找一個具有掉電恢復(fù)能力并支持損耗均衡的Flash文件系統(tǒng)時,LittleFS是一個比較好的選擇。
LittleFS在嵌入式開發(fā)過程中經(jīng)常遇到,但是如何在OpenHarmony中使用呢?本文基于OpenHarmony 3.1Release + 小凌派-RK2206開發(fā)板做LittleFS文件系統(tǒng)移植,現(xiàn)將相關(guān)移植經(jīng)驗(yàn)發(fā)布,分享給大家。文中如有問題,請大家?guī)兔χ刚?/p>
2.LittleFS移植過程
本文基于OpenHarmony3.1Release做LittleFS移植,小凌派-RK2206開發(fā)板內(nèi)部Flash有8MB大小,其中4~8MB區(qū)間為空閑區(qū)域。我將4M~5M作為LittleFS文件系統(tǒng)的/data目錄掛載硬件設(shè)備。具體移植過程主要如下所示:
1、hcs配置
1.1、hdf.hcs
創(chuàng)建/device/soc/rockchip/rk2206/hcs_config/hdf.hcs文件,具體如下:
root {
module = "rockchip,rk2206_chip";
}
(左右移動查看全部內(nèi)容)
如上所述,我將在device_info/device_info.hcs添加LittleFS設(shè)備,并在fs/fs_config.hcs添加LittleFS具體信息。
1.2、BUILD.gn
新建//device/soc/rockchip/rk2206/hdf_config/BUILD.gn,具體代碼如下所示:
import("http://drivers/adapter/khdf/liteos_m/hdf.gni")
module_switch = defined(LOSCFG_DRIVERS_HDF)
module_name = get_path_info(rebase_path("."), "name")
hdf_driver(module_name) {
hcs_sources = [ "hdf.hcs" ]
}
(左右移動查看全部內(nèi)容)
上述代碼將在編譯OpenHarmony3.1Rlease時,將編譯hdf.hcs。
1.3、device_info.hcs
創(chuàng)建/device/soc/rockchip/rk2206/hcs_config/device_info/device_info.hcs文件,在文件中添加LittleFS設(shè)備,具體代碼如下所示:
device_fs :: device {
device0 :: deviceNode {
policy = 0;
priority = 5;
permission = 0777;
moduleName = "HDF_PLATFORM_FS_LITTLEFS";
serviceName = "littlefs_config";
deviceMatchAttr = "rockchip_rk2206_fs_littlefs";
}
}
(左右移動查看全部內(nèi)容)
上述代碼表示建設(shè)一個設(shè)備驅(qū)動,該驅(qū)動的模塊名稱(即moduleName)為“HDF_PLATFORM_FS_LITTLEFS”,OpenHamrony系統(tǒng)依據(jù)該名稱匹配驅(qū)動程序;設(shè)備匹配信息(即deviceMatchAttr)添加小凌派開發(fā)板Flash特殊信息(比如:分區(qū)信息,掛載目錄名、起始地址、結(jié)束地址等)。
1.4、fs_config.hcs
新建//device/soc/rockchip/rk2206/hdf_config/fs/fs_config.hcs文件,該文件主要寫清楚設(shè)備掛載信息,具體如下:
root {
platform {
fs_config {
template fs_controller {
match_attr = "";
mount_points = [];
block_size = [];
block_start = [];
block_count = [];
}
fs_littefs :: fs_controller {
match_attr = "rockchip_rk2206_fs_littlefs";
mount_points = ["/data"];
block_size = [4096];
block_start = [1024];
block_count = [256];
}
}
}
}
(左右移動查看全部內(nèi)容)
(1)points:掛載目錄。
(2)block_size:Flash的擦除塊大小。
(3)block_start:該掛載Flash區(qū)域的起始塊地址,實(shí)際Flash地址為block_size * block_start。
(4)block_count:該掛載Flash區(qū)域的存儲塊總數(shù)。
注意:match_attr所表示的字符串要與device_info.hcs所表示的字符串要一致。
2、hdf驅(qū)動
新建//device/soc/rockchip/rk2206/hdf_driver/fs文件夾,文件夾下創(chuàng)建2個文件,具體如下所示:
2.1、fs_driver.c
2.1.1、添加必要的頭文件
(左右移動查看全部內(nèi)容)
2.1.2、添加HDF驅(qū)動
添加LittleFS匹配的hdf驅(qū)動,具體代碼如下所示:
static struct HdfDriverEntry g_fsDriverEntry = {
.moduleVersion = 1,
.moduleName = "HDF_PLATFORM_FS_LITTLEFS",
.Bind = fs_driver_bind,
.Init = fs_driver_init,
.Release = fs_driver_release,
};
(左右移動查看全部內(nèi)容)
HDF_INIT(g_fsDriverEntry);
其中,moduleName必須要與device_info.hcs中的moduleName保持一致。
2.1.3、fs_driver_init函數(shù)
fs_driver_init為hdf驅(qū)動加載函數(shù)。OpenHarmony啟動時,將根據(jù)hcs的編寫匹配對應(yīng)的驅(qū)動程序,并運(yùn)行fs_driver_init函數(shù)。該函數(shù)負(fù)責(zé):
(1)讀取hcs文件的配置參數(shù)。
(2)初始化Flash。
(3)適配LittleFS對應(yīng)的read、write、erase和sync函數(shù),并適配LittleFS相關(guān)參數(shù)。
(4)掛載LittleFS。
具體代碼如下所示:
static int32_t fs_driver_init(struct HdfDeviceObject *device)
{
int result;
int32_t ret;
struct FileOpInfo *file_op_info = NULL;
if (device == NULL) {
PRINT_ERR("device is null
");
return HDF_ERR_INVALID_OBJECT;
}
if (device->property == NULL)
{
PRINT_ERR("device is null
");
return HDF_ERR_INVALID_OBJECT;
}
/* Flash設(shè)備初始化 */
FlashInit();
/* 讀取hcS參數(shù) */
ret = fs_driver_readdrs(device->property, &m_fs_cfg[0]);
if (ret != HDF_SUCCESS)
{
PRINT_ERR("%s: fs_driver_readdrs faiLED(%d)
", ret);
return ret;
}
/* 適配LitteleFS對應(yīng)的函數(shù)和參數(shù) */
for (int i = 0; i < sizeof(m_fs_cfg) / sizeof(m_fs_cfg[0]); i++) {
if (m_fs_cfg[i].mount_point == NULL)
{
PRINT_LOG("m_fs_cfg[%d].mount_point is null
", i);
continue;
}
m_fs_cfg[i].lfs_cfg.read = flash_littlefs_read;
m_fs_cfg[i].lfs_cfg.prog = flash_littlefs_write;
m_fs_cfg[i].lfs_cfg.erase = flash_littlefs_erase;
m_fs_cfg[i].lfs_cfg.sync = flash_littlefs_sync;
m_fs_cfg[i].lfs_cfg.read_size = 4;
m_fs_cfg[i].lfs_cfg.prog_size = 4;
m_fs_cfg[i].lfs_cfg.cache_size = 256;
m_fs_cfg[i].lfs_cfg.lookahead_size = 64;
m_fs_cfg[i].lfs_cfg.block_cycles = 1000;
m_fs_cfg[i].lfs_cfg.file_max = LFS_FILE_MAX;
m_fs_cfg[i].lfs_cfg.name_max = LFS_NAME_MAX;
/* 準(zhǔn)備掛載 */
result = SetDefaultMountPath(i, m_fs_cfg[i].mount_point);
if (result != VFS_OK)
{
PRINT_ERR("SetDefaultMountPath(%d, %d) failed(%d)
", i, m_fs_cfg[i].mount_point, result);
continue;
}
/* 掛載目錄 */
result = mount(NULL, m_fs_cfg[i].mount_point, "littlefs", 0, &m_fs_cfg[i].lfs_cfg);
printf("%s: mount fs on '%s' %s
", __func__, m_fs_cfg[i].mount_point, (result == 0) ? "succeed" : "failed");
if (CheckPathIsMounted(m_fs_cfg[i].mount_point, &file_op_info) == TRUE) {
int lfs_ret = lfs_mkdir(&file_op_info->lfsInfo, m_fs_cfg[i].mount_point);
if (lfs_ret == LFS_ERR_OK) {
PRINT_LOG("create root dir(%s) success.
", m_fs_cfg[i].mount_point);
} else if (lfs_ret == LFS_ERR_EXIST) {
PRINT_LOG("root dir(%s) exist.
", m_fs_cfg[i].mount_point);
} else {
PRINT_LOG("create root dir(%s) failed.", m_fs_cfg[i].mount_point);
}
}
}
return HDF_SUCCESS;
}
(左右移動查看全部內(nèi)容)
2.2、BUILD.gn
BUILD.gn負(fù)責(zé)將fs_driver.c編譯到內(nèi)核中,具體源代碼如下所示:
import("http://drivers/adapter/khdf/liteos_m/hdf.gni")
module_switch = defined(LOSCFG_SOC_SERIES_RK22XX) && defined(LOSCFG_DRIVERS_HDF_PLATFORM) && defined(LOSCFG_FS_LITTLEFS)
module_name = get_path_info(rebase_path("."), "name")
hdf_driver(module_name) {
sources = [
"fs_driver.c",
]
include_dirs = [ "." ]
}
(左右移動查看全部內(nèi)容)
3、測試程序
我在main函數(shù)中添加一個任務(wù),負(fù)責(zé)每隔5秒讀寫文件。具體代碼如下所示:
/* 文件系統(tǒng)測試 */
static void file_rw()
{
static unsigned int cur = 0;
char file_name[] = "/data/a.txt";
int fd_w, fd_r;
unsigned char buffer[256];
/* 寫操作 */
fd_w = open(file_name, O_WRONLY | O_CREAT);
if (fd_w == -1)
{
printf("write: %s open failed!
", file_name);
return;
}
memset(buffer, 0, sizeof(buffer));
snprintf(buffer, sizeof(buffer), "Hello World and %d
", cur++);
printf("write: %s", buffer);
write(fd_w, buffer, strlen(buffer));
close(fd_w);
/* 讀操作 */
fd_r = open(file_name, O_RDONLY);
if (fd_r == -1)
{
printf("read: %s open failed!
", file_name);
return;
}
lseek(fd_r, 0, SEEK_SET);
memset(buffer, 0, sizeof(buffer));
read(fd_r, buffer, sizeof(buffer));
printf("read: %s", buffer);
close(fd_r);
}
static void IotProcess(void *arg)
{
static const unsigned int SLEEP_MAXSEC = 5;
while (1)
{
printf("%s: sleep %d sec!
", __func__, SLEEP_MAXSEC);
/* 文件系統(tǒng)測試 */
file_rw();
LOS_Msleep(SLEEP_MAXSEC * 1000);
}
}
(左右移動查看全部內(nèi)容)
3
結(jié)果
程序編譯燒寫到開發(fā)板后,按下開發(fā)板的RESET按鍵,通過串口軟件查看日志如下:
[MAIN:D]Main: OpenHarmony start schedule...
Entering scheduler
IotProcess: sleep 5 sec!
write: Hello World and 0
read: Hello World and 0
IotProcess: sleep 5 sec!
write: Hello World and 1
read: Hello World and 1
IotProcess: sleep 5 sec!
write: Hello World and 2
read: Hello World and 2
......
(左右移動查看全部內(nèi)容)
-
HDF框架
+關(guān)注
關(guān)注
0文章
10瀏覽量
2999 -
OpenHarmony
+關(guān)注
關(guān)注
33文章
3952瀏覽量
21088
原文標(biāo)題:基于OpenHarmony3.1的LittleFS文件系統(tǒng)hdf驅(qū)動實(shí)現(xiàn)
文章出處:【微信號:HarmonyOS_Community,微信公眾號:電子發(fā)燒友開源社區(qū)】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
【瑞薩FPB-RA6E2試用】SPI通信:W25Q64+LittleFS
明晚8點(diǎn)|睿擎文件系統(tǒng)實(shí)戰(zhàn):從開發(fā)到發(fā)布全流程解析
睿擎派文件系統(tǒng)指南:從開發(fā)到發(fā)布全流程實(shí)踐 | 技術(shù)解析
使用ulog 寫入日志到文件系統(tǒng),無法使用cat命令讀取文件內(nèi)容怎么解決?
nor掛載一個littlefs文件系統(tǒng)之后,把裝置斷電重啟,重啟后裝置沒有運(yùn)行是為什么?
rtt 5.1.0使用最新版的littleFS異常的原因?
技術(shù)貼|【RK3588】ELF 2開發(fā)板如何添加exFAT和NTFS文件系統(tǒng)格式
Linux三大主流文件系統(tǒng)解析
飛凌嵌入式ElfBoard ELF 1板卡-文件系統(tǒng)簡介
服務(wù)器數(shù)據(jù)恢復(fù)—ocfs2文件系統(tǒng)被格式化為Ext4文件系統(tǒng)的數(shù)據(jù)恢復(fù)案例
迅為RK3568開發(fā)板實(shí)操-HDF驅(qū)動配置UART-修改HCS配置
【北京迅為】iTOP-RK3568開發(fā)板鴻蒙OpenHarmony系統(tǒng)南向驅(qū)動開發(fā)實(shí)操-HDF驅(qū)動配置UART
如何正確選擇嵌入式文件系統(tǒng)?
北京迅為iTOP-RK3568開發(fā)板OpenHarmony系統(tǒng)南向驅(qū)動開發(fā)實(shí)操-HDF驅(qū)動配置LED
北京迅為RK3568開發(fā)板OpenHarmony系統(tǒng)南向驅(qū)動開發(fā)內(nèi)核HDF驅(qū)動框架架構(gòu)
基于OpenHarmony3.1的LittleFS文件系統(tǒng)hdf驅(qū)動實(shí)現(xiàn)
評論