3. RH850存储子系统与Flash操作

RH850 的片上非易失存储并不是“一块 Flash”这么简单。以常见的 RH850/F1x、RH850/P1x 系列为例,内部至少包含两类物理独立的 Flash:Code Flash(代码 Flash,CFlash)和 Data Flash(数据 Flash,DFlash)。二者在工艺结构、擦写单位、寿命、访问方式上都有明显差异,Bootloader 与整车刷写系统必须分别对待。理解这套存储子系统的分层关系,是后续设计刷写流程、DFlash 模拟 EEPROM 以及寿命管理的前提。

Code Flash 与 Data Flash 的定位差异

Code Flash 用于存放程序代码、常量表和中断向量,容量通常从几百 KB 到数 MB,按块(Block)组织,擦除单位较大(常见 2 KB、4 KB、8 KB 甚至更大),编程单位则较小(如 4 字节、8 字节或按页)。它的读取走 CPU 取指通道,支持高速缓存与预取,但写入和擦除必须通过 Flash 自编程控制器(如 RH850 的 FACI:Flash Access Control Interface)完成,且执行擦写时通常不能从同一 Flash 取指,需要把擦写例程搬到 RAM 中运行。

Data Flash 容量小得多,典型为 32 KB、64 KB,专门用于存放标定数据、故障码、里程、配置参数等需要频繁更新的数据。它的擦除单位更小(常见 64 字节或 128 字节),编程单位也更细,因此更适合“小数据、多次写”的场景。DFlash 模拟 EEPROM 正是利用 Data Flash 的小擦除粒度,通过软件层把 Flash 的“先擦后写”特性封装成类似 EEPROM 的按字节/按记录读写接口。

关键区别:Code Flash 追求容量与取指性能,擦写粒度大、寿命相对低;Data Flash 追求小粒度更新与高擦写次数,适合承载参数与模拟 EEPROM。

擦写单位、寿命与参数关系

Flash 的寿命以擦写次数(Erase/Write Cycles)衡量。Code Flash 典型保证 1 万~10 万次擦写,Data Flash 可达 10 万~100 万次。寿命不是按“字节写次数”算,而是按块擦除次数算——哪怕只改一个字节,也要擦除整个块。因此 DFlash 模拟 EEPROM 的核心任务之一,就是通过磨损均衡(Wear Leveling)把写操作分散到不同块,避免单块提前耗尽。

擦写时间也是重要参数:块擦除通常几毫秒到几十毫秒,编程每字节约几微秒到几十微秒。Bootloader 在刷写时必须按块计算总时间,并留出安全余量。下面这张图给出 RH850 存储子系统的结构关系与访问路径,帮助建立整体认识。

RH850 存储子系统结构与访问路径 CPU 内核 取指 / 数据访问 FACI 控制器 Flash 自编程接口 RAM 擦写例程运行区 寄存器 搬移 Code Flash (CFlash) 程序代码 / 常量 / 中断向量 擦除单位:2~8 KB / 块 编程单位:4~8 字节 寿命:约 1 万~10 万次 Data Flash (DFlash) 标定 / 故障码 / 配置参数 擦除单位:64~128 字节 编程单位:1~4 字节 寿命:约 10 万~100 万次 DFlash 模拟 EEPROM 软件层 磨损均衡 · 记录映射 · 掉电保护 对外提供按记录读写接口 底层仍按 64/128 字节块擦除 Bootloader 关注点 按块擦除、按页编程 擦写例程搬 RAM 执行 校验和 / 签名验证完整性

驱动接口与操作流程

在 RH850 上操作 Flash,通常通过 FACI 提供的寄存器接口完成。以擦除一个 Code Flash 块为例,典型步骤是:先向 FACI 写入擦除命令序列(如 0x20 → 0xAA → 0x55 之类的解锁序列,具体以芯片手册为准),再指定块地址,然后启动擦除并轮询状态寄存器直到完成。编程时则先写命令,再按编程单位写入数据,最后确认状态。整个过程必须保证供电稳定,否则可能产生坏块。

DFlash 模拟 EEPROM 的驱动接口一般对外暴露 EEP_Read、EEP_Write、EEP_Init 等函数。内部实现时,每条记录包含数据区、记录 ID、校验字段和状态标志。写入时先找空闲记录槽,写入新值并标记有效,再擦除旧记录;当块内记录写满后,触发块擦除与数据搬移。这样对外表现为“可反复写”,对内则把擦除次数摊到多个块上。

/* 示例:DFlash 模拟 EEPROM 记录结构(教学示例,非实测) */
typedef struct {
    uint16_t recordId;      /* 记录标识 */
    uint8_t  data[16];      /* 有效数据 */
    uint16_t crc;           /* 数据校验 */
    uint8_t  status;        /* 0xFF=空, 0xAA=有效, 0x00=废弃 */
} EepRecord_t;

/* 写入流程示意 */
Eep_Write(id, buf, len):
    1. 查找 status==0xFF 的空闲槽
    2. 写入 recordId、data、crc,status=0xAA
    3. 将旧记录 status 置 0x00
    4. 若空闲槽不足,触发块擦除与搬移

寿命估算与工程取舍

假设某 DFlash 块容量 64 字节,模拟 EEPROM 每 10 秒写一次里程,每次写 16 字节记录。若不做磨损均衡,单块约 10 万次擦写,10 秒一次则约 11.6 天就会耗尽。引入 8 块轮换后,理论寿命延长到约 93 天;若再配合“仅变化时写入”和“按需合并”,可进一步延长。这说明磨损均衡不是可选项,而是 DFlash 模拟 EEPROM 的必备机制。

工程建议:Code Flash 刷写按块规划,预留至少一个备份块用于回滚;DFlash 模拟 EEPROM 至少使用 4~8 个块轮换,并记录每块擦除计数,便于诊断寿命。
注意:Flash 擦写期间若发生掉电,可能导致块处于不确定状态。Bootloader 应在刷写前保存进度标记,上电后先检查标记再决定继续或回滚,避免变砖。

总结来看,RH850 存储子系统的核心是“两类 Flash、不同粒度、不同寿命、统一由 FACI 控制”。Code Flash 服务于代码刷写,Data Flash 服务于参数与模拟 EEPROM。Bootloader 与整车刷写系统必须按块管理擦除、按页管理编程、按记录管理 DFlash,并把寿命与掉电保护纳入设计,才能保证刷写可靠、参数持久。