GD32E23x flash作为静态存储的读写操作

268 阅读7分钟

一、前言

        在只有芯片没有外部存储时需要存储一些配置信息,使用flash进行存储是很好的选择了,在GD32E23x中以flash扇区为单位进行擦写,一个扇区大小为1K,需要时优先拿出最后几个扇区来作为存储区。

二、GD32E23x flash扇区地址划分

        一般来,GD32E23x的flash第一个扇区的首地址为0x0800_0000,以我使用的这一款64k的flash为例,扇区划分为:

页(Page)编号起始地址(Flash Address)结束地址(Flash Address)
Page 00x0800_00000x0800_03FF
Page 10x0800_04000x0800_07FF
Page 20x0800_08000x0800_0BFF
Page 30x0800_0C000x0800_0FFF
Page 40x0800_10000x0800_13FF
Page 50x0800_14000x0800_17FF
Page 60x0800_18000x0800_1BFF
Page 70x0800_1C000x0800_1FFF
Page 80x0800_20000x0800_23FF
Page 90x0800_24000x0800_27FF
Page 100x0800_28000x0800_2BFF
Page 110x0800_2C000x0800_2FFF
Page 120x0800_30000x0800_33FF
Page 130x0800_34000x0800_37FF
Page 140x0800_38000x0800_3BFF
Page 150x0800_3C000x0800_3FFF
Page 160x0800_40000x0800_43FF
Page 170x0800_44000x0800_47FF
Page 180x0800_48000x0800_4BFF
Page 190x0800_4C000x0800_4FFF
Page 200x0800_50000x0800_53FF
Page 210x0800_54000x0800_57FF
Page 220x0800_58000x0800_5BFF
Page 230x0800_5C000x0800_5FFF
Page 240x0800_60000x0800_63FF
Page 250x0800_64000x0800_67FF
Page 260x0800_68000x0800_6BFF
Page 270x0800_6C000x0800_6FFF
Page 280x0800_70000x0800_73FF
Page 290x0800_74000x0800_77FF
Page 300x0800_78000x0800_7BFF
Page 310x0800_7C000x0800_7FFF
Page 320x0800_80000x0800_83FF
Page 330x0800_84000x0800_87FF
Page 340x0800_88000x0800_8BFF
Page 350x0800_8C000x0800_8FFF
Page 360x0800_90000x0800_93FF
Page 370x0800_94000x0800_97FF
Page 380x0800_98000x0800_9BFF
Page 390x0800_9C000x0800_9FFF
Page 400x0800_A0000x0800_A3FF
Page 410x0800_A4000x0800_A7FF
Page 420x0800_A8000x0800_ABFF
Page 430x0800_AC000x0800_AFFF
Page 440x0800_B0000x0800_B3FF
Page 450x0800_B4000x0800_B7FF
Page 460x0800_B8000x0800_BBFF
Page 470x0800_BC000x0800_BFFF
Page 480x0800_C0000x0800_C3FF
Page 490x0800_C4000x0800_C7FF
Page 500x0800_C8000x0800_CBFF
Page 510x0800_CC000x0800_CFFF
Page 520x0800_D0000x0800_D3FF
Page 530x0800_D4000x0800_D7FF
Page 540x0800_D8000x0800_DBFF
Page 550x0800_DC000x0800_DFFF
Page 560x0800_E0000x0800_E3FF
Page 570x0800_E4000x0800_E7FF
Page 580x0800_E8000x0800_EBFF
Page 590x0800_EC000x0800_EFFF
Page 600x0800_F0000x0800_F3FF
Page 610x0800_F4000x0800_F7FF
Page 620x0800_F8000x0800_FBFF
Page 630x0800_FC000x0800_FFFF

 三、GD32E23x 固件库下载

        我这里使用的是GD32E23x标准固件库,下载地址为: (兆易创新GigaDevice-资料下载兆易创新GD32 MCU)

如图,如果只需要固件库下载GD32E23x Firmware Library即可,如果需要固件库+示例则下载GD32E23x Demo Suites:

image.png

四、GD32E23x falsh擦写操作函数封装

直接给示例吧,引用头文件gd32e23x_fmc.h的库函数,稍加封装方便调用:

//写入数据到目标扇区 参数依次:扇区首地址、数据首地址、数据大小
void flash_write_multi(uint32_t start_addr, uint32_t *data, uint32_t word_count) {
    fmc_unlock();//解锁

    fmc_page_erase(start_addr);//擦掉

	fmc_flag_clear(FMC_FLAG_END | FMC_FLAG_WPERR | FMC_FLAG_PGAERR | FMC_FLAG_PGERR );
    for (uint32_t i = 0; i < word_count; i++) {//写入新数据
        fmc_word_program(start_addr + (i * 4), data[i]);
    }
	fmc_flag_clear(FMC_FLAG_END | FMC_FLAG_WPERR | FMC_FLAG_PGAERR | FMC_FLAG_PGERR );

    fmc_lock();//加锁
}

//读取扇区数据 参数依次:扇区首地址、读取缓存区首地址、读取大小
void flash_read_multi(uint32_t start_addr, uint32_t *buffer, uint32_t word_count) {
    for (uint32_t i = 0; i < word_count; i++) {
        buffer[i] = *(volatile uint32_t*)(start_addr + (i * 4));
    }
}

五,引用示例

        这里结合结构体进行一个配置信息的保存,可以很方便的保存数据,示例代码:

#define FLASH_PAGE_SIZE  1024 //一个扇区的大小
#define FLASH_SAVE_ADDR  (0x0800FC00) //使用最后一个扇区作为静态区
#define CONFIG_SIZE      (sizeof(Config_data))  //配置信息实际大小
#define CONFIG_WORDS     ((CONFIG_SIZE + 3) / 4)  //注意最小单位是32位

#pragma pack(push, 1)
//配置信息结构体 总大小小于1K
typedef struct Config_data 
{
	uint8_t rtuid[5];
	uint8_t password[2];
    uint8_t othen[20];
} Config_data;
#pragma pack(pop)

//写入配置信息:
    uint32_t buffer[CONFIG_WORDS];
    memset(buffer, 0xFF, sizeof(buffer));
    memcpy((uint8_t*)buffer, config, CONFIG_SIZE);
    flash_write_multi(FLASH_SAVE_ADDR, buffer, CONFIG_WORDS);

//读取配置信息:
    uint32_t buffer[CONFIG_WORDS];
    flash_read_multi(FLASH_SAVE_ADDR, buffer, CONFIG_WORDS);
    memcpy(config, (uint8_t*)buffer, CONFIG_SIZE);