USB协议栈分层:物理层、设备层、配置层、接口层、端点层

USB枚举过程并非由单一模块完成,而是由协议栈中不同层级分工协作、逐层推进的结果。理解各层在枚举中的职责,是移植适配设备描述符与地址分配逻辑的前提。USB协议栈从底向上分为五层:物理层、设备层、配置层、接口层、端点层。每一层对应一组特定的描述符与状态机,在枚举中承担不同的角色。

核心观点:枚举的本质是主机通过控制传输,逐层向设备请求描述符,设备协议栈各层依次响应,最终构建出完整的设备拓扑与功能视图。

2.1 五层协议栈总览

下表总结了各层在枚举中的核心职责、关键描述符以及典型交互阶段:

协议层 枚举职责 关键描述符 交互阶段
物理层 检测设备连接、复位、建立信号通路 — 连接检测、总线复位
设备层 分配默认地址、获取设备基本属性 设备描述符 地址分配前/后
配置层 选择配置、获取整体功耗与接口数量 配置描述符 获取配置描述符
接口层 声明功能接口、关联端点集合 接口描述符 获取配置描述符集
端点层 定义数据传输通道属性 端点描述符 获取配置描述符集
移植提示:在移植USB协议栈时,物理层通常由MCU硬件IP核处理,软件栈从设备层开始介入。设备层地址分配逻辑是移植中最容易出错的环节。

2.2 物理层:连接检测与总线复位

物理层位于协议栈最底层,负责处理USB总线的电气特性与信号时序。在枚举启动前,物理层完成以下关键动作:

  • 设备连接检测:主机通过检测D+或D-线上的上拉电阻(全速/高速上拉D+,低速上拉D-)判断设备插入。
  • 总线复位:主机将D+和D-同时拉低至少10ms,设备检测到复位信号后,将地址重置为默认地址0,并准备接收第一个控制传输。
  • 速度协商:对于高速设备,在复位期间会进行chirp握手,确定最终工作速度。

物理层不涉及描述符解析,但它是枚举能够启动的物理前提。移植时需关注MCU的USB PHY配置、时钟稳定时间以及复位中断处理。

物理层枚举启动流程 设备插入检测 主机发起总线复位 速度协商完成 设备地址重置为0,端点0(控制端点)就绪 等待主机发送第一个令牌包(SETUP)

2.3 设备层:地址分配与设备描述符

设备层是枚举中软件栈最先介入的层级。主机通过默认地址0与设备通信,完成以下两个关键步骤:

  1. 获取设备描述符:主机发送请求 GET_DESCRIPTOR(DEVICE),设备返回18字节的设备描述符,包含USB规范版本、设备类、子类、协议、最大包长度(bMaxPacketSize0)、厂商ID(idVendor)、产品ID(idProduct)等信息。
  2. 分配唯一地址:主机发送 SET_ADDRESS 请求,设备收到后必须在状态阶段完成后切换到新地址。此后所有通信使用新地址。
移植陷阱:许多移植失败案例源于设备层地址切换时序错误。设备必须在状态阶段完成后才能启用新地址,部分MCU硬件需要软件显式设置地址寄存器,否则后续控制传输将无响应。

设备描述符中 bMaxPacketSize0 字段直接影响后续控制传输的包长,移植时需确保该值与硬件端点FIFO大小匹配。常见值为8、16、32、64字节。

设备层枚举交互序列 主机(地址0) 设备(地址0) GET_DESCRIPTOR(DEVICE) SET_ADDRESS(addr=7) 设备切换到新地址 7,后续通信使用地址 7

2.4 配置层:选择配置与功耗声明

地址分配完成后,主机进入配置层交互。配置层描述符定义了设备的整体功耗需求以及包含的接口数量。主机通过 GET_DESCRIPTOR(CONFIGURATION) 获取配置描述符,其结构如下:

字段 偏移 大小 说明
bLength 0 1 描述符长度(9字节)
bDescriptorType 1 1 配置描述符类型(0x02)
wTotalLength 2 2 配置描述符集总长度(含接口、端点)
bNumInterfaces 4 1 该配置支持的接口数量
bConfigurationValue 5 1 用于 SET_CONFIGURATION 的索引值
bMaxPower 8 1 最大功耗(单位2mA)

主机在获取完整配置描述符集后,发送 SET_CONFIGURATION 请求激活该配置。设备层收到后,必须使能所有属于该配置的端点。

移植要点:配置描述符中的 wTotalLength 必须精确计算,包含所有接口描述符、端点描述符以及可能的类特定描述符。长度错误会导致主机解析失败。

2.5 接口层:功能声明与端点分组

接口层位于配置层之下,每个配置可以包含多个接口。接口描述符将端点组织成逻辑功能单元,例如一个音频设备可能包含一个音频控制接口和一个音频流接口。

接口描述符关键字段:

  • bInterfaceNumber:接口编号,从0开始递增。
  • bAlternateSetting:备用设置,用于切换接口的带宽或格式。
  • bNumEndpoints:该接口使用的端点数量(不包括端点0)。
  • bInterfaceClass/SubClass/Protocol:定义接口的功能类型,如HID、Mass Storage、CDC等。

在枚举过程中,主机通过接口描述符识别设备功能,并加载对应的驱动程序。移植时需确保接口描述符中的类代码与主机驱动匹配。

接口层:端点分组与功能声明 配置描述符(bNumInterfaces=2) 接口0:HID键盘 端点1 IN (中断) | 端点1 OUT (中断) 接口1:HID鼠标 端点2 IN (中断)

2.6 端点层:传输通道属性定义

端点层是协议栈最底层的数据传输单元。端点描述符定义了每个端点的传输类型、方向、最大包长和轮询间隔。主机根据端点描述符配置主机控制器,建立数据传输通道。

端点描述符关键字段:

字段 说明 典型值
bEndpointAddress 端点号+方向(bit7=1 IN, 0 OUT) 0x81(端点1 IN)
bmAttributes 传输类型:0=控制, 1=等时, 2=批量, 3=中断 0x02(批量)
wMaxPacketSize 最大包长(等时模式含附加位) 64(全速批量)
bInterval 轮询间隔(单位:帧/微帧) 10(中断端点)
移植陷阱:端点描述符中的 wMaxPacketSize 必须与MCU硬件端点的FIFO深度匹配。例如,全速批量端点最大包长只能为8、16、32、64字节,高速批量端点可达512字节。设置错误会导致数据溢出或传输失败。

2.7 各层协作:枚举完整流程

将五层职责串联起来,USB枚举的完整流程如下:

  1. 物理层:设备插入 → 主机检测到上拉电阻 → 发起总线复位。
  2. 设备层:主机通过地址0获取设备描述符 → 分配唯一地址。
  3. 设备层→配置层:主机使用新地址获取配置描述符(含总长度)。
  4. 配置层→接口层→端点层:主机获取完整配置描述符集(含接口描述符和端点描述符)。
  5. 配置层:主机发送 SET_CONFIGURATION 激活配置,设备使能所有端点。
五层协作枚举完整流程 物理层 设备层 配置层 接口层 端点层 连接检测 → 总线复位 → 速度协商 获取设备描述符 → SET_ADDRESS → 地址切换 获取配置描述符 → SET_CONFIGURATION 解析接口描述符 → 识别功能类 解析端点描述符 → 配置FIFO/通道
移植总结:USB协议栈各层在枚举中职责清晰、顺序固定。物理层由硬件处理,设备层是软件栈入口,配置层决定设备整体行为,接口层定义功能,端点层提供传输通道。移植适配时,应逐层检查描述符数据结构的对齐方式、字节序以及硬件端点资源的映射关系。