分享一下片内flash使用小技巧--轮询写入
本帖最后由 穿西装的强子 于 2025-5-9 16:51 编辑#申请原创# @21小跑堂 以GD32F4为例,假设我们需要将一个扇区反复写入一个用户参数,例如参数有20个bytes,而反复擦写flash会导致损坏,按GD32F4的数据手册上介绍,擦除次数只有10万次,因此反复擦写太快有超过的风险。 为了解决这个问题,我们想到了将扇区所有空间都利用起来,使用索引的方式进行写入,这样就不会反复的擦除,只有在最开始的时候才会擦除,大大的减少了擦除的次数。
一、Flash 写入次数计算128K存储,假设每次存24个Bytes,整个存储可以存5461次,再擦除一次扇区,扇区可以擦写10万次,存储次数10万*5461,每10秒存一次,可以写193年。二、硬件平台与开发环境
[*]MCU:GD32F4xx
[*]开发工具:Keil MDK 或 IAR Embedded Workbench
[*]SDK:GD32F4xx Standard Peripheral Library
三、Flash 轮询写入实现步骤
[*]初始化读索引
在初始化的时候使用flash_find_index()函数进行索引的获取,索引使用一个全局变量或结构体变量进行保存,在每次写入的时候进行累加
[*]定义存储区域
根据应用需求划分 Flash 存储区域,例如使用最后一页作为用户数据区。#define USER_DATA_ADDR (0x080E0000)// 用户数据起始地址(根据芯片型号调整) ADDR_FMC_SECTOR_11
[*]轮询写数据
void flash_write_data(FlashData_t flashData;)
{
if( flash_addr == FLASH_USER_START_ADDR || flash_addr == ADDR_FMC_SECTOR_12)
{
fmc_erase_sector(fmc_sector_get(FLASH_USER_START_ADDR));
flash_addr = FLASH_USER_START_ADDR;
}
flashData.reserved = 0;
fmc_write_32bit_data(flash_addr, sizeof(flashData) / 4, (INT32*)&flashData);
flash_addr += sizeof(flashData); // 每次写入都增加存储的大小
}
4.读数据
int flash_read_data(UINT32 addr,FlashData_t *data){
FlashData_t flashData;
fmc_read_32bit_data(addr, sizeof(flashData) / 4, (INT32*)&flashData);
*data =flashData;
return TRUE;
}
5.读索引
UINT32 flash_find_index(void)
{
UINT32 addr;
FlashData_t flashData;
UINT16 i;
// 搜索未被使用的地址
for(i = 0; i < MEMORY_SIZE;)
{
addr = FLASH_USER_START_ADDR + i;
fmc_read_32bit_data(addr, sizeof(flashData) / 4, (INT32*)&flashData);
i += sizeof(flashData);
if( flashData.reserved == 0xffff) // 该值正常时为0,因此判定该值为0xff时待办该地址为被使用
{
break;
}
}
if( i == MEMORY_SIZE) // 找到最后,将地址为赋值为最新
addr = FLASH_USER_START_ADDR;
return addr;
}
四、使用流程
1. 初始化检测索引,使用flash_find_index()函数
2. 如果检测到addr为FLASH_USER_START_ADDR起始地址,则擦除并写入第一组数据
3. 写入时自动累计flash_addr值
4. 读取时使用flash_addr进行读取
五、应用场景该方案适用于传感器数据记录、设备配置保存等场景,特别适合没有外部存储介质的低成本设计方案。通过上述方法,开发者可以高效可靠地实现基于 GD32 的 Flash 数据存储功能。在实际工程中,建议结合 CRC 校验等机制进一步提升数据可靠性。
MCU片内FLASH最好不要频繁擦除 如一楼所述MCU内部flash要避免频繁擦除,适合用于存储不需要经常变动的数据。 通过扇区内的多块空间轮流写入,减少擦写次数。擦除只在整扇区写满时执行一次。 根据应用需求划分Flash存储区域 合并多次小数据写入 擦除扇区 → 写入数据 → 轮询状态寄存器(如BUSY位)→ 验证数据。 在关键应用中,可以考虑在多个块中备份重要数据,以防止数据丢失。 关键是实现磨损均衡、数据校验和错误恢复机制 通过合理设计扇区结构和循环机制,可以显著提高 Flash 使用寿命和数据可靠性。 写入时自动累加flash_addr值 Flash在写入数据之前必须先擦除。擦除操作通常比写入操作耗时更长。 批量写入时,尽量减少Flash操作次数。 在低功耗应用中,考虑在写入时关闭非关键外设以节省电量。 可以使用一个简单的算法来选择下一个写入的块,例如循环使用每个块。 Flash通常以页或扇区为单位进行擦除,因此需要合理规划写入地址,避免跨页写入导致不必要的擦除操作。
页:
[1]