2. DMA基础回顾:DMA工作原理、总线主控模式、UHCI中的DMA角色
在深入UHCI控制器初始化阶段的DMA传输优化之前,必须重新夯实DMA(Direct Memory Access,直接存储器访问)的核心原理。UHCI作为PCI总线上的主控设备,其DMA操作并非传统的“外设→内存”搬运,而是总线主控模式(Bus Mastering)下的自主传输。本节将拆解DMA的底层机制,并明确UHCI在USB传输中的DMA角色定位。
2.1 DMA工作原理:从CPU搬运到总线主控
传统I/O操作中,CPU必须逐字节或逐字地从外设读取数据并写入内存(PIO模式),这会严重占用CPU时间。DMA控制器(DMAC)或具备DMA能力的设备接管了数据总线的控制权,实现内存与外设之间的直接数据传输。
核心要点: DMA传输的本质是总线仲裁——DMA设备向CPU请求总线控制权,CPU在总线周期内释放总线,DMA设备成为总线主控,完成数据传输后释放总线。
下图展示了标准DMA传输的典型流程,包含请求、仲裁、传输和结束四个阶段:
关键区别: 传统DMA需要独立的DMA控制器芯片(如Intel 8237),而UHCI将DMA引擎集成在控制器内部。UHCI通过PCI总线接口直接发起内存读写,不需要CPU或外部DMAC介入地址生成。
2.2 总线主控模式:UHCI的DMA实现基础
UHCI控制器工作在PCI总线主控(Bus Master)模式下。这意味着UHCI可以主动发起PCI总线周期,直接读写系统内存,而无需依赖CPU或南桥中的DMA控制器。这是UHCI实现高效USB传输的基石。
下表对比了三种常见的I/O数据传输模式:
| 特性 | PIO (Programmed I/O) | 传统DMA (Third-party DMA) | 总线主控DMA (Bus Mastering) |
|---|---|---|---|
| 控制方 | CPU | 专用DMAC | 外设/控制器自身 |
| 总线仲裁 | CPU独占 | CPU→DMAC | CPU→外设 |
| 数据传输路径 | 外设→CPU→内存 | 外设↔内存 (DMAC控制) | 外设↔内存 (外设控制) |
| CPU负载 | 高(逐字节搬运) | 低(仅初始化) | 极低(仅提交描述符) |
| UHCI使用情况 | 不使用 | 不使用 | 标准模式 |
UHCI作为总线主控设备,其DMA操作的核心是描述符链表(Descriptor List)。UHCI通过读取内存中的帧列表(Frame List)和传输描述符(TD, Transfer Descriptor),自主决定何时发起DMA传输、传输多少数据、数据去向何处。
常见误解: 很多人认为UHCI的DMA是“USB数据直接进入内存”。实际上,UHCI的DMA传输的是描述符和缓冲区指针,而非USB数据本身。真正的USB数据包(SOF、令牌、数据、握手)由UHCI内部的SIE(串行接口引擎)通过UTMI总线收发,UHCI再通过DMA将数据从FIFO搬运到系统内存。
2.3 UHCI中的DMA角色:从帧列表到传输描述符
在UHCI架构中,DMA承担了三个关键角色:
- 帧列表读取器: 每1ms(1帧),UHCI通过DMA从内存中的帧列表(Frame List)读取当前帧的起始指针,指向一个传输描述符链表。
- 描述符遍历器: UHCI通过DMA依次读取链表中的TD,解析出传输方向(IN/OUT)、数据缓冲区地址、数据长度、PID类型等关键信息。
- 数据搬运工: 对于OUT传输,UHCI通过DMA从系统内存读取数据到内部FIFO;对于IN传输,UHCI通过DMA将FIFO中的数据写入系统内存。
下图展示了UHCI内部DMA引擎与系统内存、USB总线之间的数据流关系:
2.4 UHCI DMA的关键特性与优化切入点
理解UHCI的DMA角色后,可以提炼出以下关键特性,这些特性直接决定了初始化阶段的优化策略:
- 描述符驱动: UHCI不直接执行程序,而是通过遍历内存中的TD链表来驱动传输。链表的组织方式(水平链接 vs 垂直链接)直接影响DMA效率。
- 非连续DMA: UHCI的DMA传输是非连续的——每传输一个TD,UHCI需要重新读取下一个TD的指针,这导致总线利用率不如块设备DMA。
- 帧同步: UHCI的DMA操作以帧(1ms)为周期同步。帧列表的读取发生在每帧开始时的SOF(Start of Frame)时刻。
- 小数据量传输: USB全速(12Mbps)下,每个TD最大传输1024字节。对于控制传输(Setup阶段),数据量通常只有8字节。频繁的小DMA传输是性能瓶颈。
优化启示: 在初始化阶段,我们需要关注:
• 帧列表的对齐与缓存行填充(避免DMA读取跨越缓存行)
• TD链表的预构建与缓存一致性维护(避免DMA读到脏数据)
• 描述符的内存布局(减少DMA读取次数)
• 中断与DMA完成信号的同步(避免忙等)
• 帧列表的对齐与缓存行填充(避免DMA读取跨越缓存行)
• TD链表的预构建与缓存一致性维护(避免DMA读到脏数据)
• 描述符的内存布局(减少DMA读取次数)
• 中断与DMA完成信号的同步(避免忙等)
2.5 小结:UHCI DMA的“三权分立”
UHCI的DMA体系可以概括为“三权分立”的协作模型:
| 角色 | 负责内容 | DMA操作 | 优化关注点 |
|---|---|---|---|
| 帧列表管理器 | 维护1024项的帧列表,每项指向TD链表头 | 每帧开始DMA读取帧列表项 | 帧列表对齐、预取 |
| TD解析器 | 遍历TD链表,解析传输参数 | 顺序DMA读取TD | TD内存布局、链表深度 |
| 数据搬运器 | 在FIFO与系统内存之间搬运USB数据 | DMA读写数据缓冲区 | 缓冲区对齐、Cache策略 |