参考文档(国内):FAL 参考文档
一、概述
FAL (Flash Abstraction Layer) ,即 Flash 抽象层,是对 Flash 及基于 Flash 的分区进行管理、操作的抽象层,对上层统一了 Flash 及 分区操作的 API。
对于 FAL 的依赖来说,对 RT-Thread 无依赖,也可用于裸机。但是,测试命令功能需要依赖 RT-Thread FinSH/MSH。
二、FAL 的使用
对于 FAL 的使用,详细介绍可以查看上面的参考手册,这里只是做一个简单的分析。
使用的开发板是正点原子的潘多拉开发板,所以下面的分析也是以这个开发板的 bsp 源码为基础,仅供参考。
1、 定义 Flash 设备
对于要定义的 Flash 设备。可以是片内 flash, 也可以是片外的 spi flash。
简单来说,就是定义具体的 Flash 设备对象,用户需要根据自己的 Flash 情况分别实现 init、 read、 write、 erase 这些操作函数。
1.1、 片内 Flash
对于 STM32L475 的片内 Flash 驱动,RT-Thread 为我们移植好了源码,只需要打开 “Enable on-chip FLASH” 选项即可。
/* bsp/stm32/libraries/HAL_Drivers/drv_flash/drv_flash_l4.c */
const struct fal_flash_dev stm32_onchip_flash =
{
"onchip_flash", /* Flash 设备的名字 */
STM32_FLASH_START_ADRESS, /* 对 Flash 操作的起始地址:0x08000000 */
STM32_FLASH_SIZE, /* Flash 的总大小:512 KB */
FLASH_PAGE_SIZE, /* Flash 块/扇区大小:2048 */
/* Flash 的操作函数 */
{
NULL, /* init 函数 */
fal_flash_read, /* read 函数 */
fal_flash_write, /* write 函数 */
fal_flash_erase /* erase 函数 */
}
};
/* 这里的分析以 write 函数为例 */
static int fal_flash_write(long offset, const rt_uint8_t *buf, size_t size)
{
/**
* RT-Thread 已经为我们实现了 stm32_flash_write 函数
* 这个函数也是调用了 stm32 HAL 库提供的接口
**/
return stm32_flash_write(stm32_onchip_flash.addr + offset, buf, size);
}
1.2、 片外 Flash
在前面的文章中,我们提到了 SFUD,所以对于片外的 Flash 来说,可以使用 SFUD 驱动来进行相关操作的。
这里的 nor_flash 就是 W25Q128。
const struct fal_flash_dev nor_flash0 =
{
"nor_flash", /* Flash 设备的名字 */
0, /* 对 Flash 操作的起始地址:0x08000000 */
(16 * 1024 * 1024), /* Flash 的总大小:16 MB */
4096, /* Flash 块/扇区大小:4096 */
{
fal_sfud_init, /* init 函数 */
read, /* read 函数 */
write, /* write 函数 */
erase /* erase 函数 */
}
};
sfud_flash sfud_norflash0;
static int fal_sfud_init(void)
{
sfud_flash_t sfud_flash0 = NULL;
/**
* 根据 QSPI 设备获取 sfud_flash 对象,用于后续操作
* 其实就是将 uer_data 中保存的 sfud_flash 结构体给取出来
**/
sfud_flash0 = (sfud_flash_t)rt_sfud_flash_find("qspi10");
if (NULL == sfud_flash0)
{
return -1;
}
sfud_norflash0 = *sfud_flash0;
return 0;
}
/* 这里的分析以 write 函数为例 */
static int write(long offset, const uint8_t *buf, size_t size)
{
/* 调用 SFUD 驱动提供的接口 */
if (sfud_write(&sfud_norflash0, nor_flash0.addr + offset, size, buf) != SFUD_SUCCESS)
{
return -1;
}
return size;
}
2、 定义 Flash 设备表
Flash 设备表定义在 fal_cfg.h 头文件中,定义分区表前需新建 fal_cfg.h 文件(如果没有的话),请将该文件统一放在对应 BSP 或工程目录的 port 文件夹下,并将该头文件路径加入到工程。
extern const struct fal_flash_dev stm32l4_onchip_flash;
extern const struct fal_flash_dev nor_flash0;
/**
* Flash 设备表
* Flash 设备表中,有两个 Flash 对象
* 一个为 STM32L4 的片内 Flash ,一个为片外的 Nor Flash
**/
#define FAL_FLASH_DEV_TABLE \
{ \
&onchip_flash, \
&nor_flash0, \
}
3、 定义 Flash 分区表
分区表也定义在 fal_cfg.h 头文件中。Flash 分区基于 Flash 设备,每个 Flash 设备又可以有 N 个分区,这些分区的集合就是分区表。
在配置分区表前,务必保证已定义好 Flash 设备及设备表。
#ifdef FAL_PART_HAS_TABLE_CFG
#define FAL_PART_TABLE \
{ \
{FAL_PART_MAGIC_WROD, "bootloader", "onchip_flash", 0, 64 * 1024, 0}, \
{FAL_PART_MAGIC_WROD, "app", "onchip_flash", 64 * 1024, 448 * 1024, 0}, \
{FAL_PART_MAGIC_WROD, "easyflash", "nor_flash", 0, 512 * 1024, 0}, \
{FAL_PART_MAGIC_WROD, "download", "nor_flash", 512 * 1024, 1024 * 1024, 0}, \
{FAL_PART_MAGIC_WROD, "wifi_image", "nor_flash", (512 + 1024) * 1024, 512 * 1024, 0}, \
{FAL_PART_MAGIC_WROD, "font", "nor_flash", (512 + 1024 + 512) * 1024, 7 * 1024 * 1024, 0}, \
{FAL_PART_MAGIC_WROD, "filesystem", "nor_flash", (512 + 1024 + 512 + 7 * 1024) * 1024, 7 * 1024 * 1024, 0}, \
}
#endif
其中:
1)分区名保证不能重复。
2)关联的 Flash 设备务必已经在 Flash 设备表中定义好 ,并且名称一致 ,否则会出现无法找到 Flash 设备的错误。
3)分区的起始地址和大小 不能超过 Flash 设备的地址范围 ,否则会导致包初始化错误。
3、 FAL 分区的使用
从前面的分区可以知道,片外 Flash 有多个分区,如果要使用 filesystem 分区来挂载 elm FAT 系统,那么可以进行下面的操作。(别的分区后续会使用到,比如 easyflash 分区)
#include <fal.h>
#include <dfs_fs.h>
/* 挂载初始化 */
void mnt_init(void)
{
struct rt_device *rootfs = RT_NULL;
/* 使用 filesystem 分区创建块设备,块设备名称为 filesystem */
rootfs = fal_blk_device_create("filesystem");
if(rootfs == RT_NULL)
return;
/* 将 elm fat 文件系统挂载 W25Q128 的 filesystem 分区 */
if (dfs_mount("filesystem", "/", "elm", 0, 0) == 0)
{
rt_kprintf("file system initialization done!\n");
}
else
{
if(dfs_mkfs("elm", "filesystem") == 0)
{
if (dfs_mount("filesystem", "/", "elm", 0, 0) == 0)
{
rt_kprintf("file system initialization done!\n");
}
else
{
rt_kprintf("file system initialization failed!\n");
}
}
}
}