掉电安全文件系统littlefs移植

前言

通过查看oneOS中对littlefs的移植工作,发现,littlefs源码本身,有用的就4个:

  • lfs.c
  • lfs.h
  • lfs_util.c
  • lfs_util.h

剩下的就是适配层:

  • dfs_lfs.c
  • lfs_config.h(和lfs_util.h差不多)
  • lfs_crc.c(和lfs_util.c差不多)

然后再对比其源码,发现,littlefs的源码完全没有更改,更改的只有是适配层,因此,接下来重点看看适配层到底改了什么!

适配层更改

先看lfs_crc.c:

他和lfs_util.c几乎一样,唯一区别在于:

如果没有定义宏LFS_CONFIG,那么将使用lfs_util.c中的lfs_crc接口;

如果定义了宏LFS_CONFIG,那么将使用lfs_crc.c中的lfs_crc接口。

oneOS在sconscript中是定义了该宏的:

CPPDEFINES = ['LFS_CONFIG=lfs_config.h']

另外该宏在lfs_util.h中有被用到作为一个判断:

  • 用户可以通过定义一个头文件来包含自己的配置来覆盖 lfs_util.h,通过定义 LFS_CONFIG 为一个头文件来包含(-DLFS_CONFIG=lfs_config.h)。
  • 如果使用了 LFS_CONFIG,那么默认的lfs_util.h将不会被输出,必须由配置文件提供。建议复制 lfs_util.h 并根据需要修改。
#ifdef LFS_CONFIG
#define LFS_STRINGIZE(x) LFS_STRINGIZE2(x)
#define LFS_STRINGIZE2(x) #x
#include LFS_STRINGIZE(LFS_CONFIG)
#else... ...
#endif

可见,是在lfs_util.h文件中,直接include lfs_config.h

再看lfs_config.h

同样,他就是lfs_util.h改过来的,并没有太大区别。主要看点在于:

  • 如果没有定义LFS_ASSERT&&LFS_NO_ASSERTutil.h用的是assert.h里面的函数assert,而config用的是oneOS自带的os_assert
  • 如果没有定义LFS_NO_MALLOC,说明lfsmalloc,这时候util.h用的是stdlib.h里面的函数mallocfree,而config用的是oneOS自带的os_mallocos_free
适配dfs_lfs.c

最重要的适配层vfs_lfs.c,我把她单独拎出来,作为最高的敬意。

其实她的逻辑很清晰,最开始就是基本的配置,然后是littlefs需要用到的底层函数的适配,这两个都是对*struct* lfs_config结构体成员的赋值,最后则是对接vfs层的接口适配。

基本配置
#ifndef RT_DEF_LFS_DRIVERS#define RT_DEF_LFS_DRIVERS 1
#endif#if (RT_DEF_LFS_DRIVERS < 1)#error "#define RT_DEF_LFS_DRIVERS must > 0"
#endif#ifndef LFS_READ_SIZE#define LFS_READ_SIZE 256
#endif#ifndef LFS_PROG_SIZE#define LFS_PROG_SIZE 256
#endif#ifndef LFS_BLOCK_SIZE#define LFS_BLOCK_SIZE 4096
#endif#ifndef LFS_CACHE_SIZE#define LFS_CACHE_SIZE LFS_PROG_SIZE
#endif#ifndef LFS_BLOCK_CYCLES#define LFS_BLOCK_CYCLES (-1)
#endif#ifndef LFS_LOOKAHEAD_MAX#define LFS_LOOKAHEAD_MAX 128
#endif
lfs底层函数适配
static void _lfs_load_config(struct lfs_config* lfs_cfg, struct rt_mtd_nor_device* mtd_nor)
{uint64_t mtd_size;lfs_cfg->context = (void*)mtd_nor;lfs_cfg->read_size = LFS_READ_SIZE;lfs_cfg->prog_size = LFS_PROG_SIZE;lfs_cfg->block_size = mtd_nor->block_size;if (lfs_cfg->block_size < LFS_BLOCK_SIZE){lfs_cfg->block_size = LFS_BLOCK_SIZE;}lfs_cfg->cache_size = LFS_CACHE_SIZE;lfs_cfg->block_cycles = LFS_BLOCK_CYCLES;mtd_size = mtd_nor->block_end - mtd_nor->block_start;mtd_size *= mtd_nor->block_size;lfs_cfg->block_count = mtd_size / lfs_cfg->block_size;lfs_cfg->lookahead_size = 32 * ((lfs_cfg->block_count + 31) / 32);if (lfs_cfg->lookahead_size > LFS_LOOKAHEAD_MAX){lfs_cfg->lookahead_size = LFS_LOOKAHEAD_MAX;}
#ifdef LFS_THREADSAFElfs_cfg->lock = _lfs_lock;        //如果定义了线程安全,则使用mutex互斥锁lfs_cfg->unlock = _lfs_unlock;
#endiflfs_cfg->read = _lfs_flash_read;  //littlefs用到的底层函数readlfs_cfg->prog = _lfs_flash_prog;  //littlefs用到的底层函数writelfs_cfg->erase = _lfs_flash_erase;//littlefs用到的底层函数erase 直接返回OKlfs_cfg->sync = _lfs_flash_sync;  //littlefs用到的底层函数sync  直接返回OK
}
vfs对接层

