GD32 FLASH读写数据

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值