初学littlefs文件系统

这篇具有很好参考价值的文章主要介绍了初学littlefs文件系统。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

概述

一个为微控制器设计的小故障安全文件系统。

  • 掉电恢复能力: 设计用于处理随机电源故障。所有文件操作都有很强的写时拷贝保证,如果断电,文件系统将恢复到上一次已知的良好状态。

  • 动态磨损均衡: 设计考虑到闪存,并提供动态块磨损均衡。此外,littlefs可以检测坏块并在它们周围工作。

  • 有限RAM/ROM: 被设计为使用少量内存。RAM的使用是严格限制的,这意味着RAM的使用不会随着文件系统的增长而改变。文件系统不包含无界递归,动态内存仅限于可静态提供的可配置缓冲区。

在lfs.h的评论中可以找到详细的文档(或者至少是目前可用的尽可能多的细节)。 littlefs采用了一种配置结构,定义了文件系统的运行方式。配置结构为文件系统提供了块设备操作和维度、可调整的参数(用于在性能上权衡内存使用情况)以及可选的静态缓冲区(如果用户希望避免动态内存)。 littlefs的状态存储在lfs\t类型中,由用户分配,允许同时使用多个文件系统。使用lfs\u t和configuration struct,用户可以格式化块设备或挂载文件系统。 挂载后,littlefs提供了一整套类似POSIX的文件和目录功能,但文件系统结构的分配必须由用户提供。 所有POSIX操作,比如remove和rename,都是原子的,即使在断电的情况下也是如此。此外,在对文件调用sync或close之前,文件更新实际上不会提交到文件系统。

littlefs文件系统下载地址

Tags · littlefs-project/littlefs · GitHub

下载最新的即可。

源码下载下来后,只需要其中的4个文件:lfs.c、lfs.h、lfs_util.c、lfs_util.h,其他文件都是用于测试的Demo例程,调试过程中需要参考的话可以了解一下。

移植步骤

1、将lfs.c、lfs.h、lfs_util.c、lfs_util.h这4个文件放到一个新建的文件夹,并将其添加到工程中;sos_lfs.c这个文件是我对lfs.c接口二次封装生成的文件,这个文件根据你自己喜好命名,适配即可。

littlefs,学习心得,学习开发,心得分享,服务器,运维,linux

2、适配lfs_util.h

lfs_util.h中需要修改申请内存的方式,如果你代码中对malloc有修改过,就需要修改为你动态申请内存的方式

原版

littlefs,学习心得,学习开发,心得分享,服务器,运维,linux

我的系统移植了FreeRTOS系统,动态申请内存是在FreeRTOS的总内存中申请,所以我需要修改此内存申请的方式

 3、适配lfs_config结构体的内容

lfs_config结构体
结构体成员变量     说明
void *context 用于给底层块设备传参,比如:要写入的文件信息、位置、大小、是否有坏块等。该参数的数据结构由底层块设备驱动来定义。如果不需要传参的话可以不赋值
int (*read) 块设备读取函数指针
int (*prog) 块设备写入函数指针,写入前必须保证该写入块已经被擦除过
int (*erase) 块设备擦除函数指针
int (*sync) 块设备同步函数指针,若块设备不需要同步操作,可以直接返回成功
lfs_size_t read_size 最小读取字节数,所有的读取操作字节数必须是它的整数倍
lfs_size_t prog_size 最小写入字节数,所有的写入操作字节数必须是它的整数倍
lfs_size_t block_size 擦除块操作的字节数,该选项不影响 RAM 消耗,可以比物理擦除尺寸大,但是每个文件至少占用一个块,必须是读取和写入操作字节数的整数倍
lfs_size_t block_count 设备上可擦除块的数量,block_size x block_count = 块设备容量
int32_t block_cycles littlefs 系统删除元数据日志并将元数据移动到另一个块之前的擦除周期数。建议取值范围为 100 ~ 1000,较大数值有较好的性能但是会导致磨损分布不一致,若取值 -1 的话,即为禁用块级磨损均衡
lfs_size_t cache_size 块缓存大小,每个缓存都会在 RAM 中缓冲一部分块数据,littlefs 系统需要一个读取缓存、一个写入缓存,每个文件还需要一个额外的缓存。更大的缓存可以通过存储更多的数据并降低磁盘访问数量等手段来提高性能
lfs_size_t lookahead_size 先行缓冲大小,更大的先行缓冲可以提高分配操作中可被发现的块数量。即分配块时每次分配多少个块,16就表示每次分配16个块。先行缓冲以 bit 位形式来存储,故 RAM 中的一个字节对应8个块。该值必须是8的整数倍
int (*lock) 块设备加锁函数指针,需定义 LFS_THREADSAFE 宏才可用,若不需要多线程操作可不赋值
int (*unlock) 块设备解锁函数指针,需定义 LFS_THREADSAFE 宏才可用,若不需要多线程操作可不赋值
void *read_buffer 可选参数。读取静态缓冲区指针。若目标MCU不支持动态分配堆内存的话,就需要定义这个参数,用于在栈内分配静态变量
void *prog_buffer 可选参数。写入静态缓冲区指针。若目标MCU不支持动态分配堆内存的话,就需要定义这个参数,用于在栈内分配静态变量
void *lookahead_buffer 可选参数。先行分配静态缓冲区指针,需要32bit对齐。若目标MCU不支持动态分配堆内存的话,就需要定义这个参数,用于在栈内分配静态变量

