FAL结构体分析
以下是 FAL(Flash Abstraction Layer) 中关键结构体的详细分析,结合其设计原理与配置方法:
一、核心结构体概览
FAL 通过以下结构体实现 Flash 设备管理和分区操作:
1. fal_flash_dev
(Flash 设备描述结构体)
作用:描述物理 Flash 设备的属性和操作接口。
成员变量:
-
name
:设备名称(如"stm32_onchip"
),需与分区表中的设备名一致。 -
addr
:Flash 起始地址(如0x08000000
)。 -
len
:总容量(如1024 * 1024
表示 1MB)。 -
blk_size
:最小擦除块大小(如 STM32F4 为128 * 1024
,即 128KB)。 -
ops
:操作函数集合,包含init
、read
、write
、erase
函数指针。 -
write_gran
:写入粒度(单位:bit),例如:- Nor Flash 为 1 bit(按字节写入)。
- STM32F1 为 32 bits(需按 4 字节对齐)。
示例(STM32 片内 Flash 定义):
const struct fal_flash_dev stm32_onchip_flash = {.name = "stm32_onchip",.addr = 0x08000000,.len = 1024 * 1024,.blk_size = 128 * 1024,.ops = {NULL, flash_read, flash_write, flash_erase}, // init 可为空.write_gran = 8 // STM32F4 按 8-bit 写入
};
2. fal_partition
(分区描述结构体)
作用:定义逻辑分区的属性。
成员变量:
-
magic
:分区表魔数(FAL_PART_MAGIC_WORD
),用于校验合法性。 -
name
:分区名称(如"app"
),通过fal_partition_find()
获取句柄。 -
flash_name
:所属 Flash 设备名(需与fal_flash_dev.name
匹配)。 -
offset
:分区在 Flash 中的起始偏移地址。 -
len
:分区大小。
示例(分区表配置):
#define FAL_PART_TABLE \
{ \{FAL_PART_MAGIC_WORD, "boot", "stm32_onchip", 0, 64 * 1024}, \{FAL_PART_MAGIC_WORD, "app", "stm32_onchip", 64 * 1024, 256 * 1024} \
}
二、结构体应用场景
1. 驱动层适配
- 片内 Flash:需手动实现
read
、write
、erase
函数,通过ops
关联到fal_flash_dev。
例如:STM32 片内 Flash 的flash_write()
需调用 HAL 库的HAL_FLASH_Program()
。 - 片外 SPI Flash:通过 SFUD 驱动框架自动生成
fal_flash_dev
(如nor_flash0
),无需手动实现操作函数。
2. 分区表管理
- 静态配置:在
fal_cfg.h
中定义FAL_PART_TABLE
,指定分区名、设备名、偏移和大小。 - 动态装载(可选):支持从 Flash 中检索分区表,适用于多固件项目。
三、关键设计原理
-
抽象层与硬件解耦
fal_flash_dev
通过函数指针将底层操作(如flash_write()
)抽象化,上层应用无需关心具体硬件细节。- 不同 Flash 设备的差异由驱动层处理,如片内 Flash 和 SPI Nor Flash 的擦除粒度不同。
-
统一接口与模块化
- 所有分区操作通过
fal_partition_read()
、fal_partition_write()
等 API 完成,确保文件系统(如 LittleFS)、OTA 升级等模块的兼容性。 - 分区表支持多设备关联,例如同时管理片内 Flash 和外部 SPI Flash 的分区。
- 所有分区操作通过
四、调试与问题排查
-
常见问题
- 擦除失败:检查
blk_size
对齐,确保擦除地址和长度是块大小的整数倍。 - 读写错误:验证
write_gran
设置是否符合硬件特性(如 STM32F1 必须按 32-bit 写入)。 - 分区未找到:检查分区表中的
flash_name
是否与fal_flash_dev.name
一致。
- 擦除失败:检查