0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

基于OpenHarmony3.1的LittleFS文件系统hdf驱动实现

福州市凌睿智捷电子有限公司 2022-06-22 09:42 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

一、简介

LittleFS是一个小型的Flash文件系统,它结合日志结构(log-structured)文件系统和COW(copy-on-write)文件系统的思想,以日志结构存储元数据,以COW结构存储数据。这种特殊的存储方式,使LittleFS具有强大的掉电恢复能力(power-loss resilience)。分配COW数据块时LittleFS采用了名为统计损耗均衡的动态损耗均衡算法,使Flash设备的寿命得到有效保障。同时LittleFS针对资源紧缺的小型设备进行设计,具有极其有限的ROMRAM占用,并且所有RAM的使用都通过一个可配置的固定大小缓冲区进行分配,不会随文件系统的扩大占据更多的系统资源。当在一个资源非常紧缺的小型设备上,寻找一个具有掉电恢复能力并支持损耗均衡的Flash文件系统时,LittleFS是一个比较好的选择。

LittleFS在嵌入式开发过程中经常遇到,但是如何在OpenHarmony中使用呢?本文基于OpenHarmony 3.1Release + 小凌派-RK2206开发板做LittleFS文件系统移植,现将相关移植经验发布,分享给大家。文中如有问题,请大家帮忙指正。

二、LittleFS移植过程

本文基于OpenHarmony3.1Release做LittleFS移植,小凌派-RK2206开发板内部Flash有8MB大小,其中4~8MB区间为空闲区域。我将4M~5M作为LittleFS文件系统的/data目录挂载硬件设备。具体移植过程主要如下所示:

1、hcs配置

1.1、hdf.hcs

创建/device/soc/rockchip/rk2206/hcs_config/hdf.hcs文件,具体如下:

#include "device_info/device_info.hcs"#include "fs/fs_config.hcs"#include "gpio/gpio_config.hcs"#include "i2c/i2c_config.hcs"#include "spi/spi_config.hcs"root { module = "rockchip,rk2206_chip";}

如上所述,我将在device_info/device_info.hcs添加LittleFS设备,并在fs/fs_config.hcs添加LittleFS具体信息。

1.2、BUILD.gn

新建//device/soc/rockchip/rk2206/hdf_config/BUILD.gn,具体代码如下所示:

import("//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" ]}

上述代码将在编译OpenHarmony3.1Rlease时,将编译hdf.hcs。

1.3、device_info.hcs

创建/device/soc/rockchip/rk2206/hcs_config/device_info/device_info.hcs文件,在文件中添加LittleFS设备,具体代码如下所示:

device_fs :: device { device0 :: deviceNode { policy = 0; priority = 5; permission = 0777; moduleName = "HDF_PLATFORM_FS_LITTLEFS"; serviceName = "littlefs_config"; deviceMatchAttr = "rockchip_rk2206_fs_littlefs"; } }

上述代码表示建设一个设备驱动,该驱动的模块名称(即moduleName)为“HDF_PLATFORM_FS_LITTLEFS”,OpenHamrony系统依据该名称匹配驱动程序;设备匹配信息(即deviceMatchAttr)添加小凌派开发板Flash特殊信息(比如:分区信息,挂载目录名、起始地址、结束地址等)。

1.4、fs_config.hcs

新建//device/soc/rockchip/rk2206/hdf_config/fs/fs_config.hcs文件,该文件主要写清楚设备挂载信息,具体如下:

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]; } } }}

如上所述,我将LittleFS移植所需的Flash信息分为4个:

(1)mount_points:挂载目录。

(2)block_size:Flash的擦除块大小。

(3)block_start:该挂载Flash区域的起始块地址,实际Flash地址为block_size * block_start。

(4)block_count:该挂载Flash区域的存储块总数。

注意:match_attr所表示的字符串要与device_info.hcs所表示的字符串要一致。

2、hdf驱动

新建//device/soc/rockchip/rk2206/hdf_driver/fs文件夹,文件夹下创建2个文件,具体如下所示:

2.1、fs_driver.c

2.1.1、添加必要的头文件

#include#include#include "los_config.h"#include "hdf_log.h"#include "hdf_device_desc.h"#include "device_resource_if.h"#include "osal_mem.h"#include "lfs_api.h"


2.1.2、添加HDF驱动

添加LittleFS匹配的hdf驱动,具体代码如下所示:

