3. UHCI 主机控制器架构:寄存器组、端口状态机、帧列表与队列头
UHCI(Universal Host Controller Interface)是 Intel 定义的 USB 1.x 全速/低速主机控制器标准。其核心架构围绕四个关键模块构建:主机控制器寄存器组、端口状态机、帧列表(Frame List)与队列头(Queue Head)。理解这些模块的协同机制,是实现嵌入式调试端口与 DMA 传输的基础。
架构要点:UHCI 将大部分调度逻辑交给软件(驱动),硬件只负责解析帧列表、执行队列头中的传输描述符(TD),并通过寄存器暴露状态。这种设计降低了硬件复杂度,但要求软件严格遵循时序。
3.1 主机控制器寄存器组
UHCI 主机控制器通过一组 PCI 配置空间寄存器与 I/O 映射寄存器暴露控制与状态信息。软件通过读写这些寄存器完成初始化、调度启停、中断管理及端口控制。
| 寄存器名称 | 偏移地址 | 宽度 | 功能描述 |
|---|---|---|---|
| USBCMD | 0x00 | 16-bit | 运行/停止(RS)、全局复位(GR)、帧列表大小(FLSIZE)等控制位 |
| USBSTS | 0x02 | 16-bit | 主机控制器错误(HCHalted)、中断挂起(INT)、DMA 错误等状态位 |
| USBINTR | 0x04 | 16-bit | 中断使能:传输完成、短包、错误等中断源屏蔽 |
| FRNUM | 0x06 | 16-bit | 当前帧号(Frame Number),每 1 ms 递增,用于帧列表索引 |
| FLBASEADD | 0x08 | 32-bit | 帧列表基地址(4 KB 对齐),指向物理内存中的帧列表数组 |
| SOF | 0x0C | 16-bit | 帧起始(Start of Frame)调节值,控制 SOF 包发送时序 |
| PORTSC[1:2] | 0x10, 0x12 | 16-bit | 端口状态与控制寄存器,每个端口一个 |
调试端口视角:在嵌入式环境中,
USBSTS 的 HCHalted 位用于判断主机控制器是否进入停止状态;FLBASEADD 必须指向 DMA 可访问的内存区域,否则帧列表无法被硬件正确读取。
3.2 端口状态机
每个 UHCI 端口对应一个 PORTSC 寄存器,其内部状态机管理 USB 设备的连接、断开、复位、挂起与唤醒。状态机由硬件自动迁移,软件通过写控制位触发状态转换。
调试陷阱:在端口状态机处于 RESET 或 SUSPEND 时,DMA 传输请求会被主机控制器忽略。软件必须在启动 DMA 前确认 PORTSC 的 Port Enabled/Disabled 位为 1。
3.3 帧列表(Frame List)
帧列表是 UHCI 调度的核心数据结构,位于系统内存中,由 FLBASEADD 寄存器指向。它是一个包含 1024 个表项的数组(帧列表大小可通过 USBCMD.FLSIZE 调整为 256 或 512),每个表项是一个 32 位的帧指针。
- 帧指针格式:位 [31:4] 指向一个队列头或传输描述符的物理地址(16 字节对齐),位 [0] 为终止位(Terminate),位 [1] 为 QH/TD 选择位。
- 调度周期:主机控制器每 1 ms 递增 FRNUM,以 FRNUM 的低 10 位(或 8/9 位)索引帧列表,取出帧指针开始执行。
- DMA 协同:帧列表本身必须位于 DMA 可访问的内存区域,且不能被缓存(Cache)——嵌入式系统中需使用非缓存内存区域或刷新 Cache。
3.4 队列头(Queue Head)
队列头是 UHCI 传输调度的基本单元,每个 QH 对应一个 USB 端点(Endpoint)。QH 位于系统内存中,由帧指针或上一个 QH 的链接指针指向。QH 的主要字段包括:
| 字段 | 偏移 | 宽度 | 描述 |
|---|---|---|---|
| Horizontal Link Pointer | 0x00 | 32-bit | 指向下一个 QH 或 TD,格式与帧指针相同 |
| Endpoint Capabilities | 0x04 | 32-bit | 设备地址、端点号、数据速率(FS/LS)、最大包长等 |
| Current Link Pointer | 0x08 | 32-bit | 指向当前正在处理的 TD(硬件维护,软件初始化时置为 QH 首 TD) |
| Reserved / Overlay | 0x0C | 32-bit | 保留或用于 TD 覆盖(短包检测) |
DMA 传输协同:QH 中的 Horizontal Link Pointer 形成单向链表,主机控制器通过 DMA 读取 QH 和 TD。当 QH 的 Current Link Pointer 指向一个 TD 时,硬件自动发起 DMA 传输,将数据从内存搬运到 USB 总线(或反向)。传输完成后,硬件更新 TD 的状态字段,并移动到下一个 TD。
3.5 关键协同机制:帧列表 ↔ QH ↔ TD ↔ DMA
UHCI 的整个传输调度是一个从帧列表到 QH 再到 TD 的逐级解析过程,DMA 贯穿始终:
- 帧列表索引:每 1 ms 硬件以 FRNUM 为索引,从帧列表中读取一个帧指针。
- QH 遍历:帧指针指向一个 QH,硬件通过 QH 的 Horizontal Link Pointer 遍历该帧的所有 QH。
- TD 执行:在每个 QH 内部,硬件通过 Current Link Pointer 找到第一个 TD,发起 DMA 读/写操作。
- DMA 完成:TD 中的缓冲区地址指向系统内存,硬件通过 DMA 引擎直接传输数据,完成后更新 TD 状态。
- 中断触发:如果 TD 设置了中断使能位,传输完成后 USBINTR 寄存器会触发中断,通知软件处理。
嵌入式调试端口优化:将调试端口的 QH 放在帧列表的前几个表项中,可以降低调试数据的传输延迟。同时,使用 DMA 批量传输(多个 TD 链接)可以减少 CPU 干预,适合调试日志的高吞吐场景。