eMMC协议详解
eMMC 协议详解
面向对象:嵌入式固件工程师(eMMC 设备端/主机端固件开发)
适用规范:JEDEC JESD84-B51(eMMC 5.1)及此前各版本
文档性质:工程参考文档,命令号、寄存器偏移等关键信息以 JEDEC 规范及 Linux 内核实现(include/linux/mmc/mmc.h、drivers/mmc/core/mmc.c)为准
版本:v1.0 | 日期:2026-08-15
1. eMMC 概述
1.1 什么是 eMMC
eMMC(embedded MultiMediaCard,嵌入式多媒体卡)是一种将 NAND Flash 存储介质 与 存储控制器(Controller) 封装在同一芯片(BGA 封装)内的嵌入式存储标准,由 JEDEC(JESD84 系列规范)定义。控制器内部运行固件(Firmware),对主机(Host)屏蔽了 NAND 的物理特性(擦除、磨损、坏块、ECC 等),向上提供与”块设备”类似的标准接口。
eMMC 的定位:
- 面向嵌入式系统:手机、平板、机顶盒、车载、工控、IoT 等,作为不可拆卸的板载存储。
- 替代方案:UFS(面向高性能移动设备,串行接口)、SD/eMMC 卡(可拆卸)、SPI NOR/NAND(低端)。
- 接口简单:并行总线(CLK/CMD/DAT0–7),主机侧无需复杂 PHY,成本低、成熟度高。
1.2 版本演进
| 版本 | JEDEC 规范 | 主要新增特性 |
|---|---|---|
| eMMC 4.0 | JESD84-A41 | 基础协议;引入 CMD6 SWITCH、EXT_CSD、HS 模式(26/52 MHz)、Boot 分区 |
| eMMC 4.1 | JESD84-A42 | 安全性增强(RPMB 前身)、中断 |
| eMMC 4.2 | JESD84-A43 | 小幅修订 |
| eMMC 4.3 | JESD84-A44 | 增强/通用分区(GPP)、RPMB、可靠写、Sanitize 前身特性 |
| eMMC 4.4 / 4.41 | JESD84-A441 | DDR 模式(52 MHz DDR,104 MB/s)、8-bit 总线普及 |
| eMMC 4.5 | JESD84-B45 | HS200(200 MHz SDR,200 MB/s)、Cache、Packed Commands、BKOPS、HPI、TRIM |
| eMMC 5.0 | JESD84-B50 | HS400(200 MHz DDR,400 MB/s)、FFU(现场固件升级)、Sanitize、数据标签 |
| eMMC 5.1 | JESD84-B51 | 命令队列 CMDQ(深度≤32)、HS400ES(增强选通)、生命周期监控 |
| 5.1A / 5.1B | JESD84-B51A/B51B | 勘误与澄清(如生产日期字段调整) |
注:JEDEC 已将 eMMC 冻结在 5.1,后续存储演进由 UFS 承担。当前量产 eMMC 绝大多数为 5.0/5.1。
各版本对应 EXT_CSD_REV(EXT_CSD 字节 192):
| EXT_CSD_REV | 对应版本 |
|---|---|
| 1 | 4.0 |
| 2 | 4.1 |
| 3 | 4.2 |
| 4 | 4.3 |
| 5 | 4.4 / 4.41 |
| 6 | 4.5 |
| 7 | 5.0 |
| 8 | 5.1 |
1.3 eMMC 与 NAND、SD、UFS 的关系
| 特性 | 裸 NAND | eMMC | SD 卡 | UFS |
|---|---|---|---|---|
| 接口 | 并行 I/O | 并行(CLK/CMD/DAT) | 并行(同源协议) | 串行 M-PHY |
| 控制器 | 无(主机直接管) | 内置 | 内置 | 内置 |
| 坏块/ECC/磨损均衡 | 主机负责 | 控制器负责 | 控制器负责 | 控制器负责 |
| 主机复杂度 | 高 | 低 | 低 | 中 |
| 典型带宽 | 依颗粒 | 最高 400 MB/s(HS400) | 最高 ~200 MB/s(UHS-II 除外) | 最高 2.9 GB/s(UFS 3.1) |
| 使用场景 | 高密度低成本 | 中低端嵌入式 | 可拆卸存储 | 高端手机/SSD 级 |
eMMC 协议与 SD 同源(SD 由 MMC 演进而来),命令集高度相似,但存在关键差异(见 §4.7),开发时不可混用。
1.4 分层架构
从主机固件开发视角,整个系统分三层:
1 | ┌─────────────────────────────────────────────┐ |
从 eMMC 设备固件开发视角,协议栈可进一步拆分为:
- 物理层:CLK 同步、上电复位、信号电压(VCC/VCCQ)。
- 链路层:命令/响应帧格式、CRC7/CRC16 校验、位宽(x1/x4/x8)、SDR/DDR。
- 命令层:命令集、状态机(idle→ready→ident→stby→tran→data→rcv→prg→dis)。
- 寄存器层:OCR/CID/CSD/EXT_CSD 的读取与维护。
- 数据层:块读/写、擦除/TRIM/Discard、命令队列、RPMB。
- 内部管理层(不可见):FTL、磨损均衡、坏块管理、垃圾回收、掉电保护、寿命监控。
2. 硬件接口与信号
2.1 引脚定义
eMMC 采用 BGA 封装(典型 153-ball FBGA),信号定义如下:
| 信号 | 方向 | 说明 |
|---|---|---|
| CLK | Host→Device | 时钟输入,全部信号在该时钟边沿采样。注意:CLK 是单端输入,设备不产生时钟 |
| CMD | 双向 | 命令/响应线,开漏(初始化阶段)或推挽(高速阶段) |
| DAT0–DAT7 | 双向 | 数据线,支持 x1/x4/x8 三种位宽 |
| DS | Device→Host | 数据选通(Data Strobe),仅在 HS400 模式下由设备输出,与数据同相的 200 MHz 时钟 |
| RST_N | Host→Device | 硬件复位(低有效)。是否可用由 EXT_CSD[162] RST_N_FUNCTION 决定 |
| VCC | — | 主电源(Core/Flash 供电):2.7–3.6 V |
| VCCQ | — | I/O 电源:3.3 V / 1.8 V / 1.2 V,决定信号电平 |
| VSS / VSSQ | — | 地 |
2.2 上电与复位
上电时序(主机侧必须满足):
- 将 VCC、VCCQ 拉至工作电压。
- 等待电源稳定(power ramp 时间依器件不同,规范要求主机至少等待 1 ms 以上再开始初始化)。
- 保持 CLK 运行(初始化阶段频率 ≤ 400 kHz,即 f_OD/f_init),CMD/DAT 上拉或处于正确状态。
- 若 RST_N 被使能,可拉低 ≥ 1 个时钟周期完成硬件复位;否则用 CMD0 软件复位。
设备侧要求:上电后设备在收到有效命令前保持 idle 状态;检测到供电异常(掉电/欠压)时必须安全停止(见 §12.7 掉电处理)。
2.3 电压与信号电平
- VCC:3.3 V 档(2.7–3.6 V),给控制器与 NAND 供电。
- VCCQ:I/O 信号电平,支持 3.3 V / 1.8 V / 1.2 V。HS200/HS400 模式要求 1.8 V 或 1.2 V 信号。
- 设备支持的电压窗口通过 OCR 寄存器 上报(§5.1),主机通过 CMD1 协商。
- 信号电压切换 是纯主机侧行为(切换 VCCQ 电源轨),无专用命令;切换后必须重新初始化或按规范流程恢复(典型做法:降频 → 切电压 → 重新调谐/初始化)。
2.4 总线宽度与推挽/开漏
- 初始化阶段:x1 位宽、开漏(Open-Drain),便于多设备仲裁(eMMC 通常单设备,但协议保留广播命令语义)。
- 进入高速阶段后:推挽(Push-Pull),位宽可切至 x4/x8。
- 位宽切换通过 CMD6 写 EXT_CSD[183] BUS_WIDTH 完成(见 §6.4、§7.3)。
2.5 关键时序参数(设备侧上报)
主机必须依据设备上报值设置超时:
| 参数 | 来源 | 说明 |
|---|---|---|
| TAAC / NSAC | CSD[119:104] | 数据访问时间(Nac 计算依据),即从收到 CMD17/18 到首块数据的时间上限 |
| max_dtr(TRAN_SPEED) | CSD[103:96] | 最大传输速率 |
| S_A_TIMEOUT | EXT_CSD[217] | Sleep/Awake(CMD5)超时,单位 100 ns × 2^n |
| ERASE_TIMEOUT_MULT | EXT_CSD[223] | 擦除超时 = 300 ms × 该值 |
| TRIM_MULT / SEC_TRIM_MULT / SEC_ERASE_MULT | EXT_CSD[232]/[229]/[230] | TRIM/安全 TRIM/安全擦除超时倍率 |
| PART_SWITCH_TIME | EXT_CSD[199] | 分区切换超时,单位 10 ms(不小于 300 ms 兜底) |
| GENERIC_CMD6_TIME | EXT_CSD[248] | CMD6 通用切换超时,单位 10 ms |
| POWER_OFF_LONG_TIME | EXT_CSD[247] | 长关机通知(POWER_OFF_LONG)超时,单位 10 ms |
| OUT_OF_INTERRUPT_TIME | EXT_CSD[198] | HPI 中断超时,单位 10 ms |
3. 通信基础:命令与响应
3.1 命令帧格式(48 bit)
主机在 CMD 线上发送的命令为固定 48 bit:
| 字段 | 位位置 | 位宽 | 说明 |
|---|---|---|---|
| Start | bit 47 | 1 bit | 起始位,恒为 `0` |
| Dir(Transmission) | bit 46 | 1 bit | 传输位:`1` = 主机→设备(命令);`0` = 设备→主机(响应) |
| CMD index | bit 45:40 | 6 bit | 命令索引,共 64 条命令(CMD0–CMD63,实际定义见 §4) |
| Argument | bit 39:8 | 32 bit | 命令参数,随命令不同含义不同(地址、参数、标志等) |
| CRC7 | bit 7:1 | 7 bit | 对 bit[46:1](传输位至参数末位)计算,生成多项式 `x^7 + x^3 + 1`(0x89) |
| End | bit 0 | 1 bit | 结束位,恒为 `1` |
3.2 响应帧格式
3.2.1 48 bit 响应(R1/R1b/R3/R4/R5/R6/R7)
| 字段 | 位位置 | 位宽 | 说明 |
|---|---|---|---|
| Start | bit 47 | 1 bit | 起始位,恒为 `0` |
| Dir(Transmission) | bit 46 | 1 bit | 传输位:`0` = 设备→主机(响应) |
| 保留 | bit 45:40 | 6 bit | 恒为 `0` |
| 内容 | bit 39:8 | 32 bit | 响应内容(Card Status / OCR / 参数等),随响应类型不同而异 |
| CRC7 | bit 7:1 | 7 bit | 响应帧的 CRC7 |
| End | bit 0 | 1 bit | 结束位,恒为 `1` |
各 48 bit 响应类型:
| 类型 | 内容(bit[39:8]) | 说明 |
|---|---|---|
| R1 | 32 bit Card Status | 常规状态响应(多数命令) |
| R1b | 32 bit Card Status + DAT0 忙信号 | R1 且命令执行期间设备拉低 DAT0(写、擦除、切换等) |
| R3 | 32 bit OCR | 仅 CMD1,上报工作电压与能力 |
| R4 | 32 bit 参数 | 仅 CMD39 FAST_IO(工厂/调试用) |
| R5 | 32 bit 参数 | 仅 CMD40 GO_IRQ_STATE |
| R6 | RCA(16 bit) + Card Status(16 bit) | 仅 CMD3,返回相对地址 |
| R7 | 保留 8 bit + 电压(8 bit) + 回显(24 bit) | CMD8(本协议中为 SEND_EXT_CSD 命令,无 R7;R7 属 SD 兼容定义,eMMC 不产生) |
3.2.2 136 bit 响应(R2)
R2 用于 CMD2(ALL_SEND_CID)、CMD9(SEND_CSD)、CMD10(SEND_CID):
| 字段 | 位位置 | 位宽 | 说明 |
|---|---|---|---|
| Start | bit 135 | 1 bit | 起始位,恒为 `0` |
| Dir(Transmission) | bit 134 | 1 bit | 传输位:`0` = 设备→主机(响应) |
| 保留 | bit 133:128 | 6 bit | 恒为 `0` |
| 内容(CID / CSD) | bit 127:1 | 127 bit | CID 或 CSD 寄存器内容 |
| CRC7 | bit 7:1 | 7 bit | 对 bit[134:1](整个内容区)计算 |
| End | bit 0 | 1 bit | 结束位,恒为 `1` |
3.3 CRC7 计算
- 多项式:
x^7 + x^3 + 1(即 0x89),初始值 0x00。 - 覆盖范围:传输位开始至参数位结束(48 bit 帧的 bit[46:1])。
- 固件实现要点:主机控制器通常硬件完成 CRC 生成/校验;设备固件侧需对收到的 CMD 校验 CRC、对发出的 Response 生成 CRC。CRC 错误时设备忽略该命令,不更新状态(部分命令按规范返回 COM_CRC_ERROR 状态位)。
3.4 数据线上的帧(CRC16)
数据块在 DAT 线上传输时,每块后跟 16 bit CRC(多项式 x^16 + x^12 + x^5 + 1,0x1021):
1 | DAT0..n: [数据块 512B][CRC16(16 bit)][End bit(1)] |
读方向:设备发送;写方向:主机发送,设备校验。CRC 校验失败的处理见 §8.6。
3.5 命令类型(协议语义)
| 类型 | 说明 | 例 |
|---|---|---|
| bc(Broadcast) | 广播命令,无响应 | CMD0、CMD4、CMD15 |
| bcr(Broadcast with response) | 广播命令,所有设备同时响应 | CMD1、CMD2、CMD3 |
| ac(Addressed) | 点对点命令,无数据 | CMD7、CMD9、CMD13… |
| adtc(Addressed with data transfer) | 点对点命令,带数据 | CMD17/18/24/25、CMD8 |
3.6 命令类别(Command Classes,CCC)
CSD[95:84] 的 12 位 CCC 表明设备支持的命令类(固件应据其裁剪命令集):
| 位 | 类别 | 包含命令 |
|---|---|---|
| 0 | 基本 | CMD0,1,2,3,4,7,9,10,12,13,15 |
| 1 | 流式读 | CMD11(遗留) |
| 2 | 块读 | CMD16,17,18 |
| 3 | 流式写 | CMD20(遗留) |
| 4 | 块写 | CMD16,24,25,26,27 |
| 5 | 擦除 | CMD32–38 |
| 6 | 写保护 | CMD28,29,30 |
| 7 | 锁卡 | CMD16,42 |
| 8 | 厂商特定 | CMD55,56,57 等 |
| 9 | I/O 模式 | CMD5,39,40 |
| 10 | 切换 | CMD6 |
3.7 设备状态机
R1 响应的 Card Status[12:9](CURRENT_STATE)返回当前状态:
1 | idle ──CMD1──▶ ready ──CMD2──▶ ident ──CMD3──▶ stby ──CMD7──▶ tran |
| 状态 | 值 | 说明 |
|---|---|---|
| idle | 0 | 上电/复位后,仅响应 CMD0/CMD1 |
| ready | 1 | CMD1 协商成功(OCR busy 清除) |
| ident | 2 | CMD2 发送 CID 后 |
| stby | 3 | 已分配 RCA(CMD3 完成),等待 CMD7 选中 |
| tran | 4 | 已选中,可执行数据传输命令 |
| data | 5 | 数据传输中(读方向) |
| rcv | 6 | 写数据接收中 |
| prg | 7 | 编程/擦除中(DAT0 忙) |
| dis | 8 | CMD15 后非激活,只能复位恢复 |
主机固件通常用 CMD13(SEND_STATUS)轮询状态/忙;设备固件则必须精确维护状态机与每个命令的合法状态转换。
4. 命令集详解
4.1 完整命令表(CMD0–CMD63)
下表汇总 eMMC 全部命令(标注类型/参数/响应/类别,参照 JEDEC 5.1 与 Linux mmc.h)。
| CMD | 名称 | 类型 | 参数 | 响应 | 类别 | 说明 |
|---|---|---|---|---|---|---|
| 0 | GO_IDLE_STATE | bc | 0x0(或 0xFFFFFFFA 进入 Boot 模式) | 无 | 0 | 复位至 idle;带 0xFFFFFFFA 参数用于 Boot 操作(§9) |
| 1 | SEND_OP_COND | bcr | [31:0] OCR(电压窗口) | R3 | 0 | 电压协商;同时可令设备退出 Boot 模式 |
| 2 | ALL_SEND_CID | bcr | 0x0 | R2(CID) | 0 | 读取全部设备的 CID |
| 3 | SET_RELATIVE_ADDR | bcr | [31:16] RCA | R6 | 0 | 为设备分配相对地址 RCA |
| 4 | SET_DSR | bc | [31:16] DSR | 无 | 0 | 设置驱动级寄存器(若 CSD.dsr_imp=1) |
| 5 | SLEEP_AWAKE | ac | [31:16] RCA,[15] 唤醒标志 | R1b | 9 | 睡眠(flag=0)/唤醒(flag=1),超时见 S_A_TIMEOUT |
| 6 | SWITCH | ac | 见 §4.3 | R1b | 10 | 写/切换 EXT_CSD 字段,是模式切换的核心命令 |
| 7 | SELECT/DESELECT_CARD | ac | [31:16] RCA(0=去选) | R1b | 0 | 选中/取消选中设备 |
| 8 | SEND_EXT_CSD | adtc | 0x0 | R1 + 512B 数据 | 2 | 读取完整 EXT_CSD(512 字节) |
| 9 | SEND_CSD | ac | [31:16] RCA | R2(CSD) | 0 | 读取 CSD 寄存器 |
| 10 | SEND_CID | ac | [31:16] RCA | R2(CID) | 0 | 读取 CID 寄存器 |
| 11 | READ_DAT_UNTIL_STOP | adtc | 地址 | R1 + 流数据 | 1 | 流式读(遗留,4.4 后不推荐) |
| 12 | STOP_TRANSMISSION | ac | 0x0 | R1b | 0 | 中止多块传输/擦除等;写方向返回忙 |
| 13 | SEND_STATUS | ac | [31:16] RCA | R1 | 0 | 读状态字(最常用的轮询命令) |
| 14 | BUS_TEST_R | adtc | 0x0 | R1 + 数据 | 2 | 总线测试读(写测试模式后校验) |
| 15 | GO_INACTIVE_STATE | ac | [31:16] RCA | 无 | 0 | 设备进入 dis 状态(仅复位可恢复) |
| 16 | SET_BLOCKLEN | ac | [31:0] 块长 | R1 | 2 | 设块长(块寻址设备忽略,恒 512B) |
| 17 | READ_SINGLE_BLOCK | adtc | [31:0] LBA | R1 + 数据 | 2 | 单块读 |
| 18 | READ_MULTIPLE_BLOCK | adtc | [31:0] LBA | R1 + 数据 | 2 | 多块读(CMD23 预定义或 CMD12 中止) |
| 19 | SEND_TUNING_BLOCK / BUS_TEST_W | adtc | 0x0 | R1 + 数据 | 2 | 写测试数据/调谐块(写测试模式) |
| 20 | WRITE_DAT_UNTIL_STOP | adtc | 地址 | R1 + 流数据 | 3 | 流式写(遗留) |
| 21 | SEND_TUNING_BLOCK_HS200 | adtc | 0x0 | R1 + 64B 调谐块 | 2 | HS200/HS400 调谐专用(§7.4) |
| 22 | — | — | — | — | — | 保留 |
| 23 | SET_BLOCK_COUNT | adtc | [31:0] 块数 | R1 | 2 | 预定义多块读/写块数;RPMB 必需 |
| 24 | WRITE_BLOCK | adtc | [31:0] LBA | R1 | 4 | 单块写(数据后 DAT0 忙) |
| 25 | WRITE_MULTIPLE_BLOCK | adtc | [31:0] LBA | R1 | 4 | 多块写(CMD23 预定义或 CMD12 中止) |
| 26 | PROGRAM_CID | adtc | 0x0 | R1 + 128bit | 4 | 写 CID(出厂/一次性) |
| 27 | PROGRAM_CSD | adtc | 0x0 | R1 + 128bit | 4 | 写 CSD(出厂) |
| 28 | SET_WRITE_PROT | ac | [31:0] 组地址 | R1b | 6 | 设置写保护组 |
| 29 | CLR_WRITE_PROT | ac | [31:0] 组地址 | R1b | 6 | 清除写保护组 |
| 30 | SEND_WRITE_PROT | adtc | [31:0] 组地址 | R1 + 32B | 6 | 读取 256 位写保护状态 |
| 31 | — | — | — | — | — | 保留 |
| 32/33 | ERASE_WR_BLK_START / END | ac | [31:0] 地址 | R1 | 5 | 字节寻址设备的擦除边界(遗留;块寻址设备用 CMD35/36) |
| 34 | — | — | — | — | — | 保留 |
| 35 | ERASE_GROUP_START | ac | [31:0] 起始 LBA | R1 | 5 | 块寻址擦除起始边界 |
| 36 | ERASE_GROUP_END | ac | [31:0] 结束 LBA | R1 | 5 | 块寻址擦除结束边界 |
| 37 | — | — | — | — | — | 保留 |
| 38 | ERASE | ac | 见 §4.4 | R1b | 5 | 执行擦除/TRIM/Discard(含安全变体) |
| 39 | FAST_IO | ac | 复杂(寄存器读写) | R4 | 9 | 直接访问设备寄存器(工厂/调试) |
| 40 | GO_IRQ_STATE | bcr | 0x0 | R5 | 9 | 进入中断状态(测试/调试) |
| 41 | — | — | — | — | — | 保留 |
| 42 | LOCK_UNLOCK | adtc | [31:0] 标志 | R1b + 数据 | 7 | 卡加锁/解锁(口令设置,一般不用) |
| 43 | WRITE_EXTR_SINGLE | adtc | 见 §4.5 | R1 + 数据 | 4 | 写 EXT_CSD 单字节/扇区(5.1 扩展) |
| 44 | QUEUE_TASK_PARAMS | ac | 见 §4.6 | R1 | 2/4 | CMDQ:任务参数(操作码、任务号、优先级等) |
| 45 | QUEUE_TASK_ADDR | ac | [31:0] LBA | R1 | 2/4 | CMDQ:任务起始地址 |
| 46 | EXECUTE_READ_TASK | adtc | [20:16] 任务号 | R1 + 数据 | 2 | CMDQ:执行读任务 |
| 47 | EXECUTE_WRITE_TASK | adtc | [20:16] 任务号 | R1 + 数据 | 4 | CMDQ:执行写任务 |
| 48 | CMDQ_TASK_MGMT | ac | [20:16] 任务号/清除标志 | R1b | 2/4 | CMDQ:任务管理(取消/等待/清除) |
| 49–54 | — | — | — | — | — | 保留 |
| 55 | APP_CMD | ac | [31:16] RCA | R1 | 8 | 厂商特定命令前缀(SD 兼容语义,eMMC 一般不用) |
| 56 | GEN_CMD | adtc | [0] 读/写标志 | R1 + 数据 | 8 | 通用数据传输命令(厂商特定) |
| 57 | — | — | — | — | — | 保留 |
| 58/59 | — | — | — | — | — | SPI 模式专用(eMMC 不使用 SPI) |
| 60–63 | — | — | — | — | — | 保留 |
4.2 核心命令要点
- CMD0:软件复位。arg=0x0 复位到 idle;arg=0xFFFFFFFA 进入 Boot 模式(配合 §9)。Boot 模式下若使能了 Boot ACK,设备对 CMD0 返回 R1。
- CMD1:参数为”主机可提供的电压”(置位对应 OCR 位),设备用 R3 返回”设备需要且主机支持”的电压交集,并置位 OCR busy 位直至就绪。主机需循环发送直至 busy 清除。
- CMD3:多设备仲裁用;单设备场景主机通常直接分配 RCA=1。
- CMD7:arg=0 为去选(设备回 stby);arg=RCA<<16 为选中(回 tran)。从 stby 直接切到另一设备的 tran 会隐式去选原设备。
- CMD8:一次性读出 512 字节 EXT_CSD。设备固件须将 EXT_CSD 缓存到 RAM 以便快速响应;主机通常在初始化时读取并解析。
- CMD12:中止多块传输。读中止:R1,需在 2 个时钟内发出(对 DAT 状态机);写中止:R1b(等待编程结束)。
- CMD13:最常用的状态查询。arg 必须携带当前 RCA。设备固件应保证其开销极低(不回 FTL)。
4.3 CMD6 SWITCH 详解(设备固件高频接触的命令)
参数格式:
1 | bit 31:26 25:24 23:16 15:8 7:3 2:0 |
Access Mode(位[25:24]):
| 值 | 模式 | 语义 |
|---|---|---|
| 00b | 命令集切换 | 切换命令集(EXT_CSD[504] S_CMD_SET) |
| 01b | 置位(Set Bits) | 将索引字节中与 Value 对应的位置 1 |
| 10b | 清位(Clear Bits) | 将索引字节中与 Value 对应的位清 0 |
| 11b | 写字节(Write Byte) | 将索引字节写为 Value(最常用) |
- 响应为 R1b(执行期间 DAT0 忙)。
- 写只读字段返回 SWITCH_ERROR(R1 位 7)。
- 超时:优先用字段专属超时(如 PART_SWITCH_TIME、GENERIC_CMD6_TIME)。
- 常见用途:HS_TIMING(185)、BUS_WIDTH(183)、PART_CONFIG(179,分区切换)、CACHE_CTRL(33)、BKOPS_EN(163)、CMDQ_MODE_EN(15)、POWER_CLASS(187)、ERASE_GROUP_DEF(175)、RST_N_FUNCTION(162)等。
设备固件实现 CMD6 的注意点:
- 区分”模式切换类”(HS_TIMING/BUS_WIDTH,切换后必须更新内部时序参数)与”普通配置类”。
- 模式切换类命令后,主机可能立刻改变时钟频率,固件必须在 CMD6 完成(busy 释放)前 完成内部重配置。
- 写保护字段(PART_CONFIG 中已保护位)必须拒绝并回 SWITCH_ERROR。
4.4 CMD38 ERASE 参数
CMD38 的 32 位参数决定操作类型(配合 CMD35/36 或 CMD32/33 定义的范围):
| 参数值 | 操作 | 说明 |
|---|---|---|
| 0x00000000 | Erase | 标准擦除:将范围内数据置为擦除态(0x0 或 0xFF,见 ERASED_MEM_CONT) |
| 0x00000001 | TRIM | 逻辑擦除:将范围内逻辑块标记为无效(性能好,数据可读回 0/FF) |
| 0x00000003 | Discard | 丢弃:主机声明数据不再需要,设备可自由回收(不保证擦除态) |
| 0x80000000 | Secure Erase | 安全擦除:物理擦除并确保旧数据不可恢复(需 SEC_FEATURE_SUPPORT 支持) |
| 0x80000001 | Secure TRIM(阶段 1) | 安全 TRIM 第一步 |
| 0x80008000 | Secure TRIM(阶段 2) | 安全 TRIM 第二步(两阶段机制防掉电漏洞) |
- 响应 R1b(忙)。
- 范围语义:Erase/TRIM 的范围必须是擦除组(erase group)的整数倍且组对齐;Discard 可任意块。
- 擦除组大小:若 EXT_CSD[175] ERASE_GROUP_DEF=1,则取 EXT_CSD[224] HC_ERASE_GRP_SIZE(单位 512 KB);否则取 CSD 的 erase_grp_size。
- 超时:Erase = 300 ms × ERASE_TIMEOUT_MULT[223];TRIM = 300 ms × TRIM_MULT[232];Secure = 300 ms × SEC_ERASE_MULT[230]/SEC_TRIM_MULT[229]。
设备固件必须实现:范围对齐检查(越界/未对齐返回 ADDRESS_OUT_OF_RANGE 或 ERASE_PARAM)、擦除队列管理、与正在进行的写/GC 的并发互斥。
4.5 CMD43 WRITE_EXTR_SINGLE
- eMMC 5.1 引入,用于写入 EXT_CSD 之外的”扩展数据区”(设备厂商自定义的字节/扇区级扩展字段)。
- 参数:索引/扇区号 + 单字节/单扇区标志;数据随后在 DAT 线传输。
- 设备固件若未实现,应返回 ILLEGAL_COMMAND。
4.6 CMDQ 队列命令(CMD44–48)
eMMC 5.1 命令队列(详见 §8.5)使用五条命令:
| CMD | 功能 | 参数要点 |
|---|---|---|
| 44 | QUEUE_TASK_PARAMS | [20:16] 任务号;其余位携带:操作码(CMD17/18/24/25)、优先级、数据方向(读/写)、可靠写标志、FUA、块数 |
| 45 | QUEUE_TASK_ADDR | [31:0] 起始 LBA |
| 46 | EXECUTE_READ_TASK | [20:16] 任务号;随后在 DAT 线读出数据 |
| 47 | EXECUTE_WRITE_TASK | [20:16] 任务号;随后在 DAT 线接收数据 |
| 48 | CMDQ_TASK_MGMT | 取消指定任务 / 清除完成队列 / 等待完成(R1b) |
注意:CMDQ 使用 CMD44–48(与 SD 规范中 CMD60–63 的实现不同),开发时勿混淆。
5. 寄存器:OCR / CID / CSD
eMMC 设备向主机暴露四类寄存器:OCR、CID、CSD、EXT_CSD。前三者通过命令读取(CMD1/CMD2/CMD9),EXT_CSD 通过 CMD8 一次性读出 512 字节。
5.1 OCR(Operation Conditions Register,32 bit)
通过 CMD1 的 R3 响应读取。
| 位 | 字段 | 说明 |
|---|---|---|
| 31 | Card busy | 上电初始化未完成时=0;完成后=1。主机轮询 CMD1 直至此位置 1 |
| 30 | CCS(Card Capacity Status) | 1 = 高容量(块寻址,LBA);0 = 低容量(字节寻址)。≥2GB 设备必须为 1 |
| 29:24 | 保留 | — |
| 23:8 | 电压窗口(2.0–3.6 V) | 每 0.1 V 一位:位 8 = 2.0–2.1 V … 位 23 = 3.5–3.6 V |
| 7 | 低电压(1.65–1.95 V) | 支持 1.8 V 类电源 |
| 6:0 | 保留 | — |
设备固件要求:CMD1 在电压协商成功后(设备完成初始化)才置 busy 位;在电压不匹配时必须保持忙或返回不支持。
5.2 CID(Card Identification Register,128 bit)
通过 CMD2(R2)读取。eMMC(v4+)布局:
| 字段 | 位宽 | CID 位 | 说明 |
|---|---|---|---|
| MID | 8 | [127:120] | 厂商 ID(JEDEC 分配,如三星 0x15、海力士 0x90、美光 0x13 等) |
| OID | 16 | [119:104] | OEM/应用 ID(厂商自定义) |
| PNM | 48 | [103:56] | 产品名(6 个 ASCII 字符) |
| PRV | 8 | [55:48] | 产品版本(高 4 位=主版本,低 4 位=次版本) |
| PSN | 32 | [47:16] | 序列号(厂商唯一) |
| MDT | 8 | [15:8] | 生产日期:位[15:12]=月(1–12),位[11:8]=年(基准 1997,值+1997) |
| CRC | 7 | [7:1] | CID 的 CRC7 |
| 未用 | 1 | [0] | 恒为 1 |
生产日期注意:按 JESD84-B451(eMMC 4.5)起,若解码出的年份 < 2010,则需 +16 年(应对 4.41 时代字段设计不足);5.1B(rev≥9)进一步规定 < 2023 时 +16。设备固件按规范填写即可,主机端解码时按上述规则处理。
5.3 CSD(Card Specific Data Register,128 bit)
通过 CMD9(R2)读取。eMMC 使用 CSD Structure 1.2(位[127:126]=1)。关键字段:
| 字段 | 位宽 | CSD 位 | 说明 |
|---|---|---|---|
| CSD_STRUCTURE | 2 | [127:126] | =1(v1.2,eMMC 使用) |
| SPEC_VERS(mmca_vsn) | 4 | [125:122] | 规范版本(0–4,见 §1.3 的版本映射) |
| TAAC | 8 | [119:112] | 数据访问时间(mantissa+exponent 编码) |
| NSAC | 8 | [111:104] | 数据访问时间(时钟数,×100) |
| TRAN_SPEED | 8 | [103:96] | 最大传输速率(如 0x32 = 25 MHz,0x5A = 50 MHz,0x2B = 100 MHz 等) |
| CCC | 12 | [95:84] | 命令类别位图(§3.6) |
| READ_BL_LEN | 4 | [83:80] | 最大读块长(log2(字节),≥9) |
| READ_BL_PARTIAL | 1 | [79] | 支持部分块读(eMMC 恒 0) |
| WRITE_BLK_MISALIGN | 1 | [78] | 写块不对齐支持 |
| READ_BLK_MISALIGN | 1 | [77] | 读块不对齐支持 |
| DSR_IMP | 1 | [76] | 实现 DSR(配 CMD4) |
| C_SIZE | 12 | [73:62] | 容量编码(低容量设备用;高容量以 EXT_CSD SEC_CNT 为准) |
| C_SIZE_MULT | 3 | [49:47] | 容量倍率(配合 C_SIZE) |
| ERASE_GRP_SIZE | 5 | [46:42] | 擦除组大小(a,组大小 = (a+1)×(b+1) 写块) |
| ERASE_GRP_MULT | 5 | [41:37] | 擦除组倍率(b) |
| WP_GRP_SIZE | 5 | [36:32] | 写保护组大小(组数) |
| WP_GRP_ENABLE | 1 | [31] | 写保护组使能 |
| R2W_FACTOR | 3 | [28:26] | 写/读时间比(编程时间推导) |
| WRITE_BL_LEN | 4 | [25:22] | 最大写块长(log2(字节)) |
| WRITE_BL_PARTIAL | 1 | [21] | 部分块写(恒 0) |
| FILE_FORMAT_GRP / COPY / PERM_WRITE_PROT / TMP_WRITE_PROT | 4 | [15:12] | 文件格式组、复制标志、永久/临时写保护(出厂字段) |
| FILE_FORMAT | 2 | [11:10] | 文件格式 |
| ECC | 2 | [9:8] | ECC 类型 |
| CRC | 7 | [7:1] | CRC7 |
| 未用 | 1 | [0] | 恒为 1 |
容量说明(设备固件必须处理):
- 容量 < 2 GB:主机可用 CSD 的 C_SIZE 计算容量。
- 容量 ≥ 2 GB:必须置 OCR.CCS=1,容量以 EXT_CSD[212–215] SEC_CNT(扇区数,每扇区 512 B)为准,CSD 容量字段失效。
- 设备固件需保证 SEC_CNT = 各分区扇区数之和(boot+RPMB+GPP+User 的可用区域)。
6. 扩展寄存器 EXT_CSD 详解
EXT_CSD 共 512 字节,通过 CMD8 一次性读取;写入通过 CMD6(多数字段)或 CMD43(扩展字段)。以下为固件开发最常涉及的字段(偏移依据 JEDEC 5.1 / Linux mmc.h)。
6.1 字段总表(按偏移)
| 偏移 | 名称 | 访问 | 说明 |
|---|---|---|---|
| 15 | CMDQ_MODE_EN | R/W | 命令队列使能(bit0=1 使能,§8.5) |
| 25–28 | FFU_ARG | R/W | FFU 参数(固件升级,§12.3) |
| 26 | FFU_STATUS | R | FFU 执行状态(0x00=成功,0x10=错误等) |
| 27 | FFU_FEATURES | R | FFU 特性(bit0=支持多块写模式,bit1=支持 CMD23 模式等) |
| 28 | FFU_CNT | R | FFU 镜像块数(部分实现) |
| 29 | HPI_FEATURES | R | 高优先级中断特性(§12.4) |
| 32 | FLUSH_CACHE | W | 写 1 触发 cache 刷写(R1b,超时最长 30 s 量级) |
| 33 | CACHE_CTRL | R/W | bit0=1 使能写缓存 |
| 34 | POWER_OFF_NOTIFICATION | R/W | 关机通知:0=不支持,1=上电(ON),2=短关机,3=长关机(§12.7) |
| 35/36 | PACKED_FAILURE_INDEX / PACKED_CMD_STATUS | R | Packed 命令错误信息(4.5–5.0 遗留) |
| 44 | CMDQ_DEPTH | R | 队列深度(bit[4:0]+1,最大 32;≤2 视为不支持) |
| 45 | CMDQ_SUPPORT | R | bit0=1 支持 CMDQ |
| 54–55 | EXP_EVENTS_STATUS | R | 异常事件状态(bit0=紧急 BKOPS,bit1=动态容量告警等) |
| 56–57 | EXP_EVENTS_CTRL | R/W | 异常事件使能 |
| 61 | DATA_SECTOR_SIZE | R | 逻辑扇区大小:0=512 B,1=4096 B |
| 136–139 | ENH_START_ADDR | R/W | 增强区起始地址(4 字节,块寻址时 ×512) |
| 140–142 | ENH_SIZE_MULT | R/W | 增强区大小(×擦除组,见 §10.4) |
| 143–154 | GP_SIZE_MULT | R/W | GPP1–GPP4 大小(每区 3 字节,×擦除组) |
| 155 | PARTITION_SETTING_COMPLETED | R/W | 分区配置完成标志(bit0,置 1 后分区配置锁定) |
| 156 | PARTITION_ATTRIBUTE | R/W | 分区属性(bit0=User 区为增强区) |
| 160 | PARTITION_SUPPORT | R | 分区支持:bit0=GPP 支持,bit1=增强区支持 |
| 161 | HPI_MGMT | R/W | HPI 管理:写 1 使能 |
| 162 | RST_N_FUNCTION | R/W | RST_n 功能:0=禁用,1=永久使能(不可改),2=可配置使能 |
| 163 | BKOPS_EN | R/W | 后台操作使能:bit0=手动,bit1=自动(§12.5) |
| 164 | BKOPS_START | W | 写 1 触发手动 BKOPS |
| 165 | SANITIZE_START | W | 写 1 触发 Sanitize(§12.2) |
| 166 | WR_REL_PARAM | R | 可靠写参数:bit2=支持可靠写,bit4=支持 RPMB 可靠写 |
| 167 | WR_REL_SET | R/W | 可靠写分区设置(只对支持可靠写的分区有效) |
| 168 | RPMB_MULT | R | RPMB 大小倍率(×128 KB) |
| 169 | FW_CONFIG | R/W | bit0=1 禁止 FFU |
| 171 | USR_WP | R/W | User 区写保护(动态/永久) |
| 173 | BOOT_WP | R/W | Boot 区写保护(bit0=上电保护使能,bit2=永久保护使能等) |
| 174 | BOOT_WP_STATUS | R | Boot 区写保护状态 |
| 175 | ERASE_GROUP_DEF | R/W | bit0=1 时擦除组取 HC_ERASE_GRP_SIZE(512 KB 为单位) |
| 177 | BOOT_BUS_WIDTH | R/W | Boot 总线配置:bit[2:0]=宽度(0/1/2=x1/x4/x8),bit[4:3]=模式(0=SDR,1=DDR),bit5=RESET_BOOT_BUS_WIDTH |
| 178 | BOOT_CONFIG_PROT | R/W | Boot 配置保护(防误改 179) |
| 179 | PART_CONFIG | R/W | 分区配置(见 §6.2) |
| 181 | ERASED_MEM_CONT | R | 擦除态内容:0=0x00,1=0xFF |
| 183 | BUS_WIDTH | R/W | 总线宽度(见 §6.3) |
| 184 | STROBE_SUPPORT | R | bit0=1 支持增强选通(HS400ES) |
| 185 | HS_TIMING | R/W | 时序模式(见 §6.4) |
| 187 | POWER_CLASS | R/W | 电源等级选择(配合 PWRCL* 寄存器) |
| 192 | REV | R | EXT_CSD 修订号(版本映射见 §1.2) |
| 194 | STRUCTURE | R | EXT_CSD 结构版本(0–2) |
| 196 | CARD_TYPE | R | 支持的时序模式位图(见 §6.5) |
| 197 | DRIVER_STRENGTH | R | 支持的驱动强度(type 0–4 位图) |
| 198 | OUT_OF_INTERRUPT_TIME | R | HPI 中断超时(×10 ms) |
| 199 | PART_SWITCH_TIME | R | 分区切换超时(×10 ms) |
| 200–203 | PWR_CL_26/52(1.95/3.6 V) | R | 26/52 MHz 电源等级 |
| 212–215 | SEC_CNT | R | 用户区扇区数(4 字节小端),容量判定依据 |
| 217 | S_A_TIMEOUT | R | Sleep/Awake 超时(100 ns × 2^n) |
| 221 | HC_WP_GRP_SIZE | R | 高容量写保护组大小(×擦除组) |
| 222 | REL_WR_SEC_C | R | 可靠写扇区数 |
| 223 | ERASE_TIMEOUT_MULT | R | 擦除超时倍率(×300 ms) |
| 224 | HC_ERASE_GRP_SIZE | R | 高容量擦除组大小(×512 KB) |
| 226 | BOOT_MULT | R | Boot 分区大小(×128 KB) |
| 229/230 | SEC_TRIM_MULT / SEC_ERASE_MULT | R | 安全 TRIM/擦除超时倍率(×300 ms) |
| 231 | SEC_FEATURE_SUPPORT | R | 安全特性:bit0=Secure Erase,bit2=安全块级擦除,bit4=安全 GC,bit6=Sanitize |
| 232 | TRIM_MULT | R | TRIM 超时倍率(×300 ms) |
| 236–239/253 | PWR_CL_200/DDR_52/DDR_200 | R | 高速模式电源等级 |
| 246 | BKOPS_STATUS | R | BKOPS 状态等级(≥2=紧急) |
| 247 | POWER_OFF_LONG_TIME | R | 长关机超时(×10 ms) |
| 248 | GENERIC_CMD6_TIME | R | CMD6 通用超时(×10 ms) |
| 249–252 | CACHE_SIZE | R | 写缓存大小(4 字节) |
| 254–261 | FIRMWARE_VERSION | R | 固件版本(8 字节,5.0+) |
| 267 | PRE_EOL_INFO | R | 预寿命终结信息(0=正常,1=正常(>90%),2=警告,3=严重) |
| 268/269 | DEVICE_LIFE_TIME_EST_TYP_A/B | R | 估计寿命(0–10,A=MLC 区,B=SLC 区) |
| 307 | CMDQ_DEPTH | R | 队列深度(5.1 位置;与 44 并存,5.1 实际用 307) |
| 308 | CMDQ_SUPPORT | R | 队列支持(5.1) |
| 493 | SUPPORTED_MODE | R | bit0=支持 FFU |
| 498/499 | TAG_UNIT_SIZE / DATA_TAG_SUPPORT | R | 数据标签特性(5.0) |
| 502 | BKOPS_SUPPORT | R | bit0=支持 BKOPS |
| 503 | HPI_FEATURES | R | bit0=HPI 用 CMD13,bit1=HPI 用 CMD12 |
| 504 | S_CMD_SET | R/W | 当前命令集(bit0=Normal) |
注:44/45 与 307/308 同为 CMDQ 深度/支持字段——JEDEC 5.1 将正式定义放在 307/308,早期草案字段在 44/45;实现时应以 307/308 为准。
6.2 EXT_CSD[179] PART_CONFIG(分区配置)
1 | bit 7 6:5 4 3 2:0 |
- BOOT_ACK_ENABLE[7]:1 = 允许 Boot 操作时设备发送 ACK 响应。
- BOOT_PARTITION_ENABLE[6:5]:00 = 非启动设备;01 = 从 Boot1 启动;10 = 从 Boot2 启动;11 = 保留。
- PARTITION_ACCESS[2:0]:当前访问分区:000=User,001=Boot1,010=Boot2,011=RPMB,100–111=GPP1–4。
- 切换分区用 CMD6 写该字节;切换后需等待 PART_SWITCH_TIME(≥300 ms 兜底)。
- 分区切换期间设备不接受数据传输命令。
6.3 EXT_CSD[183] BUS_WIDTH(总线宽度)
| 值 | 模式 |
|---|---|
| 0x0 | x1 SDR(默认) |
| 0x1 | x4 SDR |
| 0x2 | x8 SDR |
| 0x3 / 0x4 | 保留 |
| 0x5 | x4 DDR(DDR52) |
| 0x6 | x8 DDR(DDR52 或 HS400) |
| bit7(0x80,与 0x6 组合) | 增强选通(HS400ES) |
- 切换 BUS_WIDTH 后主机必须同步调整自身控制器位宽,否则通信失败。
- 设备固件收到 BUS_WIDTH 写请求时,在 busy 释放前完成内部数据通路位宽重配置。
6.4 EXT_CSD[185] HS_TIMING(时序模式)
| 值 | 模式 | 时钟/带宽(x8) |
|---|---|---|
| 0x0 | Legacy / 向后兼容(Backward Compatible) | ≤25 MHz(或 26 MHz) |
| 0x1 | High Speed(HS) | ≤52 MHz |
| 0x2 | HS200 | 200 MHz SDR,200 MB/s |
| 0x3 | HS400 | 200 MHz DDR,400 MB/s |
| 0x4 | HS400ES | HS400 + 增强选通 |
- 切换顺序有严格约束(见 §7.3):Legacy→HS→HS200→HS400 必须逐级切换,不允许直接跳级。
- HS200/HS400 切换后必须执行调谐(HS400ES 除外,见 §7.4)。
6.5 EXT_CSD[196] CARD_TYPE(能力位图)
| 位 | 含义 |
|---|---|
| 0 | 支持 26 MHz(HS26) |
| 1 | 支持 52 MHz(HS52) |
| 2 | 支持 DDR52 @ 1.8/3.3 V I/O |
| 3 | 支持 DDR52 @ 1.2 V I/O |
| 4 | 支持 HS200 @ 1.8 V |
| 5 | 支持 HS200 @ 1.2 V |
| 6 | 支持 HS400 @ 1.8 V |
| 7 | 支持 HS400 @ 1.2 V |
| 8 | 支持 HS400ES |
设备固件必须如实上报;主机据此决定可用的最高模式(同时受主机能力约束)。
7. 设备识别与初始化流程
7.1 初始化序列总览(主机视角)
1 | 上电/复位(CLK ≤ 400 kHz,x1,开漏) |
7.2 各步骤要点
- CMD1 电压协商:主机第一次发 CMD1 用 arg=0x0(只查询),第二次用自身支持的电压窗口。设备以”主机窗口 ∩ 设备窗口”返回 R3,并保持 busy 直到内部初始化完成。若交集为空,主机应放弃。
- RCA 分配:单设备场景 RCA 取 1;多设备场景每设备不同(bit[31:16],bit[15:0] 恒 0)。设备固件保存 RCA,后续所有 ac 命令都要求匹配 RCA(不匹配的 CMD13/CMD7 等应忽略或按规范处理)。
- CMD7 选中:arg = RCA<<16。若 arg=0 则去选(回 stby)。选中后进入 tran 状态,才能执行数据传输。
- 读取 EXT_CSD:CMD8 返回 512 字节。主机解析 CARD_TYPE、BOOT_MULT、PART_CONFIG、SEC_CNT、HC_ERASE_GRP_SIZE、CMDQ/HPI/BKOPS 等能力。
- 总线宽度切换:先尝试 x8(若主机支持),失败则 x4,再失败保持 x1。可用 CMD14/CMD19(BUS_TEST_R/W)校验位宽是否真实生效——写 0x5A 测试块再读回比对,或比较不同位宽下读取的 EXT_CSD 只读字段是否一致(Linux 的 mmc_compare_ext_csds 方法)。
- 时序模式升级:按 §7.3 逐步升级并调谐。
- 特性使能:Cache(CACHE_CTRL=1,超时建议 ≥1.6 s)、BKOPS(自动模式优先)、HPI、CMDQ、POWER_OFF_NOTIFICATION(关机前)。每个都通过 CMD6 完成,注意各自超时。
7.3 时序模式切换序列(严格顺序)
Legacy → HS(≤52 MHz):
- CMD6 写 HS_TIMING=0x1(用 GENERIC_CMD6_TIME 超时)。
- 主机将 CLK 提升至 ≤52 MHz。
→ HS200(200 MHz SDR):
- 先将 I/O 电压切至 1.8 V 或 1.2 V(主机电源轨操作)。
- CMD6 写 HS_TIMING=0x2,CLK ≤ 200 MHz。
- 执行 HS200 调谐(CMD21,见 §7.4)。
→ HS400(200 MHz DDR):
- 先在 HS200 下完成调谐(HS400 复用 HS200 的调谐结果)。
- CMD6 写 HS_TIMING=0x1(回退到 HS,CLK ≤ 52 MHz)。
- CMD6 写 BUS_WIDTH=0x6(x8 DDR)。
- CMD6 写 HS_TIMING=0x3(HS400),CLK 升至 200 MHz。
- 此后设备驱动 DS 引脚(数据选通)。
→ HS400ES(设备支持且 STROBE_SUPPORT=1 时):
- 重复 HS400 的 1–3 步(HS200 调谐仍需要,用于 CMD 采样点)。
- CMD6 写 BUS_WIDTH=0x86(x8 DDR + 增强选通位)。
- CMD6 写 HS_TIMING=0x4。
降级/回退:任何模式失败时主机应回退到上一级模式重新初始化;设备固件应容忍”切换后主机不再通信”的情况(以超时/复位兜底)。
7.4 调谐(Tuning)
- 目的:HS200/HS400 在 200 MHz 下,CMD/DAT 的建立保持时间余量极小,主机必须找到最佳采样延迟。
- 机制:主机反复发送 CMD21(SEND_TUNING_BLOCK_HS200),设备每次返回固定 64 字节调谐块;主机扫描采样延迟窗口,找出 CRC/位错全部消失的中心点并锁定。
- 设备固件要求:调谐块内容固定(厂商可自定义但须稳定);调谐期间不执行 FTL 操作、不回忙。
- 主机侧注意:调谐须在每次模式进入时执行;运行中温度漂移可触发重调谐(re-tuning,由主机定时或按错误触发)。
7.5 初始化失败处理(主机侧清单)
| 现象 | 排查 |
|---|---|
| CMD0 无响应 | 检查供电、时钟(≤400 kHz)、CMD 线上拉、CRC |
| CMD1 一直忙 | 电压不匹配;等待时间不足 |
| CMD2 响应 CRC 错 | 时钟过快;信号质量(建议逻辑分析仪抓 CMD 线) |
| CMD7 后 CMD13 状态异常 | RCA 不匹配;设备未进入 tran |
| CMD8 数据 CRC 错 | 位宽/电压配置不一致;DAT 线问题 |
| 切 HS200/HS400 后通信全断 | 未调谐;电压未先切 1.8/1.2 V;跳级切换 |
8. 数据传输协议
8.1 块与寻址
- 逻辑块大小固定 512 B(DATA_SECTOR_SIZE=1 时为 4096 B,但主流设备仍为 512 B 逻辑扇区)。
- 高容量设备(CCS=1)使用 LBA 块寻址:命令参数直接是块号。
- 低容量设备(CCS=0)使用字节地址(遗留,仅旧设备)。
8.2 单块读/写
1 | 读:CMD17(LBA) → R1 → [DAT: 512B + CRC16](读方向,设备发) |
- 读数据首块开始时间受 TAAC/NSAC(Nac)限制,主机须设超时。
- 写完成后设备在 DAT0 上拉低表示编程忙;主机必须等待忙释放(或轮询 CMD13)才能发下一条命令。
8.3 多块读/写
两种方式:
预定义多块(推荐):
1
CMD23(块数 N) → R1 → CMD18/CMD25(LBA) → R1 → 连续传输 N 块
CMD23 的 SET_BLOCK_COUNT 在 CMD18/CMD25 之前发出;设备按计数自动结束,无需 CMD12。
开放多块(遗留):
1
CMD18/CMD25(LBA) → R1 → 连续传输 → CMD12(STOP_TRANSMISSION) → R1/R1b
读中止:R1;写中止:R1b(等编程结束)。设备固件在收到 CMD12 后须立即停止数据流。
- 多块传输中块间无间隙(back-to-back),块与块之间依次为 数据+CRC16+End bit。
- 对主机:推荐 CMD23 方式(省一次 CMD12 往返,且可靠写/CMDQ 依赖它)。
- 对设备固件:CMD23 的块数必须在 CMD18/25 前锁定;若 CMD23 后收到非传输命令,块数状态应复位。
8.4 擦除 / TRIM / Discard(回顾 §4.4)
| 操作 | 命令序列 | 用途 |
|---|---|---|
| Erase | CMD35 + CMD36 + CMD38(0x0) | 物理擦除(组对齐) |
| TRIM | CMD35 + CMD36 + CMD38(0x1) | 逻辑无效化(建议主机日常用) |
| Discard | CMD35 + CMD36 + CMD38(0x3) | 数据不再需要,立即回收 |
| Secure Erase | CMD35 + CMD36 + CMD38(0x80000000) | 安全擦除(需 SEC_FEATURE_SUPPORT) |
| Secure TRIM | CMD35 + CMD36 + CMD38(0x80000001→0x80008000) | 两阶段安全 TRIM |
设备固件注意:
- TRIM/Discard 范围可任意块;Erase/Secure 需组对齐,否则返回 ERASE_PARAM/ADDRESS_OUT_OF_RANGE。
- Discard 后读回值不定(可能 0x00/0xFF/旧数据),主机不得依赖;TRIM 后读回为擦除态。
- 擦除/TRIM 与 CMDQ、Cache 的交互:挂起/排队策略需固件内部处理(见 §14)。
8.5 命令队列(CMDQ,eMMC 5.1)
背景:HS400 下单次命令往返开销占比高;CMDQ 允许主机一次提交最多 32 个任务(读/写混合),设备内部排序执行,显著提升随机 IO 性能。
使能条件:
- EXT_CSD[308] CMDQ_SUPPORT=1,且深度 EXT_CSD[307] CMDQ_DEPTH ∈ [3,32]。
- 主机 CMD6 写 EXT_CSD[15] CMDQ_MODE_EN=1。
- 启用后只能使用队列命令(CMD44–48)传输数据;CMD17/18/24/25 与 Packed 命令不可用。
使用流程:
1 | 1. 使能:CMD6(CMDQ_MODE_EN=1) |
关键语义:
- 任务号 0–31 由主机分配,设备按任务号跟踪。
- 设备固件可按优先级、方向(写优先)自行调度;规范要求设备必须支持乱序完成。
- 可靠写(Reliable Write)任务保证落盘(配合 REL_WR_SEC_C);FUA 任务保证刷 cache。
- RPMB、Sanitize 等操作前必须禁用 CMDQ(Linux 中表现为临时的 cmdq 关闭再使能)。
8.6 错误处理与重试(主机侧)
| 错误 | 检测 | 处理 |
|---|---|---|
| 命令 CRC 错 | R1.COM_CRC_ERROR | 重发命令(CRC 由主机控制器校验,一般不会发生) |
| 命令非法 | R1.ILLEGAL_COMMAND | 降级特性(如不支持 TRIM 则用 Erase) |
| 地址越界 | R1.OUT_OF_RANGE | 修正范围 |
| 读数据 CRC 错 | DAT CRC16 校验失败 | 发 CMD12 中止;若已用 CMD23 则等计数结束;重读该区域 |
| 写数据 CRC 错 | 设备回 R1.ERROR 或忙后失败 | 重写;若反复失败考虑坏块 |
| ECC 无法纠正 | R1.CARD_ECC_FAILED | 数据损坏,报上层;设备侧触发坏块/刷新流程 |
| 写超时/忙超时 | DAT0 长时间忙 | 复位(CMD0 或硬件复位),必要时重新初始化 |
| 擦除超时 | 超过 300ms×MULT | 用 CMD13 确认状态,必要时复位 |
设备固件侧对应职责:CRC 校验失败时不得提交数据;编程失败(NAND 写失败/ECC 超限)必须报告(R1.ERROR/CARD_ECC_FAILED 或卡在 busy 后回错)并触发内部坏块重映射。
8.7 写保护
- 分组写保护:CMD28/CMD29 按写保护组(WP 组 = HC_WP_GRP_SIZE × 擦除组)设置/清除;CMD30 读回 256 位保护位图。
- 永久写保护:User 区用 EXT_CSD[171] USR_WP(bit0=保护使能,bit1=永久,bit2=动态);Boot 区用 EXT_CSD[173] BOOT_WP;写保护后对应分区不可再写(Boot 区保护后仅硬件复位可解除动态保护,永久保护不可逆)。
- 设备固件必须对写保护区域拒绝写/擦除命令并返回 WP_VIOLATION。
9. Boot 操作
9.1 概念
eMMC 可作为系统启动介质:上电后无需完整协议初始化,设备即可在 Boot 分区 中连续输出启动代码,供 SoC ROM 直接加载。Boot 分区为 Boot1/Boot2 两个只读分区(写需特殊配置),大小相等,由 EXT_CSD[226] BOOT_MULT × 128 KB 决定。
9.2 使能配置(生产时由工厂/主机写入)
| 配置 | 字段 | 说明 |
|---|---|---|
| 启动使能 | EXT_CSD[179] BOOT_PARTITION_ENABLE[6:5] | 01=Boot1,10=Boot2 |
| Boot ACK | EXT_CSD[179] BOOT_ACK_ENABLE[7] | 1=设备在 Boot 开始时回 R1 |
| Boot 总线 | EXT_CSD[177] BOOT_BUS_WIDTH | x1/x4/x8,SDR/DDR;bit5=启动后复位为 x1 SDR |
| 保护 | EXT_CSD[173] BOOT_WP | 防止 Boot 区被意外改写 |
9.3 Boot 操作序列
1 | 1. 上电,主机拉高电平,CLK 以 ≤400 kHz 或已协商的 Boot 频率运行 |
要点:
- Boot 数据是”流”,无块边界/无 CRC,由主机按长度裁剪;数据连续输出,主机靠时钟控制接收。
- 主机也可通过停止时钟暂停/终止 Boot(规范允许终止方式之一)。
- 若 BOOT_PARTITION_ENABLE=00,设备不进入 Boot 模式,直接响应普通 CMD0(arg=0)初始化。
- 固件注意:设备端 Boot 数据源通常是”Boot 分区内固定偏移的原始 NAND 内容”,不经 FTL 映射,因此 Boot 分区写入必须保证连续物理页布局(厂商固件内部处理)。
10. 分区管理
10.1 分区类型总览
eMMC 设备存储空间划分为以下分区:
| 分区 | 数量 | 大小公式 | 可访问性 | 用途 |
|---|---|---|---|---|
| Boot1 / Boot2 | 2 | BOOT_MULT[226] × 128 KB(两区等大) | PART_CONFIG acc=01/10 | 系统启动代码,只读保护 |
| RPMB | 1 | RPMB_MULT[168] × 128 KB | acc=03,专用协议 | 安全数据(密钥、计数器等) |
| GPP1–GPP4 | 0–4 | GP_SIZE_MULT[143–154](每区 3 字节,单位=HC_ERASE_GRP_SIZE × HC_WP_GRP_SIZE × 512 B) | acc=04–07 | 通用分区(可自定义用途) |
| User Area | 1 | SEC_CNT[212–215] − 其他分区总和 | acc=00 | 主数据区 |
10.2 分区大小计算
Boot 分区:
- 大小 = EXT_CSD[226] × 128 KB(若值=0 则无 Boot 分区)。
- 两区对称,各独立可写。
RPMB 分区:
- 大小 = EXT_CSD[168] × 128 KB。
- 若 RPMB_MULT=0,则无 RPMB 分区。
GPP(通用目的分区):
- 每个 GPP 大小 = GP_SIZE_MULT[i] × HC_ERASE_GRP_SIZE × HC_WP_GRP_SIZE × 512 B。
- HC_ERASE_GRP_SIZE = EXT_CSD[224](单位 512 KB);HC_WP_GRP_SIZE = EXT_CSD[221](单位擦除组)。
- 若 GP_SIZE_MULT=0(3 字节全 0),该 GPP 不存在。
增强区(Enhanced Area):
- 部分 User 区或 GPP 可配置为增强区(性能更高,通常是 SLC 模式或可靠写区域)。
- 起始地址:ENH_START_ADDR[136–139];大小:ENH_SIZE_MULT[140–142] × HC_ERASE_GRP_SIZE × HC_WP_GRP_SIZE × 512 B。
- 分区属性 PARTITION_ATTRIBUTE[156] bit0=1 表示 User 区有增强属性。
- 注意:分区配置一旦完成(PARTITION_SETTING_COMPLETED[155]=1),分区大小和增强区设置不可再修改(掉电不可恢复!)。
10.3 分区切换与访问
- 主机发送 CMD6 写 EXT_CSD[179] PART_CONFIG,将 PARTITION_ACCESS[2:0] 设为目标分区编码。
- 等待 PART_SWITCH_TIME(≥300 ms,由 EXT_CSD[199] 或 GENERIC_CMD6_TIME 决定)。
- 发 CMD13 确认设备处于 tran 且无错误。
- 之后的数据传输命令访问目标分区。
切换期间的限制:
- 正在编程/擦除时不可切换(设备回 SWITCH_ERROR 或 R1b 延长)。
- RPMB 切换时必须同时禁用 CMDQ(若已启用)。
- Boot 区切换后写保护可能生效(视 BOOT_WP 配置)。
10.4 分区配置的安全性
- 一次性配置:PARTITION_SETTING_COMPLETED=1 后,分区表锁定。设备固件应拒绝再修改 GP_SIZE_MULT、ENH_SIZE_MULT 等字段(回 SWITCH_ERROR)。
- 保护 Boot 区:BOOT_WP 配置(bit0=上电保护,bit2=永久保护)在分区配置完成后应设置;永久保护不可逆,须谨慎。
- RPMB 保护:RPMB 区域的读写必须经 HMAC 认证(见 §11),主机无法绕过认证直接读写。
11. RPMB(重放保护内存块)
11.1 概念
RPMB 是一个硬件级防篡改分区,专为存储安全敏感数据(密钥、设备标识、计数器、DRM 凭据等)设计。特性:
- 认证写入:每笔写操作必须附带 HMAC-SHA256 签名(256-bit 密钥),签名不匹配则拒绝。
- 抗重放:内置单调递增写计数器(Write Counter,32 bit),每次成功写入自动 +1;主机侧保存计数器值,若低于预期则拒绝(防回滚)。
- 防物理读:未认证的读操作返回数据但不保证完整性(建议主机总是认证读)。
11.2 RPMB 帧格式(512 字节)
RPMB 通信使用固定 512 字节帧,写入用 CMD25(目标=RPMB 分区),读取用 CMD17/CMD18。
请求帧(写方向,CMD25 发送):
| 字节偏移 | 字段 | 大小 | 说明 |
|---|---|---|---|
| 0–3 | 保留 | 4 B | 填 0 |
| 4–5 | 请求类型 | 2 B | 见下方 |
| 6–261 | 数据 | 256 B | 写数据(READ/WRITE)或保留 |
| 262–263 | 保留 | 2 B | — |
| 264–267 | 写计数器 | 4 B | 主机填入预期值(WRITE/SECURE_WRITE) |
| 268–279 | 地址 | 12 B | [271:268] 保留,[275:272] LBA,[279:276] 保留 |
| 280–283 | 保留 | 4 B | — |
| 284–287 | Nonce | 4 B | 随机数(READ 用,WRITE 可选) |
| 288–319 | HMAC | 32 B | HMAC-SHA256 签名 |
| 320–511 | 保留 | 192 B | 填 0 |
响应帧(读方向,CMD17/CMD18 返回):结构类似,但数据区包含读出数据。
请求/响应类型:
| 请求类型 | 值 | 说明 |
|---|---|---|
| PROGRAM_KEY | 0x0001 | 写入认证密钥(一次性,不可更改) |
| RESULT_READ | 0x0002 | 读取上一次操作结果(状态) |
| WRITE | 0x0003 | 认证写入 |
| READ | 0x0004 | 认证读取 |
| GET_WRITE_COUNTER | 0x0005 | 查询写计数器 |
响应类型:请求类型 | 0x0100(如 WRITE 响应 = 0x0103)。
结果码:
| 结果码 | 含义 |
|---|---|
| 0x0000 | 操作成功 |
| 0x0001 | 通用失败 |
| 0x0002 | 认证失败(HMAC 错误) |
| 0x0003 | 计数器失败(值不匹配) |
| 0x0004 | 地址失败(地址越界) |
| 0x0005 | 写失败 |
| 0x0006 | 读失败 |
| 0x0007 | 密钥未编程(首帧未写密钥) |
11.3 RPMB 交互流程
密钥编程(一次性,生产阶段):
1 | 1. 主机构造请求帧(type=PROGRAM_KEY,数据区放 256-bit 密钥) |
认证写:
1 | 1. 读取当前计数器(GET_WRITE_COUNTER) |
认证读:
1 | 1. 构造请求帧(type=READ,nonce 随机数) |
11.4 设备固件实现要点
- 密钥存储:密钥编程后写入 NAND 安全区域(或 OTP 区),不经过 FTL 映射;掉电后不可丢失。
- 写计数器:存于 RPMB 专属 NAND 区域(日志结构),每次成功写入原子递增;掉电时可能已完成递增但数据未完全写入——固件须保证计数器原子更新与数据写入的一致性。
- HMAC 计算:SHA-256 的 HMAC,密钥 256 bit。覆盖帧内 [4–319](不含帧头保留域,不含 HMAC 域本身)。
- 并发:RPMB 操作期间应挂起普通分区的 CMDQ/Cache 操作。
- RPMB 与可靠写:WR_REL_PARAM[166] bit4=EN_RPMB_REL_WR 时支持可靠写。
12. 安全、可靠性与维护特性
12.1 安全擦除(Secure Erase / Secure TRIM)
见 §4.4 CMD38 参数。Secure Erase(0x80000000)物理擦除所有范围内 NAND 块并确保旧数据不可恢复;Secure TRIM 用两阶段机制(CMD38 0x80000001 → 0x80008000)防止掉电导致数据残留。需 SEC_FEATURE_SUPPORT[231] bit0(Secure Erase)和 bit4(Secure GC/Trim)支持。
12.2 Sanitize
用途:TRIM/Discard 后数据可能物理残留(FTL 未回收前仍存在于 NAND);Sanitize 强制清除这些”逻辑无效但物理残留”的数据。
流程:1
2
31. 主机先对目标范围执行 TRIM/Discard(CMD38 0x1/0x3)
2. CMD6 写 EXT_CSD[165] SANITIZE_START=1(R1b,长时间忙)
3. 等待 Sanitize 完成(忙释放)——过程可能持续数分钟到数小时
- Sanitize 不可中断,不可与其他数据命令并发。
- 支持条件:EXT_CSD[231] SEC_FEATURE_SUPPORT bit6=1。
- 若设备在 Sanitize 中断电,数据状态不确定(规范未保证原子性)。
12.3 现场固件升级(FFU,eMMC 5.0+)
用途:在线更新设备内部固件,无需物理更换。
前提:EXT_CSD[493] SUPPORTED_MODE bit0=1 且 EXT_CSD[169] FW_CONFIG bit0=0。
流程:1
2
3
4
5
61. 读取 FIRMWARE_VERSION[254–261](8 字节)确认当前版本
2. 读取 FFU_FEATURES[27] 确认支持的写入模式
3. 写 FFU_ARG[25–28](4 字节)设置升级参数
4. 发送 CMD23(块数) + CMD25(起始地址) 将固件镜像写入(镜像以 512B 块计)
5. 轮询 FFU_STATUS[26]:0x00=成功,0x10=错误,0x11=设备忙,0x12=版本不匹配
6. 成功后掉电/硬件复位,新固件生效
- 固件镜像格式厂商特定,通常包含头信息(版本、校验和、分区布局)。
- 升级期间设备不响应普通数据命令。
- 升级失败(断电/校验错)设备应回退到旧固件(厂商实现,规范不强制)。
- eMMC 5.1 增强了 FFU 的多块写模式和 CMD23 支持(FFU_FEATURES[27] 各位指示)。
12.4 高优先级中断(HPI)
用途:主机中断长时间操作(擦除、TRIM、Sanitize),立即读取状态/执行其他命令。
机制:
- HPI_FEATURES[503]:bit0=支持用 CMD13 中断,bit1=支持用 CMD12 中断。
- HPI_MGMT[161]:写 1 使能 HPI。
- 主机发 HPI 命令(CMD13 或 CMD12)后,设备中止当前操作并回 R1。
- OUT_OF_INTERRUPT_TIME[198]:中断后设备保证在该时间内恢复正常状态(×10 ms)。
设备固件要求:HPI 收到时若正在 FTL/GC,需安全中止(保存中间状态);返回的 Card Status 中 READY_FOR_DATA 和 CURRENT_STATE 必须反映实际状态。
12.5 后台操作(BKOPS)
用途:设备内部的维护任务(磨损均衡、垃圾回收、坏块扫描等)。
控制:
- BKOPS_SUPPORT[502]:设备是否支持。
- BKOPS_EN[163]:bit0=手动使能,bit1=自动使能。
- BKOPS_START[164]:写 1 触发手动 BKOPS。
- BKOPS_STATUS[246]:当前 BKOPS 等级(≥2=紧急,需主机让出总线时间)。
- EXP_EVENTS_STATUS[54] bit0:URGENT_BKOPS(异常事件,设备主动通知主机)。
主机行为:在 I/O 空闲期让设备执行 BKOPS(通过 CMD6 写 BKOPS_EN=1 或发送 BKOPS_START),避免设备在繁忙时突发 GC 导致性能抖动。
12.6 Cache 与掉电
Cache 机制:
- CACHE_CTRL[33]:写 1 使能写缓存。
- 写命令数据先进入 cache(快),后台再写入 NAND(慢)。
- FLUSH_CACHE[32]:写 1 触发强制刷写(R1b,超时可长达 30 s)。
掉电流程(主机侧,见 Linux mmc_poweroff_notify):
- 刷写 cache(FLUSH_CACHE)。
- 发 POWER_OFF_NOTIFICATION[34]:短通知(快速关机)或长通知(完整刷写后关机)。
- 掉电。
- 设备收到长通知后保证 cache 落盘(POWER_OFF_LONG_TIME[247] 超时)。
- 未通知直接断电可能导致 cache 数据丢失(规范未保证)。
- 设备固件须在 掉电检测中断 中紧急刷写 cache(若有备电/大电容)。
12.7 寿命监控
| 字段 | 偏移 | 含义 |
|---|---|---|
| PRE_EOL_INFO | 267 | 0x01=正常(>90% 寿命),0x02=警告(80%消耗),0x03=严重(建议更换) |
| DEVICE_LIFE_TIME_EST_TYP_A | 268 | MLC 区估计寿命(0x01–0x0B,0x01=<10%消耗,0x02=10–20%,…,0x0B=100%消耗,0x00=未定义) |
| DEVICE_LIFE_TIME_EST_TYP_B | 269 | SLC cache 区估计寿命(同上编码) |
主机应定期读取这些字段,上报健康状态;PRE_EOL_INFO=0x03 时应触发告警/更换流程。
13. 时序模式与性能
13.1 时序模式总览
| 模式 | 时钟频率 | 位宽 | 信号方式 | 最大带宽(×8) | 引入版本 | 信号电压 |
|---|---|---|---|---|---|---|
| Legacy | 25 MHz | x1/x4/x8 | SDR | 25 MB/s(×8) | 4.0 | 3.3 V |
| High Speed(HS) | 52 MHz | x1/x4/x8 | SDR | 52 MB/s(×8) | 4.0 | 3.3 V 或 1.8 V |
| DDR52 | 52 MHz | x4/x8 | DDR | 104 MB/s(×8) | 4.4 | 1.8 V 或 1.2 V |
| HS200 | 200 MHz | x4/x8 | SDR | 200 MB/s(×8) | 4.5 | 1.8 V 或 1.2 V |
| HS400 | 200 MHz | x8 | DDR | 400 MB/s(×8) | 5.0 | 1.8 V 或 1.2 V |
| HS400ES | 200 MHz | x8 | DDR + 增强选通 | 400 MB/s | 5.1 | 1.8 V 或 1.2 V |
- SDR:数据在 CLK 上升沿采样。
- DDR:数据在 CLK 双沿采样(主机必须支持 DDR 控制器)。
- DS(Data Strobe):HS400 模式下设备输出 DS 信号(200 MHz,与数据同相),主机用 DS 而非 CLK 采样数据——大幅降低时序偏移容忍要求。HS400ES 进一步使用 DS 调谐机制(主机按 DS 边沿调整采样点)。
13.2 驱动强度
EXT_CSD[197] DRIVER_STRENGTH 上报支持的驱动强度类型:
| 类型 | 值 | 说明 |
|---|---|---|
| Type 0 | 0x1 | 50 Ω(默认) |
| Type 1 | 0x2 | 33 Ω(更强驱动,适合长走线) |
| Type 2 | 0x4 | 66 Ω |
| Type 3 | 0x8 | 100 Ω |
| Type 4 | 0x10 | 40 Ω |
- HS200/HS400 切换前可选 CMD6 写 HS_TIMING 时附带驱动强度(bit[7:4])。
- 设备固件在 HS_TIMING 写入时同步更新输出驱动强度。
13.3 性能影响因素
- SLC Cache:多数现代 eMMC 使用 TLC/QLC 颗粒,配备 SLC Cache(将部分 TLC 区当 SLC 用),写入时先进 SLC Cache(快),Cache 满后直接写 TLC(慢,持续带宽骤降)。Cache 大小由厂商决定,不可通过 EXT_CSD 配置。
- 后台操作:BKOPS/GC 期间写延迟增加。
- CMDQ:多任务并行可掩盖命令往返开销;深度 16–32 时随机 4K IOPS 显著提升。
- 写放大:FTL 的 GC 产生额外写入;TRIM/Discard 帮助 GC 预判无效块,减少写放大。
14. eMMC 设备内部架构与 FTL
本章从设备固件开发视角描述 eMMC 内部结构——这些内容在协议规范中不可见,但对固件工程师至关重要。
14.1 内部架构总览
1 | ┌──────────────────────────────────────────────────────────┐ |
14.2 NAND 颗粒特性(固件须知)
| 特性 | 说明 | 固件影响 |
|---|---|---|
| 页大小 | 4 KB / 8 KB / 16 KB(+ OOB) | 决定 LBA→物理页映射粒度 |
| 块大小 | 128–512 页(0.5–8 MB) | 决定擦除单位、GC 粒度 |
| 页类型 | SLC(1 bit/cell)/ MLC(2)/ TLC(3)/ QLC(4) | SLC 写快但容量低;TLC/QLC 写慢但容量高 |
| 读干扰 | 同一块内相邻页读次数过多导致数据错误 | 读计数管理、定期刷新 |
| 编程干扰 | 编程相邻页时可能影响已编程页 | 严格顺序编程(sequential write) |
| 数据保持 | TLC 通常 1 年(@ 室温),写入后 1 年内读出正确 | 定期刷新(read reclaim) |
| 坏块 | 出厂及使用中新产生(写/擦除计数超过阈值) | BBT 管理、坏块替换 |
| 擦除计数 | SLC: 10万次;MLC: 3千–1万;TLC: 1千–3千 | 磨损均衡必须覆盖全盘 |
14.3 FTL 核心模块
14.3.1 地址映射(L2P Table)
- 逻辑块地址(LBA)→ 物理 NAND 页地址的映射表。
- 映射粒度:通常按”逻辑页”(512 B 或 4 KB,视实现)。
- 映射表存储:SRAM(热页)+ NAND 映射区(冷页),启动时从 NAND 加载。
- 混合映射:eMMC 通常采用页级映射(page-level mapping)以支持随机写,代价是 L2P 表较大(16 GB eMMC 约需 4 MB SRAM 存映射,分层管理)。
14.3.2 垃圾回收(GC)
- 写入新数据时旧页标记为无效;无效页累积后块变”脏”。
- GC 选择脏块,将其中有效页搬移到新块,然后擦除脏块。
- GC 类型:
- 前台 GC(Foreground GC):主机写入时触发,阻塞主机——导致写延迟抖动。
- 后台 GC(Background GC):在 I/O 空闲期提前执行,减少前台抖动(BKOPS 的一部分)。
- GC 策略:选择无效页比例最高的块优先回收(贪心),或按磨损均衡选择。
14.3.3 磨损均衡(Wear Leveling)
- 动态均衡:仅对热数据块轮换使用新擦除块。
- 静态均衡:也搬移冷数据块(低擦除计数块放热数据,高计数块放冷数据),使全盘擦除计数趋同。
- eMMC 设备通常内置静态+动态均衡;固件需维护擦除计数表(NAND 或 SRAM)。
14.3.4 坏块管理(BBM)
- 出厂坏块标记:NAND 块的 spare area 第一个字节 ≠ 0xFF。
- 使用中坏块:写/擦除失败(ECC 超限、编程超时)标记为坏块。
- 替换策略:保留”预留块”(spare blocks,出厂时预留若干块),坏块发生时用预留块替换。
- BBT(Bad Block Table):存在 NAND 固定区域,启动时加载到 SRAM。
14.3.5 掉电保护
- 日志结构:FTL 的 L2P 表更新、GC 操作、擦除等写入操作用日志结构(journal)记录,掉电后通过日志恢复一致性。
- 原子写:关键操作(如 L2P 表更新)使用”先写新→再标记旧→最后提交”的方式,保证掉电后不丢失一致性。
- 备电电容:部分高端 eMMC 内置电容,掉电时可将 SRAM 中的脏数据刷入 NAND。
- POWER_OFF_NOTIFICATION(见 §12.7):设备收到通知后提前刷写缓存、完成 GC。
14.3.6 ECC 纠错
- NAND 页的 OOB 区域存储 ECC 校验码。
- 纠错能力:BCH(50–80 bit/1KB)或 LDPC(更强,适合 TLC/QLC)。
- ECC 不可纠正时返回 CARD_ECC_FAILED(R1 位 21);固件应触发坏块标记+数据恢复(从镜像/冗余页)。
- 读刷新(Read Reclaim):读取 ECC 错误接近阈值时,将页数据重写到新位置(防止进一步恶化)。
14.4 性能调优(固件侧)
- SLC Cache:写入先进 SLC 区,空闲时迁移到 TLC 区——Cache 策略(大小、迁移时机)直接影响持续写入性能。
- 多 Plane 并行:利用 NAND 多 Plane(2–4 Plane)同时读/写多个页,倍增吞吐。
- CE 交织:多 CE(Chip Enable)交错操作,隐藏 NAND 忙时间。
- 写合并:小块写入先在 SRAM 缓冲合并为整页再写入,减少 NAND 写次数。
- CMDQ 调度:接收多个任务后按最优顺序执行(如把写合并、读局部化),减少 GC 干扰。
15. 固件开发要点
15.1 设备固件模块划分(参考架构)
| 模块 | 职责 |
|---|---|
| 命令解析器(CMD Parser) | 解码 CMD 线命令,校验 CRC,更新状态机,生成响应 |
| 数据引擎(Data Engine) | 管理 DAT 线传输(块读/写/CMDQ)、CRC16 校验 |
| 寄存器管理(REG Manager) | 维护 OCR/CID/CSD/EXT_CSD,处理 CMD6 写入并同步内部配置 |
| FTL 映射 | L2P 表维护、地址翻译 |
| GC / WL / BBM | 垃圾回收、磨损均衡、坏块管理(§14.3) |
| Cache 管理 | 写缓存、SLC Cache、刷写控制(FLUSH_CACHE) |
| RPMB 管理 | HMAC 计数器、密钥管理、帧解析(§11.4) |
| 安全引擎 | AES-XTS(加密)、HMAC-SHA256(RPMB)、安全擦除 |
| NAND 驱动 | 页面读/写/擦除、ECC、坏块标记、多 Plane 控制 |
| 电源管理 | 掉电中断处理、POWER_OFF_NOTIFICATION、睡眠/唤醒(CMD5) |
| Boot 加载器 | 上电启动代码加载、Boot 分区数据流输出(§9) |
| 诊断/监控 | 寿命监控(PRE_EOL_INFO/LIFE_TIME)、BKOPS 状态、日志 |
15.2 关键设计决策(固件工程师须知)
- L2P 表粒度:页级映射(灵活但表大)vs 块级映射(表小但写放大高)→ eMMC 通常用页级。
- GC 触发策略:
- 空闲块低于阈值 → 触发前台 GC。
- BKOPS_EN=1 → 空闲时后台 GC。
- URGENT_BKOPS → 强制前台 GC。
- SLC Cache 大小:TLC 容量的 1/30–1/10;写满后降速(”稳态”性能)。
- ECC 选择:BCH vs LDPC——LDPC 纠错更强(适合 TLC/QLC),但计算量大、延迟高。
- 映射表持久化:掉电前必须刷入 NAND;启动时加载(支持从 NAND 映射区多点恢复)。
- 分区固定 vs 动态:boot/RPMB/GPP 大小出厂固定,不可动态调整——生产测试时一次性配置。
15.3 常见故障与排查
| 故障现象 | 可能原因 | 排查方向 |
|---|---|---|
| CMD1 初始化超时 | 电压不匹配、时钟过快、信号完整性差 | 示波器看 CMD 线、检查 VCC/VCCQ |
| HS200/HS400 切换后 CRC 错误 | 未调谐、信号质量差、驱动强度不匹配 | 逻辑分析仪抓 CMD21 调谐块、检查电源纹波 |
| 写性能周期性骤降 | SLC Cache 耗尽触发 TLC 直写 | 监测写带宽曲线;增加 SLC Cache 或减少 Cache 触发阈值 |
| 随机读写卡顿 | 前台 GC 阻塞 | 检查 BKOPS 设置;优化 GC 策略(增加后台 GC 投入) |
| RPMB 认证失败 | HMAC 计算错误、密钥不匹配、帧格式错误 | 逐字段 dump 对比;检查 HMAC 输入范围 |
| 偶发数据错误(ECC 失败) | NAND 坏块/读干扰、ECC 强度不足 | 增加 ECC 强度;增加读刷新频率 |
| 掉电后数据丢失 | 未刷 cache、日志不完整 | 确认 POWER_OFF_NOTIFICATION 流程;检查备电电容 |
| FFU 升级失败 | 镜像格式错误、版本不匹配、超时 | 检查 FFU_STATUS;确认镜像格式与 FFU_FEATURES |
15.4 测试与验证
| 测试项 | 方法 |
|---|---|
| 协议合规 | JEDEC CTS(Compliance Test Suite);协议分析仪(LeCroy/Keysight)抓取总线验证每条命令/响应 |
| 功能测试 | 全命令遍历(CMD0–48,含异常参数);状态机全路径覆盖;分区切换压力测试 |
| 性能测试 | fio(顺序读/写、随机 4K);持续写 10 分钟观察 SLC Cache 降速;CMDQ 深度扫描 |
| 可靠性测试 | 掉电 1000+ 次(随机时刻),数据一致性检查;写/擦除耐久(至 PRE_EOL=0x03);温度循环(-40°C–85°C) |
| 安全测试 | RPMB HMAC 篡改检测;Secure Erase 后数据残留检查(读 NAND dump);FFU 异常中断恢复 |
| 兼容性测试 | 多 SoC 平台验证(不同 Host Controller IP);多 NAND 颗粒型号适配 |
16. 附录:速查表、术语与参考资料
16.1 常用命令速查
| 命令 | 功能 | 响应 | 典型场景 |
|---|---|---|---|
| CMD0 | 复位/进 Boot | 无/R1 | 初始化、Boot |
| CMD1 | 电压协商 | R3 | 初始化 |
| CMD2 | 读 CID | R2 | 初始化 |
| CMD3 | 分配 RCA | R6 | 初始化 |
| CMD5 | 睡眠/唤醒 | R1b | 低功耗 |
| CMD6 | 写 EXT_CSD | R1b | 模式切换、配置 |
| CMD7 | 选中设备 | R1b | 初始化、分区切换 |
| CMD8 | 读 EXT_CSD | R1+Data | 初始化 |
| CMD9 | 读 CSD | R2 | 初始化 |
| CMD12 | 停止传输 | R1/R1b | 中止多块读写 |
| CMD13 | 读状态 | R1 | 状态轮询 |
| CMD17/18 | 单/多块读 | R1+Data | 数据读 |
| CMD23 | 设块数 | R1 | 预定义多块、RPMB |
| CMD24/25 | 单/多块写 | R1 | 数据写 |
| CMD35/36 | 擦除范围 | R1 | 擦除/TRIM |
| CMD38 | 执行擦除 | R1b | 擦除/TRIM/Discard |
| CMD42 | 锁/解锁 | R1b | 卡加锁 |
| CMD44–48 | CMDQ | R1/R1b | 命令队列 |
16.2 EXT_CSD 关键字节速查
| 偏移 | 名称 | 读写 | 说明 |
|---|---|---|---|
| 15 | CMDQ_MODE_EN | R/W | CMDQ 使能 |
| 32 | FLUSH_CACHE | W | 刷写 cache |
| 33 | CACHE_CTRL | R/W | Cache 使能 |
| 34 | POWER_OFF_NOTIFICATION | R/W | 关机通知 |
| 61 | DATA_SECTOR_SIZE | R | 逻辑扇区大小 |
| 155 | PARTITION_SETTING_COMPLETED | R/W | 分区配置完成 |
| 162 | RST_N_FUNCTION | R/W | RST_n 功能 |
| 163 | BKOPS_EN | R/W | BKOPS 使能 |
| 165 | SANITIZE_START | W | Sanitize 启动 |
| 168 | RPMB_MULT | R | RPMB 大小 |
| 173 | BOOT_WP | R/W | Boot 写保护 |
| 175 | ERASE_GROUP_DEF | R/W | 擦除组定义 |
| 177 | BOOT_BUS_WIDTH | R/W | Boot 总线 |
| 179 | PART_CONFIG | R/W | 分区配置 |
| 183 | BUS_WIDTH | R/W | 总线宽度 |
| 185 | HS_TIMING | R/W | 时序模式 |
| 192 | REV | R | EXT_CSD 版本 |
| 196 | CARD_TYPE | R | 支持的模式 |
| 212–215 | SEC_CNT | R | 用户区扇区数 |
| 217 | S_A_TIMEOUT | R | 睡眠超时 |
| 224 | HC_ERASE_GRP_SIZE | R | 擦除组大小 |
| 226 | BOOT_MULT | R | Boot 分区大小 |
| 231 | SEC_FEATURE_SUPPORT | R | 安全特性 |
| 248 | GENERIC_CMD6_TIME | R | CMD6 超时 |
| 249–252 | CACHE_SIZE | R | Cache 大小 |
| 254–261 | FIRMWARE_VERSION | R | 固件版本 |
| 267 | PRE_EOL_INFO | R | 预寿命终结 |
| 268/269 | LIFE_TIME EST A/B | R | 寿命估计 |
| 307 | CMDQ_DEPTH | R | 队列深度 |
| 308 | CMDQ_SUPPORT | R | CMDQ 支持 |
| 493 | SUPPORTED_MODE | R | 支持的模式(FFU) |
| 503 | HPI_FEATURES | R | HPI 特性 |
| 504 | S_CMD_SET | R/W | 命令集 |
16.3 R1 状态位速查
| 位 | 名称 | 类型 | 说明 |
|---|---|---|---|
| 31 | OUT_OF_RANGE | er,c | 地址越界 |
| 30 | ADDRESS_ERROR | erx,c | 地址错误 |
| 29 | BLOCK_LEN_ERROR | er,c | 块长错误 |
| 28 | ERASE_SEQ_ERROR | er,c | 擦除序列错误 |
| 27 | ERASE_PARAM | ex,c | 擦除参数错误 |
| 26 | WP_VIOLATION | erx,c | 写保护违规 |
| 25 | CARD_IS_LOCKED | sx,a | 卡已锁定 |
| 24 | LOCK_UNLOCK_FAILED | erx,c | 加锁失败 |
| 23 | COM_CRC_ERROR | er,b | 命令 CRC 错 |
| 22 | ILLEGAL_COMMAND | er,b | 非法命令 |
| 21 | CARD_ECC_FAILED | ex,c | ECC 不可纠正 |
| 20 | CC_ERROR | erx,c | 控制器错误 |
| 19 | ERROR | erx,c | 通用错误 |
| 18 | UNDERRUN | ex,c | 读欠载 |
| 17 | OVERRUN | ex,c | 写过载 |
| 16 | CID_CSD_OVERWRITE | erx,c | CID/CSD 覆盖 |
| 15 | WP_ERASE_SKIP | sx,c | 跳过写保护擦除 |
| 14 | CARD_ECC_DISABLED | sx,a | ECC 已禁用 |
| 13 | ERASE_RESET | sr,c | 擦除已复位 |
| 12:9 | CURRENT_STATE (4 bit) | sx,b | 当前状态 |
| 8 | READY_FOR_DATA | sx,a | 数据就绪 |
| 7 | SWITCH_ERROR | sx,c | CMD6 切换失败 |
| 6 | EXCEPTION_EVENT | sr,a | 异常事件(5.0+) |
| 5 | APP_CMD | sr,c | APP 命令标志 |
类型说明:e=错误,s=状态,r=响应,x=执行中;a=按状态清,b=按前一命令清,c=读清。
16.4 术语表
| 术语 | 全称 | 说明 |
|---|---|---|
| BGA | Ball Grid Array | 焊球阵列封装 |
| BBT | Bad Block Table | 坏块表 |
| BKOPS | Background Operations | 后台操作 |
| CMDQ | Command Queue | 命令队列 |
| CSD | Card Specific Data | 卡特定数据 |
| DS | Data Strobe | 数据选通 |
| DDR | Double Data Rate | 双倍数据速率 |
| ECC | Error Correction Code | 纠错码 |
| EXT_CSD | Extended CSD | 扩展 CSD |
| FFU | Field Firmware Update | 现场固件更新 |
| FTL | Flash Translation Layer | 闪存转换层 |
| GC | Garbage Collection | 垃圾回收 |
| GPP | General Purpose Partition | 通用目的分区 |
| HMAC | Hash-based Message Authentication Code | 基于哈希的消息认证码 |
| HPI | High Priority Interrupt | 高优先级中断 |
| LBA | Logical Block Address | 逻辑块地址 |
| L2P | Logical-to-Physical | 逻辑到物理映射 |
| OCR | Operation Conditions Register | 工作条件寄存器 |
| OID | OEM/Application ID | OEM/应用标识 |
| PNM | Product Name | 产品名 |
| RCA | Relative Card Address | 相对卡地址 |
| RPMB | Replay Protected Memory Block | 重放保护内存块 |
| SDR | Single Data Rate | 单倍数据速率 |
| SLC | Single-Level Cell | 单层单元 |
| TLC | Triple-Level Cell | 三层单元 |
| TRIM | — | 逻辑块无效化(比 Erase 快) |
| WL | Wear Leveling | 磨损均衡 |
16.5 参考资料
- JEDEC JESD84-B51:Embedded MultiMedia Card (e•MMC) Electrical Standard (5.1)
- JEDEC JESD84-B50:e•MMC 5.0 Electrical Standard
- JEDEC JESD84-B45:e•MMC 4.5 Electrical Standard
- Linux 内核源码(权威实现参考):
include/linux/mmc/mmc.h:命令定义、R1 状态位、EXT_CSD 偏移、擦除参数drivers/mmc/core/mmc.c:初始化流程、CID/CSD 解码、时序切换、CMDQ/BKOPS 使能drivers/mmc/core/mmc_ops.c:CMD6/CMD8/CMD13 实现
- SD 规范(对比参考):SD Physical Layer Simplified Specification v9.00
文档完成。如有勘误或补充,请参考 JEDEC 规范原文及 Linux 内核最新实现。

