只读分享解决方案文档调试&解决方案📅 2026-09-21🔖 Rev 1.0⏳ 29天有效(至 2026-10-31)
🔧解决方案&应用市场分析 -> 调试&解决方案 -> 存储_量产问题排查 -> 分区错位_坏块跳过不一致_量产排查

分区错位_坏块跳过不一致_量产排查

生成时间 2026-09-28 13:34:51 有效期至 2026-10-31 23:59:59(29天有效(至 2026-10-31))
同系列 · 调试&解决方案

分区错位 · 坏块跳过不一致 · NAND 类器件量产排查手册

编制日期 2026-09-21 | 版本号 Rev 1.0

XTX 芯天下 · FAE 现场技术文档 | 面向 SPI NAND / PPI NAND(并行 NAND)/ SD NAND / eMMC 裸片量产烧录 | 2026-09 版

技术事实核查纪律(执行前必读)

分区布局、坏块表位置、ECC 强度与算法以具体平台驱动代码与器件 datasheet 为准;本文仅展示机制。

  • 本文出现的所有地址、偏移、块号、字节数、ECC 纠正能力均为说明机制的示例,动手前必须逐项与器件 datasheet 和目标平台驱动代码核对,不得直接照抄。
  • NAND 类器件(SPI NAND / PPI NAND / SD NAND / eMMC)出厂自带坏块是行业常态,出厂坏块上限与标记方式以 datasheet 为准;发现坏块不等于来料不良,本文不讨论坏块本身,只讨论「两侧对坏块的理解不一致」。
  • 整片擦除、重烧、坏块表重建三类操作会永久破坏现场数据,执行前必须先完成坏块信息导出与镜像留证(见第 12.4 节)。
  • 平台相关术语(UBI / PEB / LEB、MBR / GPT、BBT、OOB、spare、BCH)在不同 SDK 中命名与含义并不统一,以所用 SDK 源码与文档为准。
  • 同一现象在不同平台可能落到不同类目,本文给的是排查顺序与判据,不是结论清单。
2 类
高发量产问题的根
分区错位 + 坏块跳过不一致,通常合并出现
3 层
必须逐层对齐的错位层
分区布局 · 坏块表 · ECC + spare
7 类
根因归类
表错位 / 镜像偏移 / 跳过分区 / 标记位置 / 建表机制 / 跳过策略 / ECC
2 视角
必须完全对齐的两侧
烧录器裸片视角 vs 系统驱动运行视角
4 方
联合确认 SOP 的参与方
固件 · 分区表 · 坏块策略 · ECC 配置

一句话结论:「烧录通过但系统找不到数据 / 文件系统挂不上」几乎从不意味着芯片坏了。 它的本质是烧录器的裸片视角(烧什么地址 → 写什么内容)与系统驱动的运行视角 (哪个逻辑块号 → 哪个物理块号、ECC 由谁算)没有完全对齐。 烧录器的 Verify PASS 只证明「你让它写的字节,它读回来是一样的」——它既不认识你的分区表, 也不认识驱动里的 BBT 和 ECC 布局。

这份文档解决什么

解决的是 NAND 类器件(SPI NAND、PPI NAND、SD NAND、eMMC)在量产裸片烧录阶段, 校验 100% 通过、装板后却「找不到数据」或「文件系统挂不上」这一类问题的定位与根治方法。 全文把问题拆成三层、七个类目,每一类都按「机制 → 判据 → 立即动作 → 根治动作」四段给出。 第 10 章是可直接翻查的速查表,第 11 章是可带进车间的四方联合确认 SOP,第 12 章是可复制的清单与模板。

需要说清楚的是:本文档讨论的不是「坏块本身」,而是「两侧对坏块与分区的理解不一致」。 NAND 出厂自带坏块是行业常态,不是来料质量问题;把坏块当成故障去换料,只会让真正的不一致继续留在产线上。

