[研电赛技术支持] GD32 FLASH读写数据

[复制链接]
68|9
guanjiaer 发表于 2025-12-12 20:28 | 显示全部楼层 |阅读模式
本工程使用GD32E230芯片,读写数据亲测正常。需要注意的是,如果定义一个存储数组Buff[6],比如写入Buff[0],其余存储数据也将会被擦除,所以尽管修改存入一个数据,使用代码时,需要将整个Buff[6]的6数据再次全部重新存入。

#include "gd32e23x_flash_eeprom.h"
#include <string.h>

/* 内部缓冲区 */
static uint8_t eeprom_buffer[EEPROM_MAX_SIZE];

/* 检查Flash是否为空 */
static uint8_t is_page_empty(uint32_t addr)
{
    uint32_t *ptr = (uint32_t *)addr;
    for(uint16_t i = 0; i < EEPROM_PAGE_SIZE/4; i++) {
        if(ptr[i] != 0xFFFFFFFF) {
            return 0;
        }
    }
    return 1;
}

/* 擦除Flash页 */
static uint8_t erase_page(void)
{
    fmc_state_enum state;

    fmc_unlock();
    state = fmc_page_erase(EEPROM_START_ADDR);
    fmc_lock();

    return (state == FMC_READY) ? 1 : 0;
}

/* 初始化EEPROM */
void eeprom_init(void)
{
    // 初始化FMC设置
    fmc_unlock();
    fmc_wscnt_set(WS_WSCNT_1);  // 设置1个等待状态
    fmc_prefetch_enable();
    fmc_lock();
}

/* 写入数据 */
uint8_t eeprom_write(uint16_t addr, uint8_t *data, uint16_t size)
{
        fmc_unlock();
    // 参数检查
    if((addr + size) > EEPROM_MAX_SIZE || data == NULL || size == 0)
        {
        return 0;
    }
    memcpy(&eeprom_buffer[addr], data, size);// 更新缓冲区
    if(!erase_page())// 擦除Flash页
        {
        return 0;
    }
    uint32_t offset = 0;// 写入数据到Flash
    fmc_unlock();

    while(offset < EEPROM_MAX_SIZE)
        {
        uint64_t data_to_write;
        // 确保双字对齐
        if((offset % 8) == 0 && (EEPROM_MAX_SIZE - offset) >= 8)
                {
            data_to_write = *(uint64_t *)(eeprom_buffer + offset);
            if(fmc_doubleword_program(EEPROM_START_ADDR + offset, data_to_write) != FMC_READY)
                        {
                fmc_lock();
                return 0;
            }
            offset += 8;
        }
                else
                {
            // 处理非对齐或剩余数据
            uint32_t word_data = 0xFFFFFFFF;
            uint16_t bytes_left = EEPROM_MAX_SIZE - offset;
            uint16_t copy_size = (bytes_left >= 4) ? 4 : bytes_left;

            memcpy(&word_data, eeprom_buffer + offset, copy_size);
            if(fmc_word_program(EEPROM_START_ADDR + offset, word_data) != FMC_READY)
                        {
                fmc_lock();
                return 0;
            }
            offset += copy_size;
        }
    }
    fmc_lock();
    return 1;
}

/* 读取数据 */
fmc_status_t eeprom_read(uint32_t offset, void *data, uint32_t size)
{
    uint32_t addr = EEPROM_START_ADDR + offset;

    // 参数检查
    if ((addr + size) > EEPROM_END_ADDR) return FMC_ERR_ADDR;
    if (size == 0) return FMC_ERR_SIZE;

    // 直接内存拷贝
    memcpy(data, (void *)addr, size);
    return FMC_OK;
}


#ifndef __GD32E23X_FLASH_EEPROM_H
#define __GD32E23X_FLASH_EEPROM_H

#include "gd32e23x.h"


/* EEPROM模拟参数配置 */
#define EEPROM_PAGE_SIZE         1024    // Flash页大小(1KB)
#define EEPROM_START_ADDR        0x0800FC00  // 使用的Flash页起始地址
#define EEPROM_MAX_SIZE          1024    // 最大存储空间(1KB)
#define EEPROM_END_ADDR           0x0800FFFF

// 错误码
typedef enum {
    FMC_OK,
    FMC_ERR_ADDR,      // 地址错误
    FMC_ERR_SIZE,      // 长度错误
    FMC_ERR_ERASE,     // 擦除失败
    FMC_ERR_WRITE      // 写入失败
} fmc_status_t;
/* 函数声明 */
void eeprom_init(void);
uint8_t eeprom_write(uint16_t ee_addr, uint8_t *data, uint16_t size);
fmc_status_t eeprom_read(uint32_t offset, void *data, uint32_t size);
#endif /* __GD32E23X_FLASH_EEPROM_H */


————————————————
版权声明:本文为CSDN博主「请叫我诗远」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/kangcongcong/article/details/148013062

jcky001 发表于 2026-1-22 13:47 | 显示全部楼层
用空间换时间,用时间换可靠性
jcky001 发表于 2026-1-22 13:47 | 显示全部楼层
在GD32E230的资源约束下,当前实现以SRAM为代价换取了存储管理的简洁性,但牺牲了写入效率和长期可靠性。
classroom 发表于 2026-1-22 13:50 | 显示全部楼层
全页擦除效率低下
cr315 发表于 2026-1-22 14:50 | 显示全部楼层
断电易导致数据丢失,需冗余备份
duo点 发表于 2026-1-22 16:51 | 显示全部楼层
对齐处理可优化
jcky001 发表于 2026-1-22 18:51 | 显示全部楼层
固定页写入加速Flash老化,寿命受限
onlycook 发表于 2026-1-22 19:52 | 显示全部楼层
关键场景需回滚机制,防止数据损坏
powerantone 发表于 2026-1-22 21:52 | 显示全部楼层
单字节写入性能差,建议强制双字对齐
stormwind123 发表于 2026-1-22 22:53 | 显示全部楼层
1KB缓冲区对小MCU负担较大
您需要登录后才可以回帖 登录 | 注册

本版积分规则

124

主题

4483

帖子

2

粉丝
快速回复 在线客服 返回列表 返回顶部
0