打印

分享一下片内flash使用小技巧--轮询写入

[复制链接]
2096|27
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 穿西装的强子 于 2025-6-6 11:52 编辑

#申请原创# @21小跑堂
      以GD32F4为例,假设我们需要将一个扇区反复写入一个用户参数,例如参数有20个bytes,而反复擦写flash会导致损坏,按GD32F4的数据手册上介绍,擦除次数只有10万次,因此反复擦写太快有超过的风险。
      为了解决这个问题,我们想到了将扇区所有空间都利用起来,使用索引的方式进行写入,这样就不会反复的擦除,只有在最开始的时候才会擦除,大大的减少了擦除的次数。

写入流程
1. 识别FLASH扇区索引,未存储区域,例如 0x08050020 无数据,记录索引为 0x08050020。
2.写数据,按索引 0x08050020  开始写,不擦除flash,写一次,索引自加(数据长度)。
3.写到扇区最后,如 0x08070000 ,索引变为 0x08050000,开始写,这个时候才擦除一次扇区,然后继续写入数据。

一、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 校验等机制进一步提升数据可靠性。



使用特权

评论回复
评论
21小跑堂 2025-5-14 11:29 回复TA
Hi 大佬 感谢谢分享,本贴内容不满800字未达原创审核门槛,可填充内容后再次申请原创~ 
沙发
zhengshuai888| | 2025-5-14 21:57 | 只看该作者
MCU片内FLASH最好不要频繁擦除

使用特权

评论回复
评论
穿西装的强子 2025-5-15 10:37 回复TA
没有反复写啊,你看下逻辑吧 
板凳
lidi911| | 2025-5-15 08:46 | 只看该作者
如一楼所述MCU内部flash要避免频繁擦除,适合用于存储不需要经常变动的数据。

使用特权

评论回复
评论
穿西装的强子 2025-5-15 10:16 回复TA
不是,你们都没仔细看吗,一个扇区用完了再擦除啊,不会频繁擦除 
地板
kepe| | 2025-5-31 01:50 | 只看该作者
通过扇区内的多块空间轮流写入,减少擦写次数。擦除只在整扇区写满时执行一次。

使用特权

评论回复
5
claretttt| | 2025-6-5 11:35 | 只看该作者
根据应用需求划分Flash存储区域

使用特权

评论回复
6
backlugin| | 2025-6-5 12:25 | 只看该作者
合并多次小数据写入              

使用特权

评论回复
7
hudi008| | 2025-6-5 13:22 | 只看该作者
擦除扇区 → 写入数据 → 轮询状态寄存器(如BUSY位)→ 验证数据。

使用特权

评论回复
8
mickit| | 2025-6-5 14:13 | 只看该作者
在关键应用中,可以考虑在多个块中备份重要数据,以防止数据丢失。

使用特权

评论回复
9
lzmm| | 2025-6-5 15:04 | 只看该作者
关键是实现磨损均衡、数据校验和错误恢复机制

使用特权

评论回复
10
maudlu| | 2025-6-5 15:55 | 只看该作者
通过合理设计扇区结构和循环机制,可以显著提高 Flash 使用寿命和数据可靠性。

使用特权

评论回复
11
jkl21| | 2025-6-5 16:53 | 只看该作者
写入时自动累加flash_addr值

使用特权

评论回复
12
rosemoore| | 2025-6-5 17:45 | 只看该作者
Flash在写入数据之前必须先擦除。擦除操作通常比写入操作耗时更长。

使用特权

评论回复
13
mollylawrence| | 2025-6-5 18:35 | 只看该作者
批量写入时,尽量减少Flash操作次数。

使用特权

评论回复
14
10299823| | 2025-6-5 19:18 | 只看该作者
在低功耗应用中,考虑在写入时关闭非关键外设以节省电量。

使用特权

评论回复
15
youtome| | 2025-6-5 21:01 | 只看该作者
可以使用一个简单的算法来选择下一个写入的块,例如循环使用每个块。

使用特权

评论回复
16
chenci2013| | 2025-6-5 21:49 | 只看该作者
Flash通常以页或扇区为单位进行擦除,因此需要合理规划写入地址,避免跨页写入导致不必要的擦除操作。

使用特权

评论回复
17
abotomson| | 2025-6-5 22:40 | 只看该作者
需要快速响应的实时系统              

使用特权

评论回复
18
lihuami| | 2025-6-6 09:48 | 只看该作者
轮询通过读取状态寄存器判断写入是否完成,避免依赖固定延时。

使用特权

评论回复
19
jimmhu| | 2025-6-6 10:34 | 只看该作者
在写入过程中,需确保电源稳定,避免电压波动导致写入失败。

使用特权

评论回复
20
maqianqu| | 2025-6-6 11:16 | 只看该作者
适用于存储不需要经常变动的数据              

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

44

主题

185

帖子

3

粉丝