类 1
分区表错位
分区起点 offset 不一致、分区尺寸没对齐擦除块边界、单位在 MB / sectors / 块号之间混用。烧录器按 A 表写,驱动按 B 表找,两个表不是同一份。
高发动作:手工改过一边的分区表
类 2
分区内镜像偏移错位
bootloader / kernel / fs 的起始地址算错:镜像自带 header、容器头、坏块空洞没有被算进去,或者烧录器把整镜像从分区起点写,驱动却到分区起点 + N 去找。
高发动作:换镜像格式不改偏移
类 3
跳过的分区选错
烧录器的跳过策略只作用于 system 区,驱动的 BBT 只覆盖 user 区。一个少跳一块、一个多跳一块,交界处物理块号整体错开。
高发动作:跳过范围按默认配置
类 4
坏块标记位置不一致
标记写在哪:block 内第 1 个 page 的 spare 首字节、前两个 page 的 spare、还是 main 区首字节。两侧约定不同,同一颗坏块在一边是坏块、在另一边是好块。
高发动作:擦除时把标记一起擦掉
类 5
坏块表重建机制不同
烧录器自己扫一遍建 BBT,驱动上电再扫一遍建 BBT;两遍扫描的标记约定、时序、ECC 状态只要有一项不同,结果就对不上。表落不落盘、落在哪,又是第三个变量。
高发动作:两边各建各的,从不比对
类 6
跳过策略不一致
BBT 表驱动跳过、顺序顺延跳过、预留块替换、靠 ECC 硬扛不跳过——四种策略可以共存于一套系统,但同一段地址空间只能由一种主导。
高发动作:默认策略两边不同
类 7
ECC 强度与位置不一致
强 ECC 烧入、弱 ECC 读出(或反之);ECC 字节在 spare 区的位置不同;驱动把写入侧的 ECC 字节当成被保护数据一起算校验。表现为 uncorrectable 刷屏,空白页也报错。
高发动作:烧录器默认开 ECC

怎么用这份文档

  1. 先用可观测现象定层:能不能读到卷头 / Superblock、报不报 ECC 错误,据此落到第 2 章的三层之一,不要一上来就换芯片。
  2. 在层内定位类目:第 3~9 章每章一类,每章开头都有「判据」,用判据筛掉不符合的类目,而不是逐个试。
  3. 一次只改一个变量:分区偏移、坏块策略、ECC 配置每次只动一处,改完全片重烧、装板实跑,禁止叠加修改。
  4. 两侧各导出一份证据再比对:烧录器侧的分区表与坏块清单、驱动侧的分区表与坏块清单,逐行 diff,不要靠记忆判断。
  5. 用装板实跑闭环:任何配置变更,最终判定以「首件装板跑通 + 断电重启通过 + 抽检与首件一致」为准。

1. 问题本质:两套视角的不一致

分区错位与坏块跳过不一致,通常不是两个独立故障,而是同一件事的两个出口: 烧录器对这片介质的理解,与目标系统驱动对这片介质的理解,不是同一套。 本章先把两套视角并排放出来,再讲清楚为什么这两类问题会结伴出现、以及为什么它最容易被误判成器件不良。

1.1 共同根因:烧录器看物理,驱动看逻辑

烧录器在裸片状态下工作,它拿到的是一整片连续的物理地址空间,动作是「你把镜像给我、 告诉我写到哪个地址,我就写过去,遇到坏块按配置处理」。 系统驱动在运行时工作,它拿到的是逻辑块号,动作是「上层要第 N 个逻辑块, 我去查 BBT,把它映射到某个物理块,再用硬件 ECC 引擎校验」。

这两个视角各自都自洽,但它们的接口处没有任何强制校验——烧录器不认识驱动的分区表, 驱动也不知道烧录器跳过的是哪几个块。只要两侧的配置不是同一份,错位就必然发生,而且校验 100% 通过。

① 烧录器:裸片视角·我面对的是一整片连续的物理地址空间没有分区概念,只有地址·我把镜像写到外部指定的物理地址这张表从哪来,我不校验·遇到坏块按工程配置跳过或不跳跳过后,后面的内容整体后移·ECC 由我算,或按配置完全不算取决于烧录工程怎么配·我校验的是:读回字节 == 源镜像Verify PASS 就交差校验口径:读回字节 == 源镜像② 系统驱动:运行视角·我面对的是逻辑块号 LBA,不是物理地址物理块号是我自己算出来的·我按驱动里的分区表把 LBA 落到某偏移这张表来自设备树或分区定义·我按 BBT 做逻辑块到物理块的映射BBT 由我扫出来或从固定位置读·ECC 由 SoC 硬件引擎算,我定覆盖范围强度与布局写死在驱动里·我校验的是:ECC 能过、卷头能找到卷头找不到就 mount 失败校验口径:ECC 能过 + 卷头能找到必须完全对齐对齐失败的两个出口分区布局错位系统找不到数据:卷头 / Superblock 不在驱动预期的偏移坏块表不一致文件系统挂不上:逻辑块号被映射到错误的物理块
图 1 · 烧录器裸片视角与系统驱动运行视角的六项差异

