RT-Thread v4.1.0中FAL介绍

描述

在 V4.1.0 中,将 fal 软件包重新定义为 RT-Thread 内部组件。

在使用方式上和以前有这些区别:原本使用 fal  需要在 RT-Thread 的包管理器中选择并进行下载;现在只需要在组件中打开使用即可。以下做详细介绍。

1、FAL介绍

FAL (Flash Abstraction Layer) Flash 抽象层,是对 Flash 及基于 Flash 的分区进行管理、操作的抽象层,对上层统一了 Flash 及 分区操作的 API (框架图如下所示),并具有以下特性:

  • 支持静态可配置的分区表,并可关联多个 Flash 设备;

  • 分区表支持 自动装载 。避免在多固件项目,分区表被多次定义的问题;

  • 代码精简,对操作系统 无依赖 ,可运行于裸机平台,比如对资源有一定要求的 Bootloader;

  • 统一的操作接口。保证了文件系统、OTA、NVM(例如:EasyFlash) 等对 Flash 有一定依赖的组件,底层 Flash 驱动的可重用性;

  • 自带基于 Finsh/MSH 的测试命令,可以通过 Shell 按字节寻址的方式操作(读写擦) Flash 或分区,方便开发者进行调试、测试;

 

RT-Thread

1.1、打开 FAL

在组件中打开使用:

RT-Thread

每个功能的配置说明如下:

  • 开启调试日志输出(默认开启);

  • 分区表是否在 fal_cfg.h 中定义(默认开启)。如果关闭此选项,fal 将会自动去指定 Flash 的指定位置去检索并装载分区表,具体配置详见下面两个选项;

  • 存放分区表的 Flash 设备;

  • 分区表的 结束地址 位于 Flash 设备上的偏移。fal 将从此地址开始往回进行检索分区表,直接读取到 Flash 顶部。如果不确定分区表具体位置,这里也可以配置为 Flash 的结束地址,fal 将会检索整个 Flash,检索时间可能会增加。

  • 启用 FAL 针对 SFUD 的移植文件(默认关闭);

  • 应输入调用 rt_sfud_flash_probe 函数时传入的 FLASH 设备名称(也可以通过 list_device 命令查看 Block Device 的名字获取)。该名称与分区表中的 Flash 名称对应,只有正确设置设备名字,才能完成对 FLASH 的读写操作。

1.2、FAL 目录

RT-Thread

 

1.3、FAL API

FAL 相关的 API 如图所示,点击此处查看 API 参数详解。(以下链接请复制至外部浏览器打开)

 

https://github.com/RT-Thread/rt-thread/blob/master/components/fal/docs/fal_api.md

 


 

RT-Thread

2、使用 FAL

使用 FAL 的基本步骤如下所示:

1、打开 FAL:从 Env 中打开 fal 组件。

2、FAL 移植:定义 flash 设备、定义 flash 设备表、定义 flash 分区表。以下主要对步骤 2 展开讲解。

3、调用 fal_init() 初始化该库:移植完成后,可在应用层调用,如在 main 函数中调用。

 

RT-Thread

2.1、定义 flash 设备

在定义 Flash 设备表前,需要先定义 Flash 设备。可以是片内 flash,  也可以是片外基于 SFUD 的 spi flash:

  • 定义片内 flash 设备可以参考 fal_flash_stm32f2_port.c

  • 定义片外 spi flash 设备可以参考 fal_flash_sfud_port.c

定义具体的 Flash 设备对象,用户需要根据自己的 Flash 情况分别实现 initreadwriteerase 这些操作函数:

  • static int init(void)可选 的初始化操作。

  • static int read(long offset, uint8_t *buf, size_t size):读取操作。

 

RT-Thread

 

  • static int write(long offset, const uint8_t *buf, size_t size) :写入操作。

 

RT-Thread

 

  • static int erase(long offset, size_t size) :擦除操作。

 

RT-Thread

用户需要根据自己的 Flash 情况分别实现这些操作函数。在文件最底部定义了具体的 Flash 设备对象 ,如下示例定义了 stm32f2 片上 flash:stm32f2_onchip_flash