主要是为了对接vfs层,让vfs的接口可以直接使用底层littfs函数。

static int _lfs_result_to_dfs(int result)  //错误码转换
static int _vfs_lfs_mount(struct vfs_filesystem* vfs, unsigned long rwflag, const void* data)  //挂载
static int _vfs_lfs_unmount(struct vfs_filesystem* vfs) //卸载
static int _vfs_lfs_open(struct vfs_file* file)         //打开文件
... ...
static int _vfs_lfs_getdents(struct vfs_file* file, struct dirent* dirp, uint32_t count) //获得目录
适配总结

由此可见,适配lfs最重要的几步:

  • 如果定义了LFS_CONFIG,要自己做好配置
  • 基本的配置要做好,底层函数要适配,归结起来就是:struct lfs_config中的结构体成员要初始化好
  • vfs对接层要做好,这是每一个底层文件系统到vfs层必须要做的
oneos-lfs对照
    part_info->dev_info.dev    = (void *)dev;part_info->config.context = &part_info->dev_info;part_info->config.read    = g_lfs_dev_ops.read;part_info->config.prog    = g_lfs_dev_ops.prog;part_info->config.erase   = g_lfs_dev_ops.erase;part_info->config.sync    = g_lfs_dev_ops.sync;
#ifdef LFS_THREADSAFEpart_info->config.lock    = g_lfs_dev_ops.lock;part_info->config.unlock  = g_lfs_dev_ops.unlock;
#endifpart_info->config.read_size    = geometry.block_size;//最小读字节数,试了下不能乱改,sectorpart_info->config.prog_size    = geometry.block_size;//最小写字节数,试了下不能乱改,sectorpart_info->config.block_size   = geometry.block_size;//硬件块大小,试了下不能乱改,blocksizepart_info->config.block_count  = geometry.capacity / geometry.block_size;//不用手动配part_info->config.block_cycles = -1;                //禁用块级磨损均衡part_info->config.cache_size    = geometry.block_size; //块缓存的大小,该值必须是读取和编程大小的倍数,并且是块大小的因数,就是要和block_size一样就好!!!part_info->config.lookahead_size= LFS_LOOKAHEAD_SIZE; //块分配时的预测深度(分配块时每次步进多少个块),这个数值必须为8的整数倍,这个可以改!!!part_info->config.read_buffer      = OS_NULL; //lfs_init中会分配!part_info->config.prog_buffer      = OS_NULL; //lfs_init中会分配!part_info->config.lookahead_buffer = OS_NULL; //lfs_init中会分配!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/28774.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python 数据持久化:使用 SQLite3 进行简单而强大的数据存储

&#x1f340; 前言 博客地址&#xff1a; CSDN&#xff1a;https://blog.csdn.net/powerbiubiu &#x1f44b; 简介 SQLite3是一种轻量级嵌入式数据库引擎&#xff0c;它在Python中被广泛使用。SQLite3通常已经包含在Python标准库中&#xff0c;无需额外安装。你只需导入 s…

IRIS论文阅读笔记

这是ICLR2023一篇world model的论文&#xff0c;提出了一个称为IRIS的world model方法模型仍然是分为两部分&#xff0c;一部分是模拟世界的world model&#xff0c;包括预测下一帧的观测&#xff0c;预测当前reward&#xff0c;预测是否terminate的三个输出&#xff1b;第二部…

BGP简介

BGP 的概念定义 BGP 的概念&#xff1a; 边界网关协议&#xff08;Border Gateway Protocol&#xff0c;BGP&#xff09; 一种用于在不同自治系统&#xff08;AS&#xff09;之间交换路由信息的动态路由协议。互联网的核心路由协议之一&#xff0c;确保了全球网络的互联性和…

Linux ubuntu安装pl2303USB转串口驱动

文章目录 1.绿联PL2303串口驱动下载2.驱动安装3.验证方法 1.绿联PL2303串口驱动下载 下载地址&#xff1a;https://www.lulian.cn/download/16-cn.html 也可以直接通过CSDN下载&#xff1a;https://download.csdn.net/download/Axugo/89447539 2.驱动安装 下载后解压找到Lin…

【Linux命令行】从时间管理->文件查找压缩的指令详解

目录 1.date 命令&#xff08;显示时间&#xff09; 1.1 显示方面 1.2 设定时间 1.3 时间戳转换 1.4 cal&#xff08;日历&#xff09; 2. 重定向 2.1 输出重定向&#xff08;echo >&#xff09;cin 2.2 追加重定向 >> 2.3 输入重定向 < cout 3.find 指…

API接口设计的艺术:如何提升用户体验和系统性能

在数字时代&#xff0c;API接口的设计对于用户体验和系统性能有着至关重要的影响。良好的设计可以显著提升应用程序的响应速度、可靠性和易用性。以下是几个关键点&#xff0c;帮助改善API接口的设计&#xff1a; 1. 理解并定义清晰的要求 用户研究&#xff1a;与最终用户进行…

