2、UFS协议基础:UFS架构、物理层、链路层、传输层、命令集与描述符

UFS(Universal Flash Storage)并不是一条简单的“高速串行线”,而是一套分层明确的存储协议栈。它借鉴了 SCSI 的命令模型,又采用 MIPI 的物理与链路规范,最终在主机与闪存设备之间形成一条可寻址、可并发、可管理的存储通路。理解 UFS 协议基础,是后续做 UFS 到 PCIe 桥接时判断“哪些语义必须保留、哪些可以映射、哪些必须转换”的前提。

一、UFS 分层架构:从应用命令到物理信号

UFS 协议自上而下大致分为四层:应用层/命令层、传输层、链路层和物理层。主机侧由 UFS 主机控制器驱动(UFSHCD)和块层发起请求,设备侧由 UFS 设备控制器解析并访问 NAND 阵列。各层职责如下:

  • 应用/命令层:定义 UPIU(UFS Protocol Information Unit)中的命令、任务管理、查询请求等语义,承载 SCSI 命令集。
  • 传输层:负责 UPIU 的封装、解封装、标签(Task Tag)管理、命令队列与响应匹配。
  • 链路层:负责 UniPro 帧的成帧、CRC 校验、重传、流控与 Lane 管理。
  • 物理层:定义 M-PHY 的电气特性、Lane 数量、速率档位(Gear)与功耗状态。

这四层不是孤立存在的。一次读命令从主机发出,会依次经过命令层生成 UPIU、传输层分配 Tag、链路层打包成 UniPro 帧、物理层通过 M-PHY Lane 发送;设备侧则反向逐层解析,最终返回数据与响应。桥接设计中最容易出错的地方,往往不是某一层单独实现,而是层与层之间的状态同步。

UFS 协议分层与数据流 主机侧 (Host) 应用/命令层 SCSI 命令 · UPIU 构造 · 查询请求 传输层 Task Tag · 命令队列 · 响应匹配 链路层 (UniPro) 成帧 · CRC · 重传 · 流控 物理层 (M-PHY) Lane · Gear · 功耗状态 设备侧 (Device) 命令解析与执行 SCSI 解析 · 逻辑块寻址 传输层 Tag 回收 · 响应生成 链路层 (UniPro) 帧校验 · 确认 · 流控 物理层 (M-PHY) Lane · Gear · 功耗状态 M-PHY 链路 差分信号 · Lane 对 UPIU 端到端传输

二、物理层与链路层:M-PHY 与 UniPro 的协作

UFS 物理层采用 MIPI M-PHY,支持 HS(High Speed)和 LS(Low Speed)两种模式。HS 模式下常见 Gear 1 至 Gear 4,单 Lane 速率从约 1.25 Gbps 到 11.6 Gbps 不等;实际带宽还取决于 Lane 数量(通常 1 或 2 Lane)和双向独立配置。链路层则基于 MIPI UniPro,负责把上层 UPIU 封装为 UniPro 帧,并完成 CRC 校验、确认与重传。

这里有一个关键点:M-PHY 的“Gear”变化和 UniPro 的“Lane”管理是两套状态机,但它们必须协同。例如,当链路空闲时,M-PHY 可能进入 Hibern8 低功耗状态;一旦有命令到达,链路层需要先唤醒物理层,再恢复帧传输。桥接设备如果只做协议转换而不跟踪这些状态,就会出现“命令已发出但设备未唤醒”的超时问题。

提示:调试 UFS 链路问题时,先确认 M-PHY 是否完成 Gear 协商,再检查 UniPro 的 Lane 是否进入 Ready 状态。很多“命令超时”实际是物理层未就绪,而不是命令层错误。

三、传输层与命令集:UPIU、Task Tag 与 SCSI

UFS 传输层的核心是 UPIU。每个 UPIU 包含事务类型、Task Tag、数据段等字段。主机可以同时发出多个命令,每个命令分配唯一 Task Tag,设备按 Tag 返回响应。这种机制让 UFS 支持命令队列,从而提升并发性能。

