3、端点描述符详解:bEndpointAddress、bmAttributes、wMaxPacketSize、bInterval 的配置策略与约束
端点描述符,说白了就是端点的「身份证」。USB 主机靠它来识别这个端点到底是干啥的、怎么传数据、一次传多少、多久传一次。我刚开始调 USB 驱动时,总觉得这玩意儿就是个固定模板,填对了就行。后来踩了几个坑才明白——这几个字段的配置,直接决定了你的批量传输能跑多快、稳不稳。
今天咱们就把这四个关键字段掰开揉碎了讲。我会结合自己项目里遇到的实际问题,告诉你哪些地方容易翻车,怎么配置才靠谱。
3.1 bEndpointAddress:方向与端点号
bEndpointAddress 是一个字节,高 1 位表示方向,低 4 位表示端点号。结构很简单:
| 位 | 含义 | 取值 |
|---|---|---|
| Bit 7 | 方向 | 0 = OUT(主机到设备),1 = IN(设备到主机) |
| Bit 6-4 | 保留 | 必须为 0 |
| Bit 3-0 | 端点号 | 0x00 ~ 0x0F(共 16 个) |
举个例子:0x81 表示端点 1 IN,0x02 表示端点 2 OUT。
这里有个容易忽略的点:同一个端点号可以同时有 IN 和 OUT 两个方向,但它们是两个独立的描述符。USB 规范允许这样做,很多设备也是这么干的。不过我个人建议,如果硬件资源允许,尽量把 IN 和 OUT 分开用不同的端点号,调试时更方便定位问题。
3.2 bmAttributes:传输类型
bmAttributes 决定端点的传输类型。对于批量传输,这个字段必须设为 0x02。但实际项目中,我见过有人不小心配成中断传输(0x03),结果主机枚举时直接报错。
| 值 | 传输类型 | 典型应用 |
|---|---|---|
| 0x00 | 控制传输 | 枚举、标准请求 |
| 0x01 | 等时传输 | 音频、视频流 |
| 0x02 | 批量传输 | 存储、数据采集 |
| 0x03 | 中断传输 | HID、键盘、鼠标 |
嗯,这里要注意:批量传输没有带宽保证,主机总线空闲时才传。所以如果你的应用对实时性要求高,比如音频流,别用批量传输,老老实实选等时或中断。
3.3 wMaxPacketSize:一次能传多少
wMaxPacketSize 是端点单次传输的最大数据包大小。这个值直接影响吞吐量——配小了带宽浪费,配大了硬件可能扛不住。
不同 USB 速度下,批量传输的 wMaxPacketSize 有固定上限:
| USB 速度 | wMaxPacketSize 上限 | 实际常用值 |
|---|---|---|
| 全速 (12 Mbps) | 64 字节 | 64 |
| 高速 (480 Mbps) | 512 字节 | 512 |
| 超高速 (5 Gbps) | 1024 字节 | 1024 |
我见过有人在全速设备上配了 512 字节的 wMaxPacketSize,结果主机枚举时直接返回错误。原因很简单——全速批量传输最大包就是 64 字节,你配大了硬件根本发不出去。
另外,wMaxPacketSize 的低 11 位是包大小,高 5 位用于等时传输的微帧数。批量传输时高 5 位必须为 0。这个细节我见过有人搞错,结果主机解析描述符时直接跳过这个端点。
3.4 bInterval:轮询间隔
bInterval 这个字段,批量传输和中断传输的含义完全不同。很多人一开始搞混,包括我自己。
- 中断传输:bInterval 表示主机轮询端点的间隔,单位是毫秒(全速)或 125µs 的倍数(高速)。
- 批量传输:bInterval 没有实际意义,主机不会按这个间隔去轮询。但规范要求高速批量端点的 bInterval 必须为 0。
说白了,批量传输的 bInterval 就是个「摆设」。但你别乱填——高速设备必须填 0,全速设备可以填 0 或任意值,但主机不会理它。
3.5 配置策略总结
下面这张图是我自己总结的端点描述符配置流程,每次做新项目我都会对照着检查一遍:
3.6 实战配置示例
下面是一个高速批量端点的描述符配置示例,我直接从项目代码里摘出来的:
// 高速批量 IN 端点描述符
0x07, // bLength: 描述符长度
0x05, // bDescriptorType: 端点描述符
0x81, // bEndpointAddress: EP1 IN
0x02, // bmAttributes: 批量传输
0x00, 0x02, // wMaxPacketSize: 512 字节 (0x0200)
0x00, // bInterval: 高速批量必须为 0
// 高速批量 OUT 端点描述符
0x07, // bLength
0x05, // bDescriptorType
0x01, // bEndpointAddress: EP1 OUT
0x02, // bmAttributes: 批量传输
0x00, 0x02, // wMaxPacketSize: 512 字节
0x00 // bInterval: 0
0x00, 0x02。我见过有人写成 0x02, 0x00,结果主机解析成 2 字节,数据根本传不出去。
好了,关于端点描述符的四个关键字段,咱们就聊到这儿。配置时记住一句话:批量传输的 wMaxPacketSize 往大了配,bInterval 往 0 填,bmAttributes 别乱改,bEndpointAddress 注意方向位。按这个思路来,基本不会出大问题。