4. UFS命令集与数据传输机制归纳总结
UFS协议的核心,说白了就是一套命令+数据的“对话规则”。主机和设备怎么打招呼、怎么传数据、怎么处理异常,全得按这套规矩来。我在项目中调试UFS驱动时,踩的坑多半都跟命令格式或者传输阶段没对齐有关。这章我把命令集和数据传输机制掰开揉碎了讲,希望能帮你少走弯路。
4.1 UFS命令集全景
UFS命令集不是凭空造的,它继承了很多SCSI的衣钵,又加上了自己独有的一套。总的来看分成三大类:
- SCSI命令:READ(10)、WRITE(10)、INQUIRY、READ CAPACITY 等,这是最基础的部分,用来读写数据和获取设备信息。
- UFS特定命令:QUERY REQUEST 系列、TASK MANAGEMENT 系列,用来管理设备属性、任务、逻辑单元等。
- UFS传输层管理:UTP(UFS Transport Protocol)本身有专门的UFS Command UPIU、Data UPIU等,这些稍后细讲。
我个人习惯把命令集分成“数据面”和“管理面”。数据面走SCSI读写,管理面走QUERY和TASK。你想想看,如果混在一块,调试时连错误码都不知道去哪个手册里查。
4.2 主要命令类型与用途
| 命令分类 | 典型命令 | 用途 |
|---|---|---|
| 数据读写 | READ(10), WRITE(10) | 主机读写LBA数据块,支持D2H/H2D方向 |
| 设备查询 | INQUIRY, READ CAPACITY | 获取设备描述符、容量等信息 |
| 属性操作 | QUERY REQUEST (Read/Write Attribute) | 读写UFS特定属性(如bPreEOLInfo) |
| 标志/描述符 | QUERY REQUEST (Read/Write Flag / Descriptor) | 操作设备标志(如fPowerOnReset)和描述符(如几何参数) |
| 任务管理 | ABORT TASK, LOGICAL UNIT RESET | 终止某个命令、重置逻辑单元等 |
注意:UFS中没有“原生”写缓存刷新命令,通常用SYNC CACHE(SCSI命令)或QUERY方式刷写。我在一个项目中遇到过设备写缓存导致掉电丢数据的情况——后来强制在每个写请求后追加SYNC CACHE才解决。
4.3 数据传输机制:UPIU 的故事
UFS所有命令和数据都打包成UPIU(UFS Protocol Information Unit)来传输。一个UPIU就是一个固定格式的包,头节点带类型、长度、标记等信息,后面跟上数据负载。
主要UPIU类型:
- Command UPIU:主机发往设备,携带命令描述符(CDB)和参数。
- Data In UPIU / Data Out UPIU:设备向主机传数据(读)或主机向设备传数据(写)。
- Response UPIU:设备对命令的响应,成功或失败信息。
- Task Management UPIU:任务管理请求/响应。
- Ready-to-Transfer UPIU (RTT):设备告诉主机准备好接收写数据了(流控机制)。
为什么要有RTT?嗯,这里要注意:写操作时主机不能一股脑把数据全扔给设备,必须等设备发RTT,表示缓冲区有空位了。这样可以防overflow。我调试一个老版本UFS驱动时,忘记等RTT就直接发Data Out,结果设备直接crashed……
4.4 一次典型数据传输流程
- 主机通过UTP发送 Command UPIU 给设备(包含LBA、长度、方向等)。
- 读场景:设备准备数据后,直接发 Data In UPIU(可能多个分段);设备发最后一个Data In时附上 Response UPIU 表示成功。
- 写场景:设备先发 RTT UPIU 表示自己准备好了;主机收到后发 Data Out UPIU;传输完毕,设备再发 Response UPIU。
注意:UFS协议允许Command UPIU和Data UPIU并发,但必须遵循“标签”规则——每个命令使用唯一的Task Tag,主设备不能同时用同一个Tag发送两个命令。我曾经遇到过因为Tag重用导致设备返回“意外响应”的bug,排查了两天才发现是Tag计数器溢出了。
下图把一次写流程的UPIU交互画了出来,重点显示RTT流控:
4.5 流控与异常处理
除了RTT流控,UFS还支持Credit-Based流控——设备可以限制主机可发送的UPIU数量。如果Credit用完,主机必须等待设备释放新的Credit。我刚开始接触UFS时,完全忽略了Credit机制,结果传输速率死活上不去,后来才发现是Credit没更新,主机一直在等待。
异常情况呢?
- Timeout:主机等待响应超时,可以发送Task Management UPIU (ABORT TASK) 终止命令。
- Unexpected UPIU:接收到的UPIU类型与当前状态机不符,设备通常回复EHS(Extended Health Status)或直接丢弃。
- 链路错误:物理层(MIPI M-PHY)出错,传输层重试机制最多3次,超过则报设备挂起。
一个小技巧:调试UFS时,在驱动里打印每个UPIU的Header(特别是类型和Tag),再配合逻辑分析仪抓M-PHY信号,基本能定位80%的数据传输问题。
UFS命令集和数据传输机制其实不算复杂,但细节磨人。我记得有一次量产测试时,发现某些UFS设备在并发写大块数据时会间歇性返回“Check Condition”,最后查出来是Device Server内部资源限制导致的,我们需要在驱动里动态调整请求队列深度——这种坑没有亲自踩过,光看协议可学不来。