1、RT_Thread Settings打开FAL组件
2、定义struct fal_flash_dev类型的flash设备
2.1、struct fal_flash_dev
先看下struct fal_flash_dev的具体成员,有flash设备名字、flash起始地址、flash大小、块大小(执行擦除时的最小颗粒)、操作函数(init、read、write、erase)、写操作最小颗粒度;
struct fal_flash_dev
{
char name[FAL_DEV_NAME_MAX];
/* flash device start address and len */
uint32_t addr;
size_t len;
/* the block size in the flash for erase minimum granularity */
size_t blk_size;
struct
{
int (*init)(void);
int (*read)(long offset, uint8_t *buf, size_t size);
int (*write)(long offset, const uint8_t *buf, size_t size);
int (*erase)(long offset, size_t size);
} ops;
/* write minimum granularity, unit: bit.
1(nor flash)/ 8(stm32f2/f4)/ 32(stm32f1)/ 64(stm32l4)
0 will not take effect. */
size_t write_gran;
};
typedef struct fal_flash_dev *fal_flash_dev_t;
2.1.1、blk_size执行擦除时的最小颗粒
1、明确flash擦除操作的对象:扇区、全部;
2、找到stm32f407扇区的大小
主存储器一共12个扇区,4个16K、1个64K、7个128K;
上面指的是F407xG,是1M的flash,F407xE是512K的flash,“理论上”相应的就是3个128K。
2.2、定义flash设备
2.2.1、drv_flash_f4.c的整体介绍
第一部分:宏定义各扇区的起始地址
第二部分:读、写、擦除
第三部分:使用了FAL之后的FLASH设备定义以及对于的读、写、擦除操作函数
2.2.2、修改drv_flash_f4.c的第三部分
如果直接编译会报错,找不到STM32_FLASH_START_ADRESS_XX和FLASH_SIZE_GRANULARITY_XX.
根据2.1、struct fal_flash_dev,知道报错这两个成员指的是flash起始地址、flash大小;
再根据2.1.1中Flash模块构成图和drv_flash_f4.c的第一部分的宏定义,得到如下flash设备定义:
//芯片型号:STM32407xG
//起始地址
#define STM32_FLASH_START_ADRESS_16K ADDR_FLASH_SECTOR_0
#define STM32_FLASH_START_ADRESS_64K ADDR_FLASH_SECTOR_4
#define STM32_FLASH_START_ADRESS_128K ADDR_FLASH_SECTOR_5
//大小
#define FLASH_SIZE_GRANULARITY_16K (4*16*1024) //4个16K
#define FLASH_SIZE_GRANULARITY_64K (64*1024) //1个64K
#define FLASH_SIZE_GRANULARITY_128K (7*128*1024) //7个128K
const struct fal_flash_dev stm32_onchip_flash_16k = { "onchip_flash_16k", STM32_FLASH_START_ADRESS_16K, FLASH_SIZE_GRANULARITY_16K, (16 * 1024), {NULL, fal_flash_read_16k, fal_flash_write_16k, fal_flash_erase_16k} };
const struct fal_flash_dev stm32_onchip_flash_64k = { "onchip_flash_64k", STM32_FLASH_START_ADRESS_64K, FLASH_SIZE_GRANULARITY_64K, (64 * 1024), {NULL, fal_flash_read_64k, fal_flash_write_64k, fal_flash_erase_64k} };
const struct fal_flash_dev stm32_onchip_flash_128k = { "onchip_flash_128k", STM32_FLASH_START_ADRESS_128K, FLASH_SIZE_GRANULARITY_128K, (128 * 1024), {NULL, fal_flash_read_128k, fal_flash_write_128k, fal_flash_erase_128k} };
3、fal_cfg.h
这个文件需要自己新建,然后添加头文件路径;
extern引入刚才定义的三个flash设备,然后定义成FLASH设备表FAL_FLASH_DEV_TABLE;
定义分区表FAL_PART_TABLE,这里要注意的是使用的是偏移地址而不是偏移地址;
#ifndef APPLICATIONS_FAL_CFG_H_
#define APPLICATIONS_FAL_CFG_H_
#include <rtconfig.h>
#include <board.h>
/* ===================== Flash device Configuration ========================= */
extern const struct fal_flash_dev stm32_onchip_flash_16k,stm32_onchip_flash_64k,stm32_onchip_flash_128k;
/* flash device table */
#define FAL_FLASH_DEV_TABLE \
{ \
&stm32_onchip_flash_16k, \
&stm32_onchip_flash_64k, \
&stm32_onchip_flash_128k, \
}
/* ====================== Partition Configuration ========================== */
#ifdef FAL_PART_HAS_TABLE_CFG
/* partition table */
#define FAL_PART_TABLE \
{ \
{FAL_PART_MAGIC_WORD,"part1","onchip_flash_16k", 0 ,64*1024 , 0}, \
{FAL_PART_MAGIC_WORD,"part2","onchip_flash_64k", 0 ,64*1024 , 0}, \
{FAL_PART_MAGIC_WORD,"part3","onchip_flash_128k", 0 ,6*128*1024 , 0}, \
{FAL_PART_MAGIC_WORD,"part4","onchip_flash_128k", 6*128*1024 ,1*128*1024 , 0}, \
}
#endif /* FAL_PART_HAS_TABLE_CFG */
#endif /* APPLICATIONS_FAL_CFG_H_ */
4、msh验证
调用FAL初始化函数,fal_init();
4.1、上电打印FLASH设备表和分区表
4.2、查看支持的指令
4.3、选择要操作的分区
4.4、读-写-读
4.5、擦除
擦除是对于扇区来说的,所以写了擦1个字节也不会真的擦一个字节。
4.6、性能测试
至少对于一个扇区进行测试,所以虽然写1024但实际是131072,131072是128K,定义blk_size的值。
对于128K的空间,擦除0.001s,写入0.524s,读出0.047s,不仅看出擦除的速度非常快,写入的速度最慢,对于写入的慢速也有一个数据来量化;
5、API测试
首先根据名称找到分区,然后进行读、写、擦除操作,简单测试如下:
int main(void)
{
int count = 1;
uint8_t read_buf[16]={0},write_buf[16]={0};
const struct fal_partition * config_info;
//初始化FAL
fal_init();
//查找flash分区
//const struct fal_partition *fal_partition_find(const char *name)
config_info = fal_partition_find("part4");
//读取
//int fal_partition_read(const struct fal_partition *part, uint32_t addr, uint8_t *buf, size_t size)
fal_partition_read(config_info,0,read_buf,16);
LOG_D("read config data:\n");
for(count=0;count<16;count++){
rt_kprintf("%02x ",read_buf[count]);
}
rt_kprintf("\n");
//擦除
//int fal_partition_erase(const struct fal_partition *part, uint32_t addr, size_t size)
fal_partition_erase(config_info,0,128*1024);
//写入
//int fal_partition_write(const struct fal_partition *part, uint32_t addr, const uint8_t *buf, size_t size)
LOG_D("start write config data...");
fal_partition_write(config_info,0,write_buf,16);
LOG_D("write done.");
//读取
//int fal_partition_read(const struct fal_partition *part, uint32_t addr, uint8_t *buf, size_t size)
fal_partition_read(config_info,0,read_buf,16);
LOG_D("read config data:\n");
for(count=0;count<16;count++){
rt_kprintf("%02x ",read_buf[count]);
}
rt_kprintf("\n");
while (count++){
//rt_kprintf("Hello World!\n");
rt_thread_mdelay(1000);
}
return RT_EOK;
}
参考链接: