转自公众号,欢迎关注
前言 板载了NM25Q128EVB,16MB的SPI接口的NOR FLASH.为了方便后面开发,先移植文件系统。 littlefs是支持NOR FLASH支持磨损均衡和掉电保护的一个不错的嵌入式文件系统,这里介绍移植该文件系统到开发板。 NOR FLASH的驱动Demo代码中已经有,基于现有的NOR FLASH的读写去移植。 基于1,验收工程(无屏幕版)工程。 过程准备代码下载代码 git clone https://github.com/littlefs-project/littlefs.git 添加代码到工程复制littlefs\bd下的lfs_filebd.c/h改名字为lfs_mybd.c/h, 这两个文件为需要移植的FLASH读写接口。 添加上述lfs_mybd.c/h和lfs.c/h,lfs_util.c/h到工程,后者不需要任何修改。
配置工程工程选项中添加头文件包含路径
底层代码移植lfs_mybd.h申明如下四个接口,分别对应flash的擦除,读,写,和同步
lfs_mybd.c
- #include "bd/lfs_mybd.h"
- #include "BSP/NORFLASH/norflash.h"
复制代码
调用norflash.h的接口,实现.h申明的4个接口 lfs_mybd_read 实现如下
- int lfs_mybd_read(const struct lfs_config *cfg, lfs_block_t block,
- lfs_off_t off, void *buffer, lfs_size_t size) {
- norflash_read(buffer, block*cfg->block_size + off, size);
- return 0;
- }
复制代码
这里理论上lfs_mybd_read要能返回失败值,这里始终返回0正确是合不合理的,但是norflash接口驱动没有实现这里先就这样。 lfs_mybd_prog实现如下,同样的改函数也应该要能返回失败值。
- int lfs_mybd_prog(const struct lfs_config *cfg, lfs_block_t block,
- lfs_off_t off, const void *buffer, lfs_size_t size) {
- norflash_write((uint8_t*)buffer, block*cfg->block_size + off, size);
- return 0;
- }
-
复制代码
lfs_mybd_erase实现如下,同样的改函数也应该要能返回失败值。
- int lfs_mybd_erase(const struct lfs_config *cfg, lfs_block_t block) {
-
- norflash_erase_sector(block);
- return 0;
- }
复制代码
lfs_mybd_sync我们这里没有缓存都是直接写入的所以不需要同步 实现如下直接返回成功即可
- int lfs_mybd_sync(const struct lfs_config *cfg) {
-
- return 0;
- }
复制代码
依赖如果没有定义LFS_NO_MALLOC则 lfs_util.h中依赖malloc和free实现lfs_malloc和lfs_free 如果定义了LFS_NO_MALLOC则不使用malloc free 此时lfs_file_open要改用lfs_file_opencfg并且设置缓冲区config.buffer 我们没有定义LFS_NO_MALLOC即使用malloc 所以这里要设置堆大一点
测试
- #include "lfs.h"
- #include "bd/lfs_mybd.h"
复制代码
main.c中定义变量
- lfs_t lfs;
- lfs_file_t file;
复制代码
flash参数配置,先设置4个接口函数的实现,然后设置flash相关参数见注释
- const struct lfs_config cfg = {
- // flash读写等接口
- .read = lfs_mybd_read,
- .prog = lfs_mybd_prog,
- .erase = lfs_mybd_erase,
- .sync = lfs_mybd_sync,
- // flash参数 参见FLASH手册
- .read_size = 256, /* 一次读的大小 为page 256字节 */
- .prog_size = 256, /* 一次编程大小 为page 256字节 */
- .block_size = 4096, /* 最小擦除单位sector/block 4k 4096字节 */
- .block_count = 4096, /* block数 4096 即4096x4k 16MB */
- .cache_size = 256, /* 读写缓冲区大小,设置大一点可以提高读写性能 必须是 read_size和prog_size的整数倍,且是block_size的因子 */
- .lookahead_size = 16, /* 必须是8的倍数 用于缓存分配新的block时的信息,一个bit对应一个block,设置大一点就会搜寻更多的block更有利于均衡 */
- .block_cycles = 500, /* 设置擦除多少次之后开始进行均衡 设置大读写性能好,但是对均衡平均不利 100-1000 设置-1则不使用磨损均衡*/
- };
复制代码
main函数中测试代码,该代码更新文件的内容,每次掉电重启递增文件内容的值,记录一共重启了多少次。可以用于随机掉电测试。
- int main(void)
- {
- HAL_Init(); /* ?????HAL?? */
- sys_STM32_clock_init(RCC_PLL_MUL9); /* ???????, 72Mhz */
- delay_init(72); /* ???????? */
- usart_init(115200); /* ?????????115200 */
- //led_init(); /* ?????LED */
- //key_init(); /* ????????? */
- norflash_init(); /* ?????NOR FLASH */
- my_mem_init(SRAMIN); /* ????????SRAM???? */
- //test_system(); /* ???????? */
-
- // 挂载文件系统
- int err = lfs_mount(&lfs, &cfg);
- // 如果挂载失败说明还未格式化过进行格式化
- if (err) {
- lfs_format(&lfs, &cfg);
- lfs_mount(&lfs, &cfg);
- }
- // 打开文件 读文件
- uint32_t boot_count = 0;
- lfs_file_open(&lfs, &file, "boot_count", LFS_O_RDWR | LFS_O_CREAT);
- lfs_file_read(&lfs, &file, &boot_count, sizeof(boot_count));
- // 更新文件内容
- boot_count += 1;
- lfs_file_rewind(&lfs, &file);
- lfs_file_write(&lfs, &file, &boot_count, sizeof(boot_count));
- // 关闭文件
- lfs_file_close(&lfs, &file);
- // 卸载文件系统
- lfs_unmount(&lfs);
- // 打印内容
- printf("boot_count: %d\r\n", boot_count);
-
- while (1)
- {
- //LED0_TOGGLE();
- delay_ms(1000);
- }
- }
复制代码
反复重启可以看到计数值累加,说明文件系统功能OK。
总结 Littlefs是一个不错的嵌入式文件系统,支持磨损均衡和掉电保护,适合嵌入到系统中,代码比较少占用rom和ram都不多,且移植非常简单实现4个接口即可。不过目前只支持spi flash不支持nand等,基于开发板的现成的norflash驱动很快就能移植使用。
|