STM32使用LittleFS文件系统记录

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


前言

在使用单片机设计的系统中经常使用价格低廉的存储方案为SPI FLASH(W25Qxx),在单片机中使用最多的文件系统为FatFS,但对于W25Qxx存储芯片来说FatFS并不是一个好的方案,原因如下:
1、FatFS不支持擦写均衡,LittleFS支持,Flash扇区有擦写寿命,如果一直擦写一个扇区会很快将一个扇区擦写坏。
2、FatFS不支持掉电保存功能,LittleFS支持,如果在写入数据时掉电虽然不会保存本次写入的数据但也不会丢失上次写入之前的数据。
3、LittleFS支持坏块检测功能,在写入后会进行回读判断写入数据是否正确
4、LittleFS占用的RAM,ROM资源少
LittleFS缺点是无法和WIndows通用


一、移植LittleFS

LittleFS下载地址
首先下载LittleFS,将lfs.c,lfs.h,lfs_util.c,lfs_util.h复制到自己的工程中,有几点需要注意:
1.在lfs_util.h中有两个函数lfs_malloc和lfs_free,虽然可以用宏定义定义LFS_NO_MALLOC不使用动态内存,但是在文件系统中打开文件时仍然调用了这个两个函数,使用在不使用动态内存时需要定义一个cache_size大小数组在lfs_malloc中返回这个数组,在不使用动态内存的情况下只能打开一个文件进行读写。

extern uint8_t file_buf[cache_size];
#define LFS_NO_MALLOC //不使用动态内存

static inline void *lfs_malloc(size_t size) {
#ifndef LFS_NO_MALLOC
    return malloc(size);
#else
    return file_buf;//返回数组
#endif
}

// Deallocate memory, only used if buffers are not provided to littlefs
static inline void lfs_free(void *p) {
#ifndef LFS_NO_MALLOC
    free(p);
#else
    (void)p;
#endif
}

2.在keil中-O0优化时lfs文件系统使用的栈最大深度大于1040个字节,-O2优化时大于800个字节,STM32的启动文件中分配的栈大小为1024个字节,所以这里需要注意,是选择-O2的优化还是和下方一样更改栈的大小,当然对于不带RTOS的程序影响不大,因为栈分配时默认是在单片机的RAM的最高地址分配向下生长的,而程序中用的变量是从RAM的低地址开始分配的,使用时只要不是将RAM全部用完了那么影响就不是很大,但对于带RTOS的程序来说就必须要注意给任务分配的栈大小了。

Stack_Size      EQU     0x00000400

更改为

Stack_Size      EQU     0x00001000

然后需要实现一个lfs.c文件中的lfs_config结构体,结构体内容如下:

context 用户自己定义的变量,LittleFS不会使用
read 一个函数指针,指向用执行Flash读操作的函数
prog 一个函数指针,指向用执行Flash写操作的函数
erase 一个函数指针,指向用执行Flash擦除扇区操作的函数
sync 一个函数指针,同步状态
lock 一个函数指针,在使用RTOS时上锁
unlock 一个函数指针,在使用RTOS时解锁
read_size 读取的最小单位
prog_size 写入的最小单位
block_size 块大小
block_count 块个数
block_cycles 擦写均衡的系数
cache_size 读写缓存区大小
lookahead_buffer 用于搜索文件的缓存区大小

我这里使用的为W25Q128,扇区大小为4K,共4096个扇区。

static uint8_t read_buf[4096];
static uint8_t write_buf[4096];
static uint8_t lookahead_buf[4096];

static struct lfs_config lfs_w25qxx_cfg = 
{
	.read = lfs_read,
	.prog = lfs_prog,
	.erase = lfs_erase,
	.sync = lfs_sync,
	
	.read_size = 1,//最小读取单位为1字节
	.prog_size = 1,//最小编程单位为1字节
	.block_size = 4096,//块大小为4096
	.block_count = 4096,//块个数为4096个
	.block_cycles = 500,//
	.cache_size = 4096,//读写缓存为4096字节
	.lookahead_size = 4096,
	
	.read_buffer = read_buf,
	.prog_buffer = write_buf,
	.lookahead_buffer = lookahead_buf,
};

二、API

int lfs_format(lfs_t *lfs, const struct lfs_config *config);
格式存储设备,一般在调用lfs_mount挂载失败后掉用。

int lfs_mount(lfs_t *lfs, const struct lfs_config *config);
挂载文件系统

int lfs_remove(lfs_t *lfs, const char *path);
删除文件或文件夹

int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath);
重命名

int lfs_stat(lfs_t *lfs, const char *path, struct lfs_info *info);
获取文件或目录信息

lfs_ssize_t lfs_getattr(lfs_t *lfs, const char *path, uint8_t type, void *buffer, lfs_size_t size);
获取文件或目录一个自定义的属性

int lfs_setattr(lfs_t *lfs, const char *path,
uint8_t type, const void *buffer, lfs_size_t size);
给文件或目录设置一个自定义的属性

int lfs_removeattr(lfs_t *lfs, const char *path, uint8_t type);
移除自定义属性