1.2 逐项对照:六个维度,每一个都可能错位

把两套视角拆成六个维度逐项对照,是定位问题的起点。现场绝大多数「说不清哪里错了」的案例, 都能在这张表里找到对应的那一行。

维度烧录器(裸片视角)系统驱动(运行视角)对不齐的后果
看待介质的方式一整片连续物理地址空间逻辑块号 LBA,需要映射分区错位的源头
分区信息从哪来外部导入的分区表 / 工程配置设备树 / 分区定义 / MBR-GPT分区起点与尺寸对不上
遇到坏块怎么办按工程配置跳过(或不跳)按 BBT 做逻辑块 → 物理块映射坏块跳过不一致
ECC 由谁算烧录器软件算 / 或完全不算SoC 硬件 ECC 引擎算不可纠错误刷屏
OOB / spare 归谁用烧录器按工程配置填驱动按 spare 布局取校验字节互相破坏
校验口径读回字节 == 源镜像ECC 能过 + 卷头能找到校验通过但系统挂不上

1.3 校验通过,到底证明了什么

这是全文最关键的一张表。烧录器的校验(Verify)本质是把写进去的内容读回来与源镜像逐字节比对, 它检验的是「数据搬运」这一件事;而系统能否找到数据、能否挂载,取决于驱动侧的「数据解释」规则。

校验通过能证明校验通过不能证明由谁决定
烧录器缓冲区里的数据与源镜像逐字节一致目标系统能找到这些数据驱动分区表 / 卷头位置
每个被写的页都编程成功分区起点与驱动期望的一致分区表是否同一份
烧录器按自己的策略处理了坏块驱动按同一策略处理了同一批坏块坏块标记位置 + 跳过策略
写进去的 ECC 字节与烧录配置一致驱动侧算 ECC 的方式与之一致ECC 生成方 / 强度 / 位置
这一颗在烧录器上能跑这一颗装到目标板上能跑装板实跑
这一颗能跑这一批 / 这个料号 / 这个批次都能跑首件确认 + 装板抽检

1.4 为什么这两类问题总是一起出现

分区错位与坏块跳过不一致之所以高发合并出现,是因为它们之间有一条直接的因果链:

  1. 烧录器跳过坏块 → 被跳过的块之后,所有内容在物理上整体后移;
  2. 分区表的 offset 是按「没有坏块」算出来的 → 于是每个分区的物理起点都被推后了若干个块;
  3. 驱动不知道烧录器跳过的是哪几个块 → 它只能按自己的 BBT 与分区表重新算一遍;
  4. 两套算法的结果差若干个块 → 分区错位;同时逻辑块号映射到错误物理块 → 坏块跳过不一致;
  5. 而这个差值随每一片的坏块分布不同而不同 → 同一工程下 A 片能起来、B 片起不来。
最容易误判的一点:逐片不同的症状不是器件不良的证据

现场最常听到的一句判断是「同一批片子有的能起有的不能起,所以是来料不良」。这个推论不成立:坏块分布逐片不同 → 跳过量逐片不同 → 物理错位量逐片不同 → 症状逐片不同,这恰恰是「两侧不一致」的典型指纹,而不是器件质量问题的指纹。

真正的证据只有一种:把能起的那片与不能起的那片各导出一份坏块清单与分区布局,逐行比对差异在哪一行。差异落在哪一行,就对应第 3~9 章的哪一类。

1.5 出厂坏块是行业常态,不是质量问题

这是本文档要纠正的第一个直觉。NAND 工艺决定了器件在出厂时就存在一定比例的坏块, datasheet 会给出出厂坏块数量上限与标记方式(具体数值与标记位置以 datasheet 为准)。 厂商在出厂前已完成标记与筛选,用户侧要做的不是「消灭坏块」,而是正确识别并一致地跳过。