下面是我的lfs_config配置表

littlefs,学习心得,学习开发,心得分享,服务器,运维,linux

3.1、block_count我用了宏定义,这个大小根据你分配内存大小给定,我分配的littlefs的内存大小是2600K,所以INTERNALFLASH_LFS_MAXSIZE是650,其中cache_size的大小和block_size、read_size的大小成比例,否则运行lfs的时候就会出现错误的问题

3.2、在单线程的情况下lock和unlock可以不适配,多线程的时候,建议适配,因为会出现抢占资源,导致不必要的错误。

3.3、.read、.prog、.erase 、.sync  、.lock 、.unlock 适配

注:因为flash中有存放了你的程序,不是整块芯片都用作littlefs文件系统,所以INTERNALFLASH_STARTADDR是我内存已经规划好相应的地址,需要偏移了指定大小的地址之后才开始被littlefs使用的;

.read

littlefs,学习心得,学习开发,心得分享,服务器,运维,linux

 .prog

littlefs,学习心得,学习开发,心得分享,服务器,运维,linux

.erase

littlefs,学习心得,学习开发,心得分享,服务器,运维,linux .sync

littlefs,学习心得,学习开发,心得分享,服务器,运维,linux

.lock

littlefs,学习心得,学习开发,心得分享,服务器,运维,linux .unlock

littlefs,学习心得,学习开发,心得分享,服务器,运维,linux

4、测试接口是否适配OK?

4.1、lfs初始化

littlefs,学习心得,学习开发,心得分享,服务器,运维,linux

littlefs,学习心得,学习开发,心得分享,服务器,运维,linux

littlefs,学习心得,学习开发,心得分享,服务器,运维,linux

4.2、测试函数接口

littlefs,学习心得,学习开发,心得分享,服务器,运维,linux