static struct HdfDriverEntry g_fsDriverEntry = { .moduleVersion = 1, .moduleName = "HDF_PLATFORM_FS_LITTLEFS", .Bind = fs_driver_bind, .Init = fs_driver_init, .Release = fs_driver_release,};


HDF_INIT(g_fsDriverEntry);

其中,moduleName必须要与device_info.hcs中的moduleName保持一致。


2.1.3、fs_driver_init函数

fs_driver_init为hdf驱动加载函数。OpenHarmony启动时,将根据hcs的编写匹配对应的驱动程序,并运行fs_driver_init函数。该函数负责:

(1)读取hcs文件的配置参数。

(2)初始化Flash。

(3)适配LittleFS对应的read、write、erase和sync函数,并适配LittleFS相关参数。

(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\n"); return HDF_ERR_INVALID_OBJECT; } if (device->property == NULL) { PRINT_ERR("device is null\n"); return HDF_ERR_INVALID_OBJECT; }

/* Flash设备初始化 */ FlashInit();

/* 读取hcs参数 */ ret = fs_driver_readdrs(device->property, &m_fs_cfg[0]); if (ret != HDF_SUCCESS) { PRINT_ERR("%s: fs_driver_readdrs failed(%d)\n", ret); return ret; } /* 适配LitteleFS对应的函数和参数 */ 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\n", 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; /* 准备挂载 */ result = SetDefaultMountPath(i, m_fs_cfg[i].mount_point); if (result != VFS_OK) { PRINT_ERR("SetDefaultMountPath(%d, %d) failed(%d)\n", 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\n", __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.\n", m_fs_cfg[i].mount_point); } else if (lfs_ret == LFS_ERR_EXIST) { PRINT_LOG("root dir(%s) exist.\n", m_fs_cfg[i].mount_point); } else { PRINT_LOG("create root dir(%s) failed.", m_fs_cfg[i].mount_point); } } } return HDF_SUCCESS;}

2.2、BUILD.gn

BUILD.gn负责将fs_driver.c编译到内核中,具体源代码如下所示:

import("//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 = [ "." ]}

3、测试程序

我在main函数中添加一个任务,负责每隔5秒读写文件。具体代码如下所示:

/* 文件系统测试 */

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!\n", file_name); return; } memset(buffer, 0, sizeof(buffer)); snprintf(buffer, sizeof(buffer), "Hello World and %d\n", 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!\n", 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!\n", __func__, SLEEP_MAXSEC); /* 文件系统测试 */ file_rw();

LOS_Msleep(SLEEP_MAXSEC * 1000); }}

三、实验结果

程序编译烧写到开发板后,按下开发板的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