1const struct fal_flash_dev stm32f2_onchip_flash =
2{
3    .name       = "stm32_onchip",
4    .addr       = 0x08000000,
5    .len        = 1024*1024,
6    .blk_size   = 128*1024,
7    .ops        = {init, read, write, erase},
8    .write_gran = 8
9};

 

  • "stm32_onchip" : Flash 设备的名字。

  • 0x08000000: 对 Flash 操作的起始地址。

  • 1024*1024:Flash 的总大小(1MB)。

  • 128*1024:Flash 块/扇区大小(因为 STM32F2 各块大小不均匀,所以擦除粒度为最大块的大小:128K)。

  • {init, read, write, erase} :Flash 的操作函数。如果没有 init 初始化过程,第一个操作函数位置可以置空。

  • 8 : 设置写粒度,单位 bit, 0 表示未生效(默认值为 0 ),该成员是 fal 版本大于 0.4.0 的新增成员。各个 flash 写入粒度不尽相同,可通过该成员进行设置,以下列举几种常见 Flash 写粒度:

  • nor flash: 1 bit

  • stm32f2/f4:  8 bit

  • stm32f1:  32 bit

  • stm32l4:  64 bit

2.2、定义 flash 设备表

Flash 设备表定义在 fal_cfg.h 头文件中,定义分区表前需 新建 fal_cfg.h 文件 ,请将该文件统一放在对应 BSP 或工程目录的 port 文件夹下,并将该头文件路径加入到工程。fal_cfg.h 可以参考 示例文件 fal/samples/porting/fal_cfg.h 完成。

设备表示例:

 1/* ===================== Flash device Configuration ========================= */
 2extern const struct fal_flash_dev stm32f2_onchip_flash;
 3extern struct fal_flash_dev nor_flash0;
 4
 5/* flash device table */
 6#define FAL_FLASH_DEV_TABLE                                          
 7{                                                                    
 8    &stm32f2_onchip_flash,                                           
 9    &nor_flash0,                                                     
10}

Flash 设备表中,有两个 Flash 对象,一个为 STM32F2 的片内 Flash ,一个为片外的 Nor Flash。

2.3、定义 flash 分区表

分区表也定义在 fal_cfg.h 头文件中。Flash 分区基于 Flash 设备,每个 Flash 设备又可以有 N 个分区,这些分区的集合就是分区表。在配置分区表前,务必保证已定义好 Flash 设备设备表。fal_cfg.h 可以参考 示例文件 fal/samples/porting/fal_cfg.h 完成。

分区表示例:

 1#define NOR_FLASH_DEV_NAME             "norflash0"
 2/* ====================== Partition Configuration ========================== */
 3#ifdef FAL_PART_HAS_TABLE_CFG
 4/* partition table */
 5#define FAL_PART_TABLE                                                               
 6{                                                                                    
 7    {FAL_PART_MAGIC_WORD,        "bl",     "stm32_onchip",         0,   64*1024, 0}, 
 8    {FAL_PART_MAGIC_WORD,       "app",     "stm32_onchip",   64*1024,  704*1024, 0}, 
 9    {FAL_PART_MAGIC_WORD, "easyflash", NOR_FLASH_DEV_NAME,         0, 1024*1024, 0}, 
10    {FAL_PART_MAGIC_WORD,  "download", NOR_FLASH_DEV_NAME, 1024*1024, 1024*1024, 0}, 
11}
12#endif /* FAL_PART_HAS_TABLE_CFG */

上面这个分区表详细描述信息如下:

RT-Thread

用户需要修改的分区参数包括:分区名称、关联的 Flash 设备名、偏移地址(相对 Flash 设备内部)、大小,需要注意以下几点:

  • 分区名保证 不能重复

  • 关联的 Flash 设备 务必已经在 Flash 设备表中定义好 ,并且 名称一致 ,否则会出现无法找到 Flash 设备的错误;

  • 分区的起始地址和大小 不能超过 Flash 设备的地址范围 ,否则会导致包初始化错误;

 

注意:每个分区定义时,除了填写上面介绍的参数属性外,需在前面增加 FAL_PART_MAGIC_WORD 属性,末尾增加 0 (目前用于保留功能)

3、Finsh/MSH 测试命令

fal 提供了丰富的测试命令,项目只要在 RT-Thread 上开启 Finsh/MSH 功能即可。在做一些基于 Flash 的应用开发、调试时,这些命令会非常实用。它可以准确的写入或者读取指定位置的原始 Flash 数据,快速的验证 Flash 驱动的完整性,甚至可以对 Flash 进行性能测试。

具体功能如下:输入 fal 可以看到完整的命令列表