/* 
* @brief : 测试little fs系统接口用例
* @param : 
* @date  : 2022.07.07
* @author: 
* @remark: 
*/
void lfs_test(void)
{
    int err;
/*****************************内部文件系统测试***************************************/
    printf("*****************内部文件系统测试*********************\r\n");
	// mount the filesystem
	err = lfs_mount(&lfs_sosInternalFlash, &intCfg);

    // reformat if we can't mount the filesystem
	// this should only happen on the first boot
	if(err){
        printf("err2=%d\r\n", err);
    	lfs_format(&lfs_sosInternalFlash, &intCfg);
    	lfs_mount(&lfs_sosInternalFlash, &intCfg);
    }
    // read current count
    uint32_t boot_count1 = 0;
    lfs_file_open(&lfs_sosInternalFlash, &lfs_file_internalFlash, "boot_count1", LFS_O_RDWR | LFS_O_CREAT);
    lfs_file_read(&lfs_sosInternalFlash, &lfs_file_internalFlash, &boot_count1, sizeof(boot_count1));
    printf("ID:%d\r\n", lfs_file_internalFlash.id);
    // update boot count
    boot_count1 += 1;
    lfs_file_rewind(&lfs_sosInternalFlash, &lfs_file_internalFlash);
    lfs_file_write(&lfs_sosInternalFlash, &lfs_file_internalFlash, &boot_count1, sizeof(boot_count1));

    // remember the storage is not updated until the file is closed successfully
    lfs_file_close(&lfs_sosInternalFlash, &lfs_file_internalFlash);

    uint32_t txt1 = 0;
    lfs_file_open(&lfs_sosInternalFlash, &lfs_file_internalFlash, "txt1", LFS_O_RDWR | LFS_O_CREAT);
    lfs_file_read(&lfs_sosInternalFlash, &lfs_file_internalFlash, &txt1, sizeof(txt1));
    printf("ID:%d\r\n", lfs_file_internalFlash.id);
    // update boot count
    txt1 += 1;
    lfs_file_rewind(&lfs_sosInternalFlash, &lfs_file_internalFlash);
    lfs_file_write(&lfs_sosInternalFlash, &lfs_file_internalFlash, &txt1, sizeof(txt1));

    // remember the storage is not updated until the file is closed successfully
    lfs_file_close(&lfs_sosInternalFlash, &lfs_file_internalFlash);


    // release any resources we were using
    lfs_unmount(&lfs_sosInternalFlash);

    // print the boot count
    printf("boot_count1: %d\r\n", boot_count1);
    printf("txt1: %d\r\n", txt1);
    printf("\r\n");
/*****************************外部文件系统测试***************************************/
    printf("*****************外部文件系统测试*********************\r\n");
    // mount the filesystem
    err = lfs_mount(&lfs_sosExternalFlash, &extCfg);
	// reformat if we can't mount the filesystem
	// this should only happen on the first boot
	if(err){
        printf("err1=%d\r\n", err);
        lfs_format(&lfs_sosExternalFlash, &extCfg);
		lfs_mount(&lfs_sosExternalFlash, &extCfg);
	}

	// read current count
	uint32_t boot_count2 = 0;
	lfs_file_open(&lfs_sosExternalFlash, &lfs_file_externalFlash, "boot_count2", LFS_O_RDWR | LFS_O_CREAT);
	lfs_file_read(&lfs_sosExternalFlash, &lfs_file_externalFlash, &boot_count2, sizeof(boot_count2));
    printf("ID:%d\r\n", lfs_file_externalFlash.id);

	// update boot count
	boot_count2 += 1;
	lfs_file_rewind(&lfs_sosExternalFlash, &lfs_file_externalFlash);
	lfs_file_write(&lfs_sosExternalFlash, &lfs_file_externalFlash, &boot_count2, sizeof(boot_count2));

	// remember the storage is not updated until the file is closed successfully
	lfs_file_close(&lfs_sosExternalFlash, &lfs_file_externalFlash);
    
    uint32_t txt2 = 0;
    lfs_file_open(&lfs_sosExternalFlash, &lfs_file_externalFlash, "txt2", LFS_O_RDWR | LFS_O_CREAT);
    lfs_file_read(&lfs_sosExternalFlash, &lfs_file_externalFlash, &txt2, sizeof(txt2));
    printf("ID:%d\r\n", lfs_file_externalFlash.id);
    // update boot count
    txt2 += 1;
    lfs_file_rewind(&lfs_sosExternalFlash, &lfs_file_externalFlash);
    lfs_file_write(&lfs_sosExternalFlash, &lfs_file_externalFlash, &txt2, sizeof(txt2));

    // remember the storage is not updated until the file is closed successfully
    lfs_file_close(&lfs_sosExternalFlash, &lfs_file_externalFlash);

	// release any resources we were using
	lfs_unmount(&lfs_sosExternalFlash);

	// print the boot count
	printf("boot_count2: %d\r\n", boot_count2);
    printf("txt2: %d\r\n", txt2);
    printf("\r\n");

}

 测试通过,读写和擦除都正常,littlefs算移植完成

5、注意事项

5.1、在创建文件的时候,如果该文件已经创建过了,你再次创建同样的名字,没有加LFS_O_EXCL属性,文件同样会创建成功,但是不会返回文件已存在的错误码,创建的次数越多,后面文件系统内存会出现泄漏,最后导致写入文件都会报内存不足的问题,需要注意

5.2、内外文件系统需要自己注意函数的调用,不要混乱使用。

5.3、lfs_config配置表看自己的需要的大小适配,不过如果配置不对,很容易报错,推荐用的我的配置表。

5.4、挂载文件系统时候,如果没有实现read、erase和write的操作,会出现错误码:-84;

5.5、没有挂载成功,调用卸载函数会导致代码卡死。

6、总结

这篇文件断断续续写的,有不足的地方希望一起探讨,后续有新的发现和注意事项,我会持续更新。文章来源地址https://www.toymoban.com/news/detail-821436.html

