【GD32学习】五、片内Flash读写实验-闪存控制器FMC

 

文章目录


前言

准备


一、存储信息

1、存储信息寄存器

这个寄存器可以获取 片上FLASH存储器容量片上SRAM容量

2、系统架构示意图

 可见Flash的操作可以通过FMC控制器尽心操作,提供字、半字、字节闪存操作,可以扇区擦除、块擦除和部分系列(GD32F470xx, GD32F427xx and GD32F425xx )还提供页擦除(4KB)

3、存储器映射

这个F4系列最大3072KB,我们用的芯片只有 512K

4、存储扇区基地址和大小

 可以看出,不同的扇区大小还不一样,有16K、64K、128K不同大小的扇区

二、解锁

1、解锁FMC_CTL、FMC_OBCTLx

复位之后 如果要操作FMC前要解锁 FMC_CTL这个控制寄存器、若果要操作选项字节需解锁FMC_OBCTLx 选项字节控制寄存器,都是先后往对应的KEY解锁寄存器写入两个对应的序列,上锁是把对应 的 LK bit 置1

FMC_CTL解锁上锁例程

/*!
    \brief    unlock the main FMC operation
    \param[in]  none
    \param[out] none
    \retval     none
*/
void fmc_unlock(void)
{
    if((RESET != (FMC_CTL & FMC_CTL_LK))) {
        /* write the FMC key */
        FMC_KEY = UNLOCK_KEY0;
        FMC_KEY = UNLOCK_KEY1;
    }
}

/*!
    \brief    lock the main FMC operation
    \param[in]  none
    \param[out] none
    \retval     none
*/
void fmc_lock(void)
{
    /* set the LK bit*/
    FMC_CTL |= FMC_CTL_LK;
}

2、解锁 也擦除配置寄存器 FMC_PECFG

 

当需要执行页擦除操作时需要 往 FMC_PEKEY 寄存器写入 0xA9B8C7D6来解锁FMC_PECFG寄存器
 

三、读操作

可以直接寻址访问 

void fmc_read_8bit_data(uint32_t address, uint16_t length, int8_t* data_8)
{
    uint8_t i;   
    for(i=0; i<length; i++)
    {
        /*直接寻址访问*/
        data_8[i] = *(__IO int8_t*)address;
        address++;
    }  
}

四、主flash编程操作

1、操作流程

a、确保FMC_CTL寄存器不处于锁定状态;
b、等待FMC_STAT寄存器的BUSY位变为0来确保没有闪存操作在进行,否则等待该操作完成;
c、按照需求设置PSZ位域,并置位FMC_CTL寄存器的PG位;
d、DBUS写一个32位整字/16位半字/8位字节(必须与FMC_CTL寄存器中的PSZ位匹配)到
        目的绝对地址(0x08XX XXXX);
e、通过检查FMC_STAT寄存器的BUSY位是否清0,来确定写操作执行完毕;
f、如果需要,使用DBUS读操作验证是否编程成功。

2、8位字节编程例程

/* 单字节编程 */
fmc_state_enum fmc_byte_program(uint32_t address, uint8_t data)
{
    fmc_state_enum fmc_state = FMC_READY;
    /* 等待BUSY忙碌标志清零、FMC就绪、FMC没有故障 */
    fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);

    if(FMC_READY == fmc_state) {

		/* 复位编程大小位有 32位整字/16位半字/8位字节*/
        FMC_CTL &= ~FMC_CTL_PSZ;
		/* 选择新的编程大小位位 8位字节*/		
        FMC_CTL |= CTL_PSZ_BYTE;
		/* 置位 FMC_CTL_PG ,PG位必须在32位整字/16位半字/8位字节编程开始前进行置位*/				
        FMC_CTL |= FMC_CTL_PG;
		/* 开始编程,往对应的地址存入数据*/		
        REG8(address) = data;

        /* 等待BUSY忙碌标志清零,操作完成 */
        fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);

        /* 清零PG位 */
        FMC_CTL &= ~FMC_CTL_PG;
    }

    /* 返回 FMC 状态 */
    return fmc_state;
}

3、页擦除(GD32F425、GD32F427、GD32F470支持)

1、流程

2、程序解析

/* 页擦除 */
fmc_state_enum fmc_page_erase(uint32_t page_addr)
{
    fmc_state_enum fmc_state = FMC_READY;

    /* 等待BUSY忙碌标志清零、FMC就绪、FMC没有故障 */
    fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);

    if(FMC_READY == fmc_state) {
        /* 解锁 FMC_PECFG */
        FMC_PEKEY = UNLOCK_PE_KEY;

        /* PE_EN置位使能页擦除、 page_addr要擦除的页地址*/
        FMC_PECFG = FMC_PE_EN | page_addr;
        /* 选择擦除扇区号 */		
        FMC_CTL &= ~FMC_CTL_SN;
        /* 主存储块扇区擦除命令置位 */		
        FMC_CTL |= FMC_CTL_SER;
        /* 发送擦除命令位 */		
        FMC_CTL |= FMC_CTL_START;

        /* 等待BUSY忙碌标志清零,操作完成 */
        fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
        /* PE_EN 停止页擦除 */		
        FMC_PECFG &= ~FMC_PE_EN;
        /* 主存储块扇区擦除命令清零 */				
        FMC_CTL &= ~FMC_CTL_SER;
    }

    return fmc_state;
}

 FMC还提供 扇区擦除、块擦除,这里不详细说明了。


总结

  • 5
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值