## 3.1 UniPro 协议栈概述 UniPro(Unified Protocol,统一协议)是 MIPI 联盟定义的**分层通信协议栈**,位于 M-PHY 物理层之上。在 UFS 系统中,UFS 主机控制器与 UFS 设备之间的所有数据和控制信息都经过 UniPro 协议栈封装、传输并重组。 UniPro 协议栈从下至上分为 **L1(数据链路层)、L2(网络层)、L3(传输层)**,每层完成独立且紧耦合的功能。本章将依次展开每层的职责、帧结构、数据传输机制与错误检测手段。
核心理解:UniPro 类似于 TCP/IP 协议栈的“微型版”,但对实时性、功耗和物理特性做了深度优化。L1 负责物理符号传输,L2 负责帧定界和纠错,L3 负责多通道复用和路由。UFS 设备探测期间,L1/L2 层的链路同步是设备是否可被发现的前提。
## 3.2 L1 层功能与帧结构 ### 3.2.1 功能职责 L1(数据链路层)直接在 M-PHY 通道上传输 **符号(Symbol)** 并完成: - 同步序列(SYNC)生成与检测 - 8b/10b 编解码(数据映射与直流平衡) - 基本错误检测(PHY 层 CRC) - 链路初始化与休眠唤醒控制 在链路训练阶段,L1 层会持续发送 **PA_INIT 控制符号**直到对端返回确认。 ### 3.2.2 L1 帧结构 L1 层数据被打包为 **符号序列(Symbol Sequence)**,每个符号为 8b/10b 编码后的 10 位数据。帧结构如下: | 字段 | 长度 | 说明 | |------|------|------| | SYNC | 1~4 个符号 | 同步头,用于恢复时钟边界 | | FRAME_START | 1 个符号 | 帧起始定界符 | | PAYLOAD | N 个符号 | 有效数据负载(最大 64 字节) | | CRC | 2 个符号 | 16 位循环冗余校验 | | FRAME_END | 1 个符号 | 帧结束定界符 | L1 层还包含 **控制符号(Control Symbol)** 用于链路状态切换,如 SLEEP、WAKEUP、SYNC_LOST。 ### 3.2.3 关键配置:L1 链路初始化参数 在主机侧配置 UniPro L1 层时,通常需要在设备描述符中指定以下寄存器:
// UniPro L1 设备描述符配置示例
u32 l1_init_config = 0;
l1_init_config |= (1 << 0);   // Enable CRC check
l1_init_config |= (2 << 4);   // SYNC pattern length: 4 symbols
l1_init_config |= (0 << 8);   // 8b/10b encoding: standard

// 写入 UniPro 设备寄存器偏移 0x100
*(volatile u32 *)(UNIPRO_BASE + 0x100) = l1_init_config;
## 3.3 L2 层功能与帧结构 ### 3.3.1 功能职责 L2(网络层)在 L1 基础上增加了**可靠的帧传输与确认(ACK/NAK)机制**,主要职责: - 帧定界(Frame Delimitation) - 序列号管理(Sequence Number, SN) - 重传与超时控制 - 多通道数据分配(如果 L3 启用多通道) L2 层帧分为 **数据帧(Data Frame)** 和 **确认帧(Acknowledgment Frame)**。 ### 3.3.2 L2 帧结构 | 字段 | 长度 | 说明 | |------|------|------| | SN | 3 位 | 帧序号范围 0~7,循环使用 | | FC | 1 位 | 帧类别:0=数据帧,1=确认帧 | | LENGTH | 8 位 | 数据负载长度(字节) | | PAYLOAD | 0~65535 字节 | CPort 数据或控制消息 | | FCS | 16 位 | 帧校验序列(全部字段参与计算) | | ACK_NAK | 1 位(内嵌在帧尾) | 确认/否定确认 | ### 3.3.3 数据传输单元:CPort 上层数据通过 **CPort(通信端口)** 映射到 L2 帧。每个 CPort 被分配一个通道号,L3 层将数据分段后为每个 CPort 创建独立的 L2 帧序列。在 UFS 协议中,CPort 0~3 被用于不同的 UPIU 类型。 ### 3.3.4 错误检测与重传 L2 层检测到 FCS 错误或序列号乱序后,会: 1. 丢弃损坏帧 2. 向发送端发送 **NAK(Negative Acknowledgment)** 3. 发送端收到 NAK 或超时后立即重传未确认帧
// L2 层错误计数器示例(日志输出片段)
UNIPRO: L2_CRC_ERROR_CNT = 0x0003
UNIPRO: L2_NAK_TX_CNT    = 0x0001
UNIPRO: L2_RETRY_CNT     = 0x0002
// 上述值表示最近发生过 3 次 CRC 错误、1 次 NAK 发送、2 次重传。
调试提示:在初始化阶段若发现 L2_CRC_ERROR_CNT 持续增长,应优先排查物理层信号完整性,而非协议栈软件配置。
## 3.4 L3 层功能与数据路由 ### 3.4.1 功能职责 L3(传输层)位于协议栈最顶层,负责: - 多 CPort 复用(Multiplexing) - 长消息分段(Segmentation)与重组(Reassembly) - 流控(Flow Control,基于 credits) - 端到端错误检测 ### 3.4.2 L3 帧结构 | 字段 | 长度 | 说明 | |------|------|------| | CPort ID | 4 位 | 目标 CPort 编号(0~15) | | SID | 8 位 | 消息分段标识,用于重组 | | EOF | 1 位 | 分段结束标志 | | CREDIT | 2 位 | 流控信用值 | | PAYLOAD | 可变 | 上层数据段 | 当上层消息大于 L3 段最大长度时(通常 2048 字节),L3 会自动切分并添加相同 SID 的分段帧。 ### 3.4.3 关键配置:L3 CPort 映射 在设备探测阶段,主机需要配置每个 CPort 的流控参数:
// CPort 0 设备描述符配置
struct cport_config {
    u8 cport_id;
    u8 credit_limit;   // 最大未确认帧数量
    u16 max_segment;   // 最大分段长度
};

