掉电安全文件系统littlefs移植

server/2024/9/24 13:23:49/
前言

通过查看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.ppmy.cn/server/48400.html

相关文章

爬取京东商品图片的Python实现方法

引言 在数据驱动的商业环境中&#xff0c;网络爬虫技术已成为获取信息的重要手段。京东作为中国领先的电商平台&#xff0c;拥有海量的商品信息和图片资源。本文将详细介绍如何使用Python编写爬虫程序&#xff0c;爬取京东商品的图片&#xff0c;并提供完整的代码实现过程。 …

一些简单却精妙的算法

文章目录 1.树状数组2.红黑树3.星星打分4.欧几里得算法5.快速幂6.并查集 在编程的世界里&#xff0c;简洁的代码往往隐藏着深邃的智慧。一起来看看那些看似简单&#xff0c;实则精妙绝伦的代码片段&#xff0c;体会编程语言的优雅与力量。 1.树状数组 int lowbit(int x) { …

Codeforces Round 952 (Div. 4)(A~E题解)

这次比较遗憾的就是第五个&#xff0c;本来直接计算就过了&#xff0c;结果存到一个数组里面一直都在超时&#xff0c;导致这次第五题都没做出来&#xff0c;确实小丑了 话不多说直接看题 A. Creating Words 题解&#xff1a;这题就直接交换一下就OK&#xff0c;没有别的事。…

【MySQL】索引

https://www.wolai.com/curry00/fzTPy3kSsMDEgEcdvo4G5w https://www.bilibili.com/video/BV1Kr4y1i7ru/?p69 https://jimhackking.github.io/%E8%BF%90%E7%BB%B4/MySQL%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/#%E7%B4%A2%E5%BC%95 索引是一种用于快速查询和检索数据的数据结构…

数组中的map方法

JavaScript中的map()方法详解 map()方法经常拿来遍历数组&#xff0c;但是不改变原数组&#xff0c;但是会返回一个新的数组&#xff0c;并且这个新的数组不会改变原数组的长度 注意&#xff1a;有时候会出现这种现象&#xff0c;出现几个undefined const array [1, 4,9, 16…

Windos10上Podman安装运行mysql8

记录以下在windows10系统上Podman v5.1.1安装MySQL8全过程。 目录 一、拉取mysql8镜像二、创建宿主目录三、创建 my.cnf文件四、创建Mysql8容器五、windows上Podman安装运行mysql8失败问题描述 解决办法① 通过PowerShell进入wsl② 修改wsl系统配置③ 重启wsl&#xff0c;Podma…

E: 仓库 “http://download...graphics:/darktable/xUbuntu_22.04 InRelease” 没有数字签名

问题 Ubuntu22.04装了darktable软件没装好&#xff0c;已经卸载了但是没卸载干净,终端使用 sudo apt update 出现的问题&#xff1a; 解决&#xff1a; sudo nano /etc/apt/sources.list.d/*darktable*.list找到了该软件的相关仓库条目&#xff1a;直接给他注释掉就行了。

NOSQL -- ES

第三个我们比较常用的NOSQL类型的数据库 --- ES 介绍: ES的全称(Elasticsearch) ES是一个分布式全文搜索的引擎 也就是我们平常在购物, 搜索东西的时候常用的, 就是一个ES的类型, 分布式全文搜索引擎 查询原理: 1>分词: 在查询之前, 其会将一些数据拆分开, 按照词进行拆分…