......


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 驱动
    +关注

    关注

    12

    文章

    1927

    浏览量

    88184
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    rtt 5.1.0使用最新版的littleFS异常的原因?

    项目中使用文件系统(存储介质是spi nor flash),测试发现正在写文件掉电会导致文件系统破坏,于是将elm(fatfs)换成littleFS,遇到一个比较奇怪的问题就是:如果首
    发表于 09-10 06:43

    Linux三大主流文件系统解析

    还在为选择哪个文件系统而纠结?作为一名摸爬滚打多年的运维老鸟,我将用最接地气的方式,带你彻底搞懂 Linux 三大主流文件系统的奥秘。
    的头像 发表于 08-05 17:37 1038次阅读

    服务器数据恢复—ocfs2文件系统被格式化为Ext4文件系统的数据恢复案例

    服务器存储数据恢复环境&故障: 人为误操作将Ext4文件系统误装入一台服务器存储上的Ocfs2文件系统数据卷上,导致原Ocfs2文件系统被格式化为Ext4文件系统
    的头像 发表于 06-10 12:03 559次阅读
    服务器数据恢复—ocfs2<b class='flag-5'>文件系统</b>被格式化为Ext4<b class='flag-5'>文件系统</b>的数据恢复案例

    【北京迅为】iTOP-RK3568开发板鸿蒙OpenHarmony系统南向驱动开发实操-HDF驱动配置UART

    【北京迅为】iTOP-RK3568开发板鸿蒙OpenHarmony系统南向驱动开发实操-HDF驱动配置UART
    的头像 发表于 03-25 11:02 1284次阅读
    【北京迅为】iTOP-RK3568开发板鸿蒙<b class='flag-5'>OpenHarmony</b><b class='flag-5'>系统</b>南向<b class='flag-5'>驱动</b>开发实操-<b class='flag-5'>HDF</b><b class='flag-5'>驱动</b>配置UART

    北京迅为iTOP-RK3568开发板OpenHarmony系统南向驱动开发实操-HDF驱动配置LED

    北京迅为iTOP-RK3568开发板OpenHarmony系统南向驱动开发实操-HDF驱动配置LED
    的头像 发表于 03-14 14:41 1099次阅读
    北京迅为iTOP-RK3568开发板<b class='flag-5'>OpenHarmony</b><b class='flag-5'>系统</b>南向<b class='flag-5'>驱动</b>开发实操-<b class='flag-5'>HDF</b><b class='flag-5'>驱动</b>配置LED

    北京迅为RK3568开发板OpenHarmony系统南向驱动开发内核HDF驱动框架架构

    北京迅为RK3568开发板OpenHarmony系统南向驱动开发内核HDF驱动框架架构
    的头像 发表于 03-11 14:13 1552次阅读
    北京迅为RK3568开发板<b class='flag-5'>OpenHarmony</b><b class='flag-5'>系统</b>南向<b class='flag-5'>驱动</b>开发内核<b class='flag-5'>HDF</b><b class='flag-5'>驱动</b>框架架构

    NFS网络文件系统深度解析

    NFS:Network File System 网络文件系统,基于内核的文件系统。Sun 公司开发,通过使用 NFS,用户和程序可以像访问本地文件一样访问远端系统上的
    的头像 发表于 03-01 14:15 1152次阅读

    迅为RK3568开发板篇OpenHarmony实操HDF驱动控制LED-编写应用APP

    HdfIoServiceBind 绑定 LED灯的 HDF 服务,获取 HDF 空间缓存区,并向该缓冲区写入控制数据。然后,通过 LED_WRITE 命令将数据发送到 HDF 驱动
    发表于 02-06 10:27

    迅为RK3568开发板篇OpenHarmony实操HDF驱动控制LED-添加内核编译

    编译内核时将该 HDF 驱动编译到镜像中,接下来编写驱动编译脚本 Makefile,代码如下所示: 加入编译体系,填加模块目录到 drivers/hdf_core/adapter/kh
    发表于 01-22 10:35

    迅为RK3568开发板篇OpenHarmony实操HDF驱动控制LED-编写内核 LED HDF 驱动程序

    接下来编译 LED 驱动,该驱动用于在基于华为设备框架(HDF)的系统中控制 LED 灯的开关,完整代码如下所示: 更多内容可以关注:迅为RK3568开发板篇
    发表于 01-17 15:13

    【S32K146 RT-thread】基于内部PFLASH的littlefs适配

    LittleFS是一个应用于单片机内部flash和外挂NORflash的文件系统。由于它相比传统的FAT文件系统更适合于小型嵌入式系统,具有以下特点:掉电恢复能力:设计用于处理随机电源
    的头像 发表于 01-14 18:32 2359次阅读
    【S32K146 RT-thread】基于内部PFLASH的<b class='flag-5'>littlefs</b>适配

    迅为RK3568开发板篇OpenHarmony配置HDF驱动控制LED-新增 topeet子系统

    hdf_led:子组件目录 app:led 应用层目录 ├── BUILD.gn:应用 APP 的 GN 文件 └── led_test.c:应用层 LED 测试程序 driver:内核 HDF
    发表于 01-13 15:59

    防止根文件系统破坏,OverlayRootfs 让你的设备更安全

    多个文件系统层合并成一个单一的视图,在Linux系统中广泛应用。使用OverlayRootfs的设备可以很轻松的实现:根文件系统写保护、恢复出厂设置功能。根
    的头像 发表于 01-08 16:33 2443次阅读
    防止根<b class='flag-5'>文件系统</b>破坏,OverlayRootfs 让你的设备更安全

    关于更新openharmony文件系统时遇到的问题

    用的固件,文件系统,内核是之前的,之前版本用起来没问题。但是 用下面三个的时候 固件可以正常烧录,也按照文档里面加载了环境变量,但是烧录内核和文件系统(都是U盘更新的)的时候出现了这样的问题
    发表于 12-30 11:55

    芯海科技系列OpenHarmony3.1芯片支持智慧生态构建

    随着OpenHarmony3.1的正式发布,芯海科技作为OpenHarmony生态的重要参与者,及时推出了两款与系统适配的新品:健康测量CS1262芯片和无线连接CST85F01模组,为智慧生态的构建贡献了芯海力量。
    的头像 发表于 12-17 17:25 898次阅读
    芯海科技系列<b class='flag-5'>OpenHarmony3.1</b>芯片支持智慧生态构建