431|3

65

帖子

0

TA的资源

一粒金砂(中级)

[雅特力AT-START-F437]littlefs移植以及nr_micro_shell下相关命令实现 [复制链接]

板载nor flash这么大,当裸数据存储区用不太好,还是移植个文件系统吧。开源的、适用于mcu的nor flash文件系统也不多,流行的就是littlefs和spiffs了。后者的开发已经基本停滞,所以笔者就选littlefs啦。

 

littlefs代码准备
从github clone或下载littlefs,把它顶层目录下的lfs.c、lfs.h、lfs_util.c、lfs_util.h拷贝到middlewares/littlefs/目录下,其余文件无用可以忽略。

git clone https://github.com/littlefs-project/littlefs.git

 

littlefs的移植
根据littlefs的README和lfs.h头文件,我们只要实现如下结构体即可:

static const struct lfs_config cfg = {
        .read = lfs_sf_read,
        .prog = lfs_sf_write,
        .erase = lfs_sf_erase,
        .sync = lfs_sf_sync,
        .read_size = 64,
        .prog_size = 256,
        .block_size = 4096,
        .block_count = 128,
        .cache_size = 256,
        .lookahead_size = 128,
        .block_cycles = 100,
};

这个结构体成员除cache_size、lookahead_size、block_cycles三个成员外,其它成员的填充需要依据flash的结构以及flash的使用量来填充,比如block_count设成128意思是准备用128个block用作littlefs,很明显大部分情况下不会把flash的所有block都用于littlefs,那block_count就是用于控制用于littlefs的flash空间大小的;像read_size、prog_size、block_size可由flash的datasheet获得。
 

而cache_size等拎出来三个成员在lfs.h中有详细的说明,比如cache_size、lookahead_size需要根据系统的sram富余程度、lfs使用频繁程度配置,这两个量均以字节为单位,消耗sram加速lfs用的;而block_cycles成员用于读写均衡,比如笔者这里配置成100,意思是擦除100次后,需要挪到其它block上。

 

接下来咱们需要实现三个重要的钩子函数.read、.prog和.erase,分别用于flash的读、写、擦除。上一篇文章我们已经实现了nor flash的读、写、擦除,所以这三个钩子函数的实现其实很简单的,笔者的实现如下:
注:sync钩子可以简单返回0即可,大部分情况下用不上的。

static int lfs_sf_read(const struct lfs_config *c, uint32_t block,
                       uint32_t offset, void *buf, uint32_t size)
{
        uint32_t addr = (block * c->block_size) + offset;

        qspi_data_read(addr, size, buf);

        return 0;
}

static int lfs_sf_write(const struct lfs_config *c, uint32_t block,
                        uint32_t offset, const void *buf, uint32_t size)
{
        uint32_t addr = (block * c->block_size) + offset;

        qspi_data_write(addr, size, buf);

        return 0;
}

static int lfs_sf_erase(const struct lfs_config *c, uint32_t block)
{
        uint32_t addr = block * c->block_size;

        qspi_erase(addr);

        return 0;
}

static int lfs_sf_sync(const struct lfs_config *c)
{
        return 0;
}

 

到此littlefs已经移植好啦,咱们可以用littlefs的API去测试或者实现一些nr_micro_shell下的相关命令,笔者就初步实现了lfs的mount、umount、demo等子命令:

static void shell_lfs_cmd(char argc, char *argv)
{
        if (!strcmp(&argv[(int)argv[1]], "mount")) {
                lfs_cmd_mount();
        } else if (!strcmp(&argv[(int)argv[1]], "umount")) {
                lfs_cmd_umount();
        } else if (!strcmp(&argv[(int)argv[1]], "demo")) {
                lfs_cmd_demo();
        }
}
NR_SHELL_CMD_EXPORT(lfs, shell_lfs_cmd);

lfs_cmd_umount()函数的实现比较简单,一行调用littlefs的api的代码就可以了:

static void lfs_cmd_umount(void)
{
        lfs_unmount(&lfs);
}

 

lfs_cmd_mount()函数稍微绕了一点,仅仅调用littlefs的相mount函数还不够,因为第一次nor flash上还没有littlefs文件系统呢,所以这时littlefs的mount会失败,这时候我们需要格式化再mount尝试一次:

static void lfs_cmd_mount(void)
{
        int err = lfs_mount(&lfs, &cfg);

        if (err) {
                lfs_format(&lfs, &cfg);
                lfs_mount(&lfs, &cfg);
        }
}

 

而其中lfs_cmd_demo()其实就是littlefs中的一个测试例子,打开一个名为boot_count的文件,读取一个整数加一后写入(第一次是空文件所以读不到,但是并不妨碍写入数据),并把这个整数同时打印到终端:

static void lfs_cmd_demo(void)
{
        lfs_file_t file;

        // read current count
        unsigned int 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));

        // update boot count
        boot_count += 1;
        lfs_file_rewind(&lfs, &file);
        lfs_file_write(&lfs, &file, &boot_count, sizeof(boot_count));

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

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

 

这样nr_micro_shell的配套命令也实现好了,coding工作可收工了。编译烧录和以前一样,在此略过不提。咱们测试看看

1.jpg

 

然后重启板子看看boot_count这个文件能否正确存储数据:

2.jpg


看到了吧,这次加一以后的整数是3,说明原来的整数是2,这个数字恰好是板子重启前写入文件的,说明littlefs移植成功。

最新回复

感谢楼主大佬的精彩分享,上次看到大佬你用的shell,我也移植到了stm32上面非常好用。这个移植文件系统也是非常有意义的,再次感谢!   详情 回复 发表于 2025-3-3 11:16

赞赏

1

查看全部赞赏


回复
举报

7184

帖子

11

TA的资源

版主

感谢楼主大佬的精彩分享,上次看到大佬你用的shell,我也移植到了stm32上面非常好用。这个移植文件系统也是非常有意义的,再次感谢!

点评

版主喜欢就好  详情 回复 发表于 2025-3-3 13:23

回复

2

帖子

0

TA的资源

一粒金砂(初级)

感谢楼主大佬的精彩分享,上次看到大佬你用的shell,我也移植到了stm32上面非常好用。这个移植文件系统也是非常有意义的,再次感谢!


回复

65

帖子

0

TA的资源

一粒金砂(中级)

lugl4313820 发表于 2025-3-1 21:19 感谢楼主大佬的精彩分享,上次看到大佬你用的shell,我也移植到了stm32上面非常好用。这个移植文件系统也是 ...

版主喜欢就好


回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网 6

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表