int lfs_file_open(lfs_t *lfs, lfs_file_t *file,
const char *path, int flags);
打开文件

int lfs_file_opencfg(lfs_t *lfs, lfs_file_t *file,
const char *path, int flags,
const struct lfs_file_config *config);
自己提供一个文件配置打开文件

int lfs_file_close(lfs_t *lfs, lfs_file_t *file);
关闭文件

int lfs_file_sync(lfs_t *lfs, lfs_file_t *file);
同步内存和片外存储,将缓冲数据写入到片外存储

lfs_ssize_t lfs_file_read(lfs_t *lfs, lfs_file_t *file,
void *buffer, lfs_size_t size);
读取文件数据

lfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file,
const void *buffer, lfs_size_t size);
写文件数据文章来源地址https://www.toymoban.com/news/detail-607447.html

三、演示

lfs_t lfs;
lfs_file_t file;
lfs_dir_t  dir;
struct lfs_info info;
int main(void)
{
	int err;
	err = lfs_mount(&lfs, &lfs_w25qxx_cfg);//第一步要挂载文件系统
	if(err < 0)
	{
		lfs_format(&lfs, &lfs_w25qxx_cfg);
		llfs_mount(&lfs, &lfs_w25qxx_cfg);
	}
	//以下操作都为假设操作成功
	//创建一个名为test的文件向文件中写入"1234"4个字节数据
	lfs_file_open(&lfs, &file, "test", LFS_O_CREAT | LFS_O_RDWR);
	lfs_file_write(&lfs, &file, "1234", 4);
	lfs_file_close(&lfs, &file);
	
	//这时虽然打开文件时也使用了LFS_O_CREAT标志但是并不会创建一个新的文件也不会报错,在加入LFS_O_EXCL标志后才会报错
	//LFS_O_RDONLY 标志表示以只读打开文件
    //LFS_O_WRONLY 标志表示以只写打开文件
    //LFS_O_RDWR 标志表示以可读可写打开文件,等价于 LFS_O_RDONLY | LFS_O_WRONLY
    //LFS_O_CREAT 打开文件时如果文件不存在就创建新文件并打开,如果存在将读写指针定位到文件开头打开文件
    //LFS_O_EXCL  打开文件时如果文件不存在就创建新文件并打开,如果存在就报错
    //LFS_O_TRUNC 打开一个已有文件并将文件大小设置为0
    //LFS_O_APPEND 打开一个已有文件并将文件的读写指针设置到文件最后
	lfs_file_open(&lfs, &file, "test", LFS_O_CREAT | LFS_O_RDWR);
	lfs_file_write(&lfs, &file, "abc", 3);
	lfs_file_sync(&lfs, &file);//这时会见内存中的缓存数据写入到Flash中,这时文件内容为"abc4"
	//LFS_SEEK_SET 用绝对位置设置文件的读写指针(用相对用文件开头的位置设置读写指针)
    //LFS_SEEK_CUR 用相对于当前的位置位置设置读写指针
    //LFS_SEEK_END 用相对用文件末尾的位置设置读写指针
	lfs_file_seek(&lfs, &file, 0, LFS_SEEK_SET);//文件指针返回到文件开头
	lfs_file_write(&lfs, &file, "1", 1);
	lfs_file_sync(&lfs, &file);//这时文件内容为"1bc4"

	lfs_file_seek(&lfs, &file, 0, LFS_SEEK_END);//文件指针设置到文件最后
	lfs_file_write(&lfs, &file, "5", 1);
	lfs_file_sync(&lfs, &file);//这时文件内容为"1bc45"

	//文件指针设置到相对于当前位置-2,1bc45| --> 1bc|45
	lfs_file_seek(&lfs, &file, -2, LFS_SEEK_CUR);
	lfs_file_write(&lfs, &file, "d", 1);
	lfs_file_sync(&lfs, &file);//这时文件内容为"1bcd5"
	lfs_file_close(&lfs, &file);

	//对test文件设置一个时间和一个日期的自定义属性,在删除文件时也会删除
	#define FILE_TIME_TYPE 1
	#define FILE_DATE_TYPE 2
	lfs_setattr(&lfs, "test", FILE_TIME_TYPE, "12:00:00", 8);
	lfs_setattr(&lfs, "test", FILE_DATE_TYPE, "2023-1-1", 8);

	//在根目录下创建了一个名为abc的目录
	//在abc目录下创建了一个名为test的文件,当前有两个test文件一个在根目录一个在abc目录中
	lfs_mkdir(&lfs, "abc");
	lfs_dir_open(&lfs, &dir, "abc");
	lfs_file_open(&lfs, &file, "test");
	lfs_file_close(&lfs, &file);
	lfs_dir_close(&lfs, &dir);

	//遍历根目录下的内容,会递归遍历根目录下的目录里的内容
	//同时每个目录都会遍历到一个"."和一个".."的文件夹表示当前文件夹和返回上一个文件夹的路径
	lfs_dir_open(&lfs, &dir, ".");
	while(1)
	{
		err = lfs_dir_read(&lfs, &dir, &info);
		if(err < 0)
			break;
	}
	lfs_dir_close(&lfs, &dir);

	lfs_unmount(&lfs);
}

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

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

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