[晕事]今天做了件晕事38 shell里的source 点号

今天碰到一个问题脚本里使用点号引入某个文件形式如下&#xff1a; . /tmp/abc但是脚本运行出现错误&#xff0c;一开始还以为是/tmp没有可执行权限&#xff08;https://mzhan017.blog.csdn.net/article/details/112178736#t16&#xff09;&#xff0c;导致abc运行不了。 后来…

如何根据使用场景选购3D扫描仪?

三维扫描建模是指通过专业的三维扫描仪对产品进行三维数据的采集&#xff0c;快速获取物体精确的3D数据&#xff0c;实现1:1复刻原物体&#xff0c;扫描后所得的数字化3D模型以obj、fbx、glb、gltf等格式保存。 积木易搭自主研发多款三维扫描设备&#xff0c;拥有多项国家专利&…

【大分享04】OFD版式赋能政务服务电子文件归档和电子档案管理

关注我们 - 数字罗塞塔计划 - 本篇是参加由电子文件管理推进联盟联合数字罗塞塔计划发起的“大分享”活动投稿文章&#xff0c;来自北京数科网维技术有限责任公司&#xff0c;作者&#xff1a;张严。 PART1 政务服务电子文件归档和电子档案管理背景 政务服务是政务服务机构…

RockChip Android12 Settings一级菜单

一:概述 在之前的文章中对Android8.1 Settings的流程进行了说明,本章将针对Android12 Settings一级菜单的加载逻辑进行详细说明,Settings版本之间的差异不是很大,有兴趣的同学可自行学习,本文不在做赘述。 Android8.1 Settings说明:RockChip Android8.1 Settings-CSDN博…

最佳websocket封装

封装了weboskect&#xff0c;完美支持了断网重连、自动心跳的功能&#xff0c;且完全兼容原生写法&#xff0c;无任何学习负担&#xff0c;开开箱即用&#xff01; import { EventDispatcher } from ./dispatcher;export class WebSocketClient extends EventDispatcher {// #…

使用 TypeScript 写一个自己的 NPM 库

和JS写法差不多&#xff0c;就是要下一个TypeScript依赖 TypeScript编写共享库并发布到npm

linux MySQL基本操作

linux MySQL基本操作 文章目录 linux MySQL基本操作1. 操作语句启动 MySQL&#xff1a;查看 MySQL 运行状态&#xff1a;登录mysql 2. mysql 内语句密码永不过期设置远程访问刷新MySQL的系统权限相关表 1. 操作语句 启动 MySQL&#xff1a; systemctl start mysqldsystemctl …

早期发现,健康生活!第三届ZAODX世界肿瘤早筛大会圆满落幕!

2024年6月15日-16日&#xff0c;第三届ZAODX世界肿瘤早筛大会在雄安新区盛大开幕&#xff01;本次会议由河北雄安新区管理委员会公共服务局指导&#xff0c;第三届ZAODX世界肿瘤早筛大会组委会和早筛网主办&#xff0c;粤港澳大湾区精准医学研究院&#xff08;广州&#xff09;…

python GUI开发: tkinter事件处理的几种方式详解与应用实战

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

GEM5 Garnet +DSENT: NoC power model 功耗模型

0. 简介 现在&#xff08;2024&#xff09;集成的是dsent。 Garnet作者&#xff0c;Turshar在2018年说Orion已经过时不在集成DSENT&#xff0c;但是集成DSENT的代码随着gem5更新也过时了&#xff0c;而他短期内没有更新的计划&#xff08;2018年说的&#xff09;。2023年还有一…

SpringBoot配置第三方专业缓存技术jetcache远程缓存方案和本地缓存方案

JetCache 是一个基于 Java 的分布式缓存解决方案&#xff0c;旨在提供高性能和可扩展性。它支持多种后端存储&#xff0c;如 Redis、Hazelcast、Tair 等&#xff0c;可以作为应用程序的缓存层&#xff0c;有效地提升数据访问性能和响应速度。 JetCache 的主要特点包括&#x…

springboot应用启动太慢排查 半天才打印日志

springboot应用启动太慢排查 半天才打印日志 解决办法 hostnamectl 命令查看主机名 vim /etc/hosts 加上主机名配置 127.0.0.1 hostname

Java_JDK下载与环境变量配置

目录 一、JDK下载安装 二、安装后配置环境变量 三、在编辑器里使用JDK 一、JDK下载安装 JDK 是Java开发工具包&#xff0c;它提供了用于开发和运行Java程序所需的工具和库。JDK包括Java编译器、Java虚拟机、Java标准库等。在IDEA中使用Java语言编写代码时&#xff0c;需要安…

为什么 Kubernetes 调试如此成问题?

在 Kubernetes 集群中调试应用程序问题通常感觉就像在迷宫中穿行。容器在设计上是短暂的&#xff0c;一旦部署就不可改变。当出现问题并且我们需要深入研究问题时&#xff0c;这会带来独特的挑战。在深入研究调试工具和技术之前&#xff0c;必须掌握核心问题&#xff1a;为什么…