1. USB中断传输概述
USB中断传输(Interrupt Transfer)是USB规范中定义的四种标准传输类型之一,专为需要周期性、低延迟、有限数据量的通信场景设计。在嵌入式Linux驱动开发中,中断端点是实现人机交互设备(HID)、游戏手柄、键盘、鼠标等实时输入设备的核心通信通道。
💡 核心认知: USB中断传输的“中断”并非硬件中断信号,而是指主机必须定期轮询设备以获取数据。这种轮询机制保证了确定性的最大延迟,是实时性优化的基础。
1.1 中断传输的定义与工作原理
USB中断传输是一种轮询驱动的单向或双向数据传输方式。主机控制器(Host Controller)为每个中断端点维护一个轮询间隔(bInterval),在每间隔到达时发起事务(Transaction)。
- 轮询机制: 主机在每帧(Full/Low Speed)或微帧(High Speed)内检查中断端点是否有数据待传。
- 数据方向: 通常为输入(IN)方向(设备→主机),也可支持输出(OUT)方向。
- 事务组成: 每个中断事务包含令牌包(Token)、数据包(Data)、握手包(Handshake)三个阶段。
- 错误重试: 支持硬件级自动重试,直到成功或超时。
📌 关键参数:bInterval
端点描述符中的bInterval字段定义了轮询间隔:
- Full/Low Speed:间隔 = bInterval × 1ms(范围1–255ms)
- High Speed:间隔 = 2^(bInterval-1) × 125μs(范围125μs–4.096ms)
端点描述符中的bInterval字段定义了轮询间隔:
- Full/Low Speed:间隔 = bInterval × 1ms(范围1–255ms)
- High Speed:间隔 = 2^(bInterval-1) × 125μs(范围125μs–4.096ms)
1.2 中断传输的核心特点
| 特性 | 描述 | 对实时性的影响 |
|---|---|---|
| 周期性 | 主机按固定间隔轮询,保证最大延迟上限 | 延迟可预测,适合硬实时场景 |
| 低延迟 | High Speed下最小间隔125μs,延迟极低 | 满足高刷新率输入设备需求 |
| 有限数据量 | 最大包大小受限(FS:64B, HS:1024B) | 适合小数据块,避免总线占用 |
| 错误重试 | 硬件自动重试,保证数据完整性 | 增加确定性延迟,但保证不丢数据 |
| 带宽保证 | USB规范保证中断传输占用不超过90%帧时间 | 避免被批量传输饿死 |
⚠️ 常见误区: 中断传输的“中断”二字容易让人误解为硬件中断驱动。实际上,USB中断传输完全依赖主机主动轮询,设备不能主动发起通信。这与PCIe/MSI等硬件中断有本质区别。
1.3 典型应用场景
1.3.1 HID设备(键盘、鼠标、触摸板)
HID(Human Interface Device)是中断传输最广泛的应用。键盘、鼠标等设备需要实时响应用户操作,数据量小(通常≤8字节),但对延迟敏感。
- 键盘: 每次按键产生8字节报告(按键码+修饰键),轮询间隔通常8ms(125Hz)
- 鼠标: 每次移动产生4-8字节报告(X/Y位移+按键),轮询间隔4ms(250Hz)
- 触摸板: 多点触摸报告可达64字节,轮询间隔2ms(500Hz)
1.3.2 游戏手柄与摇杆
游戏外设对实时性要求极高,尤其是竞技类游戏。现代游戏手柄通常使用中断传输实现高轮询率。
- Xbox/PlayStation手柄: 轮询间隔1ms(1000Hz),报告包含摇杆、扳机、按键状态
- 飞行摇杆: 多轴模拟输入,报告大小16-32字节,轮询间隔2ms
- 方向盘: 力反馈数据通过OUT中断下发,需要双向中断端点
1.3.3 其他实时应用
- 工业传感器: 温度、压力等周期性数据采集,间隔10-100ms
- 医疗设备: 心电监测、血糖仪等低数据率实时传输
- 智能卡读卡器: 卡片插入检测和命令响应
1.4 与批量/同步传输的区别
理解中断传输与其他传输类型的差异,是正确选择端点类型和优化实时性的前提。下表从多个维度进行对比:
| 对比维度 | 中断传输 | 批量传输 | 同步传输 |
|---|---|---|---|
| 传输特性 | 周期性轮询,保证延迟 | 尽力而为,无延迟保证 | 等时传输,固定带宽 |
| 延迟 | 可预测(ms级) | 不可预测(可能被阻塞) | 固定延迟(μs级) |
| 数据完整性 | 硬件重试保证 | 硬件重试保证 | 无重试,可能丢数据 |
| 最大包大小 | FS:64B, HS:1024B | FS:64B, HS:512B | FS:1023B, HS:1024B |
| 带宽占用 | ≤90%帧时间(保证) | 剩余带宽(无保证) | 预留带宽(固定) |
| 典型应用 | HID、游戏手柄、传感器 | U盘、打印机、存储 | 音频、视频、摄像头 |
| 端点数量 | 最多16个IN + 16个OUT | 最多16个IN + 16个OUT | 最多3个IN + 3个OUT |
| 错误处理 | 自动重试(3次) | 自动重试(无限) | 不重试,丢弃错误数据 |
🎯 选型建议:
- 需要保证数据完整性 + 低延迟 → 选择中断传输(HID、手柄)
- 需要高吞吐量 + 数据完整 → 选择批量传输(存储设备)
- 需要固定带宽 + 可容忍丢包 → 选择同步传输(音频流)
- 需要保证数据完整性 + 低延迟 → 选择中断传输(HID、手柄)
- 需要高吞吐量 + 数据完整 → 选择批量传输(存储设备)
- 需要固定带宽 + 可容忍丢包 → 选择同步传输(音频流)
1.5 中断端点在USB描述符中的定义
在Linux内核中,中断端点通过端点描述符(Endpoint Descriptor)定义。以下是典型的端点描述符结构:
/* USB 2.0 规范中的端点描述符结构 */
struct usb_endpoint_descriptor {
__u8 bLength; /* 描述符长度:7字节 */
__u8 bDescriptorType; /* 描述符类型:0x05 */
__u8 bEndpointAddress; /* 端点地址:bit7=方向(0:OUT,1:IN), bit3-0=端点号 */
__u8 bmAttributes; /* 传输类型:0x03=中断传输 */
__le16 wMaxPacketSize; /* 最大包大小(字节) */
__u8 bInterval; /* 轮询间隔(单位见规范) */
} __attribute__ ((packed));
/* 实际设备示例:USB键盘中断端点 */
static struct usb_endpoint_descriptor keyboard_intr_ep = {
.bLength = 7,
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = 0x81, /* IN端点,端点号1 */
.bmAttributes = 0x03, /* 中断传输 */
.wMaxPacketSize = cpu_to_le16(8), /* 每次最多8字节 */
.bInterval = 8, /* 轮询间隔8ms(125Hz) */
};
🔧 驱动开发提示: 在Linux USB驱动中,通过
usb_rcvintpipe(dev, endpoint) 和 usb_sndintpipe(dev, endpoint) 宏构造中断传输的URB管道。轮询间隔由硬件决定,驱动只能读取,不能修改。
1.6 本章小结
- USB中断传输是一种轮询驱动的周期性传输,提供可预测的低延迟。
- 核心参数bInterval决定了轮询频率,直接影响实时性。
- 典型应用包括HID设备、游戏手柄、工业传感器等小数据量实时场景。
- 与批量传输相比,中断传输有延迟保证;与同步传输相比,有数据完整性保证。
- 在Linux驱动中,中断端点通过URB(USB Request Block)进行数据交互,驱动开发者需要理解端点描述符和轮询机制。