4. 坏块表设计与存储

坏块表是星载存储系统可靠写入的“账本”。它记录哪些物理块已经失效、哪些块被保留、哪些块正在使用,以及这些状态在轨期间是否发生过变化。星载环境与地面消费级存储最大的不同在于:NAND Flash 出厂即可能存在初始坏块,在轨运行中还会因单粒子翻转、累积辐照剂量、擦写磨损继续产生新增坏块;同时,承载坏块表本身的存储介质也会受到辐射影响。因此,坏块表设计必须同时解决四个问题:结构如何组织、冗余如何备份、上电如何加载、在轨如何更新,并在此基础上对坏块表自身做抗辐射加固。

一、坏块表结构:主表 + 位图 + 校验

星载 NAND 常见页大小为 2KB 或 4KB,块大小为 128KB~512KB。以一片 4Gb(512MB)SLC NAND、块大小 128KB 为例,总块数为 4096 块。若每块用 1 字节记录状态,主表仅需 4KB,可放在一个页内。但工程上更常用“位图 + 状态字”的混合结构:

  • 位图区:每块 2 bit,编码 00=好块、01=保留块、10=已用块、11=坏块。4096 块共需 1024 字节。
  • 状态字区:对坏块额外记录 4 字节信息,包括坏块编号、失效类型(出厂坏块/擦写失败/ECC 超限/辐射翻转)、首次标记时间戳、累计擦写次数。
  • 校验区:对整个坏块表计算 CRC32 或 BCH 校验码,用于上电加载时判断表体是否被辐射翻转。

这种结构的好处是:位图区可快速扫描定位可用块,状态字区保留可追溯的失效原因,校验区保证表体完整性。位图区与状态字区应放在同一页或相邻页,避免跨页读取时因单页失效导致表结构撕裂。

二、冗余备份:三副本 + 版本号

坏块表不能只存一份。推荐采用“三副本 + 版本号 + 独立校验”的冗余策略:主副本存放在专用元数据块,副本 A、副本 B 分别存放在不同物理块,且尽量分布在不同 NAND 芯片或不同 bank 上,避免单芯片失效导致三份同时丢失。每个副本头部包含:

  • 魔数(如 0x42425442,“BBTB”);
  • 版本号(单调递增,每次更新 +1);
  • 副本序号(0/1/2);
  • 表体长度;
  • 表体 CRC32;
  • 头部自身 CRC16。

上电加载时,依次读取三份副本,先校验头部,再校验表体,选择“校验通过且版本号最大”的副本作为有效表。若三份都校验失败,则进入安全模式,使用出厂坏块表作为兜底,并禁止写入新数据,等待地面干预。

坏块表三副本存储与上电加载流程 NAND 芯片 0 主副本 · 版本 v37 出厂坏块表(只读) NAND 芯片 1 副本 A · 版本 v37 副本 B · 版本 v36 NAND 芯片 2 副本 C · 版本 v35 备用元数据块 上电加载:读取三副本 → 校验头部 CRC16 → 校验表体 CRC32 → 选版本号最大且校验通过者 若三份均失败 → 进入安全模式,加载出厂坏块表,禁止新写入 在轨更新策略:先写新副本,再更新版本号,最后回收旧副本 ① 检测到新增坏块 → ② 在备用块写入新表(版本 v38)→ ③ 校验通过后标记为有效 ④ 更新主副本指针 → ⑤ 旧副本延迟回收,保留至少一个历史版本用于回滚 ⑥ 每次更新记录日志,包含时间戳、坏块编号、失效类型、操作结果

三、上电加载:校验优先,版本决胜

上电加载是坏块表可靠性的第一道关口。星载处理器上电后,Boot 程序应在初始化文件系统之前完成坏块表加载。具体流程如下:

  1. 依次读取主副本、副本 A、副本 B 的头部,校验魔数和头部 CRC16;
  2. 对头部合法的副本,读取表体并计算 CRC32,与头部记录值比对;
  3. 在通过校验的副本中,选择版本号最大者作为当前有效表;
  4. 将有效表加载到 RAM,并在 RAM 中维护一份“工作副本”,后续读写以 RAM 为准;
  5. 若三份均失败,加载出厂坏块表,置位“安全模式”标志,向上层报告故障。

这里有一个容易忽略的细节:版本号本身也可能被辐射翻转。因此版本号应采用“格雷码 + 冗余位”或“三取二”编码,避免因单比特翻转导致版本号跳变,从而误选旧表。例如版本号用 3 字节存储,每字节重复 3 次,读取时按位投票。

四、在轨更新:先写后换,保留回滚

在轨更新坏块表不能“原地覆盖”,否则一旦更新过程中断电或发生单粒子翻转,可能导致三份副本同时损坏。推荐采用“先写新副本,再切换指针,最后回收旧副本”的策略:

  • 当检测到新增坏块时,在备用元数据块中写入一份完整的新表,版本号 = 当前版本 +1;
  • 写入完成后,回读校验 CRC32,确认无误;
  • 更新主副本指针,使其指向新表;
  • 旧副本不立即擦除,保留至少一个历史版本,用于异常回滚;
  • 每次更新写入一条日志记录,包含时间戳、坏块编号、失效类型、操作结果。

更新频率也需要控制。若每检测到一个坏块就更新一次,会加速元数据块磨损。工程上可设置“批量更新阈值”:当新增坏块数达到 8 个,或距上次更新超过 24 小时,或系统进入安全模式前,才触发一次完整更新。这样既保证实时性,又降低擦写次数。

五、坏块表自身抗辐射加固

坏块表存放在 NAND 中,而 NAND 本身对总剂量和单粒子翻转都敏感。加固方法可分为存储层、编码层和系统层:

层级加固方法作用
存储层三副本分布在不同芯片/bank;元数据块采用 SLC 模式避免单点失效,提高擦写寿命
编码层表体 CRC32 + BCH(4144,4096) 纠错;头部 CRC16检测并纠正多位翻转
系统层RAM 工作副本定期回写;看门狗监控加载流程;安全模式兜底防止错误扩散,保证可恢复

此外,对坏块表中的关键字段(如版本号、坏块计数)可采用三模冗余:在 RAM 中维护三份工作副本,每次读取时按位投票,写入时三份同时更新。若三份不一致,以多数值为准,并触发一次表体重建。对于时间戳等非关键字段,可只做 CRC 校验,不参与投票,以节省资源。

工程提示:坏块表更新日志建议单独存放在一个只追加的日志块中,日志块写满后整体擦除并迁移。日志本身也应带 CRC,且日志块不计入坏块表的“可用块”统计,避免日志写入影响正常数据块管理。

综合来看,坏块表设计的核心不是“记录坏块”这一动作,而是围绕“结构可校验、副本可恢复、加载可判断、更新可回滚、自身可加固”形成闭环。只有把坏块表当作与用户数据同等重要的元数据来对待,星载存储系统才能在长期在轨运行中保持可靠写入能力。