相关文章

  • STM32CubeMX教程28 SDIO - 使用FatFs文件系统读写SD卡

    正点原子stm32f407探索者开发板V2.4 STM32CubeMX软件(Version 6.10.0) keil µVision5 IDE(MDK-Arm) ST-LINK/V2驱动 野火DAP仿真器 XCOM V2.6串口助手 使用STM32CubeMX软件配置STM32F407开发板 SDIO使用FatFs中间件读写4线SD卡,并实现以轮询方式读写SD卡或以DMA方式读取SD卡 FatFs文件系统相关知识请读者

    2024年02月19日
    浏览(51)
  • STM32CubeMX教程29 USB_HOST - 使用FatFs文件系统读写U盘

    正点原子stm32f407探索者开发板V2.4 STM32CubeMX软件(Version 6.10.0) keil µVision5 IDE(MDK-Arm) ST-LINK/V2驱动 野火DAP仿真器 XCOM V2.6串口助手 使用STM32CubeMX软件配置STM32F407开发板 USB_OTG_FS为工作在Mass Storage Host Class(大容量存储主机类)模式下的USB_HOST(USB主机),并使用FatFs文件系统对

    2024年02月19日
    浏览(45)
  • STM32使用HAL库SPI驱动W25Q16 使用FATFS文件系统+USB虚拟U盘

    使用stm32F407驱动W25Q16,使用FATFS文件系统,USB虚拟优盘功能,W25Q16一共512个扇区,其中128作为flash存取相关数据,其他的384个扇区用作虚拟U盘使用 W25Q16.c W25Q16.h user_diskio.c usbd_storage_if.c main.c STORAGE_BLK_NBR 表示扇区数量 STORAGE_BLK_SIZ 表示扇区大小 电脑上的U盘容量跟这两个参数密

    2024年04月28日
    浏览(45)
  • 学习笔记 02:关于在某宝上面购买的stm32f103c8t6最小系统开发板如何使用USBtoTTL模块烧录程序的记录

            最近在学习用stm32制作,于是乎在某宝上面买了一个最小系统。我身边因为没有STLink、JLink等烧录器。无法烧录,痛苦面具的我差点就要去买一个烧录器,好在突然想起我之前搞蓝牙调试的时候有一块USBtoTTL模块,我可以用它来烧录程序,做一下笔记备忘。 stm32f103c8

    2024年02月05日
    浏览(44)
  • STM32学习记录——声音传感器的使用

    文章目录 前言 一、学习目的 二、模块介绍 三、代码记录 今天记录的是声音传感器模块的学习        我的学习目的是学会使用声音传感器模块,并通过检测声音的有无控制LED的亮灭。我使用的是STM32F103C8T6核心板上的自带LED,引脚是PC13。        我用的是上图所示的声音传

    2024年02月16日
    浏览(39)
  • STM32学习记录——烟雾传感器的使用

    文章目录 前言 一、学习目的 二、模块介绍 三、代码记录 总结        这次记录一下烟雾传感器的学习,由于烟雾传感器的资料比较杂,算法比较多,对我来说也比较难,所以我的代码中算法部分是不太具有参考价值,但是也可以做到随烟雾浓度的变化数值呈线性相关,以

    2024年02月09日
    浏览(38)
  • STM32 大小端与字节对齐使用记录

    串口数据包解析 接收到的数据包: 其中数据内容为: 我们设计的结构体 使用内容复制函数 想要的数据: 实际的数据: 解决方法: CMSIS都已经给你写好的,请看core_cm3.h 执行完这个代码后 我们希望 实际上 解决方法:

    2024年02月07日
    浏览(37)
  • STM32学习记录——光敏传感器的使用

    文章目录 前言 一、学习目的 二、模块介绍 三、代码记录 总结        只做 学习记录 ,记录自己如何从零学会使用一个模块,仅仅只是会用,缺乏专业知识。如果需要了解更多原理,可以从我推荐的技术大佬的文章中获取。        我的学习目的就是通过STM32的ADC功能,学

    2024年02月07日
    浏览(65)
  • STM32 CAN使用记录:FDCAN基础通讯

    CAN是非常常用的一种数据总线,被广泛用在各种车辆系统中。这篇文章将对STM32中FDCAN的使用做个示例。 CAN的一些基础介绍与使用可以参考下面文章: 《CAN基础概念》https://blog.csdn.net/Naisu_kun/article/details/132814079 《STM32 CAN使用记录:bxCAN基础通讯》https://blog.csdn.net/Naisu_kun/arti

    2024年02月07日
    浏览(57)
  • 【STM32】sct 分散加载文件的格式与应用

    当工程按默认配置构建时,MDK 会根据我们选择的芯片型号,获知芯片的内部FLASH 及内部 SRAM 存储器概况, 自动生成 一个以工程名命名的后缀为*.sct 的分散加载文件(Linker Control File,scatter loading),链接器根据该文件的配置分配各个节区地址,生成分散加载代码,因此我们通过

    2024年02月07日
    浏览(58)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包