关于出厂坏块的三条事实
  • NAND 出厂时即存在一定比例坏块,属工艺常态;出厂坏块数量上限与标记方式以器件 datasheet 为准。
  • 出厂坏块在出厂前已被标记(标记位置遵循器件规范),用户侧只需正确识别并跳过,不应尝试擦掉标记重用。
  • 使用过程中还会产生新的坏块,由驱动在运行期识别与管理;这类坏块的处理策略属于驱动行为,必须与烧录侧的静态策略区分开看。
贯穿全文的一条纪律

「烧录通过 ≠ 找得到数据」。只要现象是「校验 100% 通过但系统找不到数据或挂不上」,就不要把时间花在怀疑芯片质量上——先去对齐两侧的规则。现场统计里,器件本体不良的概率远低于配置不一致的概率。

2. 三层错位总览(决策树)

七个类目不是并列的七种故障,而是分布在三个层次上。 先定层、再定类,可以把排查路径从「七选一」缩短到「三选一,再三选一」。 本章给决策树与三层的对齐对象,后面七章每一章对应树上的一个叶子。

2.1 决策树:从现象到类目

树根是共同的现象——烧录通过,但系统找不到数据或挂不上。 往下分三条枝,分别对应三个层次;每条枝上是该层内的具体类目。 每个层面板底部有一块「判据」,先读判据:符合哪一块的判据,就进哪一层。

烧录通过,但系统找不到数据或挂不上分区布局层错位本质:写在哪 ≠ 找在哪类 1 · 分区表 offset 不一致分区起点、尺寸、单位三项中任一对不上类 2 · 分区内镜像偏移错位bootloader / kernel / fs起始地址算错一层类 3 · 跳过的分区选错烧录器跳 system,驱动跳 user交界处整体错开判据容量对、能读、能写,但卷头 / Superblock 不在驱动预期的偏移上坏块表层错位本质:跳过的块 ≠ 记录的块类 4 · 坏块标记位置不一致spare 首字节 vs main 首字节同一块两边结论相反类 5 · 坏块表重建机制不同烧录器自建 vs 驱动运行时建两遍扫描结果对不上类 6 · 跳过策略不一致BBT / 顺序跳过 / 预留块同一段地址两套主导判据同一片换台烧录器或换个驱动,结果就变;坏块清单两边长度不等ECC + spare 层错位本质:算 ECC 的不是同一个人类 7 · ECC 强度不一致强 ECC 烧入,弱 ECC 读出或反过来类 7 · ECC 字节位置不一致写入侧与读出侧 spare 布局落在不同字节区间类 7 · 保护范围不一致驱动把 spare 前几字节也算进被保护数据判据uncorrectable 刷屏,连空白页也报 ECC 错;换片不换配置症状一致三层不是三种故障,而是同一份数据被三套规则解释;排查时先定层,再在层内定类。定层的唯一依据是可观测现象(能不能读到卷头、报不报 ECC),不是经验猜测。
图 2 · 分区错位与坏块跳过不一致的三层决策树

2.2 三层的对齐对象与拍板方

三层各自的对齐内容、配错后的暴露点、以及由谁拍板,都不一样。 这张表的用法是:先确定争议属于哪一层,再去找对应的责任方对齐, 不要跨层协商——跨层协商的典型结果是谁都觉得自己没错。

层要对齐什么配错后的暴露点由谁拍板
分区布局层
(类 1~3)
分区起点 offset、分区尺寸、单位、是否对齐擦除块 / PEB 边界卷头 / Superblock 读不到;mount 失败;能读到数据但内容错固件 + 烧录工程
(同一份分区表)
坏块表层
(类 4~6)
坏块标记位置、建表方、跳过策略、BBT 落盘位置与格式逻辑块号映射到错误物理块;ECC 报错;同一片换工具结果就变驱动 + 烧录工程
(同一份坏块清单)
ECC + spare 层
(类 7)
ECC 生成方、纠正强度、算法、字节在 spare 中的位置、覆盖范围uncorrectable 刷屏;空白页也报错;换片换工具症状不变SoC 硬件 + 驱动
(同一份 ECC 配置)

