FAL 组件介绍
FAL (Flash Abstraction Layer) Flash 抽象层,是对 Flash 及基于 Flash 的分区进行管理、操作的抽象层,对上层统一了 Flash 及 分区操作的 API
fal组件文件结构
├─ fal
│ ├─ inc
│ │ ├─ fal.h
│ │ └─ fal_def.h // flash dev 和 flash partition 的结构体定义
│ ├─ Kconfig
│ ├─ samples
│ │ ├─ porting
│ │ │ ├─ fal_cfg.h // 放置flash device table 和 flash partition table
│ │ │ ├─ fal_flash_sfud_port.c // 片内flash ops 实现的例子
│ │ │ ├─ fal_flash_stm32f2_port.c // 片外flash ops 实现的例子
│ │ │ └─ README.md
│ │ └─ README.md
│ ├─ SConscript
│ └─ src
│ ├─ fal.c // 提供fal_init()接口,flash device及 flash partition的初始化。==> 调用不同的flash device 的init 操作;检查partitiont的信息
│ ├─ fal_flash.c // flash device 相关的ops实现
│ ├─ fal_partition.c // flash partition 相关的ops实现
│ └─ fal_rtt.c // 提供了字符设备/块设备/MTD nor 设备的创建读写API
FAL使用
定义flash设备
定义具体的 Flash 设备对象,用户需要根据自己的 Flash 情况分别实现 init、 read、 write、 erase 这些操作函数:
const struct fal_flash_dev stm32f2_onchip_flash =
{
.name = "stm32_onchip",
.addr = 0x08000000,
.len = 1024*1024,
.blk_size = 128*1024,
.ops = {init, read, write, erase}, // 需要不同的flash设备自己提供
.write_gran = 8
};
定义 flash 设备表
Flash 设备表定义在 fal_cfg.h 头文件中,定义分区表前需 新建 fal_cfg.h 文件 ,该文件统一放在对应 BSP 或工程目录的 port 文件夹下
/* ===================== Flash device Configuration ========================= */
extern const struct fal_flash_dev stm32f2_onchip_flash;
extern struct fal_flash_dev nor_flash0;
/* flash device table */
#define FAL_FLASH_DEV_TABLE \
{ \
&stm32f2_onchip_flash, \
&nor_flash0, \
}
定义 flash 分区表
分区表也定义在 fal_cfg.h 头文件中。Flash 分区基于 Flash 设备,每个 Flash 设备又可以有 N 个分区,这些分区的集合就是分区表。在配置分区表前,务必保证已定义好 Flash 设备 及 设备表。
#define NOR_FLASH_DEV_NAME "norflash0"
/* ====================== Partition Configuration ========================== */
#ifdef FAL_PART_HAS_TABLE_CFG
/* partition table */
#define FAL_PART_TABLE \
{ \
{FAL_PART_MAGIC_WORD, "bl", "stm32_onchip", 0, 64*1024, 0}, \
{FAL_PART_MAGIC_WORD, "app", "stm32_onchip", 64*1024, 704*1024, 0}, \
{FAL_PART_MAGIC_WORD, "easyflash", NOR_FLASH_DEV_NAME, 0, 1024*1024, 0}, \
{FAL_PART_MAGIC_WORD, "download", NOR_FLASH_DEV_NAME, 1024*1024, 1024*1024, 0}, \
}
#endif /* FAL_PART_HAS_TABLE_CFG */
// 分区名保证不能重复;
// 关联的 Flash 设备 务必已经在 Flash 设备表中定义好 ,并且 名称一致 ,否则会出现无法找到 Flash 设备的错误;
// 分区的起始地址和大小 不能超过 Flash 设备的地址范围 ,否则会导致包初始化错误;
操作API
fal_rtt.c中实现了几种上层逻辑设备的创建,读写,擦除操作,设备是基于flash partition 创建的,各个操作会调用底层flash device 提供的操作。
// flash device 提供的OPS
static int init(void);
static int read(long offset, uint8_t *buf, size_t size);
static int write(long offset, const uint8_t *buf, size_t size);
static int erase(long offset, size_t size);
// block device ops
struct rt_device *fal_blk_device_create(const char *parition_name);
static rt_err_t blk_dev_control(rt_device_t dev, int cmd, void *args);
static rt_size_t blk_dev_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size);
static rt_size_t blk_dev_write(rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size);
const static struct rt_device_ops blk_dev_ops =
{
RT_NULL,
RT_NULL,
RT_NULL,
blk_dev_read,
blk_dev_write,
blk_dev_control
};
//char device ops
struct rt_device *fal_char_device_create(const char *parition_name);
static rt_size_t char_dev_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size);
static rt_size_t char_dev_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size);
const static struct rt_device_ops char_dev_ops =
{
RT_NULL,
RT_NULL,
RT_NULL,
char_dev_read,
char_dev_write,
RT_NULL
};
// MTD nor flash
struct rt_device *fal_mtd_nor_device_create(const char *parition_name);
static rt_err_t mtd_nor_dev_erase(struct rt_mtd_nor_device* device, rt_off_t offset, rt_uint32_t length);
static rt_size_t mtd_nor_dev_write(struct rt_mtd_nor_device* device, rt_off_t offset, const rt_uint8_t* data, rt_uint32_t length);
static rt_size_t mtd_nor_dev_read(struct rt_mtd_nor_device* device, rt_off_t offset, rt_uint8_t* data, rt_uint32_t length);
static const struct rt_mtd_nor_driver_ops _ops =
{
RT_NULL,
mtd_nor_dev_read,
mtd_nor_dev_write,
mtd_nor_dev_erase,
};
测试命令
rt-threa提供了fal的一些测试命令。
msh />fal
Usage:
fal probe [dev_name|part_name] // 如果没有带参数,就列出分区表,如果带了参数,显示分区或者设备,显示详细信息
fal read addr size // fal probe + 分区选中相应的分区或者设备后,可以使用本指令进行数据的读取,addr 为相对偏移
fal write addr data1 ... dataN // 原理同上
fal erase addr size // 原理同上
fal bench <blk_size> // 测试 Flash 的擦除、写入及读取速度,同时将会测试写入及读取数据的准确性,保证整个 Flash 或整个分区的 写入与读取 数据的一致性
// fal bench 4096 yes