2、USB主机控制器架构:OHCI/UHCI/EHCI/xHCI控制器对比、寄存器模型、DMA与中断机制

USB主机控制器(Host Controller)是USB系统中连接软件栈与物理总线的硬件引擎。从USB 1.x到USB 3.x,业界先后定义了OHCI、UHCI、EHCI和xHCI四种标准规范。理解它们的架构差异、寄存器模型以及DMA/中断机制,是进行USB枚举移植适配的硬件基础。

2.1 四种主机控制器标准对比

OHCI(Open Host Controller Interface)与UHCI(Universal Host Controller Interface)均面向USB 1.x全速/低速设备;EHCI(Enhanced Host Controller Interface)面向USB 2.0高速设备;xHCI(eXtensible Host Controller Interface)则统一支持USB 3.x/2.0/1.x所有速率。下表从关键维度进行对比:

特性 OHCI UHCI EHCI xHCI
支持速率 USB 1.x (FS/LS) USB 1.x (FS/LS) USB 2.0 (HS) USB 3.x/2.0/1.x (SS/HS/FS/LS)
传输类型 控制、批量、中断、同步 控制、批量、中断、同步 控制、批量、中断、同步 控制、批量、中断、同步、流
调度方式 软件调度(帧列表) 软件调度(帧列表) 异步列表+周期列表 事件环+命令环+传输环
寄存器数量 约64个 约16个 约32个 约128个(含扩展能力)
DMA引擎 内置(链表遍历) 依赖软件(TD处理) 内置(异步/周期列表) 内置(多环并行)
中断模型 帧开始中断+完成中断 完成中断+错误中断 完成中断+端口状态中断 事件中断(MSI-X支持)
兼容性 需配套UHCI或EHCI 需配套OHCI或EHCI 需配套OHCI/UHCI(HS根集线器) 原生兼容所有速率
移植适配要点:在嵌入式系统中,xHCI已成为主流选择,因为它统一了寄存器接口和调度模型,减少了驱动适配工作量。但若目标平台仅支持USB 2.0,EHCI+OHCI/UHCI组合仍广泛存在。

2.2 寄存器模型对比

每种主机控制器都定义了一套内存映射寄存器(MMIO),用于控制状态、调度传输和处理事件。下面以xHCI为例展示核心寄存器组,并与EHCI进行对比。

2.2.1 xHCI寄存器模型

xHCI寄存器分为三部分:能力寄存器(CAPLENGTH)、操作寄存器(OP)和扩展能力寄存器(XECP)。核心寄存器包括:

  • CAPLENGTH / HCIVERSION:能力寄存器长度和版本号。
  • USBCMD / USBSTS:运行/停止命令与状态。
  • DNCTRL:设备通知控制。
  • CRCR:命令环控制寄存器(Command Ring Control Register)。
  • DCBAAP:设备上下文基地址数组指针。
  • CONFIG:最大设备槽位数配置。
  • PORTSC:端口状态与控制寄存器(每个端口一组)。
/* xHCI 操作寄存器基地址偏移示例(32位) */
#define XHCI_USBCMD     0x00  /* USB Command */
#define XHCI_USBSTS     0x04  /* USB Status */
#define XHCI_PAGESIZE   0x08  /* Page Size */
#define XHCI_DNCTRL     0x14  /* Device Notification Control */
#define XHCI_CRCR       0x18  /* Command Ring Control */
#define XHCI_DCBAAP     0x30  /* Device Context Base Address Array Pointer */
#define XHCI_CONFIG     0x38  /* Configure */
#define XHCI_PORTSC_BASE 0x400 /* Port Status and Control (每个端口16字节) */

2.2.2 EHCI寄存器模型

EHCI寄存器相对简洁,核心包括:

  • USBCMD / USBSTS:命令与状态。
  • FRINDEX:帧索引计数器。
  • PERIODICLISTBASE / ASYNCLISTADDR:周期列表基地址和异步列表地址。
  • PORTSC:端口状态与控制。
/* EHCI 操作寄存器基地址偏移示例(32位) */
#define EHCI_USBCMD     0x00
#define EHCI_USBSTS     0x04
#define EHCI_FRINDEX    0x0C
#define EHCI_PERIODICLISTBASE 0x14
#define EHCI_ASYNCLISTADDR    0x18
#define EHCI_PORTSC_BASE      0x44
关键差异:xHCI使用环(Ring)结构管理传输描述符,而EHCI使用链表(List)结构。xHCI的寄存器空间更大,支持动态扩展能力,适合复杂SoC集成。

2.3 DMA机制与传输调度

USB主机控制器通过DMA(Direct Memory Access)在系统内存与USB总线之间搬运数据,无需CPU逐字节干预。不同控制器的DMA引擎设计差异直接影响驱动实现复杂度。

2.3.1 xHCI的DMA环结构

xHCI使用三种环:命令环(Command Ring)、传输环(Transfer Ring)和事件环(Event Ring)。每个环由一组循环的TRB(Transfer Request Block)组成,TRB是DMA传输的最小单元。

xHCI DMA环结构示意图 命令环 (CR) TRB 0 TRB 1 TRB 2 TRB N-1 传输环 (TR) TD 0 TD 1 TD 2 TD M-1 事件环 (ER) 事件 0 事件 1 事件 2 事件 K-1 DMA传输流程 1. 驱动将TRB写入命令环 → 2. xHCI DMA引擎自动读取并执行 → 3. 完成事件写入事件环 4. 驱动通过中断读取事件环 → 5. 回收传输环TD → 6. 更新生产者/消费者指针