2.3 分层的三条纪律

  • 先定层,再定类。跳过分层的直接后果是在七个类目之间反复横跳,每类都改一遍, 最后连原本能跑的配置也改坏了,现场再也回不到基线。
  • 每层只认一份数据源。分区布局认分区表,坏块认坏块清单,ECC 认配置项; 三份都必须版本化归档,且烧录侧与驱动侧引用的是同一个文件、同一个版本。
  • 改完必须回到基线上验证。任何一层的变更都要全片重烧 + 装板实跑, 禁止在「上一次改动还没验证」的状态上继续叠加第二次改动。
最容易踩的一条直觉错误:把三层混在一起调

现场最常见的低效排查是这样进行的:先怀疑坏块,改一次跳过策略;没好,再怀疑偏移,改一次分区表;还没好,又怀疑 ECC,改一次强度。三次改动叠加后,即使问题被碰巧解决,也没人知道是哪一次起的作用,下次换料号还会重来一遍。

正确的做法是:用第 2.1 节的判据先定层 → 在该层内用第 3~9 章的判据定类 → 只改那一处 → 全片重烧 → 装板实跑 → 通过后再归档配置快照。

3. 第 1 类:分区表错位

分区表错位是三类分区问题里最基础的一类:烧录器按 A 表写,驱动按 B 表找,而 A 与 B 不是同一份。 它有三种典型形式——起点 offset 不一致、尺寸没对齐擦除块边界、单位混用。三者可以同时存在。

3.1 机制:写在哪与找在哪不是同一张表

烧录器工作时需要的只是「镜像文件 + 起始地址」,它不会去校验这张分区表是不是驱动要用的那张。 驱动侧的分区定义来自设备树、分区表分区(MBR / GPT)或内核命令行,同样不会去问烧录器。 两边各拿各的表,只要这两份表在某个边界上差了一点点,后续所有分区的物理位置就整体错位。

① 烧录器(按表 A 写)② 驱动(按表 B 找)SPLenvkernelrootfsuser0x00x400000x800000x2800000x680000SPLenvkernelrootfsuser0x00x400000x600000x2800000x600000Δ1Δ2Δ3Δ4Δ1~Δ4:四处边界全部对不上;三类错位与它们的直接后果offset 不一致分区起点差几个块卷头就永远读不到尺寸未对齐擦除块分区边界没落在block / PEB 边界上单位混用MB / sectors / 块号三者换算差一个量级
图 3 · 分区表 A 与分区表 B 的 offset 错位示意

3.2 三种错位形式的对照

错位形式典型表现高发原因立即动作
分区起点 offset 不一致卷头 / Superblock 在预期偏移读不到;能读到数据但内容明显错位分区表版本不同;一边手工改过;单位不同导致换算偏差两侧各导出一份分区表逐行 diff,统一到字节再比
分区尺寸未对齐擦除块边界能读但写入报错;UBI attach 失败;分区尾部数据丢失按 MB 取整,没有按 block / PEB 大小对齐所有边界按块大小向上取整对齐(块大小以 datasheet 为准)
单位混用:MB vs sectors vs 块号偏移差一个数量级,或正好差 512 倍 / 1024 倍一边用 1000 进制一边用 1024 进制;扇区号与字节地址混写分区表内部一律用字节;MB / sectors 只在展示层出现

3.3 立即动作

  1. 两侧各导出一份分区表,逐行 diff。烧录器侧从工程配置导出,驱动侧用 cat /proc/mtd 与设备树 / 分区定义交叉核对;两份表的字段必须能一一对应。
  2. 统一到字节。把所有 start / size 换算成字节再比对,避免单位差异掩盖真实差异。
  3. 把所有边界向上对齐到擦除块 / PEB 边界。这一步要按器件 datasheet 的块大小与平台 PEB 大小来算。
  4. 确认分区表是同一份文件。固件侧与烧录侧必须引用同一个版本化文件,不允许各存各的副本。
  5. 改完全片重烧,装板实跑验证。只看烧录器校验通过不算数。
单位混用是最隐蔽的一种:它的特征是「差得很整齐」

单位错位的典型指纹是偏差恰好是某个整数倍:正好差 512 倍(sectors 与 bytes 混用)、正好差 1.024 倍(1000 进制与 1024 进制混用)、正好差一个块大小(块号与字节混用)。

出现这种「整齐的偏差」时,先怀疑单位,不要先怀疑器件。这一条能省下大量换料、送检的时间。

铁律:分区表内部一律用字节;MB / sectors / 块号只允许出现在给人看的展示层,且必须在表头显式标注换算基数。

