第3章 总线协议基础:命令、响应、数据与CRC
咱们今天聊聊eMMC通信最底层的规矩——总线协议。说白了,就是Host和Device之间怎么“说话”、怎么“回话”、怎么“传东西”,以及怎么保证传的东西没出错。
我刚开始接触eMMC时,总觉得协议就是一堆枯燥的时序图。后来在一个项目里,因为没搞懂命令格式,导致初始化流程卡死,调了整整两天……从那以后,我就老老实实把这块啃透了。你想想看,总线协议就像交通规则,不搞清楚,车跑得再快也得翻。
3.1 命令格式:Host怎么说
Host给Device发命令,用的是CMD线(双向)。每一帧命令都是48位固定长度。嗯,这一点很关键:不管你发什么命令,长度都一样。
| 位域 | 位置 | 描述 |
|---|---|---|
| 起始位 | Bit 47 | 固定为'0',表示命令开始 |
| 传输位 | Bit 46 | '1'表示Host→Device方向 |
| 命令索引 | Bit 45 ~ 40 | 6位,范围0~63,如CMD0、CMD8 |
| 参数 | Bit 39 ~ 8 | 32位,具体含义由命令定义 |
| CRC7 | Bit 7 ~ 1 | 7位CRC,保护命令索引+参数 |
| 结束位 | Bit 0 | 固定为'1',表示命令结束 |
我个人习惯把命令格式看作一个“小信封”:起始位是信封开口,传输位标明寄信人,命令索引是收件人编号,参数是正文,CRC7是防伪封条,结束位是信封底。任何一个位错了,Device都不会认。
3.2 响应类型:Device怎么回
Device收到命令后,通过CMD线回响应。响应长度分两种:48位(短响应)和136位(长响应)。
为什么要分长短?你想,有些响应只需要传个状态(比如R1、R6),48位就够了;但有些响应要传CID、CSD这种一大串寄存器内容,48位装不下,就得用136位。
| 类型 | 长度 | 典型命令 | 说明 |
|---|---|---|---|
| R1 | 48位 | 大多数命令 | 标准状态响应,32位状态标志 |
| R2 | 136位 | CMD2、CMD9、CMD10 | CID/CSD寄存器内容 |
| R3 | 48位 | CMD5、CMD8 | OCR寄存器内容 |
| R4 | 48位 | CMD6(切换功能) | 模式切换状态 |
| R5 | 48位 | 中断请求相关 | R5比较特殊,项目用得少 |
3.3 数据块传输机制:怎么传大批量数据
说到数据块传输,HS400模式很特殊。它用的是8位并行总线(也就是DATA0~DATA7),并且是双沿采样——时钟上升沿和下降沿都采样数据。这意味着数据传输率直接翻倍。
说白了,HS400在物理层就是一个“双倍速”的并行通道。Host和Device之间传数据,都是以块为单位。HS400支持的块大小默认是512字节,但也可以配置成1024字节等。
// 数据块传输的典型流程(伪代码)
// 1. Host发命令,告诉Device要读写
send_command(CMD18, start_block_address); // 多块读
// 2. Device返回响应
resp = wait_response(R1);
// 3. 检查响应状态
if (resp.status & CARD_STATUS_READY_FOR_DATA) {
// 4. 开始数据传输(HS400模式下)
// 每个时钟沿传输8位,所以一个块512字节需要256个时钟周期
for (int i = 0; i < block_count; i++) {
read_data_block(buffer + i * 512, 512); // 包含CRC16验证
}
} else {
// 设备没准备好,重试或报错
handle_error();
}
这个过程里有个细节:每一个数据块传输完,Device会追加2字节的CRC16校验码。Host读到后,要用相同的多项式再算一遍,如果对不上,就得重传这个块。
我记得有一次在产品量产阶段,发现个别板子在大批量读写时会偶发CRC16校验失败。排查后发现是PCB走线过长导致信号完整性问题。所以你看,协议层面有校验保护,但物理层的问题还是要靠硬件设计来解决。
3.4 CRC校验:防错机制
eMMC用了两种CRC:
- CRC7:用于命令和短响应,保护49位数据(命令索引+参数,或响应内容)
- CRC16:用于数据块传输,保护整个数据块
CRC7的多项式是:x^7 + x^3 + 1(对应二进制0x89)。CRC16的多项式是:x^16 + x^12 + x^5 + 1(对应0x1021)。
这里有个常见坑:CRC7算的是“左对齐”的,也就是要先把数据左移7位再除多项式。我第一次实现时抄了一个网上查表法,结果跟eMMC规范对不上,折腾了老半天才发现是初始值和输出差异的问题。
3.5 本章知识总览
为了让你一眼看清这三大部分的关系,我画了这张图:
3.6 实战小结
这一章我们拆解了协议最核心的三部分:命令格式、响应类型、数据块传输与CRC。你不一定要背下每个位域的值,但一定要理解它们的“职责”:
- 命令是Host发出的48位“指令信封”,Device必须解码并校验CRC7后才能执行。
- 响应是Device的回执,R1最常用,R2用来获取寄存器内容。
- 数据块传输在HS400模式下利用8位并行双沿采样,每块带CRC16校验,保证数据完整性。
- CRC7和CRC16是eMMC最底层的防错机制,实现时一定要对照规范,否则“差之毫厘,谬以千里”。