2.3.2 EHCI的DMA链表结构

EHCI使用异步列表(Asynchronous List)和周期列表(Periodic List)。异步列表用于控制传输和批量传输,周期列表用于中断传输和同步传输。每个列表由队列头(QH)和传输描述符(qTD)组成。

/* EHCI 队列头(QH)结构示例 */
struct ehci_qh {
    uint32_t qh_horiz_link;   /* 水平链接指针 */
    uint32_t qh_endpoint_caps; /* 端点特性 */
    uint32_t qh_current_qtd;  /* 当前qTD指针 */
    uint32_t qh_next_qtd;     /* 下一个qTD指针 */
    uint32_t qh_alt_next_qtd; /* 备用qTD指针 */
    uint32_t qh_token;        /* 令牌 */
    uint32_t qh_buffer[5];    /* 缓冲区指针(5个页面) */
} __attribute__((packed));
DMA对齐要求:所有主机控制器都要求传输描述符在内存中按32字节或64字节对齐。xHCI的TRB必须16字节对齐,EHCI的qTD必须32字节对齐。移植时需确保DMA内存分配满足对齐约束,否则控制器会忽略描述符。

2.4 中断机制

USB主机控制器通过中断通知驱动处理完成事件、错误或端口状态变化。不同规范的中断模型差异显著。

2.4.1 xHCI事件中断

xHCI采用事件中断(Event Interrupt)模型,支持MSI/MSI-X。每个中断对应一个事件环,驱动通过读取事件环中的事件TRB判断中断原因。中断类型包括:

  • 传输完成中断:数据传输成功或失败。
  • 端口状态变化中断:设备连接/断开/复位完成。
  • 命令完成中断:命令环上的命令执行完毕。
  • 主机控制器错误中断:系统错误或HCE。
/* xHCI 中断处理伪代码 */
void xhci_irq_handler(void) {
    uint32_t status = readl(regs + XHCI_USBSTS);
    if (status & STS_EINT) {  /* 事件中断 */
        struct xhci_event_ring *er = &xhci->event_ring;
        while (er->dequeue != er->enqueue) {
            struct xhci_trb *event = &er->trbs[er->dequeue];
            switch (TRB_TYPE(event)) {
                case TRB_TRANSFER:
                    handle_transfer_event(event);
                    break;
                case TRB_PORT_STATUS:
                    handle_port_status_event(event);
                    break;
                case TRB_COMMAND_COMPLETE:
                    handle_command_complete(event);
                    break;
            }
            er->dequeue = (er->dequeue + 1) % ER_SIZE;
        }
        writel(STS_EINT, regs + XHCI_USBSTS); /* 写1清除中断 */
    }
}

2.4.2 EHCI中断模型

EHCI中断相对简单,主要中断源包括:

  • USB完成中断(USBINT):异步列表或周期列表中的传输完成。
  • USB错误中断(USBERRINT):传输错误。
  • 端口变化中断(PCD):端口连接状态变化。
  • 帧列表滚动中断(FRLISTROLL):帧列表循环完成。
/* EHCI 中断状态寄存器位定义 */
#define STS_USBINT      (1 << 0)  /* 传输完成 */
#define STS_USBERRINT   (1 << 1)  /* 传输错误 */
#define STS_PCD         (1 << 2)  /* 端口变化 */
#define STS_FRLISTROLL  (1 << 3)  /* 帧列表滚动 */
#define STS_HCHALTED    (1 << 5)  /* 主机控制器暂停 */

2.4.3 中断延迟与性能

在嵌入式系统中,中断延迟直接影响USB枚举速度和实时性。下表对比不同控制器的中断特性:

特性 OHCI UHCI EHCI xHCI
中断合并 不支持 不支持 不支持 支持(中断调节器)
MSI-X支持 否 否 否 是
中断频率 每帧1次(1ms) 每帧多次 每微帧1次(125μs) 按事件触发(可配置)
典型延迟 1-2ms 0.5-1ms 125-250μs 10-100μs(可调)
移植优化建议:在xHCI驱动中,利用中断调节器(Interrupt Moderation)可以降低高吞吐场景下的中断频率,减少CPU占用。对于枚举阶段,建议关闭调节器以获得最低延迟。

2.5 主机控制器架构总结

下表从移植适配角度总结四种控制器的核心差异:

适配维度 OHCI UHCI EHCI xHCI
驱动复杂度 中等 高(软件管理TD) 中等 高(环管理复杂)
DMA内存开销 低 低 中 高(多环+上下文)
枚举速度 慢(1ms帧) 慢 快(125μs微帧) 最快(事件驱动)
多速率支持 仅FS/LS 仅FS/LS 仅HS(需配套OHCI/UHCI) SS/HS/FS/LS原生
寄存器访问 MMIO MMIO MMIO MMIO + 扩展能力

理解这些架构差异后,下一阶段将深入USB设备枚举的完整流程,包括设备描述符获取、地址分配和配置选择。在移植适配时,应根据目标平台选择对应的主机控制器驱动框架,并针对寄存器模型和DMA机制进行底层适配。