3. USB协议基础(二):USB传输类型、帧与微帧机制、带宽管理
USB协议定义了四种不同的传输类型,分别对应不同的应用场景:控制传输、批量传输、中断传输和等时传输。理解这四种传输类型的特性、事务格式以及适用场景,是开发USB设备驱动和主机控制器驱动的核心基础。同时,USB的帧/微帧机制和带宽管理策略,决定了主机如何高效、公平地分配总线资源。
3.1 四种USB传输类型详解
USB是一种基于轮询(Polling)的总线协议,所有传输都由主机(Host)发起。设备只能被动响应主机的请求。四种传输类型在可靠性、延迟、数据量等方面各有侧重。
| 传输类型 | 可靠性 | 延迟 | 数据量 | 重试机制 | 典型应用 |
|---|---|---|---|---|---|
| 控制传输 | 最高(保证送达) | 中等 | 小(通常≤64字节) | 硬件重试,错误重传 | 枚举、配置、命令 |
| 批量传输 | 高(CRC校验+重试) | 不确定(尽力而为) | 大(8/16/32/64字节) | 硬件重试,错误重传 | U盘、打印机数据 |
| 中断传输 | 高(CRC校验+重试) | 有界(保证轮询间隔) | 小(≤1024字节) | 硬件重试,错误重传 | 鼠标、键盘、HID |
| 等时传输 | 无(无重试) | 固定(保证带宽) | 大(≤1023字节) | 无重试,允许丢包 | 音频、视频、摄像头 |
3.1.1 控制传输(Control Transfer)
控制传输是USB设备枚举和配置的基础,也是唯一必须实现的传输类型。它采用请求-应答模式,由主机发起一个设置事务(Setup Transaction),然后可选地跟随数据事务(Data Transaction)和状态事务(Status Transaction)。
- 阶段组成:控制传输分为三个阶段:Setup阶段、Data阶段(可选)、Status阶段。
- 端点:默认使用端点0(双向端点)。
- 数据包大小:低速设备为8字节,全速设备为8/16/32/64字节,高速设备为64字节。
- 可靠性:硬件层面保证重试,直到成功或主机放弃。
usb_control_msg() 函数发起。该函数封装了Setup包、数据缓冲区和超时时间。驱动开发者需要熟悉USB标准请求(如GET_DESCRIPTOR、SET_CONFIGURATION)以及类特定请求。
// Linux内核中发起控制传输的典型调用
int ret;
struct usb_device *udev = interface_to_usbdev(intf);
ret = usb_control_msg(udev,
usb_rcvctrlpipe(udev, 0), // 接收方向,端点0
USB_REQ_GET_DESCRIPTOR, // bRequest
USB_DIR_IN, // bmRequestType
(USB_DT_DEVICE << 8), // wValue
0, // wIndex
buf, // 数据缓冲区
sizeof(struct usb_device_descriptor), // wLength
USB_CTRL_GET_TIMEOUT); // 超时时间
if (ret < 0) {
dev_err(&intf->dev, "Failed to get device descriptor: %d\n", ret);
}
3.1.2 批量传输(Bulk Transfer)
批量传输用于传输大量数据,且对实时性要求不高。它利用总线空闲时间进行传输,当总线带宽紧张时,批量传输会被延迟。
- 特点:保证数据完整性(CRC校验+硬件重试),但不保证延迟。
- 数据包大小:全速最大64字节,高速最大512字节,超高速最大1024字节。
- 事务格式:由IN/OUT事务组成,每个事务包含令牌包、数据包和握手包。
- 应用:U盘(BOT协议)、打印机、大容量存储设备。
3.1.3 中断传输(Interrupt Transfer)
中断传输并非硬件中断,而是主机保证在固定的时间间隔内轮询设备,以获取数据。它适用于需要定期查询且数据量较小的场景。
- 轮询间隔:设备在描述符中声明所需的轮询间隔(bInterval)。全速设备间隔为1~255ms,高速设备间隔为1~16(单位125µs微帧)。
- 数据包大小:全速最大64字节,高速最大1024字节。
- 可靠性:与批量传输相同,具有CRC校验和硬件重试。
- 应用:鼠标、键盘、游戏手柄、HID设备。
3.1.4 等时传输(Isochronous Transfer)
等时传输是唯一不保证数据可靠性的传输类型。它牺牲了重试机制,以换取固定的带宽和可预测的延迟。
- 特点:无握手阶段,无重试,允许数据丢失(CRC错误时直接丢弃)。
- 带宽保证:在枚举阶段,主机控制器会为等时端点预留带宽。如果带宽不足,枚举会失败。
- 数据包大小:全速最大1023字节,高速最大1024字节。
- 应用:USB音频设备(扬声器、麦克风)、USB视频设备(摄像头)、实时数据采集。
3.2 帧与微帧机制
USB总线的时间被划分为固定长度的帧(Frame)或微帧(Microframe)。主机控制器(HC)在每个帧/微帧开始时发送SOF(Start of Frame)包,用于同步和计时。
| USB速度 | 帧长度 | 微帧数量 | SOF间隔 |
|---|---|---|---|
| 低速/全速(USB 1.x) | 1 ms | 1 | 1 ms |
| 高速(USB 2.0) | 1 ms | 8 | 125 µs |
| 超高速(USB 3.x) | 125 µs | 1(总线间隔) | 125 µs |
帧/微帧是主机控制器进行带宽分配和调度的基本时间单位。在每个帧/微帧的开始,主机控制器会执行一个调度列表,决定哪些端点可以在这个时间片内进行事务。
3.3 带宽管理
USB主机控制器(如EHCI、xHCI)负责在每个帧/微帧内调度所有端点的事务。带宽管理是确保所有周期性传输(等时和中断)满足其延迟和带宽要求的关键。
3.3.1 带宽分配原则
- 周期性传输优先:在每个微帧开始时,主机控制器首先处理等时传输和中断传输。这些传输具有预留带宽。
- 非周期性传输填充:在完成周期性传输后,剩余的帧时间用于批量传输和控制传输。
- 带宽上限:USB 2.0规定,所有周期性传输(等时+中断)最多占用一个微帧的90%(即112.5 µs)。剩余的10%用于批量传输、控制传输和协议开销(SOF、EOF等)。
- 超高速增强:USB 3.x进一步优化了带宽利用率,支持更大的数据包和更高效的调度。
3.3.2 带宽计算示例
假设一个全速USB音频设备,使用等时传输,每个微帧传输64字节数据。计算其带宽占用:
- 事务时间:全速模式下,传输64字节数据需要约 13 × 64 + 开销 ≈ 832 µs?错误。全速模式下,一个64字节的等时IN事务大约需要 13 + (64 × 8) / 12 ≈ 55 µs(包含协议开销)。
- 带宽占用:55 µs / 1000 µs = 5.5%。
- 多个端点:如果总线上有多个等时端点,总占用不能超过90%。
-ENOSPC)。驱动开发者必须处理这种错误,并考虑降低数据率或使用更小的数据包。
3.3.3 主机控制器调度策略
不同主机控制器(UHCI/OHCI/EHCI/xHCI)的调度实现不同,但核心思想一致:维护一个帧列表(Frame List)或调度树(Schedule Tree)。
3.3.4 带宽管理在驱动开发中的影响
- 端点描述符的bInterval字段:驱动开发者在配置端点时,必须正确设置轮询间隔。对于等时端点,这个值决定了每个微帧/帧传输的数据量,直接影响带宽占用。
- URB(USB Request Block):在Linux内核中,驱动通过提交URB来发起传输。对于等时URB,驱动需要指定每个微帧传输的数据包数量(
number_of_packets)和每个包的大小(iso_frame_desc)。 - 带宽预留失败处理:当主机控制器无法为等时端点预留所需带宽时,
usb_submit_urb()会返回-ENOSPC。驱动应该优雅地处理此错误,例如降低采样率或通知用户。
// Linux内核中等时URB的提交示例
struct urb *urb;
int ret;
urb = usb_alloc_urb(ISO_PACKETS, GFP_KERNEL);
if (!urb)
return -ENOMEM;
urb->dev = udev;
urb->pipe = usb_rcvisocpipe(udev, endpoint->bEndpointAddress);
urb->transfer_buffer = buffer;
urb->transfer_buffer_length = ISO_PACKETS * ISO_PACKET_SIZE;
urb->complete = isoc_complete;
urb->number_of_packets = ISO_PACKETS;
urb->interval = 1; // 每个微帧传输一次
for (i = 0; i < ISO_PACKETS; i++) {
urb->iso_frame_desc[i].offset = i * ISO_PACKET_SIZE;
urb->iso_frame_desc[i].length = ISO_PACKET_SIZE;
}
ret = usb_submit_urb(urb, GFP_KERNEL);
if (ret) {
dev_err(&intf->dev, "Failed to submit isoc URB: %d\n", ret);
usb_free_urb(urb);
return ret;
}
3.4 本章小结
- USB定义了四种传输类型:控制、批量、中断、等时,分别对应不同的可靠性、延迟和带宽需求。
- 帧(1ms)和微帧(125µs)是USB总线的时间基础,主机控制器在每个时间单元内调度事务。
- 带宽管理遵循“周期性传输优先”原则,等时和中断传输预留带宽,批量传输利用空闲时间。
- 驱动开发者必须理解端点描述符中的带宽参数(如wMaxPacketSize、bInterval),并正确处理带宽不足的错误。