3. UFS 协议栈简介:四层结构
UFS 协议栈看着复杂,拆开看就四层:应用层、传输层、链路层、物理层。跟 OSI 七层模型比,它砍掉了会话层和表示层,因为存储场景不需要那么多花活。我自己刚开始啃 UFS 规范时,就盯着这四层看,一层一层扒开,心里才踏实。
为什么分四层?说白了,每层只干一件事,解耦。你改物理层的信号幅度,不用动上面三层。我团队以前有个项目,M-PHY 换了一个版本,链路层配置调了几个寄存器就搞定,应用层代码一行没改——这就是分层的好处。
3.1 应用层:命令的入口
应用层是离用户最近的一层。它处理 SCSI 命令集和 UFS 原生命令。比如读写、格式化、安全擦除。我早期有个项目,主机一直发 READ CAPACITY 命令,设备就是不回数据。查到最后,是应用层命令队列的 tag 冲突——同一个 tag 被用了两次,设备直接忽略。嗯,从那以后我检查命令标签特别仔细。
| 命令类别 | 典型命令 | 功能 |
|---|---|---|
| 基本 I/O | READ/WRITE | 逻辑块读写 |
| 管理命令 | FORMAT UNIT | 低格设备 |
| 安全命令 | SECURITY PROTOCOL IN/OUT | 加密密钥管理 |
| UFS 特有 | QUERY REQUEST | 读写设备属性、标志 |
3.2 传输层:UFS 的“快递员”
传输层干的事——把应用层命令打包成 UPIU(UFS Protocol Information Unit),再通过下层传出去。UPIU 有固定格式,头部包含命令类型、LUN、任务标签等。你看下面这张表,常见 UPIU 就几种:
| UPIU 类型 | 方向 | 主要用途 |
|---|---|---|
| COMMAND UPIU | Host → Device | 携带 SCSI 命令描述块 (CDB) |
| DATA IN UPIU | Device → Host | 读取数据回传 |
| DATA OUT UPIU | Host → Device | 写入数据发送 |
| RESPONSE UPIU | Device → Host | 命令完成状态 |
| TASK UPIU | Host → Device | 任务管理(中止、复位) |
为什么要有这么多类型?因为 UFS 是双工通信,数据可以在数据段里混着控制信息。有一次我在分析 trace 时,发现 RESPONSE UPIU 居然带了一段 payload——原来是设备把额外的 sense data 塞进去了。幸亏规范允许这么做,否则我可能冤枉它是个 bug。
3.3 链路层:UniPro 的可靠性保障
链路层基于 MIPI UniPro 协议。它负责帧定界、流控、检错重传。说白了,就是保证前面包装的 UPIU 能完整地传到对面,不丢包、不乱序。
UniPro 有多个版本(1.6、1.8、2.0 等)。我踩过一个坑:两个芯片用的 UniPro 版本不一样,链路层协商时一直失败,链路始终上不了。后来发现是 PA(Physical Adapter)层的配置参数不兼容。解决办法?强制降级到低版本协议。
3.4 物理层:M-PHY 的高速公路
物理层用的是 MIPI M-PHY,差分信号传输。有高速模式(HS)和低速模式(LS)。HS 能跑几 Gbps,LS 用于电源管理。链路启动时,先低速握手机制(PWM 模式),再切换到高速。
说到物理层,我不得不提眼图。那时候项目量产前,有一批芯片温度高了就丢包。换上示波器看眼图,发现 HS 通道的摆幅偏低,信号幅度只有 200mV,而规范要求至少 360mV。排查下来是 PCB 走线阻抗失配,还窜了一根时钟线的谐波。改版后眼图张开漂亮,再没出过问题。
| 模式 | 符号率 | 每通道带宽 | 典型场景 |
|---|---|---|---|
| HS-G1 | 1.248 Gbps | ~1.16 GB/s | 常见高速模式 |
| HS-G2 | 2.496 Gbps | ~2.32 GB/s | UFS 2.1 及以上 |
| HS-G3 | 5.824 Gbps | ~5.36 GB/s | UFS 3.0 起步 |
| LS-PWM | 几十 MHz ~ 几百 MHz | 低功耗 | 空闲、休眠 |
3.5 四层如何协作?
举个例子:你发一条 READ (LBA=100, len=8)。应用层生成 SCSI READ 命令,传给传输层。传输层封装成 COMMAND UPIU,附上 LUN、tag。链路层把 UPIU 切成数据帧,加上 CRC,发送。物理层把比特流变成差分信号,穿过去。设备端反向解析,最后通过 RESPONSE UPIU 返回数据。
如果任何一层出问题,链路要么起不来,要么数据错。所以排查问题时,我习惯先确定物理层眼图 OK,再确认链路层帧计数正常,最后看传输层 UPIU 类型对不对。一层一层剥开,不盲目猜。