本工程使用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 */