1. 目的与范围
本规范规定PPI NAND(Parallel Peripheral Interface NAND,即传统并行接口裸 NAND)软件层的设计约束与推荐实现,目标是:
- 正确实现CLE / ALE / CE# / WE# / RE# / R/B#(及可选 DQS)时序下的命令、地址、数据周期
- 规范HAL / NFC 控制器与驱动的职责边界(时序寄存器、位宽、EDMA、ECC 引擎)
- 保证读/编/擦可靠性(超时、R/B# + Status 双重确认、Fail 位、掉电安全)
- 正确处理坏块管理(BBM)、片上/主机 ECC(含8-bit 下 ≥6 bit 迁块标坏)、OOB/Spare
- 落实整页一次写入与Partial Page Program 次数限制(默认 ≤4)、块内顺序编程、擦后 Blank Check
- 控制物理擦写次数(软件防抖 / 磨损均衡 / 读干扰 scrub / FTL)
- 规范使用ONFI Parameter Page、Read ID、UID、OTP、WP# / 分区锁、Cache、多 Plane 等能力
- 落实SDR 保底与 NV-DDR/Toggle 防变砖、替换池耗尽降级、Boot 非 XIP
- 规范PPI NAND 与文件系统的分层选型、分区(重要性/频率隔离)、挂载与掉电策略
与 SPI NOR / SPI NAND / SD NAND 的本质差异(必须理解):
| 维度 | SPI NOR | SPI NAND | PPI NAND | SD NAND |
|---|---|---|---|---|
| 主机视角 | SPI 字节命令 | SPI 页 Cache 命令 | 并行总线命令周期(CLE/ALE) | SD 块设备 |
| 坏块 / ECC | 通常无 / 可选 | 主机 BBM + ECC | 主机 BBM + ECC(同裸 NAND) | 片内 FTL 完成 |
| 忙判定 | WIP(05h) | Feature C0h OIP | R/B# 引脚 + Status70h | DAT0 Busy / 令牌 |
| 发现参数 | SFDP | Feature + Param Page | ONFI Parameter Page / ID 表 | CID/CSD |
| 接口 | SPI/QSPI | SPI/QSPI | 8/16-bit IO + 控制线 | SD/SPI |
| 文件系统 | 可直挂友好 FS | 禁裸挂 FatFS | 禁裸挂 FatFS(同 SPI NAND) | 可挂 FatFS |
PPI NAND 与 SPI NAND 在阵列语义上高度一致(页编程、块擦除、坏块、ECC、FTL);差异几乎全在主机接口与命令组帧。本规范 BBM / ECC / FS 策略对齐《SPI NAND》,接口与 HAL 章节按并行总线展开。
不在本规范范围:PCB 走线与 DDR/Toggle 电气完整性细则、具体厂商扩展命令全表(以 Datasheet 为准)、完整 FTL 算法论文级细节、某一 SoC NFC 寄存器手册全文。
2. 术语与缩写
| 术语 | 说明 |
|---|---|
| PPI NAND | Parallel Peripheral Interface NAND;并行接口裸 NAND(相对 SPI NAND) |
| CLE / ALE | Command Latch Enable / Address Latch Enable;锁存命令或地址 |
| CE# / WE# / RE# | Chip Enable / Write Enable / Read Enable(低有效惯例) |
| R/B# | Ready/Busy#;忙时拉低,完成后释放为高(开漏常见,需上拉) |
| I/Ox | 双向数据总线;常见×8或×16 |
| DQS | 源同步数据选通(NV-DDR / Toggle 模式) |
| SDR / Async | 异步单数据速率接口(经典并行 NAND,本规范默认) |
| NV-DDR / Toggle | ONFI / Toggle 源同步高速模式 |
| NFC / EBI / FSMC | SoC 侧并行 NAND / 外部总线控制器(名称因芯片而异) |
| Page | 编程最小单位;常见 2KB+64B、4KB+128/218/224B 等(含 OOB) |
| Block | 擦除最小单位;常见 64/128/256 页 |
| Plane / LUN / Die / Target | 多平面/逻辑单元/Die/目标片选;影响并行与 CE# 选择 |
| Column / Row | 页内字节偏移 / 页号(含 Block+Page,多 Plane 含平面位) |
| OOB / Spare | 页外带区;ECC、坏块标记、FTL 元数据 |
| Status Register | 读状态命令(常70h)返回的 SR;含 Ready、Fail、WP 等 |
| Fail | Program Fail / Erase Fail 状态位(命名因厂而异) |
| ONFI | Open NAND Flash Interface |
| Parameter Page | ONFI 参数页(几何、时序、特性、CRC) |
| ECC 强度 | 每码字可纠正最大比特数;本规范默认示例8-bit |
| 位翻转阈值 | 可纠正错误达阈值时迁块;默认8-bit 下 ≥6 bit |
| PPP | Partial Page Program,同一物理页在两次 Erase 之间的部分编程次数 |
| BBM | Bad Block Management |
| FBBT | Factory Bad Block Table;由扫描 OOB 工厂标记生成 |
| BB Marker | 坏块标记:通常为 Block 内指定页 Spare 首字节非0xFF |
| 初始坏块率 | 出厂允许坏块比例,行业常见上限约2%总块数 |
| FTL / NFTL | Flash Translation Layer;向通用 FS 提供块设备抽象 |
| LBA | Logical Block Address |
| GC | Garbage Collection |
| tCLS/tCLH/tALS/tALH | 命令/地址建立与保持时间 |
| tWP / tWH / tRP / tREH | WE#/RE# 脉冲宽度与高电平时间 |
| tWB / tR / tPROG / tBERS / tRST | 命令后忙、读阵列、编程、擦除、复位时间 |
| tVSL / tPOR | 上电到允许命令的等待时间 |
| WP# | Write Protect 引脚;硬件写保护 |
| Cache Read / Program | 页缓冲流水命令,用于吞吐优化 |
| Copyback | 片内页搬移;默认禁止作用户迁移主路径 |
容量与几何换算约定:
- 软件内部统一用字节逻辑地址或(target, lun, plane, block, page, column);驱动层必须能互转
- 禁止把 PPI NAND 当成“按 4KB Sector 擦的 NOR”或“SD 块设备”来建模
- 禁止把 SPI NAND 的
13h/0FhFeature 帧直接套到 PPI 总线上 - ×16 器件:能力表必须写明 Column 与主机缓冲是按字节还是按字计数
3. 软件分层架构 推荐
┌──────────────────────────────────────────────┐ │ 应用 / 文件系统 (UBIFS / LittleFS+FTL...) │ ├──────────────────────────────────────────────┤ │ FTL / 磨损均衡 / 逻辑卷 │ ├──────────────────────────────────────────────┤ │ BBM(坏块表、替换、标记) │ ├──────────────────────────────────────────────┤ │ PPI NAND 驱动(命令序列、ECC、超时、ONFI) │ ├──────────────────────────────────────────────┤ │ HAL:周期原语 + 时序/位宽/DMA/硬件 ECC │ ├──────────────────────────────────────────────┤ │ 并行 NAND 控制器(FSMC/EBI/NFC/GPIO bitbang)│ └──────────────────────────────────────────────┘
强制要求:
- 应用层禁止直接拨 CLE/ALE 发 Erase / Program;必须经驱动统一入口。
- 坏块判定与替换不得散落在业务代码;统一由 BBM 层处理。
- HAL 只提供:发命令 / 发地址 / 写数据 / 读数据 / 读 R/B# / 可选硬件 ECC 结果;不得在 HAL 内散落业务超时策略。
- 驱动初始化必须完成:等待 tVSL→ Reset(
FFh)→ 等 R/B# → Read ID → 读 ONFI Parameter Page / 静态几何表 → 配置时序/位宽/ECC → 扫描/加载坏块表 →(可选)挂载 FTL。 - 同一颗料的SDR / DDR / Toggle模式切换必须有能力表与恢复路径;禁止未验证就开高速模式。
3.1 上电时序 tVSL 强制
VCC 到达工作电压后,PPI NAND不能立刻接收命令。Datasheet 规定的tVSL / tPOR(厂商命名不一)未满足时发90h/70h/FFh等,可能导致:ID 全0x00/0xFF、R/B# 假 Ready、擦写进入不确定态,甚至把控制器时序状态机卡死在错误模式。并行总线比 SPI 更依赖电源稳定——IO 上拉、CE# 默认态、R/B# 开漏在上电斜坡期间都可能处于中间电平。
| 项 | 要求 |
|---|---|
| 等待起点 | 以“电源好 / 电压监控释放 / ADC 确认 VCC≥VCC(min)”为起点,而非仅以 MCU 复位释放为起点 |
| 等待时间 | ≥ 目标器件 DatasheetMax tVSL / tPOR;多料号兼容时取清单内最大值 |
| 典型量级 | 常见数十 µs ~ 数 ms(以 Datasheet 为准;禁止凭经验写死过小值) |
| 与 BOR 关系 | Brown-out 恢复后视为重新上电,必须重新等待 tVSL,并强制回SDR 安全时序 |
| 首条命令 | tVSL 满足前:禁止Read ID / Status / Parameter Page / 擦写 / 切 DDR |
| Soft Reset | FFh后须满足tRST并等 R/B# Ready(双重确认),再发其它命令 |
| R/B# 上拉 | 开漏必须有合适上拉;上电初期高阻/毛刺不得判为 Ready——以 Status 为准 |
| 实现位置 | 建议在ppi_nand_init()最前部统一等待,避免各调用点遗漏 |
wait_until_vcc_ok() delay_at_least(tVSL_max) hal_set_bus_sdr_safe() // 控制器回异步安全时序 nand_reset() // CLE: FFh wait_rb_ready_double() // R/B# 或 Status Ready,双重确认 id = read_id() // CLE: 90h + ALE + 读 ID param = read_parameter_page() // ECh 等 configure_timing_ecc_wp() scan_or_load_bbt()3.2 Boot / 启动架构 强制
PPI NAND通常不支持像 SPI NOR 那样的 CPU Memory-Map XIP 直接取指启动(部分 SoC 的 NFC BootROM 属专项认证例外)。
| 项 | 要求 |
|---|---|
| 启动介质 | BootROM / 片内 ROM /小容量 SPI NOR/ eMMC 等可执行介质加载一级 Loader |
| NAND 角色 | 存放 App、文件系统、资源;由 Loader/App通过命令模式访问 |
| 禁止 | 假定把 NAND 映射到地址空间即可执行代码(除非芯片与料号明确支持且已专项认证) |
| 双 Flash | 推荐:NOR 存 Bootloader + 关键恢复镜像;PPI NAND 存大容量数据 |
| 恢复 | NAND BBT/FTL 损坏时,仍须能从 NOR/ROM 进入维护模式重刷 |
| Loader 接口 | Loader必须能在Async SDR下完成 Reset / ID / 基本页读 |
Power-On → ROM/NOR 启动 Loader → 初始化 PPI NAND 驱动(§3.1) → 加载 BBT / 挂载 FTL → 校验并跳转 App(代码先拷入 RAM,或按平台支持方式加载)3.3 HAL 原语与职责边界 强制
| HAL 原语(示例) | 职责 |
|---|---|
cmd(uint8_t c) | CLE=1, ALE=0,写入命令字节,满足 tCLS/tCLH/tWP |
addr(uint8_t *a, n) | CLE=0, ALE=1,写入 n 个地址字节 |
write_data(buf, n) | CLE=0, ALE=0,WE# 写入数据 |
read_data(buf, n) | CLE=0, ALE=0,RE# 读出数据 |
rb_is_busy() | 采样 R/B#(注意开漏与毛刺) |
ecc_hw_* | 可选:启动/取回硬件 ECC 结果 |
| 项 | 要求 |
|---|---|
| 禁止 | HAL 内写死某料号的“擦完延时 3ms 就返回成功” |
| 禁止 | 业务层直接操作 NFC 寄存器绕过驱动锁 |
| EDMA | DMA 完成 ≠ 阵列操作完成;仍须 Ready 双重确认 |
| 中断 | R/B# 边沿中断可唤醒轮询,不可单独作为成功依据 |
3.4 控制器时序配置 强烈推荐
软件必须在能力表/设备树中配置(名称因 SoC 而异),并与 Datasheet全温最差取交:
| 参数类 | 示例 | 说明 |
|---|---|---|
| 命令/地址 | tCLS, tCLH, tALS, tALH, tCS, tCH | 建立/保持 |
| 写脉冲 | tWP, tWH, tDS, tDH | 数据建立相对 WE# |
| 读脉冲 | tRP, tREH, tREA, tRHZ | 数据有效窗 |
| 模式 | SDR / DDR / Toggle、DQS 延迟 | 高速模式专项 |
| 位宽 | ×8 / ×16 | 与料号一致 |
配错 tREA/tRP 的典型症状:读数据偶发错位、ECC 误报升高、ID 字节漂移。量产前必须在高低温下抽测。
4. 读 / 编 / 擦操作与 Timeout 强制
4.1 命令模型(与 SPI NAND 对照)
PPI NAND 通过命令周期 + 地址周期 + 数据周期访问阵列,不是 SPI 单帧 Opcode。
4.1.1 读页(Page Read)— 典型 ONFI / 传统序列
1. CLE: 00h 2. ALE: Column(通常 2 字节)+ Row(通常 3 字节) // 以 Datasheet 为准 3. CLE: 30h 4. 等待 tWB 后轮询 R/B# → Ready(双重确认);或读 Status Ready 5. 检查 / 准备 ECC(On-Die 状态或主机解码) 6. (可选)CLE: 00h + ALE Column 重定位 → RE# 突发读出 Main/OOB 7. 主机侧处理 OOB / 软件 ECC(若未用 On-Die / 硬件 ECC)4.1.2 Random Data Output(页内随机读出)
1. 已完成 00h-30h 且 Ready 2. CLE: 05h 3. ALE: Column 4. CLE: E0h 5. RE# 读出从 Column 起的数据用途:只读 OOB、只读某 ECC step、BBT 扫描。禁止用错误 Column 宽度导致读飞。
4.1.3 编程(Page Program)
1. CLE: 80h 2. ALE: Column + Row 3. 写入 Main [+ OOB] 数据(WE# 周期;主机 ECC 则先编码) 4. CLE: 10h 5. 等待 R/B# Ready(双重确认) 6. CLE: 70h 读 Status;检查 Fail;失败则按坏块策略处理4.1.4 Random Data Input(页内随机写入)
CLE: 85h + ALE Column + 写数据仍计入PPP;与 Main 同一次10h提交前的多次85h也计入次数(以 Datasheet 为准)。
4.1.5 擦除(Block Erase)
1. CLE: 60h 2. ALE: Row(指向块内约定页,通常首页) 3. CLE: D0h 4. 等待 R/B# Ready(双重确认) 5. Status 检查 Erase Fail;失败则标记坏块多 Plane 擦除(若启用):按 Datasheet 使用60h-60h-D0h等变体;默认产品路径关闭。
4.2 与 SPI NAND 命令映射(防混用速查)
| 操作 | SPI NAND(典型) | PPI NAND(典型) |
|---|---|---|
| 页读到阵列完成 | 13h+ 轮询 C0h OIP | 00h…30h+ 等 R/B# |
| 从页缓冲读出 | 03h/0Bh… | RE# 读数据 /05h-E0h |
| 编程 | 06h+Load+10h | 80h+data+10h |
| 擦除 | 06h+D8h | 60h+D0h |
| 读状态 | Get Feature0Fh+C0h | 70hStatus |
| 读 ID | 9Fh | 90h |
| Reset | FFh/66h+99h | FFh |
| 参数页 | Feature OTP + Page Read | EChRead Parameter Page |
| 配置 | Set Feature1Fh | ONFIEFh/EEh(若支持) |
4.3 基本原则
并行 NAND 的“操作完成”由阵列内部状态决定,主机无法从“发完命令”推断结果。噪声、假 Ready、掉电半完成都会让“盲延时成功返回”变成静默坏数据。
强制规则:
- 所有Page Read(阵列搬移)/ Program / Block Erase必须:
- 按 Datasheet 发送完整命令/地址/数据周期(CLE/ALE/数据节拍不得缺周期)
- 等待 R/B# Ready,并用Status 双重确认(见 §4.5;本规范唯一合法完成模板)
- 同时施加分类 Timeout(读 / 编 / 擦 / Reset 分表,禁止万能超时)
- 完成后检查Fail / ECC status;Fail 或不可纠正 ECC 不得当成功
- 禁止仅靠固定
delay_ms()盲等;轮询为主,Timeout 为辅。 - Timeout 到期后:禁止假定成功;应读 Status、必要时 Soft Reset(
FFh)并回 SDR,返回可区分错误码。 - 禁止在 R/B# 忙期间发起无关命令(除 Datasheet 允许的 Read Status
70h)。 - 禁止在未持驱动锁时穿插另一任务的 CLE/ALE 序列(总线被打断等价于命令损坏)。
- Program/Erase 前确认目标块不在坏块表;读路径也须拒绝对已知坏块的“当好块用”。
4.4 Timeout 取值策略
Timeout 过短 → 正常慢擦被当成失败并误标坏块;Timeout 过长 → 真卡死拖死整机看门狗。并行 NAND 的 tR / tPROG / tBERS 随工艺、温度、循环次数变化大,必须按料号分类配置。
| 优先级 | 方法 | 说明 |
|---|---|---|
| 1 | Datasheet Max | tR / tPROG / tBERS / tRST 最大值 +20%~50%余量 |
| 2 | Parameter Page | 若提供典型/最大时间字段则优先解析并交叉核对 Datasheet |
| 3 | 产品配置表 | 按 Read ID / ONFI 签名查本地能力表(兼容无有效 Parameter 的料) |
推荐默认量级(仅参考,必须以料号为准):
| 操作 | 典型量级 | 软件 Timeout 建议 |
|---|---|---|
| Page Read(tR) | 20 ~ 100 µs | Max × 1.5,且 ≥ 1 ms |
| Page Program(tPROG) | 0.3 ~ 3 ms | Max × 1.5,且 ≥ 10 ms |
| Block Erase(tBERS) | 2 ~ 15 ms(SLC)~ 更长(MLC/TLC) | Max × 1.5,且 ≥ 50~100 ms |
| Soft Reset(tRST) | 按 Datasheet | Max + 余量;单独配置 |
| Cache 相关 | 按 Datasheet | 单独配置,禁止复用 tR/tPROG |
| 命令后进忙(tWB) | 数十~数百 ns 量级 | 轮询前可插入极短等待,但不得替代 Ready 判定 |
禁止与 SPI NOR 共用 Sector/Chip Erase 超时表;禁止与 SPI NAND 共用“只轮询 Feature、不接 R/B#”的实现;禁止全项目一个“万能 5 秒超时”。
高温、接近寿命末端时 tPROG/tBERS 可能显著变长:能力表可提供timeout_hot_scale(例如 ×1.2),与 §7.5 温度策略联动。
4.5 R/B# 与 Status 双重确认 强制
擦写/页读阵列操作期间,R/B# 引脚可能因上拉过弱、线缆噪声、ESD、控制器采样毛刺、器件内部状态切换瞬间等原因出现偶发假 Ready;单独一次 Status 读也可能因总线毛刺得到假 Ready 位。 因此:仅观察到一次 Ready,不得判定 Page Read / Program / Erase 完成。
与《SPI NOR》§4.3(WIP 双重确认)、《SPI NAND》§4.4(OIP 双重确认)同级加严;接口不同,语义相同。
实现注意:本节以下伪代码为唯一合法完成判定模板。禁止再实现“R/B# 变高就返回成功”或“读一次70hReady 即成功”的简化逻辑。
强制规则:
- 判定 Page Read / Program / Erase 完成前,必须满足:
- R/B# 为 Ready,且连续 ≥2 次独立读 Status(
70h)均为 Ready;或 - 无可靠 R/B# 连线时:连续 ≥2 次Status Ready(两次独立命令事务),并仍强烈建议接 R/B#。
- 两次 Status 读之间应有短暂间隔(建议 ≥ 1~10 µs);至少完成两次独立 CLE
70h事务。 - 若第一次 Ready、第二次 Busy:视为未完成,清零确认计数,继续轮询直至双重确认成功或 Timeout。
- 双重确认通过后,再检查Fail / ECC(编擦看 Fail;读看 ECC)。Fail 或不可纠正不得当成功。
- DMA/EDMA 半包/全包中断后,禁止用“已传输字节数”代替 Ready 判断——DMA 完成 ≠ 阵列操作完成。
- R/B# 上拉过弱或干扰导致毛刺时,以 Status 为准,并记录
rb_glitch类告警;长期毛刺须改硬件/时序。 - Soft Reset、模式切换、故障恢复路径同样适用本规则。
推荐伪代码(标准实现 — 唯一合法模板):
t0 = now() ready_streak = 0 required = 2 // 连续 Ready 次数,默认 2,可配置 ≥2 do { if (rb_pin_is_busy()) { ready_streak = 0 } else { st = read_status_70h() // 独立命令事务:CLE 70h + 读 1B if (!status_ready(st)) { // Ready 位定义须按料号替换 ready_streak = 0 } else { ready_streak++ if (ready_streak >= required) break } } if (now() - t0 > timeout) return PPI_NAND_ERR_TIMEOUT yield_or_sleep(poll_interval) // 建议 10µs~1ms,避免占死 CPU } while (1) if (op == PROGRAM && status_fail(st)) return PPI_NAND_ERR_P_FAIL if (op == ERASE && status_fail(st)) return PPI_NAND_ERR_E_FAIL if (op == READ) return decode_ecc_status(...) // 见 §6说明:
- 部分 Datasheet 仅要求“等 R/B# 再读 Status”;本规范在此基础上加严为R/B# + 连续两次 Status Ready(或无脚时两次 Status)。
- Status 位定义(Ready / Fail / WP)因厂而异,能力表必须提供解析掩码;附录 E 仅为模板。
- Memory-Mapped NFC 读阵列不得代替 Status 忙判定。
- 多 LUN / 多 CE# 时,确认的是本次命令目标的状态(必要时用 Enhanced Status
78h等,以 Datasheet 为准)。
4.6 Cache Read / Cache Program(可选增强)
| 项 | 要求 |
|---|---|
| 目的 | 流水化提升顺序吞吐 |
| 启用 | 能力表显式打开;单页路径验证稳定前禁止 |
| 退出 | 异常、BBT 扫描、模式切换、故障恢复前必须回到已知空闲态(必要时FFh) |
| 错误 | Cache 路径同样必须检查 Fail / ECC;禁止“为快而跳过状态” |
| 与锁 | Cache 序列必须原子持锁,禁止中途插入其它 Target 命令 |
4.7 失败与恢复
| 失败类型 | 处理 |
|---|---|
| Timeout | 记录 op/row/status/R/B#;尝试 Soft Reset;重新 ID;返回ERR_TIMEOUT |
| Program Fail | 该页/块视为不可靠;标记坏块;返回ERR_P_FAIL |
| Erase Fail | 标记坏块;返回ERR_E_FAIL |
| ECC 不可纠正 | 返回ERR_ECC_UNCORRECTABLE;按 §6整块迁移 + 标记坏块 |
| ECC 可纠正且 bitflip≥ 迁块阈值(8-bit 默认 ≥6) | 按 §6整块迁移 + 标坏 |
| ECC 可纠正且 bitflip< 阈值 | 返回成功并上报 corrected bits |
| 时序模式异常 | 回 SDR + Reset;返回ERR_TIMING_MODE |
PPI-NAND-SW-SPEC-001 · V1.2 · 与 SPI-NAND / SD-NAND / SPI-NOR 规范配套 · 可浏览器打开或打印为 PDF
后续章节请下载「芯参谋」查看
……(篇幅原因, 还有43章· 详见芯参谋→方案设计)
当前分享仅开放前5章正文。详细资料请在芯参谋客户端中打开完整文档。
打开路径:🔧解决方案&应用市场分析 -> 原理方案设计 -> PPI_NAND_软件设计规范
📥 下载芯参谋客户端