一、RTT 配置步骤
1、在RT_Thread Settings中打开FAL组件,如下:
2、定义struct fal_flash_dev类型的flash设备
- struct fal_flash_dev的具体成员:flash设备名字、flash起始地址、flash大小、块大小(执行擦除时的最小颗粒)、操作函数(init、read、write、erase)、写操作最小颗粒度;
- 找到STM32F407VET6扇区的大小,主存储器一共5个扇区,4个16K、1个64K、3个128K;
3、drv_flash_f4.c代码:
- 第一部分:宏定义各扇区的起始地址
/* Base address of the Flash sectors Bank 1 */
#define ADDR_FLASH_SECTOR_0 ((uint32_t)0x08000000) /* Base @ of Sector 0, 16 Kbytes */
#define ADDR_FLASH_SECTOR_1 ((uint32_t)0x08004000) /* Base @ of Sector 1, 16 Kbytes */
#define ADDR_FLASH_SECTOR_2 ((uint32_t)0x08008000) /* Base @ of Sector 2, 16 Kbytes */
#define ADDR_FLASH_SECTOR_3 ((uint32_t)0x0800C000) /* Base @ of Sector 3, 16 Kbytes */
#define ADDR_FLASH_SECTOR_4 ((uint32_t)0x08010000) /* Base @ of Sector 4, 64 Kbytes */
#define ADDR_FLASH_SECTOR_5 ((uint32_t)0x08020000) /* Base @ of Sector 5, 128 Kbytes */
#define ADDR_FLASH_SECTOR_6 ((uint32_t)0x08040000) /* Base @ of Sector 6, 128 Kbytes */
#define ADDR_FLASH_SECTOR_7 ((uint32_t)0x08060000) /* Base @ of Sector 7, 128 Kbytes */
#define ADDR_FLASH_SECTOR_8 ((uint32_t)0x08080000) /* Base @ of Sector 8, 128 Kbytes */
#define ADDR_FLASH_SECTOR_9 ((uint32_t)0x080A0000) /* Base @ of Sector 9, 128 Kbytes */
#define ADDR_FLASH_SECTOR_10 ((uint32_t)0x080C0000) /* Base @ of Sector 10, 128 Kbytes */
#define ADDR_FLASH_SECTOR_11 ((uint32_t)0x080E0000) /* Base @ of Sector 11, 128 Kbytes */
/* Base address of the Flash sectors Bank 2 */
#define ADDR_FLASH_SECTOR_12 ((uint32_t)0x08100000) /* Base @ of Sector 0, 16 Kbytes */
#define ADDR_FLASH_SECTOR_13 ((uint32_t)0x08104000) /* Base @ of Sector 1, 16 Kbytes */
#define ADDR_FLASH_SECTOR_14 ((uint32_t)0x08108000) /* Base @ of Sector 2, 16 Kbytes */
#define ADDR_FLASH_SECTOR_15 ((uint32_t)0x0810C000) /* Base @ of Sector 3, 16 Kbytes */
#define ADDR_FLASH_SECTOR_16 ((uint32_t)0x08110000) /* Base @ of Sector 4, 64 Kbytes */
#define ADDR_FLASH_SECTOR_17 ((uint32_t)0x08120000) /* Base @ of Sector 5, 128 Kbytes */
#define ADDR_FLASH_SECTOR_18 ((uint32_t)0x08140000) /* Base @ of Sector 6, 128 Kbytes */
#define ADDR_FLASH_SECTOR_19 ((uint32_t)0x08160000) /* Base @ of Sector 7, 128 Kbytes */
#define ADDR_FLASH_SECTOR_20 ((uint32_t)0x08180000) /* Base @ of Sector 8, 128 Kbytes */
#define ADDR_FLASH_SECTOR_21 ((uint32_t)0x081A0000) /* Base @ of Sector 9, 128 Kbytes */
#define ADDR_FLASH_SECTOR_22 ((uint32_t)0x081C0000) /* Base @ of Sector 10, 128 Kbytes */
#define ADDR_FLASH_SECTOR_23 ((uint32_t)0x081E0000) /* Base @ of Sector 11, 128 Kbytes */
- 第二部分:读、写、擦除
// Read data from flash.
int stm32_flash_read(rt_uint32_t addr, rt_uint8_t *buf, size_t size);
// Write data to flash.
int stm32_flash_write(rt_uint32_t addr, const rt_uint8_t *buf, size_t size);
// Erase data on flash.
int stm32_flash_erase(rt_uint32_t addr, size_t size);
- 第三部分:修改drv_flash_f4.c的宏定义
//芯片型号:STM32407xE
//起始地址
#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 (3*128*1024) // 3个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} };
4、fal_cfg.h文件编写
-
在driver文件的include下添加fal_cfg,h文件:
-
可以添加多个块进行读写,多个块地址不能交叉,但注意擦除是以扇区进行擦除的。
添加代码:
#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;
extern const struct fal_flash_dev stm32_onchip_flash_64k;
extern const struct fal_flash_dev 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 , 4*16*1024 , 0}, \
{FAL_PART_MAGIC_WORD,"part2","onchip_flash_64k", 0 , 1*64*1024 , 0}, \
{FAL_PART_MAGIC_WORD,"part3","onchip_flash_128k", 0 , 2*128*1024 , 0}, \
{FAL_PART_MAGIC_WORD,"part4","onchip_flash_128k", 2*128*1024 , 1*128*1024 , 0}, \
}
#endif /* FAL_PART_HAS_TABLE_CFG */
#endif /* APPLICATIONS_FAL_CFG_H_ */
二、Flash读写验证
- flash.c文件
#include "flash.h"
#include "power.h"
#include "adc.h"
/*======================================================###### 宏定义 ######==================================================*/
const data_info_t Flash_Data_Deal[] =
{
{"temp", 2, &g_power.temp},
};
// 定义一个GPIO引脚初始化列表计数值
const rt_uint32_t Flash_Data_CNT = ARRAY_CNT(Flash_Data_Deal);
/*=====================================================####### END #######=================================================*/
/*======================================================### 静态函数调用 ###==================================================*/
/**
* @brief 读取数据处理
*/
static void Read_Data_Deal(void)
{
for (int i = 0; i < Flash_Data_CNT; ++i)
{
*Flash_Data_Deal[i].variable = (g_flash.buff[Flash_Data_Deal[i].index * 2] << 8) +
(g_flash.buff[Flash_Data_Deal[i].index * 2 + 1]);
}
}
/**
* @brief 更新数据处理
*/
static void Update_Data_Deal(void)
{
for (int i = 0; i < Flash_Data_CNT; ++i)
{
g_flash.buff[Flash_Data_Deal[i].index * 2] = (*Flash_Data_Deal[i].variable) >> 8;
g_flash.buff[Flash_Data_Deal[i].index * 2 + 1] = (*Flash_Data_Deal[i].variable);
}
}
/**
* @brief flash读取数据
*/
static void Flash_Read_Data(void)
{
// 查找flash分区
g_flash.config_info = fal_partition_find(FLASH_DEVICE_BLK);
// 读取数据
fal_partition_read(g_flash.config_info, 0, g_flash.buff, FLASH_DATA_BUFFER_SIZE);
}
/*=====================================================####### END #######=================================================*/
/*======================================================##### 外部调用 #####==================================================*/
/**
* @brief 读取flash偏移地址
*/
int Flash_Read_Offset_Addr(void)
{
uint8_t buff[ONE_DATA_NUM] = {0};
// 查找flash分区
g_flash.config_info = fal_partition_find(FLASH_DEVICE_BLK);
for (int i = 0; i < FIND_ADDR_COUNT; ++i)
{
// 读取偏移地址
fal_partition_read(g_flash.config_info, i * ONE_DATA_NUM, buff, ONE_DATA_NUM);
// 数据验证
if (buff[0] == buff[1] && buff[0] == 0xFF)
{
return i * ONE_DATA_NUM;
}
}
// 擦除分区
fal_partition_erase(g_flash.config_info, 0, FLASH_PARTITION_SIZE);
return 0;
}
/**
* @brief 根据地址写入指定长度的数据
* @param data: 写入的错误信息
*/
void Flash_Write_Data_Addr(uint16_t data, uint32_t time)
{
uint8_t buff[ONE_DATA_NUM] = {0};
int addr = Flash_Read_Offset_Addr();
buff[0] = time >> 16;
buff[1] = time >> 8;
buff[2] = time;
buff[3] = data >> 8;
buff[4] = data;
// 写入数据
fal_partition_write(g_flash.config_info, addr, buff, ONE_DATA_NUM);
}
/**
* @brief flash读取数据并处理
*/
void Flash_Read_Data_Deal(void)
{
// 读数据
Flash_Read_Data();
// 数据处理
Read_Data_Deal();
}
/**
* @brief flash写数据
*/
void Flash_Write_Data(void)
{
// 读取数据
Flash_Read_Data();
// 更新数据
Update_Data_Deal();
// 擦除分区
fal_partition_erase(g_flash.config_info, 0, FLASH_PARTITION_SIZE);
// 写入数据
fal_partition_write(g_flash.config_info, 0, g_flash.buff, FLASH_DATA_BUFFER_SIZE);
}
/**
* @brief flash读写测试
*/
void Flash_Read_Write_Test(void)
{
fal_init();
// 读数据
Flash_Read_Data();
LOG_E("read config data...\n");
for (int i = 0; i < 6; ++i)
{
printf("%2x ", g_flash.buff[i]);
}
printf("\n");
// 数据处理
Read_Data_Deal();
LOG_E("read data deal...\n");
// printf("%d %d %d\n", g_power.output_vol, g_power.output_curr, g_power.temp);
g_power.output_vol = 165;
g_power.output_curr = 65231;
g_power.temp = 479;
// 写数据
Flash_Write_Data();
LOG_E("write data end...\n");
for (int i = 0; i < 6; ++i)
{
printf("%2x ", g_flash.buff[i]);
}
printf("\n");
LOG_E("write data deal...\n");
// printf("%d %d %d\n", g_power.output_vol, g_power.output_curr, g_power.temp);
}
/*=====================================================####### END #######=================================================*/
- flash.h文件
#ifndef APPLICATIONS_INC_FLASH_H_
#define APPLICATIONS_INC_FLASH_H_
#include <rtthread.h>
#include <drv_common.h>
#define DBG_TAG "main"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>
#include <fal.h>
#include "sys_string.h"
/**=====================================================###### 宏定义 ######==================================================*/
#define FLASH_DEVICE_BLK "part4" // flash存储分区4
#define FLASH_DEVICE_BLK5 "part5" // flash存储分区5
#define FLASH_DATA_BUFFER_SIZE 50 // 数据缓冲区大小,一个数据使用两位,50则是存储25个数据
#define ONE_DATA_NUM 5 // 一组数据的个数
#define FIND_ADDR_COUNT 26214 // 寻址次数
#define FLASH_PARTITION_SIZE (128 * 1024) // flash分区大小
/**====================================================####### END #######=================================================*/
/**=====================================================### 全局变量定义 ####=================================================*/
// 数据处理结构体
typedef struct
{
const char *name; // 变量名字
uint16_t index; // 序号
uint16_t *variable; // 变量
} data_info_t;
// flash结构体
typedef struct
{
const struct fal_partition *config_info; // flash结构体
uint8_t buff[FLASH_DATA_BUFFER_SIZE]; // 接收数据缓冲区
uint8_t save_flag; // 存储标志
} flash_info_t;
flash_info_t g_flash;
/**====================================================####### END #######=================================================*/
/**==================================================##### 函数及变量声明 #####===============================================*/
extern int Flash_Read_Offset_Addr(void); // 读取flash偏移地址
extern void Flash_Write_Data_Addr(uint16_t data, uint32_t time); // 根据地址写入指定长度的数据
extern void Flash_Read_Data_Deal(void); // flash读取数据并处理
extern void Flash_Write_Data(void); // flash写数据
extern void Flash_Read_Write_Test(void); // flash读写测试
/**====================================================####### END #######=================================================*/
#endif /* APPLICATIONS_INC_FLASH_H_ */
三、数据验证
-
设备开机初始化
-
通过串口助手发送读写指令进行数据的读写