介绍
LittleFS 由ARM官方发布,ARM mbedOS的官方推荐文件系统,具有轻量级,掉电安全的特性。主要用在微控制器和flash上,特点如下:
- 掉电恢复,在写入时即使复位或者掉电也可以恢复到上一个正确的状态。
- 擦写均衡,有效延长flash的使用寿命。例如W25QXX系列的spi接口的flash,擦写次数大概在10万次,如果是操作flash比较频繁那么这10万次很快就会到达上限从而导致芯片废掉。
- 有限的RAM/ROM,相对于FATFS节省ROM和RAM空间
缺点:不兼容windows。
移植
LittleFS的移植是比较简单的,但是移植接口官方说的不是很明白,并且提供了动态内存和静态内存两种使用方式,所以还是有一些需要注意的地方,本教程基于nordic52840+内部FLASH芯片进行移植教程。
解压LittleFS源码后,我们只需要将这四个文件加入我们的工程即可:
我还新建了一个lfs_port.c文件,将这个文件作为移植接口:
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不支持动态分配堆内存的话,就需要定义这个参数,用于在栈内分配静态变量
在使用 LittleFS 文件系统的地方还需要定义3个变量:
- lfs_t lfs; // lfs 文件系统对象
- lfs_file_t file; // lfs 文件对象
- struct lfs_config cfg; // lfs 文件系统配置结构体
在lsf_port.c文件实现接口函数和测试代码
#include "lfs_port.h"
#include "lfs.h"
#include "in_flash_manage.h"
// variables used by the filesystem
__align(4) static uint8_t m_lfs_buf[PAGE_SIZE+16];
__align(4) static uint8_t m_lfs_read_buf[PAGE_SIZE+16];
__align(4) static uint8_t m_lfs_prog_buf[PAGE_SIZE+16];
__align(4) static uint8_t m_lfs_lookahead_buf[PAGE_SIZE+16];
#pragma pack(1)
lfs_t lfs;
lfs_file_t file