1. GD32 FMC闪存控制器基础解析
第一次接触GD32的FMC控制器时,我盯着数据手册发呆了半小时——寄存器名称像密码一样难懂,操作流程复杂得像迷宫。但真正用起来才发现,这套控制器设计得非常巧妙。FMC(Flash Memory Controller)是GD32内部专门管理闪存读写的模块,相当于电脑的硬盘控制器,只不过嵌入式场景下我们需要手动配置每个细节。
以常用的GD32F4系列为例,芯片上电后FMC默认处于锁定状态,就像保险箱上了密码锁。要操作闪存必须先解锁,这个设计防止了程序跑飞时误修改关键数据。解锁方法很有意思:需要向FMC_KEY寄存器连续写入两个特定数值(0x45670123和0xCDEF89AB),就像转动密码锁的左右旋钮。我曾在项目里犯过低级错误——忘记检查FMC_CTL寄存器的LK位状态,结果在已解锁状态下重复解锁导致硬件异常。
闪存组织结构也很有特点。不同于RAM的均匀分布,GD32的Flash被划分为不同大小的扇区(16KB/64KB/128KB),就像一本书被分成不同章节。例如GD32F450系列:
- 前4个扇区各16KB(0-3)
- 接着1个64KB扇区(4)
- 剩余空间都是128KB扇区(5-11)
这种设计带来一个实际影响:擦除时必须整扇区操作。有次我需要保存10KB的配置数据,直接放在第一个16KB扇区开头。后来发现每次更新配置都要擦除整个16KB区域,不仅耗时还影响闪存寿命。解决方案是改用最后128KB扇区,划分多个4KB页来存储(部分型号支持页擦除)。
2. 闪存操作实战三部曲
2.1 解锁与配置技巧
解锁操作看似简单,但实际项目中有几个坑我踩过多次。首先是时序问题——两次密钥写入必须连续完成,中间不能插入其他操作。我曾因为在这之间加了调试打印语句导致解锁失败。正确的做法应该是:
void safe_fmc_unlock(void) {
__disable_irq(); // 关闭中断确保原子操作
if(FMC_CTL & FMC_CTL_LK) {
FMC_KEY = 0x45670123;
FMC_KEY = 0xCDEF89AB;
}
__enable_irq();
}
另一个容易忽略的是选项字节(Option Bytes)的解锁。当需要修改写保护配置或读保护等级时,必须单独解锁FMC_OBCTLx寄存器:
void ob_unlock(void) {
FMC_OBKEY = 0x08192A3B; // 第一组密码
FMC_OBKEY = 0x4C5D6E7F; // 第二组密码
}
2.2 数据读取的优化策略
直接指针访问是最简单的读取方式,但在实际项目中可能会遇到效率问题。比如需要读取大量数据时,使用字节逐个读取的方式会非常慢。这时可以采用DMA配合FMC的方案:
void flash_to_ram_dma(uint32_t


3297

被折叠的 条评论
为什么被折叠?



