USB协议核心知识
一、USB协议架构
1.1 协议分层
USB协议采用分层架构设计,从下至上分为物理层、链路层、协议层、应用层,各层独立封装,降低开发复杂度。
1.1.1 物理层
定义USB接口的硬件特性,包括引脚定义、电压等级、传输速率等。
- USB 2.0:支持低速(1.5Mbps)、全速(12Mbps)、高速(480Mbps)
- USB 3.x:新增超高速(5Gbps)、超高速+(10Gbps)模式,引脚数量与信号定义更复杂
1.1.2 链路层
负责数据的编码/解码、差错检测与纠正、数据包的收发控制。
- 采用差分信号传输
- 通过NRZI编码方式提升抗干扰能力
- 支持CRC校验确保数据完整性
1.1.3 协议层
定义USB的核心通信协议,包括设备枚举、端点配置、数据传输类型、控制命令等,是开发调试的核心关注层。
核心作用:
- 将应用层的功能需求转化为可在总线上传输的标准化数据包
- 解析总线上接收的数据包并向上层反馈
- 作为物理层/链路层与应用层的桥梁
- 直接决定设备与主机的通信兼容性和稳定性
1.1.4 应用层
针对不同USB设备类(如HID、CDC、存储类等)定义的专用协议规范,决定设备的具体功能实现。
1.2 协议层核心定义
协议层的核心是围绕"数据包交互"构建的规则体系。
1.2.1 数据包结构
所有USB通信均以数据包为单位,协议层定义了统一的基础字段格式,同时针对不同类型数据包扩展专属字段。
USB数据包基础结构(通用框架)
| 字段 | 长度 | 取值范围/固定值 | 核心功能 |
|---|---|---|---|
| 同步字段(SYNC) | 8位(1字节) | 固定值:0x80 | 时钟同步,数据包起始标识 |
| 包标识符(PID) | 8位(1字节) | 类型码4位+校验码4位 | 包类型标识 |
| 地址字段(ADDR) | 7位 | 0~127 | 设备寻址 |
| 端点字段(ENDP) | 4位 | 0~15 | 端点寻址 |
| 数据字段(DATA) | 可变 | 上限:64/1024字节 | 承载业务数据 |
| 校验字段(CRC) | 5位/16位 | - | 数据完整性校验 |
| 结束字段(EOP) | 3位 | 2低+1高 | 包结束标识 |
说明:
- 地址字段(ADDR)与端点字段(ENDP)仅存在于令牌包中,DATA包、握手包无这两个字段
- 数据字段(DATA)仅存在于SETUP令牌包和DATA包中,其他类型包无此字段
- 校验字段(CRC)的类型与长度随包类型变化
1.2.2 各字段详细定义
1.2.2.1 同步字段(SYNC)
- 长度:8位(1字节)
- 固定值:0x80(二进制10000000)
- 功能:
- 同步主机与设备的时钟频率
- 确保双方对后续数据的采样时序一致
- SYNC字段是数据包的起始标识
- 设备检测到该字段后开始准备接收后续数据
1.2.2.2 包标识符(PID)
- 长度:8位
- 结构:“4位类型码 + 4位校验码”
- 校验码:为类型码的反码(用于校验PID传输正确性)
根据PID值,数据包分为三大类:
| 数据包类型 | 常见PID值(十六进制) | 类型码(二进制) | 核心功能 |
|---|---|---|---|
| 令牌包(Token) | IN(69)、OUT(E1)、SETUP(2D)、SOF(A5) | 对应类型编码 | 发起传输请求,指定方向、地址、端点 |
| 数据包(Data) | DATA0(C3)、DATA1(4B)、DATA2(87)、MDATA(0F) | 对应类型编码 | 承载实际业务数据,支持交替重传机制 |
| 握手包(Handshake) | ACK(D2)、NAK(5A)、STALL(1E)、NYET(96) | 对应类型编码 | 反馈传输结果,无数据字段 |
注:
- SOF仅适用于USB 2.0低速/全速模式
- NYET为高速模式专属
各类型详细说明:
令牌包(Token Packet):
- 用于发起一次传输请求
- 告知设备传输方向、地址及端点
- 常见PID:
- IN(0x69):主机从设备读取数据
- OUT(0xE1):主机向设备写入数据
- SETUP(0x2D):主机向设备发送控制命令
- SOF(0xA5):帧起始标记,仅USB 2.0低速/全速模式,用于同步帧周期
数据包(Data Packet):
- 用于承载实际数据
- 仅在令牌包发起后传输
- 无令牌包前置时设备会忽略DATA包
- 常见PID:
- DATA0(0xC3)
- DATA1(0x4B)
- DATA2(0x87):高速模式
- MDATA(0x0F):高速模式
- 用于支持批量传输和等时传输的数据包交替机制(解决数据重传时的歧义)
握手包(Handshake Packet):
- 用于反馈传输结果
- 无数据字段
- 仅作为响应包存在,不能主动发起
- 常见PID:
- ACK(0xD2):确认数据接收成功
- NAK(0x5A):设备忙无法接收/发送数据,主机需重试
- STALL(0x1E):设备功能异常或不支持该请求,需主机查询状态
- NYET(0x96):高速模式专属,告知主机无需重试
1.2.2.3 地址字段(ADDR)
- 长度:7位
- 取值范围:0~127
- 功能:标识总线上的USB设备
特性:
- 地址0为默认地址,仅用于设备枚举阶段(复位后设备默认使用地址0)
- 枚举完成后主机为设备分配唯一的非0地址
- 地址字段仅存在于令牌包中
- DATA包和握手包无此字段(依赖前置令牌包的地址信息定位设备)
1.2.2.4 端点字段(ENDP)
- 长度:4位
- 取值范围:0~15
- 功能:标识设备上的具体端点
特性:
- 端点0为控制端点,所有设备必带,用于枚举和控制命令交互
- 其他端点为功能端点,需通过描述符定义属性
- ENDP字段与ADDR字段组合,实现"设备-端点"的精准寻址
- 仅存在于令牌包中
1.2.2.5 数据字段(DATA)
- 长度:可变
- 限制:需符合对应端点的最大数据包大小限制
- 适用范围:仅存在于DATA包和SETUP令牌包中
不同类型的数据字段:
SETUP包数据字段:
- 固定为8字节
- 结构如下:
| 字段 | 长度 | 字节序 | 说明 |
|---|---|---|---|
| 请求类型 | 1字节 | - | 请求方向、类型、接收方 |
| 请求码 | 1字节 | - | 具体的命令代码 |
| 值 | 2字节 | Little-Endian | 命令参数 |
| 索引 | 2字节 | Little-Endian | 索引/偏移量 |
| 长度 | 2字节 | Little-Endian | 数据长度 |
DATA包数据字段:
- 承载实际业务数据(如描述符内容、传感器数据、文件数据等)
- 高速模式下最大长度为1024字节
- 全速/低速模式下最大为64字节
1.2.2.6 校验字段(CRC)
分为CRC5和CRC16两种,根据数据包类型选择:
| 适用数据包类型 | 校验长度 | 校验覆盖范围 | 核心作用 |
|---|---|---|---|
| 令牌包(IN/OUT/SETUP) | 5位 | ADDR字段+ENDP字段 | 校验寻址信息正确性 |
| DATA包 | 16位 | 整个数据字段 | 校验业务数据完整性 |
特性:
- CRC校验由发送方计算生成,接收方验证
- 若校验失败则丢弃数据包,触发重传(等时传输除外)
1.2.2.7 结束字段(EOP)
- 长度:2位低电平+1位高电平
- 功能:标识数据包结束
特性:
- 设备检测到EOP后停止数据接收,完成一次数据包处理
- EOP字段由硬件自动生成,无需固件/驱动干预
- 传输过程中EOP信号异常会导致数据包丢失
1.2.3 数据包交互逻辑
USB总线交互以"令牌包-数据包-握手包"的三段式流程为核心(部分传输类型简化),遵循"主机主导、设备响应"的原则。
1.2.3.1 基础交互规则
1. 交互发起
- 所有交互由主机发起
- 主机通过发送令牌包(IN/OUT/SETUP)指定传输方向、目标设备及端点
- 开启一次传输周期
- 设备通过持续监测总线,解析SYNC和PID字段
- 当检测到匹配自身地址和端点的令牌包时,开始响应
- 否则忽略该令牌包及后续数据包
2. 数据传输
根据令牌包类型执行对应数据传输:
| 令牌包类型 | 传输流程 | 数据流向 |
|---|---|---|
| SETUP | 主机发送8字节DATA包 → 设备接收 → 设备返回握手包 | 主机→设备 |
| OUT | 主机发送DATA包 → 设备接收校验CRC16 → 设备返回ACK | 主机→设备 |
| IN | 设备发送DATA包 → 主机接收校验 → 主机返回ACK | 设备→主机 |
特性:
- SETUP令牌包后,主机立即发送8字节DATA包(控制命令参数)
- 设备接收SETUP数据后无需返回DATA包,直接反馈握手包
- OUT传输校验成功后返回ACK,失败则不返回握手包(主机超时后重试)
- IN传输主机校验成功后返回ACK,失败则不返回(设备超时后重试)
3. 握手反馈
握手包是传输结果的唯一反馈,主机根据设备返回的握手包调整后续操作:
| 握手包类型 | 含义 | 主机后续操作 |
|---|---|---|
| ACK | 确认数据接收成功 | 结束本次传输,进入下一次传输周期 |
| NAK | 设备忙无法接收/发送数据 | 等待预设时间后重新发送令牌包,重试次数由固件/驱动配置 |
| STALL | 设备功能异常或不支持该请求 | 停止传输,发起"获取设备状态"命令,排查异常原因 |
| 无握手包 | 超时 | 判定为超时,触发重传或报错 |
4. 帧同步(低速/全速模式)
- 主机每1ms发送一次SOF令牌包(PID=0xA5)
- SOF包包含帧编号(11位)
- 用于同步设备的中断传输周期和等时传输带宽分配
- 设备根据SOF包的帧编号调整自身数据发送时序
- 确保实时性传输的稳定性
- 高速模式下无SOF包,通过总线时钟同步时序
5. 异常处理
传输过程中若出现以下问题,接收方会丢弃数据包,不返回握手包:
- CRC校验失败
- EOP信号异常
- 数据长度超限
主机检测到超时(默认超时时间为10ms~50ms)后:
- 会重新发起令牌包重试
- 重试次数达到阈值后判定传输失败
- 向上层返回错误信息
等时传输因无重传机制,校验失败则直接丢弃数据,优先保证传输速率。
1.2.4 不同传输类型的数据包交互差异
1.2.4.1 控制传输
采用"SETUP阶段 + DATA阶段 + Status阶段"三段式交互:
| 阶段 | 交互内容 | 说明 |
|---|---|---|
| SETUP阶段 | SETUP令牌包 + 8字节DATA包 + ACK握手包 | 发送控制命令 |
| DATA阶段 | IN/OUT令牌包 + DATA包 + ACK握手包(可选) | 传输数据,无数据时跳过 |
| Status阶段 | 反向握手(设备向主机发送状态数据) | 确认配置完成 |
特性:
- 全程依赖端点0
- 优先级最高,可抢占其他传输类型的总线资源
1.2.4.2 中断传输
- 主机按预设周期(通过端点描述符配置,1ms~255ms)发送IN令牌包
- 设备响应DATA包,主机返回ACK
- 若设备无数据则返回NAK,主机下周期重试
- 无STALL反馈(中断设备异常时直接停止响应)
- 适用于小量实时数据传输
1.2.4.3 批量传输
- 主机在总线空闲时发送IN/OUT令牌包
- 设备响应DATA包,主机返回ACK
- 若设备忙则返回NAK,主机等待总线空闲后重试
- 支持DATA0/DATA1交替机制,解决重传歧义
- 无固定传输周期,优先保证数据完整性
- 适用于大量非实时数据传输
1.2.4.4 等时传输
- 主机按固定周期发送IN/OUT令牌包
- 设备响应DATA包,无握手包反馈(不校验CRC,不重传)
- 占用固定总线带宽,传输速率稳定
- 适用于音视频等实时性要求极高的场景
- 允许少量数据丢失
1.2.5 设备地址与端点管理
地址管理:
- 协议层规定主机为每个接入设备分配唯一的7位地址(0~127)
- 默认地址0用于枚举阶段
- 枚举完成后使用分配的唯一地址通信
端点管理:
- 每个设备支持最多16个端点(0~15)
- 端点0固定为控制端点,用于枚举和控制命令交互
- 其他端点需通过描述符定义传输类型、方向、数据包大小等属性
- 协议层负责端点的寻址和数据路由
1.2.6 控制命令集
协议层定义了标准化的控制命令,主机通过这些命令完成设备枚举、配置、状态查询等操作:
| 核心命令 | 功能说明 |
|---|---|
| 获取描述符(Get Descriptor) | 读取设备描述符信息 |
| 设置地址(Set Address) | 为设备分配USB地址 |
| 设置配置(Set Configuration) | 选择设备配置 |
| 获取状态(Get Status) | 查询设备状态 |
- 命令通过SETUP令牌包发起
- 配合数据和握手包完成交互
1.2.7 传输时序规则
协议层明确了不同传输类型的时序逻辑:
| 传输类型 | 时序规则 | 目的 |
|---|---|---|
| 控制传输 | 三阶段(Setup、Data、Status)时序 | 确保配置的完整性 |
| 中断传输 | 主机查询周期 | 满足实时性要求 |
| 批量传输 | 总线空闲抢占机制 | 保证数据完整性 |
| 等时传输 | 固定带宽分配规则 | 确保传输速率稳定 |
这些规则确保多种传输类型在同一总线上有序共存,避免冲突。
1.3 协议层实现要点
协议层的实现需依托硬件(USB控制器)和固件/驱动的协同。
1.3.1 USB控制器驱动适配
固件侧:
- 配置USB控制器的寄存器
- 使能对应的传输模式、端点属性、数据包大小
- 绑定端点中断服务函数(ISR)
主机侧驱动:
- 识别USB控制器类型
- 对接协议层的数据包收发接口
- 实现地址分配、命令下发等逻辑
1.3.2 数据包收发与解析
固件侧:
- 通过USB控制器的FIFO缓冲区接收和发送数据包
- 在中断服务函数中解析PID,区分令牌包、数据包和握手包
- 根据命令类型执行对应操作
- 示例:接收SETUP命令后读取描述符并返回
主机侧:
- 通过控制器接口发起令牌包
- 等待设备返回数据包或握手包
- 处理重传、STALL等异常情况
1.3.3 枚举流程的协议适配
固件侧:
- 需严格按照协议层定义的枚举时序
- 在不同阶段响应主机的命令
- 示例:
- 复位后准备好设备描述符
- 地址分配后切换至新地址响应配置描述符请求
主机侧:
- 需遵循枚举步骤,逐步获取描述符并完成配置
- 处理枚举过程中的超时、描述符错误等异常
1.3.4 异常处理机制
协议层需实现标准化的异常处理:
| 设备侧响应 | 含义 | 主机侧处理 |
|---|---|---|
| NAK | 设备忙 | 需重试 |
| STALL | 功能异常 | 需查询设备状态 |
同时需处理总线复位、设备断开等突发情况,确保通信链路的稳定性。
1.4 典型例子:HID设备枚举的协议层交互过程
以常见的USB键盘(HID类设备)为例,说明协议层在枚举过程中的具体交互实现。
1.4.1 复位阶段
- 主机检测到键盘接入后
- 通过D+引脚发送复位信号(低电平保持10ms以上)
- 协议层触发设备侧USB控制器复位
- 设备恢复默认状态
- 地址设为0
- 仅端点0使能
- 等待主机命令
1.4.2 获取设备描述符
主机发送:
- SETUP令牌包(PID=SETUP,ADDR=0,ENDP=0)
- 携带"获取设备描述符"命令
- 请求类型=0x80
- 请求码=0x06
- 值=0x0000
- 索引=0x0000
- 长度=0x0012
设备响应:
- 设备侧端点0中断触发
- 解析SETUP数据包
- 从固件缓冲区读取18字节设备描述符
- 通过DATA1数据包返回
- 包含VID=0x0483
- PID=0x5750
- 设备类=0x00(接口类定义)等信息
主机确认:
- 主机接收后返回ACK握手包
- 确认数据接收成功
1.4.3 分配地址
主机发送:
- SETUP令牌包
- 携带"设置地址"命令
- 请求类型=0x00
- 请求码=0x05
- 值=0x0001
- 索引=0x0000
- 长度=0x0000
设备响应:
- 设备解析命令后
- 将USB控制器的地址寄存器设为1
- 返回ACK握手包
后续通信:
- 后续主机与设备的通信均使用地址1
1.4.4 获取配置描述符
主机发送:
- SETUP令牌包
- 携带"获取配置描述符"命令
- 请求类型=0x80
- 请求码=0x06
- 值=0x0200
- 索引=0x0000
- 长度=0x0029
设备返回:
- 配置描述符(9字节)
- 含供电方式、最大电流、接口数量=1
- 接口描述符(9字节)
- 含接口类=0x03(HID类)
- 端点数量=1
- HID类描述符(16字节)
- 含HID版本、报告描述符长度
- 端点描述符(7字节)
- 含端点1、中断输入
- 最大数据包大小=8
- 查询周期=10ms
主机确认:
- 主机接收后返回ACK
- 确认描述符获取完成
1.4.5 设置配置
主机发送:
- SETUP令牌包
- 携带"设置配置"命令
- 请求类型=0x00
- 请求码=0x09
- 值=0x0001
- 索引=0x0000
- 长度=0x0000
设备响应:
- 设备解析命令后
- 启用接口1和端点1
- 配置中断传输参数
- 返回ACK握手包
- 完成枚举进入工作状态
1.4.6 总结
上述过程中,协议层全程主导交互逻辑:
- 主机侧协议层按枚举时序下发标准化命令
- 设备侧协议层解析命令并返回合规数据
- 双方通过PID识别数据包类型
- 通过握手包确认交互状态
- 严格遵循地址分配、描述符交互、配置启用的协议规则
- 最终实现设备与主机的通信建立
若协议层实现存在偏差(如描述符长度错误、地址切换延迟),会导致枚举失败,设备无法被主机识别。
1.5 设备枚举流程
USB设备接入主机后,需完成枚举流程才能建立正常通信,枚举是开发调试中易出问题的环节。
1.5.1 枚举核心步骤
| 步骤 | 操作 | 说明 |
|---|---|---|
| 1. 设备上电 | USB设备接入主机后,主机通过VBUS引脚为设备供电(标准USB端口提供5V/500mA,USB 3.x可提供更多功率) | |
| 2. 主机检测 | 主机通过D+、D-引脚的电平变化检测到新设备接入(低速/全速设备拉低D-,高速设备先拉低D-,协商后切换至高速模式) | |
| 3. 复位设备 | 主机向设备发送复位信号,设备进入默认状态,使用默认端点0(控制端点)进行通信 | |
| 4. 读取设备描述符 | 主机通过端点0读取设备的设备描述符,获取VID、PID、设备类等基础信息 | |
| 5. 分配地址 | 主机为设备分配唯一的USB地址,设备后续使用该地址进行通信 | |
| 6. 读取配置描述符 | 主机读取设备的配置描述符、接口描述符、端点描述符,了解设备的配置选项、接口数量及端点属性(传输类型、数据包大小等) | |
| 7. 设置配置 | 主机根据设备描述符信息,选择合适的配置并发送设置命令,设备进入配置状态,完成枚举 |
二、USB传输类型
USB协议定义了四种传输类型,适用于不同的应用场景,开发时需根据需求选择对应的传输类型及端点配置。
2.1 传输类型对比
| 传输类型 | 核心特性 | 数据包大小 | 典型应用场景 | 优先级 |
|---|---|---|---|---|
| 控制传输(Control) | 枚举、配置修改、命令交互,双向传输 | 端点0 | 设备枚举、控制命令 | 最高 |
| 批量传输(Bulk) | 大量数据传输,对实时性要求低,但要求数据完整性,支持重传 | 高速512字节/USB 3.x 1024字节 | U盘、打印机 | 中等 |
| 中断传输(Interrupt) | 小量数据的实时传输,固定查询周期,支持重传 | 描述符定义 | 键盘、鼠标、传感器 | 中等 |
| 等时传输(Isochronous) | 实时性要求极高的大量数据传输,无重传和CRC校验,允许数据丢失 | 高速1023字节 | 摄像头、音频设备 | 低(等时优先) |
2.2 各传输类型详细说明
2.2.1 控制传输(Control Transfer)
- 用于设备枚举、配置修改、命令交互等核心操作
- 具有最高优先级,支持双向传输
- 依赖端点0实现
- 传输过程分为Setup阶段、Data阶段(可选)、Status阶段
2.2.2 批量传输(Bulk Transfer)
- 适用于大量数据传输
- 对实时性要求低,但要求数据完整性
- 支持CRC校验和重传机制
- 常见于U盘、打印机等设备
- USB 2.0高速模式下批量端点最大数据包大小为512字节
- USB 3.x可提升至1024字节
2.2.3 中断传输(Interrupt Transfer)
- 适用于小量数据的实时传输
- 主机定期查询设备端点获取数据
- 具有固定的查询周期
- 支持重传
- 常见于键盘、鼠标、传感器等HID设备
- 中断端点的最大数据包大小和查询周期需在描述符中定义
2.2.4 等时传输(Isochronous Transfer)
- 适用于实时性要求极高的大量数据传输
- 不支持重传和CRC校验
- 允许数据丢失,优先保证传输速率
- 常见于摄像头、音频设备等
- USB 2.0高速模式下等时端点最大数据包大小为1023字节
三、USB描述符
USB描述符是设备向主机汇报自身属性的核心数据结构,主机通过读取描述符了解设备信息并完成配置。
3.1 常见描述符类型
| 描述符类型 | 长度 | 核心内容 |
|---|---|---|
| 设备描述符(Device Descriptor) | 固定18字节 | VID、PID、设备类、子类、协议、端点0最大数据包大小、配置数量等 |
| 配置描述符(Configuration Descriptor) | 固定9字节 | 配置编号、供电方式(总线供电/自供电)、最大电流、接口数量等 |
| 接口描述符(Interface Descriptor) | 固定9字节 | 接口编号、端点数量、接口类/子类/协议等 |
| 端点描述符(Endpoint Descriptor) | 固定7字节 | 端点地址(方向+编号)、传输类型、同步类型、最大数据包大小、查询周期等 |
| 字符串描述符(String Descriptor) | 不固定 | 设备名称、厂商名称、接口名称等字符串信息,支持多语言 |
3.2 描述符注意事项
- 格式严格:描述符的字段顺序、数据长度、取值范围必须严格遵循USB协议规范
- 参数合理:描述符中的参数(如数据包大小、查询周期)需符合实际硬件能力
- 兼容性:描述符格式错误会导致主机无法识别设备或枚举失败
- 顺序正确:描述符的返回顺序需符合协议要求(如设备描述符→配置描述符→接口描述符→端点描述符)
文档版本: 1.0
最后更新: 2026-01-28