1. USB子系统概述:USB主机控制器、USB设备、USB协议栈分层结构
USB(Universal Serial Bus)子系统是Linux内核中最为复杂且成熟的子系统之一。理解其整体架构是进行USB驱动开发的基础。本章将从硬件控制器、设备类型以及软件协议栈三个维度,系统性地剖析USB子系统的核心组成。
1.1 USB系统拓扑结构
USB采用树形拓扑,由USB主机控制器、USB Hub和USB功能设备组成。主机控制器位于根节点,负责管理总线上的所有事务。
核心概念:在USB系统中,所有通信必须由主机发起。设备不能主动向主机发送数据,只能响应主机的请求。这种主从模式简化了设备设计,但增加了主机控制器的复杂度。
1.2 USB主机控制器
USB主机控制器(Host Controller)是USB系统的核心硬件,负责实现USB协议的低层传输。Linux内核支持多种主机控制器规范,每种规范对应不同的硬件接口和软件驱动。
| 规范名称 | 总线类型 | 最大速度 | Linux驱动 | 典型硬件 |
|---|---|---|---|---|
| OHCI (Open HCI) | USB 1.x | 12 Mbps (全速) | ohci-hcd |
早期嵌入式SoC、部分x86南桥 |
| UHCI (Universal HCI) | USB 1.x | 12 Mbps (全速) | uhci-hcd |
Intel/VIA x86主板 |
| EHCI (Enhanced HCI) | USB 2.0 | 480 Mbps (高速) | ehci-hcd |
大多数x86/ARM USB 2.0控制器 |
| xHCI (eXtensible HCI) | USB 3.x | 5/10/20 Gbps (超高速) | xhci-hcd |
现代x86/ARM USB 3.x控制器 |
开发提示:在嵌入式Linux开发中,xHCI已成为主流。xHCI向后兼容USB 2.0/1.1设备,且支持更灵活的端点管理和流式传输。在设备树中,通常通过
compatible = "generic-xhci"或厂商特定的兼容字符串来绑定xHCI驱动。
1.3 USB设备分类
USB设备根据功能分为不同的设备类(Device Class)。每个设备类定义了标准的通信协议和描述符格式,使得同一类设备可以使用通用的驱动程序。
- HID (Human Interface Device):键盘、鼠标、游戏手柄、触摸屏。使用中断传输,低延迟。
- Mass Storage:U盘、移动硬盘、SD卡读卡器。使用批量传输,大数据量。
- CDC (Communication Device Class):以太网适配器、串口转换器(如CP2102、CH340)、Modem。
- Video:摄像头、视频采集卡。使用等时传输,保证带宽。
- Audio:USB声卡、麦克风、扬声器。使用等时传输,实时性要求高。
- Hub:USB扩展器。负责端口管理和电源分配。
1.4 USB协议栈分层结构
Linux USB协议栈采用分层架构,从硬件到用户空间共分为五层。每一层负责不同的抽象级别,层与层之间通过标准接口通信。
- 硬件层:物理USB总线、主机控制器寄存器、DMA引擎。
- 主机控制器驱动层 (HCD):直接操作硬件寄存器,实现OHCI/UHCI/EHCI/xHCI规范。提供统一的
struct hc_driver接口给上层。 - USB核心层 (USB Core):管理设备枚举、地址分配、描述符解析、电源管理、URB(USB Request Block)调度。提供
usb_submit_urb()等核心API。 - 设备驱动层:针对特定设备类或厂商设备实现功能逻辑,如
usbhid、usb-storage、cdc_acm。 - 用户空间层:通过
libusb、/dev/usb/*或sysfs接口与内核交互。
1.5 URB:USB请求块
URB(USB Request Block)是Linux USB协议栈中最核心的数据结构,用于在设备驱动和USB Core之间传递I/O请求。每个URB描述了一次USB传输的所有信息。
struct urb {
struct list_head urb_list; /* 链表节点 */
struct usb_device *dev; /* 目标USB设备 */
unsigned int pipe; /* 管道:端点方向+类型+地址 */
int status; /* 传输状态 */
unsigned int transfer_flags; /* 传输标志 */
void *transfer_buffer; /* 数据缓冲区 */
dma_addr_t transfer_dma; /* DMA地址 */
int transfer_buffer_length; /* 缓冲区长度 */
int actual_length; /* 实际传输长度 */
unsigned char *setup_packet; /* 控制传输设置包 */
int interval; /* 中断/等时传输间隔 */
usb_complete_t complete; /* 完成回调函数 */
void *context; /* 回调上下文 */
};
注意事项:URB的生命周期管理是USB驱动开发中的常见错误点。URB必须使用
usb_alloc_urb()分配,使用usb_submit_urb()提交,在回调函数中检查urb->status判断传输结果。切勿在中断上下文中调用usb_free_urb()。
1.6 设备枚举流程
当USB设备插入时,主机控制器驱动和USB Core协同完成设备枚举。枚举过程是理解USB协议栈工作的关键。
| 步骤 | 动作 | 描述 | 涉及层 |
|---|---|---|---|
| 1 | 检测连接 | Hub检测端口状态变化,报告给主机 | HCD + Hub驱动 |
| 2 | 复位设备 | 主机发送复位信号,设备地址重置为0 | HCD |
| 3 | 分配地址 | 主机分配唯一地址,设备进入Address状态 | USB Core |
| 4 | 读取描述符 | 获取设备描述符、配置描述符、接口描述符、端点描述符 | USB Core |
| 5 | 选择配置 | 主机选择一个配置,设备进入Configured状态 | USB Core |
| 6 | 加载驱动 | USB Core根据usb_device_id匹配并绑定设备驱动 |
USB Core + 设备驱动 |
1.7 设备树中的USB绑定
在嵌入式系统中,USB主机控制器通常通过设备树(Device Tree)描述。设备树节点提供控制器基地址、中断号、PHY引用、时钟等信息。
/* 典型的xHCI控制器设备树节点 */
usb@f0930000 {
compatible = "generic-xhci";
reg = <0x0 0xf0930000 0x0 0x8000>;
interrupts = <0 56 4>;
clocks = <&clock 0x2 0x9>;
clock-names = "core";
phys = <&usb_phy0>;
phy-names = "usb";
status = "okay";
};
关键字段说明:
compatible:驱动匹配字符串,内核通过它找到对应的HCD驱动。reg:控制器寄存器地址范围和大小。interrupts:中断号、触发类型(高电平、上升沿等)。phys/phy-names:引用USB PHY(物理层收发器),用于初始化高速/超高速信号。clocks:控制器工作时钟,通常包括AHB/APB总线时钟和USB参考时钟。
1.8 本章小结
本章从硬件拓扑、主机控制器规范、设备分类、协议栈分层、URB机制、枚举流程到设备树绑定,全面梳理了USB子系统的核心概念。掌握这些基础知识,是后续深入学习USB PHY初始化、设备树定制以及驱动开发实战的前提。