struct cport_config cp0 = {
    .cport_id     = 0,
    .credit_limit = 4,       // 初始信用值 4
    .max_segment  = 512,     // 分段大小 512 字节
};

// 写入 UniPro L3 寄存器区
write_unipro_l3_cport(UNIPRO_BASE + 0x200, &cp0, sizeof(cp0));
## 3.5 UniPro 协议栈三层交互流程 以下 SVG 图展示 UFS 设备探测阶段 UniPro L1/L2/L3 层的典型交互序列: 图3-1 UniPro 三层交互序列(设备探测阶段) 主机 L3 主机 L2 主机 L1 设备 L3 设备 L2 设备 L1 SYNC / FRAME / CRC ACK / NAK / 重传 分段 / 信用流控 交互说明: 1. L1 先建立符号同步(M-PHY 线速协商) 2. L2 开始发送 PA_INIT 控制序列,完成链路确认 3. L3 交换 CPort 映射与信用值,建立数据通道 4. 设备探测命令(QUERY)作为 L3 段数据下发 5. 所有层均参与错误检测与重传保障 ## 3.6 常见错误与修复 | 错误现象 | 可能原因 | 修复措施 | |----------|----------|----------| | L1 SYNC 超时 | M-PHY 速率不匹配 / 信号完整性差 | 检查线速协商寄存器;降低速率调试 | | L2 CRC 持续递增 | 物理层噪声 / 8b/10b 编码失锁 | 使用示波器检查数据眼图;增加重试阈值 | | L2 NAK 风暴(超过 10% 帧重传) | M-PHY 链路抖动 / L2 缓冲区不足 | 增大 L2 重试窗口;检查 M-PHY 驱动强度 | | L3 信用耗尽导致挂起 | CPort credit_limit 配置过小 | 将 credit_limit 至少设为 4~8 | | 设备探测失败(未收到 L3 段响应) | L3 SID 未对齐 / 分段重组错误 | 抓取 L3 段日志,检查 SID 与 EOF 位 |
现场排查实战:使用调试工具(如 UFS Trace Analyzer)监测 UniPro L2 帧日志时,重点观察 PA_INIT 控制符号插入频率。如果设备在 5ms 内未收到 PA_INIT_COMPLETE,很可能 L1 链路未能锁定,此时应首先复位 M-PHY 并重新发起链路训练。
## 3.7 调试日志分析示例 以下是从真实 UFS 调试中截取的 UniPro 层消息片段(仅保留关键字段):
[Host L1]  SYNC found @ symbol 0x55
[Host L1]  FRAME_START detected
[Host L2]  SN=3 FC=0 LEN=48 FCS=0xA3B2
[Host L2]  ACK sent for SN=3
[Dev  L2]  NAK received for SN=3, retransmit scheduled
[Host L2]  Retry SN=3 (attempt 2)
[Dev  L2]  ACK received for SN=3, clearing pending
[Host L3]  CPort=0 SID=0x1A EOF=1 CREDIT=4
[Dev  L3]  Segment reassembled, message complete
**日志解读:** - 主机 L1 在第 0x55 符号上获得同步,随后检测到帧起始。 - L2 帧携带序列号 3,FCS 校验正确,设备返回 ACK。 - 但设备在收到第一次 SN=3 时返回 NAK(可能 CRC 错误),主机重传后成功。 - L3 层最终完成一段完整的 CPort 0 消息传输。 这类日志是判断 UniPro 链路稳定性的第一手证据。若 NAK 比例超过 1%,需优先排查物理层并考虑增大 L2 重试窗口。 --- 本章完整介绍了 UniPro 三层协议栈的结构、帧格式、错误检测与恢复机制,并给出了设备探测阶段的交互流程与常见问题排障方法。理解这些细节是后续章节中配置 UFS 设备描述符、优化链路训练成功率的基础。