面向嵌入式系统 eMMC(embedded MultiMediaCard,JESD84 / eMMC 5.1)主机侧驱动的设计约束与推荐实现: 覆盖 初始化状态机、EXT_CSD 寄存器体系、分区与启动、读写擦命令序列、 Cache 与掉电保护、BKOPS / HPI 与 健康寿命管理,逐条给出可落地的命令序列、判据与超时预算。
18章节
5附录
512 B扇区访问粒度
CMD6EXT_CSD 唯一写入口
| EMMC-SW-SPEC-001 |
| V1.0 · 正式发布 |
| JEDEC eMMC 4.5 / 5.0 / 5.1 器件(BGA-153 / BGA-169 / BGA-100 / BGA-221),容量 4 GB ~ 256 GB |
| XTX TLC eMMC 5.1(HS400)XT28EG32GA2YUECGA(32 GB)/ XT28EG64GA2YUECGA(64 GB),FBGA-153 11.5×13×1.0 mm,VCC=3.3 V / VCCQ=1.8 V;文中标注「本器件」的数值均取自该手册 版本号 V1.0 |
| JEDEC JESD84-B51(eMMC 5.1)· JESD84-B50(5.0)· JESD84-A441(4.41)· XTX eMMC Spec Rev 1.0 |
| eMMC_电路设计指南.html(原理图 / 双电源 / BGA 扇出 / HS400 布线 / 焊接与生产) |
0. 目的与范围
本规范约束 eMMC 器件在嵌入式固件中的主机侧软件行为:初始化状态机、EXT_CSD 配置、分区切换、 读写擦命令序列、Cache 与掉电保护、后台操作与健康管理。凡本文与器件 datasheet 冲突,以 datasheet 为准。
- 统一初始化路径:CMD0 → CMD1 → CMD2 → CMD3 → CMD7 → CMD8 固化为唯一标准流程,提速必须「先宽度、后时序、切完必验」。
- 统一配置入口:所有器件配置只走 CMD6 写 EXT_CSD,禁止裸写、禁止批量改字节。
- 统一 busy 判据:以 DAT0 释放 + CMD13 状态位为准,禁止用固定延时代替。
- 统一掉电语义:明确哪些操作是原子的、哪些必须 flush、哪些必须提前通知器件。
- 统一健康策略:寿命字段读什么、读到什么值做什么动作,形成可运维的闭环。
不在本规范范围:硬件原理图、电源设计、PCB 布线与焊接(见《eMMC 电路设计指南》); 文件系统与 FTL 算法选型(eMMC 的 FTL 在器件内部,主机不可干预);RPMB 的密码学协议细节与密钥托管方案。
一句话结论:eMMC 是「把麻烦事都封进 BGA 里的 Managed NAND」—— 坏块、ECC、磨损均衡、映射表全部由器件内部完成,主机只面对 512 B 扇区的块设备接口。 代价是主机必须自己管好三件事:Cache 什么时候 flush、掉电前怎么通知器件、后台操作什么时候让器件做。 这三件事没做好,是 eMMC 项目里 90% 的丢数据与掉速事故的根因。
文档使用说明
- 本文是《eMMC 电路设计指南》的软件配套篇:硬件篇解决「怎么接、怎么供电、怎么走线」,本文解决「驱动怎么写、协议怎么等、错误怎么救」。
- 命令码、EXT_CSD 偏移、时序值取自 JESD84-B51。不同厂商、不同固件版本的器件在可选特性上存在差异,移植前必须逐条核对 datasheet。
- 文中 C 代码为协议骨架伪代码,演示命令序列与判断条件,非特定平台可直接编译的完整实现;mmc_send_cmd()、now_ms() 等为平台相关底层。
- EXT_CSD 偏移量统一写作 EXT_CSD[179] 形式,方括号内为字节偏移(0~511),不是 bit 位。
贯穿全文的四条铁律
① 绝不用固定延时替代 busy 判断——编程/擦除/GC 时间受磨损、温度、随机性影响,波动可达数量级; ② 每个 CMD6 都当成一次「写操作」——它返回 R1b,必须等 DAT0 释放并检查 SWITCH_ERROR; ③ 提速前先确认双方能力——读 DEVICE_TYPE 再决定切哪一档,切完必须读写回环验证并保留回退路径; ④ Cache 是性能开关,也是风险开关——开启前先想清楚掉电时有没有时间 flush,想不清楚就别开。
1 · 器件定位与系统架构
eMMC 不是一颗裸 NAND,而是「NAND 阵列 + 控制器 + FTL + MMC 接口」的完整子系统。 软件设计的第一件事,是认清主机到底能管什么、管不了什么——把器件内部的事当成自己的事,是新手最常见的过度设计。
1.1 器件定位与关键参数
512 B
访问粒度
读写擦一律按扇区(Sector)寻址
6 类
可寻址分区
Boot1/2 · RPMB · GPP1~4 · User
400 MB/s
HS400 峰值
8-bit DDR 200 MHz + DS 选通
4~256 GB
容量范围
典型 8 / 16 / 32 / 64 GB
1.8 V
VCCQ(HS 模式)
本器件仅支持 1.8 V 档(DEVICE_TYPE=57h)
370 ms
通用 CMD6 超时
本器件 GENERIC_CMD6_TIME = 0x25
2550 ms
掉电通知超时
本器件 POWER_OFF_LONG_TIME = 0xFF
≤ 80%
建议容量使用率
给 FTL 留足 GC 与磨损均衡空间
参数取自 JESD84-B51 与主流器件 datasheet;具体数值(Cache 容量、Erase Group 大小、P/E 次数)以所用料号 datasheet 为准。
1.2 系统分层与器件内部架构
eMMC 对外只暴露一组 MMC 总线(CLK / CMD / DAT0~7 / DS / RST_n),且是点对点连接—— 一条总线上只能挂一颗 eMMC,不支持多设备并联(这与 SD 卡的多卡总线是本质区别)。
eMMC 系统分层:主机 / 总线 / 器件内部三层主机 SoC:eMMC Host 控制器块设备层 → MMC 协议层 → 主机控制器驱动(HAL)MMC 总线(点对点,只允许挂一颗器件)CLK · CMD · DAT0~7 · DS(HS400 选通) · RST_neMMC 器件(BGA 封装)MMC 接口 + 协议引擎(命令解析 / 数据 FIFO / CRC)Flash 控制器:FTL 映射 · ECC · 磨损均衡 · 坏块替换 · 垃圾回收NAND 阵列:MLC / TLC + OP 预留空间(对主机完全不可见)主机只看到「512 B 扇区块设备」,坏块 / ECC / 磨损均衡全部由器件内部完成
图 1-1 eMMC 系统分层与内部架构(主机只面对块设备接口)
主机能管的 vs 器件自己管的
主机负责:初始化与提速、分区切换、读写擦命令序列、Cache 开关与 flush、掉电通知、BKOPS 调度、寿命监控、写保护策略。
器件内部负责(主机不可见也不可干预):坏块管理与替换、ECC 纠错、磨损均衡、逻辑到物理地址映射、垃圾回收、OP 预留空间管理。
这意味着:不要再在主机侧实现一套坏块表或磨损均衡——那既无效又浪费 RAM。主机真正要做的是「给器件留出做这些事的时间与空间」。
1.3 地址空间与访问粒度
eMMC 把复杂的 NAND 几何全部藏了起来,主机看到的是一个连续的 32 bit 扇区地址空间。 但有三种粒度在软件里迟早要碰到:
eMMC 地址空间与三种访问粒度主机可见:User Data Area / Boot1 / Boot2 / RPMB / GPP1~4全部按 32 bit 扇区地址(Sector,512 B)线性寻址器件内部(主机不可见)Erase Group擦除粒度 = HC_ERASE_GRP_SIZE × 512 KB;Erase 命令按它对齐Write Protect Group写保护粒度 = HC_WP_GRP_SIZE × Erase Group;写保护按它对齐NAND Page / Block真正的读写擦物理单元,由 FTL 自行映射,主机无从干预软件结论:读写按 512 B 对齐即可,Trim / Erase / 写保护才需要关心内部粒度
图 1-2 eMMC 地址空间与三种访问粒度
- Sector(512 B):读写的最小单位,也是所有地址参数的单位(容量 > 2 GB 的器件)。读写必须 512 B 对齐。
- Erase Group:擦除粒度 = HC_ERASE_GRP_SIZE × 512 KB(本器件 = 1 → 512 KB)。CMD35/CMD36 的地址会被器件向下取整到 Erase Group 边界。
- Write Protect Group:写保护粒度 = HC_WP_GRP_SIZE × HC_ERASE_GRP_SIZE × 512 KB(本器件 = 16 × 512 KB = 8 MB)。写保护只能按它整块施加。
本器件实测粒度(EXT_CSD)
HC_ERASE_GRP_SIZE[224] = 1 → Erase Group = 512 KB; HC_WP_GRP_SIZE[221] = 0x10 → Write Protect Group = 8 MB; SEC_COUNT[215:212] = 07480000h(64 GB 版)→ 用户区扇区总数;BOOT_SIZE_MULT[226] = 0x20 → Boot1/Boot2 各 4096 KB;RPMB_SIZE_MULT[168] = 0x20 → RPMB 4096 KB。 这些值必须运行时从 EXT_CSD 读出,不要按「典型 eMMC」硬编码——换料、换固件版本都可能变。
Erase 的地址会被「悄悄对齐」
给 CMD35 一个未对齐的地址,器件不会报错,而是忽略低于 Erase Group 大小的低位、向下取整。 后果是多擦了相邻区域——如果那里放着有效数据,就静默丢了。正确做法:擦除前自己把起止地址按 Erase Group 大小对齐,并确认范围内的所有数据都不再需要。
1.4 与 SD NAND / SPI NAND / SPI NOR 的关键差异(移植必读)
| 主机接口 | SPI(1/2/4 线) | SPI(1/2/4 线) | SDIO / SPI | MMC 总线(1/4/8 bit + DS) |
| 访问粒度 | 字节 | 页(2048 B + 备用区) | 块(512 B) | 扇区(512 B) |
| 坏块管理 | 无 | 主机必须做(BBT) | 器件内部 | 器件内部(主机无需参与) |
| ECC | 无 | 片内 / 主机侧,须判读 | 器件内部 | 器件内部,主机不可见 |
| 擦除 | Sector/Block 擦 | Block 擦(64 页) | 器件内部 | Erase Group(器件内部调度) |
| 可寻址分区 | 无 | 无 | 无 | Boot1/2 · RPMB · GPP1~4 · UDA |
| 掉电通知 | 无 | 无 | 无 | POWER_OFF_NOTIFICATION(独有) |
| 寿命查询 | 无 | 靠自己统计 P/E | 无 | DEVICE_LIFE_TIME_EST / PRE_EOL_INFO |
| Cache | 无 | 页 Cache 寄存器 | 无 | 写 Cache(需显式 flush) |
| 封装 / 可焊性 | SOP/WSON,易 | WSON/LGA,易 | LGA/WSON,易 | BGA,需 HDI + X 光检测 |
从 SPI NAND / SD NAND 移植过来最危险的三个假设
- 假设「写完就落盘」:裸 NAND 里 10h 后轮询 OIP 结束就是写完了;eMMC 开了 Cache 后,DAT0 释放只代表数据进了 Cache。
- 假设「要自己管坏块」:SPI NAND 必须有 BBT;eMMC 完全没有坏块概念,实现一套是纯粹的浪费。
- 假设「掉电就掉电」:eMMC 提供了标准掉电通知机制,不用它就是放弃了一个免费的可靠性提升。
2 · 术语与缩写
本章统一术语口径。eMMC 的术语体系与 NAND 系(页/块/备用区)完全不同,混用会导致文档与代码对不上。
2.1 接口与协议术语
| eMMC | embedded MultiMediaCard | 板载 Managed NAND 子系统;本文默认 JESD84-B51(5.1) |
| CMD / Resp | Command / Response | 48 bit 命令帧与响应;R1/R1b/R2/R3 等响应类型 |
| RCA | Relative Card Address | 器件相对地址,由 CMD3 分配(常用 0x0001) |
| OCR | Operating Conditions Register | 电压窗口与上电完成标志;CMD1 响应 bit31 = 就绪 |
| CID | Card IDentification | 128 bit 器件标识:厂商 ID、产品名、序列号、生产日期 |
| CSD | Card Specific Data | 器件基础参数(CMD9 读取) |
| EXT_CSD | Extended CSD | 512 字节扩展寄存器(CMD8 读 / CMD6 写),eMMC 的核心管理面 |
| R1 / R1b | — | 32 bit 状态响应;R1b 附带 busy 信号(DAT0 拉低) |
| SWITCH_ERROR | — | R1 bit7;CMD6 写 EXT_CSD 失败标志 |
2.2 存储与分区术语
| Sector | — | 512 B,读写与寻址的最小单位 |
| Erase Group | — | 擦除粒度 = HC_ERASE_GRP_SIZE × 512 KB |
| Write Protect Group | — | 写保护粒度,通常远大于 Erase Group |
| UDA | User Data Area | 用户数据区,默认承载全部容量,文件系统主要用这里 |
| Boot 1 / Boot 2 | Boot Area Partition | 启动分区,容量 = 128 KB × BOOT_SIZE_MULT |
| RPMB | Replay Protected Memory Block | 带 HMAC-SHA256 认证与防重放的分区;密钥 / 计数器放这里 |
| GPP 1~4 | General Purpose Partition | 通用分区,可做增强属性与独立写保护,用于系统 / 数据 / 日志隔离 |
| Enhanced / pSLC | Enhanced User Data Area | 把部分区域配置为 pseudo-SLC:容量换寿命、性能与数据保持 |
| OP | Over-Provisioning | 器件内部预留空间(主机不可见)+ 用户主动留出的空闲容量 |
| FTL | Flash Translation Layer | 器件内部的逻辑→物理映射层,主机不可干预 |
2.3 特性与机制术语
| HS200 / HS400 | — | 高速时序档位;HS200 = SDR 200 MHz,HS400 = DDR 200 MHz + DS 选通 |
| DS | Data Strobe | HS400 模式下由器件输出的选通信号,用于主机采样 |
| Tuning | — | HS200/HS400 下用 CMD21 找最佳采样相位的过程 |
| Cache | — | 器件内部写缓存;开则快、掉电则丢,需 FLUSH_CACHE 落盘 |
| Reliable Write | — | CMD23 bit31;要求该次写入原子完成(要么新要么旧) |
| Forced Programming | — | CMD23 bit24;仅 Cache 开启时有效,强制立即写入 NAND |
| BKOPS | Background Operations | 器件内部垃圾回收与磨损均衡等后台任务 |
| HPI | High Priority Interrupt | 高优先级中断;打断器件长时间操作(CMD12/CMD13 带 HPI 标志) |
| Trim / Discard | — | 标记数据无效;Trim 读出值确定,Discard 不确定 |
| Sanitize | — | 物理清除所有未映射数据,用于出厂恢复与报废清密 |
| FFU | Field Firmware Update | 器件固件在线升级;过程掉电可能变砖 |
| POWER_OFF_NOTIFICATION | — | EXT_CSD[34];主机断电前通知器件的标准机制 |
2.4 本文书写约定
- 命令写作 CMD13 形式(不加 h 后缀),与 JEDEC 文本一致。
- EXT_CSD 字段写作 EXT_CSD[179],方括号内为字节偏移;位域写作 EXT_CSD[179][2:0]。
- 数值:十六进制用 0x 前缀;位序 bit0 为最低位。
- 时序:「典型值 / 最大值」成对给出时,软件超时一律按最大值预算;typ 值只用于安排轮询节奏。
- 代码示例为 C 伪代码,省略主机控制器寄存器细节,只表达命令序列与判据。
3 · 驱动架构与初始化
eMMC 的初始化是一条不能跳步的状态机:每一步都把器件推到下一个状态,跳步的直接后果是「命令发出去没响应」。 提速则是初始化之后单独的一段,必须「先慢后快、切完必验」。
3.1 分层职责
| 文件系统 / 块设备层 | 提交 bio / request;下发 flush、discard 语义 | 直接拼 MMC 命令、直接算扇区边界之外的地址 |
| MMC 核心协议层 | 初始化状态机、EXT_CSD 解析、分区切换、BKOPS 调度 | 绕过状态检查直接发读写命令 |
| 命令封装层 | CMD17/18/24/25、CMD23、CMD13、CMD6、CMD35/36/38 | 省略 busy 等待、忽略 SWITCH_ERROR |
| 主机控制器驱动(HAL) | 时钟、总线宽度、DMA、CRC、tuning 引擎、超时 | 在数据传输中途改时钟频率或总线宽度 |
3.2 上电初始化流程
完整的识别流程只有一条标准路径,六步缺一不可:
上电初始化:MMC 协议状态机推进顺序CMD0GO_IDLE_STATE→ IdleCMD1SEND_OP_COND轮询 OCR bit31→ ReadyCMD2ALL_SEND_CID→ IdentCMD3SET_RELATIVE_ADDR→ StbyCMD7SELECT_CARDRCA ≪ 16→ TranCMD8SEND_EXT_CSD读回 512 B→ Tran① CMD1 必须循环重发并设超时(典型 1 s),不可用固定延时代替轮询② CMD8 只能在 Transfer 态发送;EXT_CSD 未读到则无从判断能力提速:必须「先慢后快、先宽度后时序」,切完必验配总线宽度CMD6 → BUS_WIDTH[183]1→4→8 bit切时序CMD6 → HS_TIMING[185]HS / HS200HS200 TuningCMD21 采样相位找到采样窗口切 HS400CMD6 → HS_TIMING=3DS 选通 + DDR⑤ 切换后必须做读写回环校验;失败要能逐级回退到低速模式HS400 不允许直接从 Legacy/HS 切入,必须先经 HS200 完成 tuning
图 3-1 上电初始化状态机与提速路径
int mmc_init(void)
{
uint32_t resp, rca = 0x0001;
uint8_t ext_csd[512];
/* ① 电源与复位就绪:VCC/VCCQ 稳定、RST_n 释放、输出 400 kHz 以下时钟 */
host_set_clock(400000); /* 识别阶段必须低速 */
host_set_width(1);
/* ② CMD0:复位到 Idle */
send_cmd(CMD0, 0x00000000, RSP_NONE); /* GO_IDLE_STATE → Idle(0xF0F0F0F0 是 GO_PRE_IDLE_STATE,用于复位后重引导 boot) */
delay_us(200);
/* ③ CMD1:电压协商 + 等待上电完成(bit31 = 1) */
if (wait_cmd1_ready(1000) != 0) /* 超时 1 s,循环重发 */
return -E_MMC_NO_RESPONSE;
/* ④ CMD2 / CMD3:读 CID、分配 RCA */
send_cmd(CMD2, 0, RSP_R2); /* 128 bit CID */
send_cmd(CMD3, rca << 16, RSP_R1); /* → Standby */
/* ⑤ CMD7:选中,进入 Transfer 态 */
send_cmd(CMD7, rca << 16, RSP_R1);
/* ⑥ CMD8:读 512 B EXT_CSD(只能在 Transfer 态发) */
if (mmc_send_ext_csd(ext_csd) != 0)
return -E_MMC_EXT_CSD;
return mmc_setup_from_ext_csd(ext_csd); /* 提速 + 分区(见 3.4 / 第 5 章) */
}
/* CMD1 必须循环重发并设超时 —— 固定延时必然在某些器件上翻车 */
static int wait_cmd1_ready(uint32_t timeout_ms)
{
uint32_t t0 = now_ms(), resp;
do {
send_cmd(CMD1, 0x40FF8080, RSP_R3);
resp = host_last_resp();
if (resp & 0x80000000u) /* bit31 = 上电完成 */
return 0;
delay_ms(10);
} while (now_ms() – t0 < timeout_ms);
return -E_TIMEOUT;
}
CMD1 用固定延时代替轮询,是「某些批次起不来」的经典原因
器件的上电就绪时间随容量、温度、内部初始化任务(尤其是掉电恢复)波动,可以从几十毫秒到几百毫秒。 写死一个 delay_ms(100) 在实验室样机上没问题,量产时换个批次或低温冷启动就起不来。
正确做法:循环发送 CMD1 并检查 OCR bit31,总超时设 1 s。这是 JEDEC 明确要求的做法,没有捷径。
3.3 器件识别与能力协商
初始化完成后,器件的全部能力都在 CID / CSD / EXT_CSD 里。驱动必须从寄存器读,不许硬编码:
| 厂商 / 型号 / 序列号 | CID(CMD2) | MID、PNM、PSN | 日志、追溯、产线记录 |
| eMMC 版本 | EXT_CSD[192] REV | 0x07 = 5.0,0x08 = 5.1 | 决定可用特性集(5.1 才有 pSLC 增强等) |
| 用户区容量 | EXT_CSD[215:212] SEC_COUNT | 容量 = SEC_COUNT × 512 B | 唯一的容量来源,不要用 CSD 推算 |
| 支持的速度档位 | EXT_CSD[196] DEVICE_TYPE | 位域:HS200/HS400 及对应电压 | 决定能切到哪一档 |
| Cache 容量 | EXT_CSD[252:249] CACHE_SIZE | 0 = 无 Cache;否则 × 1 KB | 是否值得开 Cache |
| 可靠写扇区数 | EXT_CSD[222] REL_WR_SEC_C | 单次可靠写的最大扇区数 | Reliable Write 的分批依据 |
| Erase / Trim 粒度 | EXT_CSD[224] / [232] | HC_ERASE_GRP_SIZE、TRIM_MULT | 擦除对齐与超时预算 |
| 分区切换时间 | EXT_CSD[199] | PARTITION_SWITCH_TIME | 切分区后的等待时间 |
| 寿命与预警 | EXT_CSD[267..269] | PRE_EOL_INFO、LIFE_TIME_A/B | 健康管理(第 12 章) |
/* 能力解析:全部从 EXT_CSD 取,禁止硬编码容量与几何 */
static int mmc_setup_from_ext_csd(const uint8_t *e)
{
uint32_t sec = le32(e + 212); /* SEC_COUNT[215:212] */
uint64_t cap = (uint64_t)sec * 512; /* 用户区字节容量 */
uint8_t rev = e[192]; /* EXT_CSD_REV */
uint8_t dtype = e[196]; /* DEVICE_TYPE */
uint32_t cache = le32(e + 249); /* CACHE_SIZE[252:249] */
mmc.capacity = cap;
mmc.rev = rev;
mmc.hs200_1v8 = !!(dtype & 0x02); /* HS200 @ 1.8 V */
mmc.hs400_1v8 = !!(dtype & 0x04); /* HS400 @ 1.8 V */
mmc.cache_kb = cache; /* 0 = 无 Cache */
log_i("eMMC rev=%d cap=%llu MB cache=%u KB hs400=%d",
rev, cap >> 20, cache, mmc.hs400_1v8);
return 0;
}
3.4 提速:先宽度、后时序、切完必验
上电后器件默认1-bit + Legacy(最高 26 MHz),所有高速档位都要主机主动切换。顺序错了会直接通信失败。
/* 提速:每一步都等 busy、每一步都检查 SWITCH_ERROR */
static int mmc_switch(uint8_t index, uint8_t value, uint32_t timeout_ms)
{
uint32_t arg = (0x03u << 24) /* Access = Write Byte */
| ((uint32_t)index << 16)
| ((uint32_t)value << 8)
| 0x00u; /* CmdSet = 标准命令集 */
uint32_t st;
send_cmd(CMD6, arg, RSP_R1b);
if (wait_dat0_release(timeout_ms)) /* 关键:CMD6 也带 busy */
return -E_TIMEOUT;
send_cmd(CMD13, mmc.rca << 16, RSP_R1);
st = host_last_resp();
if (st & (1u << 7)) /* SWITCH_ERROR */
return -E_SWITCH_ERR;
return 0;
}
int mmc_upgrade_to_hs400(void)
{
mmc_switch(183, 2, 500); /* BUS_WIDTH = 8-bit */
mmc_switch(185, 2, 500); /* HS_TIMING = HS200 */
if (host_hs200_tuning()) /* CMD21 采样相位调谐 */
return -E_TUNING;
mmc_switch(183, 6, 500); /* 8-bit DDR */
mmc_switch(185, 3, 500); /* HS_TIMING = HS400 */
return mmc_speed_verify(); /* 读写回环校验,失败即回退 */
}
超时别写 100 ms:本器件通用 CMD6 超时是 370 ms
JEDEC 给的通用默认 GENERIC_CMD6_TIME = 0x0A(10 × 10 ms = 100 ms),但本器件实测为 0x25 = 37 → 370 ms。 按 100 ms 判超时,在 Cache 回收、GC 撞车、分区切换等场景下会误判失败,进而触发本不必要的复位与回退。
正确做法:超时值从 GENERIC_CMD6_TIME 读出再乘单位(10 ms)算出来,再加 30% 余量;只有那些自带更长超时字段的操作(Sanitize、掉电通知、分区切换、初始化后第一次分区生效)才改用对应字段。
跳过 tuning 的后果是「偶发数据错误」,不是「连不上」
HS200/HS400 下如果不做 tuning,器件能连上、能跑、大部分时间也对, 只在特定温度、电压、老化程度下偶尔出现 CRC 错误或数据位错。这类问题在实验室几乎抓不到,量产时才爆发。
另一类常见错误是HS400 直接从 Legacy 切入:协议要求先到 HS200 完成 tuning,跳过这一步的器件行为未定义。
3.5 初始化自检清单
- 上电时钟 ≤ 400 kHz,CMD1 循环轮询 bit31 且超时 ≥ 1 s
- CMD8 在 Transfer 态发送,已成功读回 512 B EXT_CSD
- 容量从 SEC_COUNT 计算,未硬编码;已与预期容量对账
- 提速前已确认 DEVICE_TYPE 与 VCCQ 电压档位匹配
- 总线宽度与 HS_TIMING 的写入顺序正确(宽度在前)
- HS200/HS400 已完成 tuning,并有读写回环验证
- 提速失败有逐级回退路径,且回退后功能可用
- 初始化日志记录了 REV、容量、速度档位、Cache 容量,便于现场追溯
4 · EXT_CSD 寄存器体系
EXT_CSD 是 eMMC 的管理面:512 字节,包罗万象。 所有配置只有一个入口——CMD6。理解它的分段、写入规则与生效时机,是写对 eMMC 驱动的前提。
4.1 512 字节的分段
EXT_CSD:512 字节,CMD8 读 / CMD6 写Properties Segment [0..191]只读:容量(SEC_COUNT)、版本(REV)、能力(DEVICE_TYPE)、寿命、时序Mode Segment [192..511]可读写:总线宽度、HS_TIMING、分区配置、Cache、BKOPS、写保护访问方式:CMD8 读整块(512 B) / CMD6 改单个字节写后一律返回 R1b:必须等 DAT0 释放,并检查 SWITCH_ERROR(R1 bit7)常见误解:EXT_CSD 不是「寄存器数组」,每次 CMD6 只能改一个字节,且部分字段要断电/复位才生效
图 4-1 EXT_CSD 512 字节分段与访问方式
- Properties Segment(0~191):只读。容量、版本、能力、时序、寿命都在这里。
- Mode Segment(192~511):可读写。总线宽度、时序、分区、Cache、BKOPS、写保护都在这里。
4.2 CMD6:唯一的写入口
CMD6(SWITCH)32 bit 参数位域31:26置 025:24Access23:16Index15:8Value7:3置 02:0CmdSetAccess:00 = 命令集切换 01 = 置位 10 = 清位 11(0x3) = 写字节(最常用)Index = EXT_CSD 字节偏移(0~511) Value = 写入值 CmdSet = 0(标准命令集)例:切 HS400 → arg = (0x03≪24) | (185≪16) | (0x03≪8) | 0x00例:开 Cache → arg = (0x03≪24) | (33≪16) | (0x01≪8) | 0x00
图 4-2 CMD6(SWITCH)32 bit 参数位域
CMD6 是 R1b 命令,自带 busy
这一点最容易被忽略:CMD6 不是「写个寄存器就完事」,它可能触发器件内部的重新配置、分区重算甚至内部擦除。 返回类型是 R1b,器件会把 DAT0 拉低直到操作结束。不等 busy 就发下一条命令,会得到不可预期的结果。
超时由 GENERIC_CMD6_TIME 给出,单位 10 ms:本器件 = 0x25 → 370 ms(JEDEC 通用默认 0x0A → 100 ms,切勿照抄); 个别操作(Sanitize、掉电通知、分区切换、初始化后第一次分区生效)有自己的更长超时字段,见附录 C 与附录 F。
4.3 写 EXT_CSD 六步准则
4.4 生效时机:三种,别搞混
| 立即生效 | HS_TIMING、BUS_WIDTH、CACHE_CTRL、PARTITION_ACCESS | 写完等 busy 结束即可使用新配置 |
| 复位后生效 | PARTITION_CONFIG 的 BOOT 相关位、部分写保护设置 | 写完需 CMD0 或 RST_n 才生效 |
| 断电 / 硬件复位后生效 | BOOT_SIZE_MULT、RPMB_SIZE_MULT、GP_SIZE_MULT、ENH_SIZE_MULT | 分区容量类配置必须 power cycle,只复位不一定够,以 datasheet 为准 |
分区容量配置写完没断电,是「分区大小不对」的头号原因
典型事故:主机写完 GP_SIZE_MULT 后只做了软件复位,然后立刻按新分区大小去读写—— 器件还停留在旧的分区布局上,轻则读不到数据,重则写到错误的分区(比如把文件系统镜像写进了 Boot 区)。
产线流程必须把「配置分区 → 断电 → 重新上电 → 校验分区布局」做成不可跳过的固定步骤。
4.5 高频字段速查
| 34 | POWER_OFF_NOTIFICATION | R/W | 0x00 不支持 / 0x01 POWERED_ON / 0x02 SHORT / 0x03 LONG / 0x04 SLEEP | 掉电通知(第 10 章) |
| 32 | FLUSH_CACHE | W | bit0 FLUSH = 1 触发回写 | Cache 落盘(第 7 章) |
| 33 | CACHE_CTRL | R/W | bit0 Cache_EN:0 关 / 1 开 | Cache 开关 |
| 161 | HPI_MGMT | R/W | bit0 HPI_EN | 使能 HPI(第 11 章) |
| 163 | BKOPS_EN | R/W | bit0 MANUAL_EN,bit1 AUTO_EN | 一次性可编程,不可回退 |
| 164 | BKOPS_START | W | 0x01 手动触发一次后台操作 | 空闲时主动 GC |
| 165 | SANITIZE_START | W | 0x01 启动物理清除 | 出厂恢复 / 报废清密 |
| 175 | ERASE_GROUP_DEF | R/W | 0 = 用 CSD 定义 / 1 = 用 EXT_CSD 定义 | 高密度器件必须置 1 |
| 179 | PARTITION_CONFIG | R/W | [7] BOOT_ACK / [5:3] BOOT_PARTITION_ENABLE / [2:0] PARTITION_ACCESS | 分区切换与启动配置 |
| 183 | BUS_WIDTH | R/W | 0/1/2 = 1/4/8-bit;5/6 = 4/8-bit DDR | 总线宽度 |
| 185 | HS_TIMING | R/W | 0/1/2/3/4 = Legacy/HS/HS200/HS400/HS400ES | 速度档位 |
| 192 | REV | R | 0x08 = eMMC 5.1 | 版本判断 |
| 196 | DEVICE_TYPE | R | 位域:HS200 / HS400 及各电压档 | 能力协商 |
| 212 | SEC_COUNT | R | 4 字节小端;容量 = SEC_COUNT × 512 B | 容量唯一来源 |
| 246 | BKOPS_STATUS | R | 0 = 无需求;1~3 = 需求等级递增 | 是否该让器件做 GC |
| 267 | PRE_EOL_INFO | R | 0 Normal / 1 Warning / 2 Urgent | 寿命终期预警 |
| 268 | DEVICE_LIFE_TIME_EST_A | R | 0x01 0–10% … 0x0A 90–100%,0x0B 超期 | 常规模式寿命 |
| 269 | DEVICE_LIFE_TIME_EST_B | R | 同 A 的分档规则 | pSLC / SLC 模式寿命 |
完整字段定义见 JESD84-B51 第 7 章;厂商自定义字段以器件 datasheet 为准。本器件(XT28EG32/64GA2YUECGA)上电默认实测值见附录 F.1——其中 RST_n_FUNCTION[162] = 0(硬件复位默认未使能)、HPI_MGMT[161] = 0、BKOPS_EN[163] = 0、CACHE_CTRL[33] = 0、CMQ_MODE_EN[15] = 0 都是「支持但默认关」,必须由主机显式打开。
4.6 常见陷阱
| 不等 CMD6 的 busy | 后续命令无响应或返回错乱状态 | 把 CMD6 一律当 R1b 处理,等 DAT0 释放 |
| 不查 SWITCH_ERROR | 配置静默失败,实际仍在旧档位 | 每次 CMD6 后 CMD13 查 bit7 |
| 用 3.3 V VCCQ 切 HS400 | 高速下大量 CRC 错误 | 切高速前先把 VCCQ 切到 1.8 V(本器件不支持 1.2 V 档) |
| 照抄 JEDEC 默认超时 | Cache 回收 / GC 撞车时误判 CMD6 失败 | 超时一律从 GENERIC_CMD6_TIME 读出算,本器件 370 ms |
| 分区配置后未断电 | 分区大小不对,甚至写错分区 | 配置 → 断电 → 上电 → 校验,固化为产线步骤 |
| 把 BKOPS_EN 当普通开关 | 写入后无法回退(一次性可编程) | 只在确认需要时写入,并留记录 |
| 改 ERASE_GROUP_DEF 后不重算几何 | 擦除范围算错 | 置 1 后从 EXT_CSD 重新读取所有几何参数 |
后续章节请下载「芯参谋」查看
……(篇幅原因, 还有20章· 详见芯参谋→方案设计)
当前分享仅开放前 5 章正文。详细资料请在芯参谋客户端中打开完整文档。
打开路径:🔧解决方案&应用市场分析 -> 原理方案设计 -> eMMC_软件设计规范
📥 下载芯参谋客户端




