打印
[研电赛技术支持]

GD32的flash读、擦除、写操作

[复制链接]
2666|6
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
tpgf|  楼主 | 2021-9-8 07:27 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
GD32的flash特征
1、在flash的前256K字节空间内,CPU执行指令零等待;在此范围外,CPU读取指令存在较长延时;
2、对于flash大于512KB(不包括等于512KB)的GD32F10x_CL和GD32F10x_XD,使用了两片闪存;前512KB容量在第一片闪存(bank0)中,后续的容量在第二片闪存(bank1)中;
3、对于flash容量小于等于512KB的GD32F10x_CL和GD32F10x_HD,只使用了bank0;
4、对 于 GD32F10x_MD , 闪 存 页 大 小 为 1KB 。 GD32F10x_CL 和 GD32F10x_HD ,GD32F10x_XD,bank0的闪存页大小为2KB,bank1的闪存页大小为4KB;
5、支持32位整字或16位半字编程,页擦除和整片擦除操作;

GD32的flash结构
GD32F10x_MD



使用特权

评论回复
沙发
tpgf|  楼主 | 2021-9-8 07:28 | 只看该作者
GD32F10x_CL,GD32F10x_HD 和 GD32F10x_XD


GD32的flash读操作
flash可以像普通存储空间一样直接寻址访问。

value=*(uint32_t*)FlashAddr;
1
uint16_t IAP_ReadFlag(void)
{
        return *(volatile uint16_t*)(FLASH_ADDR);  
}


使用特权

评论回复
板凳
tpgf|  楼主 | 2021-9-8 07:29 | 只看该作者
GD32的flash擦除操作
页擦除
每一页可以被独立擦除,步骤如下:

确保FMC_CTLx寄存器不处于锁定状态;
检查FMC_STATx寄存器的BUSY位来判定闪存是否正处于擦写访问状态,若BUSY位为1,则需等待该操作结束,BUSY位变为0;
置位FMC_CTLx寄存器的PER位;
将待擦除页的绝对地址(0x08XX XXXX)写到FMC_ADDRx寄存器;
通过将FMC_CTLx寄存器的START位置1来发送页擦除命令到FMC;
等待擦除指令执行完毕,FMC_STATx寄存器的BUSY位清0;
如果需要,使用DBUS读并验证该页是否擦除成功。
代码上直接调用GD的库函数即可:

void fmc_erase_page(uint32_t Page_Address)
{
        fmc_unlock();  //fmc解锁
    /* clear all pending flags */
    fmc_flag_clear(FMC_FLAG_BANK0_END);
    fmc_flag_clear(FMC_FLAG_BANK0_WPERR);
    fmc_flag_clear(FMC_FLAG_BANK0_PGERR);

    /* erase the flash pages */
        fmc_page_erase(Page_Address);
       
        /* clear all pending flags */
        fmc_flag_clear(FMC_FLAG_BANK0_END);
        fmc_flag_clear(FMC_FLAG_BANK0_WPERR);
        fmc_flag_clear(FMC_FLAG_BANK0_PGERR);
       
        fmc_lock();  //fmc上锁
}



要擦除连续的几页:

void fmc_erase_pages(void)
{
    uint32_t erase_counter;

    /* unlock the flash program/erase controller */
    fmc_unlock();

    /* clear all pending flags */
    fmc_flag_clear(FMC_FLAG_BANK0_END);
    fmc_flag_clear(FMC_FLAG_BANK0_WPERR);
    fmc_flag_clear(FMC_FLAG_BANK0_PGERR);

    /* erase the flash pages */
    for(erase_counter = 0; erase_counter < page_num; erase_counter++){
        fmc_page_erase(FMC_WRITE_START_ADDR + (FMC_PAGE_SIZE * erase_counter));
        fmc_flag_clear(FMC_FLAG_BANK0_END);
        fmc_flag_clear(FMC_FLAG_BANK0_WPERR);
        fmc_flag_clear(FMC_FLAG_BANK0_PGERR);
    }

    /* lock the main FMC after the erase operation */
    fmc_lock();
}



整片擦除
void fmc_erase_page(uint32_t Page_Address)
{
        fmc_unlock();  //fmc解锁
    /* clear all pending flags */
    fmc_flag_clear(FMC_FLAG_BANK0_END);
    fmc_flag_clear(FMC_FLAG_BANK0_WPERR);
    fmc_flag_clear(FMC_FLAG_BANK0_PGERR);

    /* erase whole chip */
        fmc_mass_erase();
       
        /* clear all pending flags */
        fmc_flag_clear(FMC_FLAG_BANK0_END);
        fmc_flag_clear(FMC_FLAG_BANK0_WPERR);
        fmc_flag_clear(FMC_FLAG_BANK0_PGERR);
       
        fmc_lock();  //fmc上锁
}



使用特权

评论回复
地板
tpgf|  楼主 | 2021-9-8 07:29 | 只看该作者
GD32的flash写操作
往flash的某个地址写入数据前,一般要先擦除该地址。
16位半字编程:

void IAP_WriteFlag(uint16_t flag)
{
        fmc_unlock();
        fmc_page_erase(IAP_FLAG_ADDR);
        fmc_halfword_program(IAP_FLAG_ADDR,flag);
        fmc_lock();
}



32位整字编程:

void fmc_program(void)
{
    /* unlock the flash program/erase controller */
    fmc_unlock();

    address = FMC_WRITE_START_ADDR;

    /* program flash */
    while(address < FMC_WRITE_END_ADDR){
        fmc_word_program(address, data0);
        address += 4;
        fmc_flag_clear(FMC_FLAG_BANK0_END);
        fmc_flag_clear(FMC_FLAG_BANK0_WPERR);
        fmc_flag_clear(FMC_FLAG_BANK0_PGERR);
    }

    /* lock the main FMC after the program operation */
    fmc_lock();
}


使用特权

评论回复
5
呐咯密密| | 2021-9-9 12:18 | 只看该作者
有没有测试过写一次半字需要多久,

使用特权

评论回复
6
weifeng90| | 2021-9-9 20:31 | 只看该作者
擦除速度和读写速度测试过没?

使用特权

评论回复
7
tail066| | 2021-9-10 14:25 | 只看该作者
不错啊 ,差不多全了

使用特权

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

本版积分规则

1923

主题

15596

帖子

11

粉丝