打印

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

[复制链接]
160|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 穿西装的强子 于 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 校验等机制进一步提升数据可靠性。



使用特权

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

本版积分规则

35

主题

168

帖子

3

粉丝