1msh />fal
2Usage:
3fal probe [dev_name|part_name]   - probe flash device or partition by given name
4fal read addr size               - read 'size' bytes starting at 'addr'
5fal write addr data1 ... dataN   - write some bytes 'data' starting at 'addr'
6fal erase addr size              - erase 'size' bytes starting at 'addr'
7fal bench              - benchmark test with per block size
8
9msh />

3.1、指定待操作的 Flash 设备或 Flash 分区

当第一次使用 fal 命令时,直接输入 fal probe  将会显示分区表信息。可以指定待操作的对象为分区表里的某个分区,或者某个 Flash 设备。

分区或者 Flash 被成功选中后,还将会显示它的一些属性情况。大致效果如下:

 1msh />fal probe    
 2No flash device or partition was probed.
 3Usage: fal probe [dev_name|part_name]   - probe flash device or partition by given name.
 4[I/FAL] ==================== FAL partition table ====================
 5[I/FAL] | name      | flash_dev    |   offset   |    length  |
 6[I/FAL] -------------------------------------------------------------
 7[I/FAL] | bl        | stm32_onchip | 0x00000000 | 0x00010000 |
 8[I/FAL] | app       | stm32_onchip | 0x00010000 | 0x000b0000 |
 9[I/FAL] | ef        | norflash0    | 0x00000000 | 0x00100000 |
10[I/FAL] | download  | norflash0    | 0x00100000 | 0x00100000 |
11[I/FAL] =============================================================
12msh />
13msh />fal probe download
14Probed a flash partition | download | flash_dev: norflash0 | offset: 1048576 | len: 1048576 |.
15msh />
16

3.2、擦除数据

先输入 fal erase ,后面跟着待擦除数据的起始地址以及长度。以下命令为:从 0 地址(相对 Flash 或分区)开始擦除 4096 字节数据

注意:根据 Flash 特性,擦除动作将按扇区对齐进行处理。所以,如果擦除操作地址或长度未按照 Flash 的扇区对齐,将会擦除掉与其关联的整个扇区数据。

1msh />fal erase 0 4096
2Erase data success. Start from 0x00000000, size is 4096.
3msh />

3.3、写入数据

先输入 fal write ,后面跟着 N 个待写入的数据,并以空格隔开。以下命令为:从地址 8 的位置依次开始写入 1、2、3、4 、 5 这 5 个字节数据

1msh />fal write 8 1 2 3 4 5
2Write data success. Start from 0x00000008, size is 5.
3Write data: 1 2 3 4 5 .
4msh />

3.4、读取数据

先输入 fal read ,后面跟着待读取数据的起始地址以及长度。以下命令为:从 0 地址开始读取 64 字节数据

1msh />fal read 0 64
2Read data success. Start from 0x00000000, size is 64. The data is:
3Offset (h) 00 01 02 03 04 05 06 07 08 09 000000F
4[00000000] FF FF FF FF FF FF FF FF 01 02 03 04 05 FF FF FF 
5[00000010] FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 
6[00000020] FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 
7[00000030] FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 
8
9msh />

3.5、性能测试

性能测试将会测试 Flash 的擦除、写入及读取速度,同时将会测试写入及读取数据的准确性,保证整个 Flash 或整个分区的 写入与读取 数据的一致性。

先输入 fal bench ,后面跟着待测试 Flash 的扇区大小(请查看对应的 Flash 手册,SPI Nor Flash 一般为 4096)。由于性能测试将会让整个 Flash 或者整个分区的数据丢失,所以命令最后必须跟 yes

1msh />fal bench 4096 yes
2Erasing 1048576 bytes data, waiting...
3Erase benchmark success, total time2.674S.
4Writing 1048576 bytes data, waiting...
5Write benchmark success, total time7.107S.
6Reading 1048576 bytes data, waiting...
7Read benchmark success, total time2.716S.
8msh />

4、常见应用

  • 基于 FAL 分区的 fatfs 文件系统例程

https://github.com/RT-Thread/IoT_Board/tree/master/examples/15_component_fs_flash

  • 基于 FAL 分区的 littlefs 文件系统应用笔记

https://www.rt-thread.org/document/site/application-note/components/dfs/an0027-littlefs/

  • 基于 FAL 分区的 EasyFlash 移植说明

https://github.com/armink-rtt-pkgs/EasyFlash/tree/master/ports

 

 


原文标题:RT-Thread v4.1.0 特性解析之 FAL 探秘

文章出处:【微信公众号:RTThread物联网操作系统】欢迎添加关注!文章转载请注明出处。

审核编辑:汤梓红
打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分