到了这里,关于初学littlefs文件系统的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • FPGA学习心得分享——交通灯(EGO1)

      学期快结束了,学了一个学期FPGA课程,通过自己思索加上老师的指导我完成了自己第一份交通灯的作业,我希望把经验分享给学习Verilog遇到困难的同学,更希望大家都能顺利完成自己的作业。   灯能左右改变方向,作品能够模拟红、黄、绿、左右转弯灯等形式,按键可以

    2024年02月07日
    浏览(40)
  • AI绘图学习心得分享-Midjourney绘画AI,让你少走一些弯路

    本教程收集于:AIGC从入门到精通教程 AI绘图学习心得分享-Midjourney绘画AI,让你少走一些弯路 本篇没有什么长篇大论,全部都是实用心得总结。接下来,我们将分享关于Midjourney绘画AI的实用心得总结,包括构图指令结构、常用指令、操作技巧、常用风格词汇和构图词汇。 如果

    2024年02月09日
    浏览(41)
  • 工作7年了,从“功能测试”到了现在的“测试开发”,年薪35W+,分享下我的心得

    时光飞逝,转眼间从事软件测试已经是第7个年头了。从最开始的毛头小子到现在的独当一面经历了太多,也学习了太多知识,所幸最后结果是好的,目前在上海工作从事测试开发岗位,年薪35W+, 曾就职于美团测试开发框架组,搭建过美团platuo测试框架,thrift测试框架,自动

    2024年02月01日
    浏览(57)
  • 国服浪潮服务器操作系统——KeyarchOS多容器架设体验心得

    浪潮信息KeyarchOS用途广泛,当下已经有完备的CentOS迁移技术,本文来做一个具体演示,希望能给大家带来一定的帮助。 学校的老师们都应该知道,基本所有的大学都停止了CentOS的教学以及使用,下图是某高校的官网上的新闻,也是说的很直接,用的是不再允许的字样。 那么

    2024年02月05日
    浏览(28)
  • 干货分享:AI绘图学习心得-Midjourney绘画AI,让你的AI绘画之路少走弯路

    本篇没有什么长篇大论,全部都是实用心得总结。接下来,我们将分享关于Midjourney绘画AI的实用心得总结,包括构图指令结构、常用指令、操作技巧、常用风格词汇和构图词汇。 如果你想入门MidJourney可以查看这篇教程:Midjourney最全操作指南,从入门到精通 AI绘画的核心就是

    2024年02月11日
    浏览(38)
  • 【Linux后端服务器开发】基础IO与文件系统

    目录 一、基础IO 1. C语言文件读写 2. 标志位传参 3. C语言与系统调用关系 二、文件系统 1. 文件描述符 2. 输入输出重定向 文件调用 库函数接口: fopen、fclose、fwrite、fread、fseek 系统调用接口:open、close、write、read、lseek r/w/a :读/写/追加 若打开的文件不存在,“r”报错,“

    2024年02月15日
    浏览(54)
  • 学完python的心得体会,初学者对python的感想

    大家好,给大家分享一下学了一年的python的收获和感想,很多人还不知道这一点。下面详细解释一下。现在让我们来看看! Python今年是排名前3的最受欢迎和增长最快的编程语言之一。 它是一种多用途,高级别,面向对象,交互式,解释型和对用户非常友好的编程语言。 那么

    2024年02月08日
    浏览(32)
  • Linux_红帽8学习笔记分享_8(文件系统管理FS Management)

    它的全称是Basic Input/Output System即基本输入/输出系统,是比较老的传统的操作系统启动方式,如果笔记本电脑是win7之前的,红帽企业6之前的,那么它采用的启动方式都是BIOS启动方式。它在开机时需要进行自检,启动过程较复杂,时间较长。它无法识别GPT分区表,只能识别MBR分区

    2024年02月02日
    浏览(37)
  • 初学unity开发学习笔记----第一天

    以下是学习unity知识的心得,类似备忘录,肯定是存在有漏洞的地方或者专业名词使用不恰当的地方。。。 目标:编写小球wasd移动的效果 1.下载unity hub和unity引擎: (1).前往官网:Unity实时内容开发平台 -实时3D引擎、2D、VRAR可视化数据 | Unity中国官网 (2).选择unity选项卡,选择下载

    2024年02月09日
    浏览(32)
  • 【学习心得】sublime text 4 自定义编译系统

    在电脑中有多个版本的Python解释器,而sublime默认选择最新版本的解释器,如何指定自己想要的解释器呢?  文件中的代码如下:  

    2024年02月15日
    浏览(28)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包