UFS 软件设计规范
编制日期 2026-09-24 | 版本号 Rev 1.5
UFS-SW-SPEC-001 · V1.0
面向嵌入式与移动终端UFS(Universal Flash Storage,JEDEC JESD220 系列)主机侧驱动的设计约束与推荐实现: 覆盖协议栈与 UPIU 事务模型、初始化状态机、Descriptor / Flag / Attribute 配置体系、LU 逻辑单元管理、读写擦命令序列、RPMB 与写保护、掉电保护、低功耗与错误恢复,逐条给出可落地的判据与流程。
18章节
6附录
4 KB逻辑块大小
32任务队列深度
| 文档编号 | UFS-SW-SPEC-001 |
|---|---|
| 版本 / 状态 | V1.0 · 正式发布 |
| 适用器件 | JEDEC UFS 2.0 / 2.1 / 3.0 / 3.1 / 4.0(JESD220B~F)器件,容量 32 GB ~ 1 TB |
| 基准器件 | UFS 3.1 器件(HS-G3,2 lane,VCCQ=1.2 V / VCCQ2=1.8 V,4 KB 逻辑块,LU 队列深度 32);文中标注「本器件」的数值取自该档器件典型手册值 |
| 参考标准 | JEDEC JESD220F / E(UFS 4.0 / 3.1)· MIPI UniPro v2.0 · MIPI M-PHY v5.0 · SCSI SPC-4 / SBC-3 / SAM-4 |
| 配套文档 | UFS_电路设计指南.html(电源时序 / REF_CLK / 差分 Layout / SI 与故障排查) |
0 · 文档说明
0.1 目的与范围
本规范约束 UFS 主机侧驱动的命令序列、配置口径、判据与超时预算,目标是让不同平台、不同人员的实现保持一致,避免"能跑但不稳"的实现进入量产。与 eMMC 最大的差别在于:UFS 是基于 UPIU 的事务模型 + SCSI 命令集,且引入了任务队列与三态配置对象(Descriptor / Flag / Attribute)。
范围内
主机驱动(UFS Host Controller Driver)的初始化、读写擦、配置管理、Boot、RPMB、掉电保护、低功耗、错误恢复与 API 语义。
范围外
① M-PHY / UniPro 链路层以下的实现(由主控 IP 提供);② 文件系统与 FTL 策略(器件内部实现,主机不可见);③ UFS 卡(JESD223)的热插拔协议;④ 具体 SoC 寄存器编程细节。
0.2 文档使用说明
- 「必须 / 禁止」表示硬性约束,违反会导致可靠性问题或量产事故。
- 「建议 / 推荐」表示经验值,可按平台能力调整,但需记录理由。
- 所有
0x前缀为十六进制,b前缀表示 1 字节字段(Byte),d前缀表示 4 字节(Dword),w前缀表示 2 字节(Word),沿用 UFS 规范的匈牙利命名。 - IDN(Identifier Number)等具体编号以所选器件手册为准,本文给出的是常见档位的典型值。
- 硬件相关(电源、时钟、复位、Layout)问题请先查《UFS 电路设计指南》。
0.3 书写约定
| 记号 | 含义 | 示例 |
|---|---|---|
bXxx | 1 字节字段 / Attribute | bBootLunEn |
dXxx | 4 字节字段 | dNumAllocUnits |
wXxx | 2 字节字段 | wManufacturerID |
fXxx | Flag(布尔) | fDeviceInit |
LU n | 第 n 个逻辑单元 | LU 0、LU 1 |
W-LUN | Well-Known LU(特殊功能单元) | RPMB0x44 |
1 · 器件定位与协议栈架构
UFS 把「SCSI 命令集」搬进了嵌入式存储:主机发的是标准 SCSI CDB,传输靠 UPIU 事务包,底层是 UniPro + M-PHY 串行链路。理解这套分层,才能看懂后面的所有命令序列。
1.1 定位与关键参数
| 维度 | 典型值 | 说明 |
|---|---|---|
| 命令集 | SCSI SPC / SBC 子集 | 主机下发标准 CDB |
| 传输单元 | UPIU(UFS Protocol Information Unit) | 命令、数据、响应、任务管理、查询 |
| 逻辑块大小 | 4 KB(主流) | 由bLogicalBlockSize决定,部分器件支持 512 B |
| 逻辑单元 | LU 0~7 | 最多 8 个可配置 LU + 若干 W-LUN |
| 队列深度 | ≤ 32(每 LU) | 由bLUQueueDepth与主机能力取小 |
| 单次 UPIU 负载 | ≤ bMaxDataIn/OutSize × 512 B | 典型 8~32(4~16 KB) |
| 双工 | 全双工 | 读写可并发 |
| 安全区 | RPMB | 独立认证访问通道 |
1.2 协议栈四层模型
| 层 | 规范 | 职责 | 驱动可见性 |
|---|---|---|---|
| 应用层 | UFS Command Set(SCSI 子集) | 读写擦、模式页、诊断、安全协议 | 完全可见(驱动构造 CDB) |
| 传输层 UTP | UFS Transport Protocol | UPIU 封装、Task Tag 管理、流控 | 完全可见(驱动组装 UPIU) |
| 数据链路层 | MIPI UniPro | 连接建立、可靠传输、功耗管理 | 部分可见(通过主机控制器寄存器) |
| 物理层 | MIPI M-PHY | HS / PWM 模式、差分传输 | 不可见(硬件完成) |
一句话分工
驱动负责构造 CDB 并包成 UPIU;主机控制器负责把 UPIU 交给 UniPro / M-PHY;链路问题表现为 UPIU 超时或链路重训,而不是 CDB 报错。
1.3 UPIU 事务模型
UPIU 是主机与器件之间交换的最小协议单元。常见事务类型与其事务码(Transaction Code):
| UPIU 类型 | 事务码 | 方向 | 用途 |
|---|---|---|---|
| NOP OUT / NOP IN | 0x00 / 0x20 | 双向 | 链路探测、保活 |
| COMMAND / RESPONSE | 0x01 / 0x21 | 双向 | 承载 SCSI CDB 与其响应 |
| DATA OUT / DATA IN | 0x02 / 0x22 | 双向 | 承载实际数据负载 |
| READY TO TRANSFER(RTT) | 0x31 | 器 → 主 | 流控:告知可发送多少数据 |
| TASK MANAGEMENT REQ / RSP | 0x04 / 0x24 | 双向 | 中止任务、LU 复位等 |
| QUERY REQUEST / RESPONSE | 0x16 / 0x36 | 双向 | 读写 Descriptor / Flag / Attribute |
| REJECT | 0x3F | 器 → 主 | 拒绝非法 UPIU |
典型写事务:COMMAND → RTT → DATA OUT → RESPONSE主机侧器件侧COMMAND UPIU (0x01)WRITE(10) CDB + LBA + 长度RTT UPIU (0x31)允许发送 N 个数据块DATA OUT UPIU (0x02)按 RTT 额度分批发送,直到写完RESPONSE UPIU (0x21)SCSI Status + Sense 数据关键约束:DATA OUT 必须等 RTT,不可一次全发;每批不超过 bMaxDataOutSize;响应中的 Status 非 GOOD 时必须取 Sense 判因Task Tag:同一时刻最多 32 个在途任务,由主机分配并回收
图 1 · 典型写事务的 UPIU 交互序列:COMMAND → RTT → DATA OUT → RESPONSE
关于 RTT
写方向由器件通过RTT控制节奏,主机必须遵守额度,不能一次把全部数据推下去;读方向则由主机发 COMMAND 后等待DATA IN。这是 UFS 与"发完就等"的 eMMC 流程最大的不同。
1.4 寻址:LU 与 LBA
- LU(Logical Unit)是 UFS 的分区单位,最多 8 个(LU 0~7),每个 LU 有独立的容量、逻辑块大小、写保护与队列深度。
- LBA在每个 LU 内独立编址,从 0 开始;命令中的 LUN 字段决定访问哪个 LU。
- W-LUN(Well-Known LU)不是存储区,而是功能入口:REPORT LUNS、UFS Device、Boot、RPMB。
- 访问粒度是逻辑块(典型 4 KB),不是 NAND 页——主机看不到物理页与坏块,这部分完全由器件 FTL 负责。
1.5 与 eMMC 的关键差异
| 对比项 | eMMC | UFS |
|---|---|---|
| 配置方式 | EXT_CSD 512 B,CMD6 单一入口 | Descriptor / Flag / Attribute 三类,QUERY UPIU 读写 |
| 命令模型 | CMD + 响应,半双工 | SCSI CDB + UPIU,全双工 + 队列 |
| 并发 | 单命令串行 | 最多 32 个在途任务 |
| 分区 | Boot / RPMB / GPP 分区 | LU 0~7 + Boot LU + RPMB W-LUN |
| 初始化 | CMD0/1/2… + 提速 | 链路启动 → NOP 探测 → fDeviceInit → 配置 |
| 掉电通知 | Power Off Notification(CMD6) | START STOP UNIT(Power Down)+ SYNCHRONIZE CACHE |
2 · 术语与缩写
2.1 协议栈术语
| 术语 | 全称 / 含义 |
|---|---|
| UPIU | UFS Protocol Information Unit,主机与器件交换的协议包 |
| UTP | UFS Transport Protocol,传输层,负责 UPIU 的封装与任务管理 |
| UniPro | MIPI 统一协议,UFS 的数据链路层 |
| M-PHY | MIPI 物理层,UFS 的差分串行接口 |
| HS-Gear | High Speed Gear,M-PHY 高速档位(G1~G5) |
| PWM-Gear | Pulse Width Modulation Gear,低速档位,用于建链与休眠 |
| Lane | 一对收发差分线,UFS 支持 1~2 lane |
| Task Tag | 在途任务的编号,最多 32 个,主机分配 |
| CDB | Command Descriptor Block,SCSI 命令描述块 |
| RTT | Ready To Transfer,器件发给主机的流控许可 |
2.2 存储与 LU 术语
| 术语 | 全称 / 含义 |
|---|---|
| LU | Logical Unit,逻辑单元,UFS 的分区单位(0~7) |
| W-LUN | Well-Known LU,功能型逻辑单元(Boot / RPMB / Report LUNs / UFS Device) |
| LBA | Logical Block Address,逻辑块地址,LU 内从 0 编址 |
| Allocation Unit | 分配单元,器件内部容量管理粒度 |
| Thin Provisioning | 精简配置,LU 容量按需分配而非一次性占用 |
| UNMAP | SCSI 命令,释放逻辑块(等价于 Trim) |
| Purge | UFS 的安全擦除操作,使数据不可恢复 |
| RPMB | Replay Protected Memory Block,重放保护存储区 |
2.3 特性与机制术语
| 术语 | 全称 / 含义 |
|---|---|
| WriteBooster | UFS 3.1 起的 pseudo-SLC 写缓存,提升突发写性能 |
| HPB | Host Performance Booster,把 L2P 映射表缓存到主机内存以加速随机读 |
| FFU | Field Firmware Update,现场固件升级 |
| Descriptor | 只读或可写的结构化配置块(Device / Unit / Geometry 等) |
| Flag | 布尔型开关(fDeviceInit / fPurgeEnable 等) |
| Attribute | 数值型参数(bMaxDataInSize / bBootLunEn 等) |
| Query | 读写上述三类对象的 UPIU 事务 |
| SSU | START STOP UNIT,SCSI 命令,用于功耗状态切换 |
| Device Init | 器件内部初始化阶段,由 fDeviceInit 触发,需轮询等待完成 |
3 · 驱动架构与初始化
UFS 初始化比 eMMC 多两个环节:链路启动(UniPro/M-PHY)和器件内部初始化(fDeviceInit)。跳过或判错这两步,是 Bring-up 阶段最常见的坑。
3.1 分层职责
| 层次 | 职责 | 典型实现 |
|---|---|---|
| Block / 文件系统 | 提交 bio / 请求,管理脏页与回写 | 内核通用层,无 UFS 特有逻辑 |
| UFS 驱动核心 | UPIU 组装、Task Tag 管理、错误恢复、电源管理 | UFS Host Controller Driver |
| 主机控制器(HCI) | DoorBell 寄存器、DMA 传输列表、中断 | SoC IP,寄存器编程 |
| UniPro / M-PHY | 链路建立、HS 训练、功耗状态 | 硬件 + PHY 固件 |
驱动核心要管好三件事
①Task Tag 池:分配、回收、超时回收;②错误恢复:区分链路级(重训)与命令级(重试/复位);③电源状态:与 Runtime PM 联动,唤醒后正确地恢复链路。
3.2 上电初始化流程
UFS 上电初始化流程(硬件链路 → 软件配置 → 就绪)① 电源与时钟就绪VCC / VCCQ / VCCQ2 稳定,REF_CLK 输出,释放 RST_n② UniPro 链路启动PWM 建链 → 协商 → 切换 HS-Gear(硬件完成)③ NOP OUT / NOP IN 探测确认 UTP 层可用,失败则判为链路未通④ 读 Device / Geometry Descriptor获取厂商、型号、容量、队列能力⑤ 置位 fDeviceInit 并轮询器件内部初始化,未完成时禁止下发数据命令⑥ 下发配置并枚举 LUbMaxDataIn/OutSize、电源模式,REPORT LUNS 枚举步骤 ⑤ 是最易出错的环节fDeviceInit 置位后需轮询该 Flag 直至器件清除;期间下发读写会返回错误或产生不可预期行为步骤 ③ 失败时的判定NOP 无响应 = 链路未通,优先查硬件:电源、REF_CLK、RST_n、焊接,而不是反复重试软件流程步骤 ⑥ 的配置顺序先配 bMaxDataInSize / bMaxDataOutSize(影响吞吐),再配电源模式与 LU 属性,最后枚举 LU超时预算(建议初值,按平台调整)链路启动:秒级(硬件完成,驱动等待中断)NOP 探测:100 ms ~ 1 sfDeviceInit 轮询:建议上限 5 s,超时应报错而非死等普通读写命令:按数据量估算,小命令建议 1~5 sFORMAT UNIT / Purge:分钟级,必须给足超时初始化完成后,驱动应记录:器件型号 / 固件版本 / HS-Gear / lane 数 / 逻辑块大小 / 各 LU 容量,供后续诊断使用
图 2 · UFS 上电初始化流程:硬件链路 → NOP 探测 → 读 Descriptor → fDeviceInit → 配置与枚举
两条硬规则
①必须在 NOP 探测成功后才继续,NOP 无响应时不许反复重试——那是硬件问题;
②必须轮询fDeviceInit直到器件清除该标志,未完成前禁止下发任何读写命令。
3.3 器件识别与能力协商
| 读取项 | 来源 | 用途 |
|---|---|---|
| wManufacturerID | Device Descriptor | 厂商识别,用于 quirk 匹配 |
| 产品型号 / 固件版本 | Device Descriptor / String Descriptor | 版本追踪与升级判断 |
| dNumAllocUnits + 单元大小 | Geometry / Unit Descriptor | 计算 LU 容量 |
| bLogicalBlockSize | Unit Descriptor | 逻辑块大小(常见 12 → 4 KB) |
| bLUQueueDepth | Unit Descriptor | 队列深度上限 |
| bMaxDataInSize / OutSize | Attribute | 单次 UPIU 数据负载上限 |
| bBootLunEn / Boot 能力 | Attribute / Device Descriptor | 是否支持启动 |
能力协商原则:主机能力 ∩ 器件能力,取交集。若主控 M-PHY 只支持 HS-G3 而器件是 UFS 4.0,链路会在 HS-G3 上工作;软件不应按器件标称的最高性能来做调度假设。
3.4 配置下发与生效
- 配置分三类下发:Attribute 写值(数值)、Flag 置位/清除/翻转(布尔)、Descriptor 写(结构块,仅部分可写)。
bMaxDataInSize/bMaxDataOutSize必须在第一次数据传输前配置,取值受主控 DMA 与器件能力共同限制。- 部分配置(如 LU 容量、写保护)需要 LU 处于未使用状态或需要下电复位才生效,务必查手册。
- 配置完成后建议回读校验:写入后再 Query 读一次,确认值已生效且未被器件拒绝。
3.5 初始化自检清单
- 三路电源电压与时序符合硬件规范(见配套硬件文档)。
- REF_CLK 已稳定,RST_n 已释放且低电平时间充足。
- 链路启动完成,HS-Gear 与 lane 数符合预期。
- NOP OUT/IN 成功返回。
- Device Descriptor 读取成功,厂商与型号符合 BOM。
- fDeviceInit 已置位并轮询到清除。
- bMaxDataInSize / bMaxDataOutSize 已配置并回读校验。
- REPORT LUNS 枚举成功,LU 数量与容量符合预期。
- 初始化日志已记录(型号 / 固件 / Gear / lane / 块大小)。
4 · Descriptor / Flag / Attribute
UFS 的配置体系是「三类对象 + 一个 Query 通道」。与 eMMC 的 EXT_CSD 相比更结构化,但也更容易写错时机。
4.1 三类配置对象
| 类型 | 形态 | 访问方式 | 典型成员 |
|---|---|---|---|
| Descriptor | 结构化数据块(若干字节) | READ / WRITE DESCRIPTOR | Device、Geometry、Unit、Power、Health |
| Flag | 布尔(True / False) | READ / SET / CLEAR / TOGGLE FLAG | fDeviceInit、fPurgeEnable、fBackgroundOpsEn |
| Attribute | 数值(1 / 2 / 4 字节) | READ / WRITE ATTRIBUTE | bBootLunEn、bMaxDataInSize、bCurrentPowerMode |
4.2 Query Request / Response
三类对象都通过QUERY REQUESTUPIU(0x16)访问,器件回QUERY RESPONSE(0x36)。请求包里用Function(操作码)与IDN(对象编号)定位目标。
Query Request / Response:三类对象的统一访问通道QUERY REQUEST UPIU(0x16)Transaction Code = 0x16Function(操作码)IDN(对象编号)Index(LU 序号等)SelectorValue / Data(写操作携带)0x01~0x08见附录 BQUERY RESPONSE UPIU(0x36)Transaction Code = 0x36Response 字段:成功 / 失败原因Value / Data(读操作返回)判据:先看 Response 字段非成功时不得使用返回数据;常见失败原因:对象不可写、时机不允许、参数越界建议:写后立即回读校验
图 3 · Query Request / Response:Function + IDN + Index 定位对象,先看 Response 再信数据
| Function | 操作码 | 作用 |
|---|---|---|
| READ DESCRIPTOR | 0x01 | 读取 Descriptor |
| WRITE DESCRIPTOR | 0x02 | 写入可写 Descriptor |
| READ ATTRIBUTE | 0x03 | 读取 Attribute |
| WRITE ATTRIBUTE | 0x04 | 写入 Attribute |
| READ FLAG | 0x05 | 读取 Flag |
| SET FLAG | 0x06 | 置位 Flag |
| CLEAR FLAG | 0x07 | 清除 Flag |
| TOGGLE FLAG | 0x08 | 翻转 Flag |
4.3 Descriptor 清单
| Descriptor | IDN | 主要内容 | 可写性 |
|---|---|---|---|
| Device Descriptor | 0x00 | 厂商、型号、LU 数量、Boot 能力、队列深度 | 只读 |
| Configuration Descriptor | 0x01 | 当前配置状态(部分字段可写) | 部分可写 |
| Unit Descriptor | 0x02 | 每 LU 的容量、块大小、写保护、队列深度 | 部分可写 |
| Interconnect Descriptor | 0x04 | UniPro / M-PHY 参数 | 只读为主 |
| String Descriptor | 0x05 | 型号名、固件版本等字符串 | 只读 |
| Geometry Descriptor | 0x07 | 总容量、分配单元大小、最大块数 | 只读 |
| Power Parameters Descriptor | 0x08 | 各功耗状态的电流与超时参数 | 只读 |
| Device Health Descriptor | 0x09 | 寿命估计、EOL 信息、异常计数 | 只读 |
| RPMB Unit Descriptor | 版本相关 | RPMB 区域大小与特性 | 只读 |
注:IDN 取值在不同 UFS 版本间存在差异,实现前请以器件手册核对;RPMB Unit Descriptor 的编号随版本变化,本文不给出固定值。
4.4 Flag 与 Attribute 清单
| Flag | IDN | 作用 | 备注 |
|---|---|---|---|
| fDeviceInit | 0x01 | 触发器件内部初始化 | 置位后需轮询至清除 |
| fPermanentWPEn | 0x02 | 永久写保护使能 | 不可逆,慎用 |
| fPowerOnWPEn | 0x03 | 上电写保护使能 | 下电后失效 |
| fBackgroundOpsEn | 0x04 | 后台操作使能 | 建议保持开启 |
| fPurgeEnable | 0x06 | Purge 操作使能 | 执行 Purge 前先置位 |
| fWriteBoosterEn | 0x0E | WriteBooster 使能(3.1+) | 配合缓存容量配置 |
| fHPBEn | 0x10 | HPB 使能(3.1+) | 需主机侧配套实现 |
| Attribute | IDN | 作用 | 备注 |
|---|---|---|---|
| bBootLunEn | 0x00 | 启动 LU 使能 | 01h = Boot LU A,02h = B |
| bCurrentPowerMode | 0x02 | 当前功耗模式 | 只读为主,用于状态确认 |
| bActiveICCLevel | 0x03 | Active 状态电流档位 | 0~15,越大性能越高 |
| bOutOfOrderDataEn | 0x04 | 乱序数据传输使能 | 按需开启 |
| bBackgroundOpStatus | 0x05 | 后台操作状态 | 用于判断是否需让行 |
| bPurgeStatus | 0x06 | Purge 操作状态 | 轮询判断完成 |
| bMaxDataInSize | 0x0A | 读方向单次 UPIU 负载 | 单位 512 B |
| bMaxDataOutSize | 0x0B | 写方向单次 UPIU 负载 | 单位 512 B |
| bRefClkFreq | 0x0D | 参考时钟频率 | 与硬件设计一致 |
| bDeviceLifeTimeEstA/B/C | 见手册 | 寿命估计(Device Health) | 见 §12 |
注:上表 IDN 为常见档位典型值,UFS 4.0 新增字段较多,实现前请以器件手册核对。
4.5 写入准则与生效时机
- 先读后写:修改前先读回当前值,避免覆盖其他位。
- 写后回读:写入后立即 Query 读一次,确认生效。
- 判 Response:Query Response 非成功时,不得认为配置已生效。
- 注意时机:LU 容量、写保护类配置通常要求 LU 无在途 IO,甚至要求下电复位。
- 不可逆操作二次确认:永久写保护、Purge、FFU 等不可逆操作,必须在上层增加显式确认与日志。
- 并发保护:Query 通道在同一时刻应串行化,避免多线程同时下发 Query 造成竞态。
4.6 常见陷阱
| 陷阱 | 表现 | 规避 |
|---|---|---|
| 未等 fDeviceInit 完成就下发 IO | 命令返回错误或行为异常 | 轮询 Flag 至清除,设超时上限 |
| 把 Descriptor 当普通内存改写 | 只读字段写失败、配置无效 | 区分可写性,只改允许字段 |
| 写 Flag 用错 Function | 本想置位却做了翻转 | 明确使用 SET / CLEAR,不用 TOGGLE |
| 忽略 Query Response | 配置静默失败,问题延后爆发 | 统一封装:非成功即报错 |
| 多线程并发 Query | 偶发配置错乱 | Query 通道加互斥锁 |
| 按 eMMC 经验找 EXT_CSD | 概念错位、配置无处下手 | 改用三类对象 + Query 通道 |
后续章节请下载「芯参谋」查看
……(篇幅原因, 还有20章· 详见芯参谋→方案设计)
当前分享仅开放前5章正文。详细资料请在芯参谋客户端中打开完整文档。
打开路径:🔧解决方案&应用市场分析 -> 原理方案设计 -> UFS_软件设计规范
📥 下载芯参谋客户端