2. UFS协议分层架构(物理层、链路层、传输层、应用层)
好,我们开始第二讲。UFS协议栈长什么样?很多刚接触的朋友一上来就看UFS Spec,几千页,直接懵掉。我个人的习惯是:先看分层,再看每层干了什么事,最后再串起来。分层架构搞明白了,后面的一致性测试你才知道该测哪一层。
UFS协议栈严格遵循OSI七层模型的思想,但做了大幅裁剪。它总共分为四层:物理层、链路层、传输层和应用层。说白了,从上到下就是:你要发什么数据(应用层)→ 怎么组织成帧(传输层)→ 怎么可靠地传过去(链路层)→ 靠什么物理信号传(物理层)。
这张图我反复用过很多次。你仔细看,会发现每个层次之间都有严格的分界。我做验证时,最痛苦的一次是某个host端死活连不上device,最后定位到是链路层的Link Startup时序少了一拍。你说测试重不重要?
2.1 物理层——最底下的硬功夫
物理层负责的是最原始的比特传输。UFS用的是MIPI联盟定义的M-PHY。嗯,这里要注意:M-PHY不是UFS独有的,它是一套高速串行接口标准,Camera、Display也都在用。
M-PHY支持多种速率模式,从HS-G1(大概1.45Gbps/lane)到HS-G5(目前UFS 4.0已经支持)。每增加一代,速率翻倍。我建议你记住下面这张表格,做一致性能测试的时候你会频繁用到:
| 速率代际 | 单通道数据速率 | UFS版本支持 |
|---|---|---|
| HS-G1 | 1.45 Gbps | UFS 2.0 / 2.1 |
| HS-G2 | 2.9 Gbps | UFS 2.0 / 2.1 |
| HS-G3 | 5.8 Gbps | UFS 2.1 / 3.0 |
| HS-G4 | 11.6 Gbps | UFS 3.0 / 3.1 |
| HS-G5 | 23.2 Gbps | UFS 4.0 |
这里有坑。我曾经碰过一个case:device标称支持HS-G4,但物理层测试时眼图一直不过。查了半天,发现是PCB走线阻抗没控好,导致高速信号反射严重。物理层验证不光是看协议,更得搭上信号完整性一起看。
2.2 链路层——可靠的搬运工
链路层在UFS里面对应的是UniPro协议栈的数据链路层。它解决的问题很简单:怎么保证物理层传过来的数据是可靠的?
链路层提供了几个关键机制:
- 流控(Flow Control):防止发送方把接收方撑爆。我见过一些新手调试时发现吞吐上不去,一查是流控门限设得太保守。
- 重传(Retransmission):丢包了怎么办?链路层有ACK/NAK机制,超时没收到确认就重发。
- Link Startup:上电后Host和Device是怎么握手的?这里有一套定时的序列,少一个都不行。
我个人习惯拿逻辑分析仪抓链路层的帧头,看PA_LAYER和DME_SAP的交互。有一次测新芯片,发现设备在Link Startup阶段发了CFG_ACK后一直不回CFG_CNF,最后定位是固件里DME配置的时序参数写错了。你想想看,这种问题在传输层根本看不出来,只有链路层的trace才能逮住。
2.3 传输层——UFS协议的核心
传输层在UFS里叫UTP(UFS Transport Protocol)。它的作用是把应用层的命令、数据、任务管理请求封装成UPIU(UFS Protocol Information Unit)。
UPIU是传输层的基本数据单元。说白了,就是一块有固定格式的包。常见的UPIU类型有:
| UPIU类型 | 用途 | 方向 |
|---|---|---|
| COMMAND UPIU | Host发送SCSI命令到Device | Host → Device |
| DATA IN UPIU | Device向Host传输数据 | Device → Host |
| DATA OUT UPIU | Host向Device传输数据 | Host → Device |
| RESPONSE UPIU | Device向Host反馈命令结果 | Device → Host |
| TASK MANAGEMENT UPIU | 任务管理(如Abort、Reset) | 双向 |
做传输层一致性测试,我最常看的是字段校验。比如COMMAND UPIU里的LUN(逻辑单元号)、Flags、Expected Data Transfer Length这些是否正确。我之前帮客户解决过一个读速度慢的问题,就是因为Device每次回RESPONSE UPIU时,都把Data Residual字段算错了,Host认为数据没收完,反复触发重传。
核心要点:传输层的验证重点是UPIU帧结构的字段合法性与响应时序。推荐使用的测试方法是:构造异常UPIU,检查Device是否会按照Spec定义的错误码回复。
2.4 应用层——命令的最终执行者
应用层是离用户最近的一层。它定义了Host怎么通过SCSI命令来操作存储设备:读、写、查询、配置等等。
UFS应用层支持的命令集包括:
- UFS Command Set:基于SCSI命令的一个子集,比如READ(10)、WRITE(10)、SYNC CACHE、UNMAP等。
- Task Management Functions:比如Abort Task、Logical Unit Reset、Target Reset。
- UFS Feature Extension:UFS特有的命令,比如Query Request用于读写设备描述符、属性、标志位。
举个例子,你要查Device的串号(Serial Number),就得用Query Request发一个Read Descriptor的命令,指定是Device Descriptor,偏移和长度都对上才行。我见过有的实现把Descriptor ID填错了,结果一直读到乱码。应用层的每个字段都得卡着UFS Spec的表格来,一个字都不能差。
我的小技巧:应用层验证时,我会先把UFS Spec里所有的命令支持矩阵整理成一张表。哪些命令是必须的(Mandatory),哪些是可选的(Optional),在测试计划里标清楚。测试设备对这些命令的响应是否一致。
注意:应用层最容易出现的问题是“实现不一致”。Spec里有些行为描述得比较模糊,比如Power Mode切换时的宽限时间。不同厂家的芯片理解不一样,导致互操作性问题。所以应用层的一致性测试,除了测命令本身,还要测超时和异常场景。
2.5 分层间的交互——一张图串起来
刚才我们分着讲了四层,但它们工作时是串在一起的。我画一个简单的流程,你感受一下:
Host启动读流程(简化版):
1. 应用层:构造SCSI READ(10)命令
2. 传输层:封装成COMMAND UPIU,添加Transaction ID
3. 链路层:将UPIU切分成UniPro帧,加流控和校验
4. 物理层:M-PHY将帧转成串行差分信号发送
--- 到Device侧反向解析 ---
5. 物理层:接收串行信号,恢复成比特流
6. 链路层:校验帧完整性,丢包则请求重传
7. 传输层:解析UPIU,恢复出SCSI命令
8. 应用层:执行读命令,准备数据返回
这个流程里任何一层出错,整个话就断了。做一致性测试的时候,我们不仅要测每一层的单层协议,还要测层间接口的行为。比如传输层发给链路层的UPIU,如果长度超出了链路层的MTU怎么办?这种边界case才是高手的试金石。
我记得有一次调一个UFS 3.0的项目,Device在UFSHCI寄存器里配置了DME Local Controller,结果链路层就是起不来。最后追到是物理层的HS-Gear切换时序没对齐链路层的期望。你看,一个看似是物理层的问题,影响到链路层,最终表现为设备无法枚举。所以分层搞懂之后,你才能快速定位问题到底出在哪一层。