USB 端点与设备枚举:端点 0、描述符、SETUP 事务与地址分配
更新时间:2026-09-19。前置:理解 valid/ready 与 FIFO。USB 是严格的主机轮询总线——设备从不主动发起,所有传输由主机调度。
本文要回答的问题
- 什么是端点(endpoint),为什么 IN/OUT 是相对主机定义的?
- 四种传输类型各自用于什么场景?
- 设备插上到能用,枚举(enumeration)这一串握手发生了什么?
- 设备控制器里端点缓冲/FIFO 怎么组织,枚举为什么会失败?
一、端点:通信的逻辑终点
每个 USB 设备对外呈现若干端点,端点是「主机一侧软件」与「设备一侧硬件缓冲」之间的逻辑通道。
- 端点 0:每个设备必有,双向,专用于控制传输(枚举/配置),一上电就存在。
- 端点号 1~15:按设备需要实现,每个端点有方向(IN 或 OUT),故最多 15 IN + 15 OUT(加上 EP0)。
- 方向以主机为参照:IN = 设备→主机(设备填数据等主机 IN 令牌来取);OUT = 主机→设备。
四种传输类型:
| 类型 | 特点 | 典型 |
|---|---|---|
| 控制 Control | 有 SETUP/DATA/STATUS 三阶段、保证、用于 EP0 | 枚举、配置 |
| 批量 Bulk | 占用空闲带宽、可靠(CRC+ACK 重传)、无时间保证 | U 盘、打印机 |
| 中断 Interrupt | 主机周期性轮询、有延迟上限、可靠 | HID 键鼠 |
| 同步 Isochronous | 周期性、有带宽保证、不重传 | 摄像头、音频 |
二、枚举全过程(设备侧视角)
bash
1. 插入/上电:设备拉 D+ 或 D-(上拉电阻)报告速度(FS/HS)
2. 主机检测到连接 → 发 USB 复位(SE0 ≥10ms)
3. 复位后设备用默认地址 0、端点0就绪
4. 主机 → EP0: SET_ADDRESS,设备获得唯一地址(1~127)
5. 主机 → 新地址 EP0: GET_DESCRIPTOR(Device)
6. 主机读完整设备/配置/接口/端点描述符,选择配置
7. 主机: SET_CONFIGURATION(configuration value)
8. 设备配置好非0端点,接口可用,加载对应类驱动控制传输(EP0)的三段:
- SETUP 阶段:8 字节标准请求(bmRequestType/bRequest/wValue/wIndex/wLength),如
GET_DESCRIPTOR、SET_ADDRESS。 - DATA 阶段:按方向传描述符或参数(可为 0 长度)。
- STATUS 阶段:零长度包(ZLP)确认。
三、描述符层级
bash
Device Descriptor(VID/PID、设备类、支持的配置数)
└ Configuration Descriptor(bConfigurationValue、功耗、接口数)
└ Interface Descriptor(接口类、备用设置)
└ Endpoint Descriptor(端点号/方向/传输类型/最大包长/轮询间隔)
(可多接口:复合设备,如音频=控制+流接口)设备控制器硬件里通常有:一组端点缓冲(每个 EP 一块 RAM/FIFO,配最大包长)、EP0 的 SETUP 包寄存器、in/out 令牌中断、stall/NAK/NYET 状态位。设备固件要在收到 SETUP 中断后把描述符指针填进 EP0 IN FIFO。
四、常见的坑
- IN/OUT 方向搞反:以为 IN 是「发给设备」,导致固件把数据放错缓冲、NAK 不断。
- 描述符长度/层级错误:wTotalLength 没包含所有接口/端点描述符,主机读到截断就枚举失败。
- SET_ADDRESS 时序错:必须在 STATUS 阶段后才切到新地址响应;太早/太晚都失联。
- GET_DESCRIPTOR 只准备 64/18 字节:主机第一次只要前若干字节探长度,固件要能正确处理短读与再次请求。
- 端点最大包长与描述符不符:EP0 全速必须 8/16/32/64,高速 64;硬件实际 FIFO 与描述符不一致导致溢出。
- 不回 ZLP/不完成 STATUS 阶段:控制传输必须有状态阶段,缺了主机超时报枚举失败(code 43)。
- 高速协商失败仍按全速跑:没有 chirp/K 握手或 PHY 不支持 HS,设备被识别为全速。
- STALL 后未清:协议错误要 STALL EP0 并等下一个 SETUP 自动清,挂着 stall 会一直失败。
- 枚举电流/供电:配置前只能取 ≤100mA,bMaxPower 描述与实际不符可能被端口拒绝。
- VID/PID 为 0/乱填:无合法 VID 虽能部分枚举,但无厂商驱动/被系统标记未知设备。
- 复合设备接口关联 IAD 缺失:多类设备无 IAD,系统只加载第一个类驱动。
相关与延伸
高速串行 PHY 见 混合信号边界常识;缓冲与反压见 Skid Buffer、AXI4-Stream/DMA。
总结
USB 是主机轮询、面向端点的主从总线:每个设备必有双向端点 0 跑控制传输,其余端点按 IN/OUT 和控制/批量/中断/同步四类组织;枚举即「复位→默认地址0→SET_ADDRESS 分配地址→GET_DESCRIPTOR 读取设备/配置/接口/端点描述符树→SET_CONFIGURATION 使能非0端点」;设备固件要正确服务 EP0 的 SETUP/DATA/ZLP 三段——方向定义反、描述符 wTotalLength 截断和 SET_ADDRESS 时序错是枚举失败三大根因。