3.4 分区表模板

第 12.2 节给了一份可直接复制的分区表模板,核心是强制用字节做单位、强制标注对齐基准、强制标注 ECC 与坏块策略三列。 把这三列写进模板,可以让「单位混用」这类错误在评审阶段就被拦住,而不是等到产线。

4. 第 2 类:分区内镜像偏移错位

分区起点对了,不代表镜像在分区内部的位置也对。 bootloader、kernel、fs 三段各有各的偏移来源,而且这些偏移是叠加的: 分区表给的起点只是一层,镜像自带的 header / 容器头是第二层,坏块跳过留出的空洞是第三层。

4.1 机制:偏移是三层叠加的

现场最常见的错误是只盯最终地址:把分区起点调来调去,试图用一个数把三层偏差全补回来。 这在某些片上能对上(因为那几片恰好没有坏块),换一片就失效——因为第三层偏差是逐片变化的, 而第一、二层是固定的,用一个固定数去补一个变量,必然只能对上一部分片子。

① 分区表给的起点(示例 P = 0x80000)P = 0x80000(示例)本分区之前的空间② 分区内镜像偏移(分区内视图,示例 +0x400)header镜像 payload 从这里才开始+0x400③ 坏块跳过导致的物理后移(分区内视图,示例 +2 block)跳过的坏块 ×2镜像内容从这里才开始+2 block数据实际所在 = P + A + B三层偏移叠加后的最终物理地址驱动去找 = P + A'(不知道 B)少算一层,就永远差若干个块Δ = 2 个块:驱动每次都差两个块,且这个差值随每一片的坏块分布不同而不同(示例数值)排查时必须逐层验证:只看「最终地址对不对」,无法定位到底是哪一层错了。
图 4 · 分区内镜像偏移是三层偏移叠加的结果

4.2 三段的偏移来源与判据

段偏移的常见来源错位的典型原因判据
bootloader / SPL分区起点 + 镜像头(IVT / DCD / 容器头等,格式与长度以平台手册为准)烧录器把整镜像从分区起点写,驱动却到「分区起点 + 头长」去找SPL 能跑起来,但读不到下一级;或 BootROM 直接报找不到镜像
kernel / 内核分区起点 + 容器头 + 坏块跳过留出的空洞被跳过的坏块数没有被算进偏移;换片后坏块数变了,偏移就变了kernel 起一半挂掉;或长时间等待根设备
fs / 根文件系统分区起点(UBI 层在自己管理 PEB 到 LEB 的映射)分区起点没有对齐 PEB;或卷头位置与驱动期望不符UBI attach 失败;报空卷;报坏 PEB

4.3 判据采集命令

下面这组命令的用途是把驱动侧认定的分区与偏移取出来,与烧录器工程里的配置逐项比对。 命令名与输出格式随平台与内核版本而变,以所用系统的实际输出为准。

# 驱动侧视角:把分区与偏移取出来(命令与输出以所用平台 / 内核版本为准)
cat /proc/mtd          # 驱动侧看到的分区起点与大小(十六进制字节)
cat /proc/partitions   # 块设备视角的分区(注意:单位是块,不是字节)
mtdinfo /dev/mtd2      # 该分区的擦除块大小、最小 IO 单位、OOB / spare 大小
ubinfo  /dev/ubi0      # UBI 视角:PEB / LEB 数量与大小、可用块数

# 烧录器侧视角:把工程里的分区表导出成同样的字段
# 重点核对三列,必须完全一致:
#     start(hex byte)      size(hex byte)      eraseblock / PEB size
# 任何一列不一致,先回第 3 章解决分区表,不要继续调镜像偏移

# 比对模板(两侧各存一份,用 diff 看差异)
diff prog_partition.txt  drv_partition.txt
不要用一个固定数去补一个变量

把分区起点硬调若干个块,是现场最高频的临时手段,也是最容易埋雷的手段:它在没有坏块落在关键分区里的那批片子上是有效的,一旦换一片、换一批料,坏块分布变了,这个补偿量就错了。

正确的处理顺序是:先让两侧用同一份分区表(第 3 章),再让烧录器与驱动用同一套坏块策略(第 6~8 章),最后才谈镜像内部的 header 偏移。把这个顺序反过来做,问题一定会复发。