1. USB Gadget框架概述
USB Gadget子系统是Linux内核中用于让嵌入式设备模拟USB外设(如U盘、串口、网卡、音频设备)的核心框架。与USB主机侧(Host)驱动不同,Gadget驱动运行在设备侧(Device),通过UDC(USB Device Controller)硬件与主机通信。理解其架构是后续DMA与中断优化的基础。
核心概念: Linux USB Gadget框架将复杂的USB协议分层抽象,使得开发者只需关注功能逻辑,而无需处理底层硬件寄存器操作。
1.1 子系统架构总览
USB Gadget子系统采用分层设计,从上到下依次为:Gadget功能驱动层、USB功能层(Function)、USB配置层(Configuration)、UDC核心层(UDC Core)以及UDC驱动层。数据流与命令流在各层之间通过标准API传递。
优化切入点: 从架构图可以看出,DMA优化主要作用于UDC驱动层与硬件控制器之间;中断处理优化则贯穿UDC核心层与UDC驱动层,尤其是请求完成回调与端点中断服务例程。
1.2 UDC驱动层详解
UDC驱动层是Gadget框架中最接近硬件的一层,直接操作USB控制器寄存器,负责端点管理、DMA传输、中断处理等底层任务。不同SoC厂商提供不同的UDC驱动实现。
| UDC驱动 | 适用平台 | DMA支持 | 中断模型 | 性能特点 |
|---|---|---|---|---|
| dwc2 | STM32、Allwinner、Rockchip | 内置DMA(可选) | 共享中断 + 端点中断 | 中等吞吐,兼容性好 |
| dwc3 | 高通、TI、Xilinx、Intel | 强制DMA(TRB链) | MSI-X / 共享中断 | 高吞吐,支持SuperSpeed |
| chipidea | NXP i.MX、Freescale | PIO + 可选DMA | 单中断线 | 低延迟,适合实时场景 |
| musb | TI DaVinci、OMAP | DMA引擎分离 | 多中断源 | 灵活但配置复杂 |
| renesas_usb3 | Renesas R-Car | 强制DMA | 专用中断 | 高可靠,汽车级 |
性能陷阱: 某些UDC驱动在PIO模式下(无DMA)处理大数据包时,CPU占用率可达80%以上,且中断延迟会随负载增加而急剧恶化。这是后续章节重点优化的场景。
1.3 Gadget功能驱动层
Gadget功能驱动层实现具体的USB设备功能,如以太网(ECM/RNDIS)、串口(ACM)、大容量存储(MSC)、音频(UAC)等。每个功能驱动通过usb_function结构体注册到UDC核心层。
功能驱动的核心数据结构:
// include/linux/usb/composite.h
struct usb_function {
const char *name;
struct usb_gadget_strings **strings;
struct usb_descriptor_header **fs_descriptors;
struct usb_descriptor_header **hs_descriptors;
struct usb_descriptor_header **ss_descriptors;
int (*bind)(struct usb_configuration *c, struct usb_function *f);
void (*unbind)(struct usb_configuration *c, struct usb_function *f);
int (*set_alt)(struct usb_function *f, unsigned interface, unsigned alt);
int (*get_alt)(struct usb_function *f, unsigned interface);
void (*disable)(struct usb_function *f);
int (*setup)(struct usb_function *f, const struct usb_ctrlrequest *ctrl);
bool (*req_match)(struct usb_function *f, const struct usb_ctrlrequest *ctrl,
bool config0);
void (*suspend)(struct usb_function *f);
void (*resume)(struct usb_function *f);
/* 端点与请求管理 */
struct usb_ep *eps[USB_FUNCTION_MAX_EPS];
struct list_head requests;
};
关键回调:
setup() 处理控制传输(Setup包),set_alt() 激活特定接口的备选设置,disable() 停用功能。这些回调的执行效率直接影响USB枚举速度和功能切换性能。
1.4 USB协议栈交互流程
一次完整的USB数据传输在Gadget框架中经历以下步骤:
- 请求分配: 功能驱动调用
usb_ep_alloc_request()分配struct usb_request。 - 缓冲区准备: 填充数据缓冲区,设置
buf、length、complete回调。 - 请求提交: 调用
usb_ep_queue()将请求提交到UDC核心层。 - UDC核心调度: UDC核心层将请求加入端点队列,调用UDC驱动的
queue()方法。 - 硬件传输: UDC驱动配置DMA或PIO,启动USB事务。
- 传输完成中断: 硬件触发中断,UDC驱动在ISR中处理完成事件。
- 请求完成回调: UDC核心层调用
usb_request.complete(),通知功能驱动。 - 请求回收: 功能驱动处理数据后,调用
usb_ep_free_request()释放请求。
1.5 关键数据结构关系
理解Gadget框架中的核心数据结构及其关系,是进行性能优化的前提。下表总结了各层之间的数据传递纽带:
| 数据结构 | 所属层 | 作用 | 与DMA/中断的关系 |
|---|---|---|---|
struct usb_gadget |
UDC核心层 | 代表一个USB设备控制器实例 | 包含DMA掩码、中断号 |
struct usb_ep |
UDC核心层 | 表示一个USB端点 | 端点类型决定DMA通道选择 |
struct usb_request |
UDC核心层 | 描述一次数据传输请求 | 包含DMA缓冲区地址、完成回调 |
struct usb_function |
功能驱动层 | 描述一个USB功能 | 管理端点与请求的生命周期 |
struct usb_configuration |
配置层 | 描述一个USB配置 | 决定功能组合与带宽分配 |
性能优化视角:
struct usb_request 中的 sg(Scatter-Gather列表)和 num_sgs 字段是DMA批量传输优化的关键。当功能驱动支持SG时,UDC驱动可以一次DMA操作传输多个不连续缓冲区,大幅减少中断次数。
1.6 本章小结
USB Gadget框架通过五层架构实现了从硬件到功能的完整抽象:
- UDC驱动层 直接操作硬件,是DMA和中断优化的主战场。
- UDC核心层 提供统一的端点管理和请求调度接口。
- 配置层 负责功能组合与复合设备绑定。
- 功能层 实现具体的USB设备逻辑。
- 功能驱动层 是开发者最常接触的编程接口。