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

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

3天内不再提示

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

电子发烧友开源社区 来源:未知 作者:电子发烧友开源社 2022-09-30 18:32 次阅读

1.简介

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文件系统移植,现将相关移植经验发布,分享给大家。文中如有问题,请大家帮忙指正。

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

(左右移动查看全部内容)

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

(左右移动查看全部内容)

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!
", 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);


    /* 文件系统测试 */
    file_rw(); 


    LOS_Msleep(SLEEP_MAXSEC * 1000);
  }
}

(左右移动查看全部内容)

3

结果

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

(左右移动查看全部内容)


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

    关注

    0

    文章

    9

    浏览量

    2760
  • OpenHarmony
    +关注

    关注

    25

    文章

    3658

    浏览量

    16145

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

文章出处:【微信号:HarmonyOS_Community,微信公众号:电子发烧友开源社区】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    stm32单片机基于rt-thread 的 littlefs 文件系统 的使用

    简介littlefs是ARM官方推出的,专为嵌入式系统设计的文件系统,相比传统的文件系统littlefs具有以下优点:1、自带擦写均衡2、
    的头像 发表于 11-06 08:04 302次阅读
    stm32单片机基于rt-thread 的 <b class='flag-5'>littlefs</b> <b class='flag-5'>文件系统</b> 的使用

    Linux根文件系统的挂载过程

    Linux根文件系统(rootfs)是Linux系统中所有其他文件系统和目录的起点,它是内核启动时挂载的第一个文件系统
    的头像 发表于 10-05 16:50 268次阅读

    小型文件系统如何选择?FatFs和LittleFs优缺点比较

    和删除文件实现了数据的持久化存储和分层次的目录结构。文件系统的存在极大地简化了数据管理任务,提升了系统整体的稳定性和便利性,对于系统配置、
    的头像 发表于 09-29 16:14 961次阅读
    小型<b class='flag-5'>文件系统</b>如何选择?FatFs和<b class='flag-5'>LittleFs</b>优缺点比较

    [2K300适配OpenharmonyV4.1]根文件系统制作请教

    文件系统rootfs.img烧录到2k300上,烧录失败。对比2k300开源资料中的Openharmony 文件系统,该文件系统为ext4格式,但是2k500编译出来的为Ubifs
    发表于 09-11 11:18

    如何修改buildroot和debian文件系统

    本文档主要介绍在没有编译环境的情况下,如何修改buildroot和debian文件系统方法,如在buildroot文件系统中添加文件、修改目录等文件操作,在debian
    的头像 发表于 07-22 17:46 416次阅读
    如何修改buildroot和debian<b class='flag-5'>文件系统</b>

    linux--sysfs文件系统

    sysfs文件系统 sysfs,全称为System Filesystem,是一个由Linux内核实现的虚拟文件系统。它扮演着一个桥梁的角色,将内核中的设备和驱动程序信息以
    的头像 发表于 07-08 11:37 718次阅读
    linux--sysfs<b class='flag-5'>文件系统</b>

    esp32s2写文件系统时io外部中断触发不及时,怎么解决?

    芯片esp32s2,idf release v4.4,目前问题,io配置为边沿触发,需要采集上升沿下降沿之间的脉冲宽度,假如一个40ms的脉冲,在写文件系统时脉冲采集到的宽度为10-20ms,不写文件系统没问题,文件系统使用FA
    发表于 06-12 08:29

    如何将Littlefs安装到通过qspi连接到电路板的外部串行闪存上?

    我正试图在 XMC7100 V1.1 中的 qspi 外部串行闪存上闪存 littlefs 文件系统。 我看到库中的 mtb-littlefs 不包括在 XMC7100 套件中。 如果我下载任何
    发表于 05-27 06:03

    【嵌入式SD NAND】基于FATFS/Littlefs文件系统的日志框架实现

    文章目录 【嵌入式】基于FATFS/Littlefs文件系统的日志框架实现 1. 概述 2. 设计概要 3. 设计实现 3.1 初始化 `i
    的头像 发表于 03-14 18:13 1007次阅读
    【嵌入式SD NAND】基于FATFS/<b class='flag-5'>Littlefs</b><b class='flag-5'>文件系统</b>的日志框架<b class='flag-5'>实现</b>

    【嵌入式SD NAND】基于FATFS/Littlefs文件系统的日志框架实现

    文章目录 【嵌入式】基于FATFS/Littlefs文件系统的日志框架实现 概述 设计概要 设计实现 3.1 初始化 init 3.2 日志
    发表于 03-14 18:12

    【嵌入式SD NAND】基于FATFS/Littlefs文件系统的日志框架实现

    文章目录【嵌入式】基于FATFS/Littlefs文件系统的日志框架实现1.概述2.设计概要3.设计实现3.1初始化`init`3.2日志写
    的头像 发表于 03-14 18:12 1124次阅读
    【嵌入式SD NAND】基于FATFS/<b class='flag-5'>Littlefs</b><b class='flag-5'>文件系统</b>的日志框架<b class='flag-5'>实现</b>

    Linux系统如何扩展文件系统

    当数据盘没有创建分区,只在设备上创建了文件系统。或者格式化了硬盘,就直接mount上系统使用。
    的头像 发表于 02-21 09:53 798次阅读

    鸿蒙轻内核源码分析:虚拟文件系统 VFS

    VFS(Virtual File System)是文件系统的虚拟层,它不是一个实际的文件系统,而是一个异构文件系统之上的软件粘合层,为用户提供统一的类 Unix 文件操作接口。由于不同
    的头像 发表于 02-18 14:50 759次阅读

    LittleFS是否可以应用于SD卡中呢?

    LittleFS是一个应用于单片机内部flash和外挂NOR flash的文件系统
    的头像 发表于 12-28 16:41 4100次阅读
    <b class='flag-5'>LittleFS</b>是否可以应用于SD卡中呢?

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

    由于工作人员的误操作,将Ext4文件系统误装入到存储中Ocfs2文件系统数据卷上,导致原Ocfs2文件系统被格式化为Ext4文件系统。 由于Ext4
    的头像 发表于 12-04 10:49 419次阅读
    服务器数据恢复—ocfs2<b class='flag-5'>文件系统</b>被误格式化为Ext4<b class='flag-5'>文件系统</b>的数据恢复案例