4. MCX存储器映射与Flash编程模型

MCX系列MCU内部集成Flash控制器(Flash Memory Controller,FMC),它并不是一块“可以直接按字节写”的存储器,而是一个需要按命令序列驱动、按扇区/页粒度擦写、并受ECC与RWW约束的外设。理解存储器映射与编程模型,是后续生产烧录、校验、量产脚本设计的基础。

一、存储器映射:地址空间与访问属性

以MCX A系列(如MCXA153)为例,Flash主阵列通常映射在 0x0000_0000 起始的Code空间,同时通过别名地址(Alias)映射到 0x1000_0000 附近,便于在Boot ROM与用户程序之间切换向量表。典型映射关系如下:

区域起始地址典型容量访问属性
Flash主阵列0x0000_0000512 KB读/取指,写需命令
Flash别名区0x1000_0000同主阵列读/取指
Boot ROM0x0300_000016 KB只读
SRAM0x2000_000096 KB读/写
外设寄存器0x4000_0000—读/写

需要特别注意的是:Flash的“写”并不是普通的总线写。对Flash地址执行STR指令不会直接修改内容,而是触发控制器错误或忽略。真正的编程必须通过FMC的命令寄存器(如 FCTL_CMD)与数据寄存器(FCTL_DATA)完成。

二、Flash命令序列:从解锁到完成

MCX的Flash控制器采用“命令+参数+执行+查询”的模型。一次完整的编程操作通常包含以下阶段:

  1. 解锁:向 FCTL_KEY 依次写入两个魔数(如 0xA5、0x5A),解除命令寄存器写保护。
  2. 选择命令:写入 FCTL_CMD,如页编程(0x02)、扇区擦除(0x03)、全片擦除(0x04)、校验(0x05)。
  3. 写入地址与数据:将目标地址写入 FCTL_ADDR,数据写入 FCTL_DATA(页编程需按字/双字连续写入)。
  4. 启动执行:置位 FCTL_CTRL[START],控制器开始内部时序。
  5. 查询状态:轮询 FCTL_STAT[BUSY],直到清零;同时检查 ERR、DONE 标志。

下面是一段典型的页编程命令序列(示例参数,非实测):

FCTL->KEY   = 0xA5;          // 解锁步骤1
FCTL->KEY   = 0x5A;          // 解锁步骤2
FCTL->CMD   = 0x02;          // 页编程命令
FCTL->ADDR  = 0x0000_8000;   // 目标页起始地址
for (i = 0; i < 32; i++) {   // 128字节页,按4字节写入
    FCTL->DATA = buf[i];
}
FCTL->CTRL |= FCTL_CTRL_START_MASK;
while (FCTL->STAT & FCTL_STAT_BUSY_MASK);
if (FCTL->STAT & FCTL_STAT_ERR_MASK) {
    // 编程失败处理
}

三、扇区/页擦写规则

Flash的物理结构决定了“擦除按扇区、编程按页”的基本规则。MCX常见配置为:扇区(Sector)2 KB,页(Page)128 B。擦除的最小单位是扇区,编程的最小单位是页。这意味着:

  • 要修改一个字节,必须先擦除其所在扇区,再重新编程整个扇区内容。
  • 页编程只能将位从1变为0,不能从0变回1;因此重复编程同一页而不擦除,会导致ECC错误。
  • 擦除后扇区内容为全1(0xFF),编程时按需将目标位清零。
注意:对未擦除的页执行编程,或对同一页重复编程,都会触发ECC校验失败,严重时可能锁死该扇区,只能通过全片擦除恢复。

四、ECC与RWW特性

MCX Flash内置ECC(Error Correcting Code)机制,通常采用SEC-DED(单错纠正、双错检测)。每次读取一个Flash字(如64位)时,控制器同时读取ECC校验位并实时校验:

  • 单比特错误:自动纠正,读取数据正确,但会置位 FCTL_STAT[SBC] 标志,可用于健康监测。
  • 双比特错误:无法纠正,触发总线错误或NMI,需通过异常处理记录故障地址。

RWW(Read-While-Write)指在编程/擦除一个扇区的同时,可以从另一个扇区读取代码或数据。MCX通常将Flash划分为多个RWW分区(如P0、P1),同一分区内不能同时读写,跨分区则可并行。生产烧录时,若Bootloader位于P0、应用区位于P1,就能实现“边写应用区、边执行Bootloader”的在线升级。

MCX Flash 编程模型与 RWW 分区示意 Flash 命令序列 ① 写 KEY 解锁 (0xA5,0x5A) ② 写 CMD 选择命令 ③ 写 ADDR / DATA ④ 置 START 启动 ⑤ 轮询 BUSY 清零 ⑥ 检查 ERR / DONE Flash 阵列结构 RWW 分区 P0 Sector 0 (2 KB) Sector 1 (2 KB) … Sector N RWW 分区 P1 Sector 0 (2 KB) Sector 1 (2 KB) … Sector M ECC 校验 单比特错 → 自动纠正 双比特错 → 总线异常 SBC 标志可监测 RWW 并行操作 P0:执行 Bootloader P1:擦写应用区 同分区不可同时读写 跨分区可并行 驱动 读取 分区

五、编程时序约束

Flash编程不是“写完立即生效”,控制器内部有严格的时序:

  • 页编程时间:典型值约 100 μs~200 μs(示例值,具体以数据手册为准),期间BUSY保持置位。
  • 扇区擦除时间:典型值约 20 ms~50 ms,远大于页编程。
  • 全片擦除:可达数百毫秒,量产时需预留足够超时。
  • 命令间隔:两次命令之间需等待BUSY清零,否则新命令被忽略。
  • 高压稳定时间:擦除/编程期间不能掉电或复位,否则可能产生半擦除状态,导致ECC异常。
生产烧录脚本中,建议对每个扇区擦除后增加一次“空读校验”(读回全0xFF),再执行页编程,最后做CRC或逐字节比对。这样可以把擦除不彻底、编程失败、ECC错误三类问题分开定位。

六、生产视角下的关键结论

把上述模型落到量产烧录上,可以归纳为几条工程约束:第一,烧录算法必须按扇区擦除、按页编程,不能假设可以“就地改写”;第二,擦除与编程期间要严格轮询BUSY,并设置合理超时;第三,若使用RWW做在线升级,Bootloader与应用区必须落在不同RWW分区;第四,ECC标志(SBC)可作为Flash健康度的早期指标,量产测试中可读取并记录;第五,任何掉电中断都可能留下半编程页,恢复流程应先擦除再重写,而不是直接补写。