UFS 命令集主要基于 SCSI。常见的命令包括:

命令 作用 典型 UPIU 类型
READ(10) / READ(16) 从设备读取逻辑块数据 COMMAND UPIU + DATA IN UPIU
WRITE(10) / WRITE(16) 向设备写入逻辑块数据 COMMAND UPIU + DATA OUT UPIU
INQUIRY 查询设备基本信息 COMMAND UPIU + DATA IN UPIU
TEST UNIT READY 检查设备是否就绪 COMMAND UPIU + RESPONSE UPIU
REQUEST SENSE 获取错误详情 COMMAND UPIU + DATA IN UPIU

除了 SCSI 命令,UFS 还定义了查询请求(Query Request),用于读写设备描述符、配置属性、设置标志等。查询请求不经过块数据通路,而是通过独立的 UPIU 类型完成,常用于初始化、电源管理和错误恢复。

四、描述符与属性:设备如何被识别和配置

UFS 设备通过描述符(Descriptor)向主机描述自身能力。描述符是只读或可写的数据结构,主机在枚举阶段读取它们,以决定使用哪些配置。常见描述符包括:

  • Device Descriptor:设备整体信息,如 UFS 版本、Lane 数量、容量等。
  • Configuration Descriptor:可配置项,如 Lane 数量、Gear 速率、电源模式。
  • Unit Descriptor:逻辑单元信息,如 LUN 编号、容量、写保护状态。
  • Geometry Descriptor:存储介质几何信息,如块大小、可擦除块数量。
  • Health Descriptor:设备健康状态,如寿命、温度、错误计数。

属性(Attribute)则是可读写的运行时参数,例如 bCurrentPowerMode、bActiveICCLevel、bRefClkFreq 等。标志(Flag)用于控制设备行为,如 fDeviceInit、fPurgeEnable。主机通过 Query Request 读写这些描述符、属性和标志,完成设备初始化与动态管理。

// 示例:通过 Query Request 读取 Device Descriptor
// 伪代码,展示 UPIU 字段结构
Query Request UPIU:
  Transaction Type = QUERY_REQUEST
  Query Function  = READ_DESCRIPTOR
  Descriptor ID   = DEVICE_DESCRIPTOR
  Index           = 0
  Selector        = 0
  Data Segment    = 返回的描述符内容

五、案例与误区:桥接场景下的常见问题

假设我们要把 UFS 设备桥接到 PCIe 主机。主机通过 PCIe 发出 NVMe 或自定义命令,桥接芯片需要将其转换为 UFS UPIU。此时最容易出现的误区有三个:

  1. 忽略 Task Tag 生命周期:UFS 的 Tag 是有限资源,桥接层如果只做命令转发而不跟踪响应回收,会导致 Tag 耗尽,后续命令无法下发。
  2. 混淆描述符与属性访问:描述符通常只读,属性可读写,但两者都通过 Query Request 访问。桥接层若把描述符读取当作普通数据读取,可能返回错误长度或错误类型。
  3. 忽略电源状态同步:UFS 设备可能处于 Sleep 或 PowerDown 状态,桥接层必须先发唤醒或查询状态,再发数据命令,否则会出现链路超时。
注意:UFS 的 UniPro 链路层有重传机制,但重传次数有限。如果桥接层持续发送错误帧,链路可能进入错误恢复状态,表现为设备“掉线”。此时应优先检查物理层信号质量和 Gear 配置,而不是反复重试命令。

总结来说,UFS 协议基础可以概括为:物理层提供 Lane 与 Gear,链路层保证可靠传输,传输层用 UPIU 和 Task Tag 管理并发,命令层承载 SCSI 与查询请求,描述符和属性则让主机能够识别并配置设备。只有把这五部分串起来理解,才能在 UFS 到 PCIe 桥接中做出正确的语义映射与状态管理。