4. UHCI 状态寄存器(USBSTS)详解

UHCI 状态寄存器(USBSTS)是主机控制器向软件报告当前运行状态、错误条件和中断事件的核心寄存器。软件通过读取 USBSTS 判断控制器是否正常、传输是否完成、是否发生错误。本章将逐一解析 USBSTS 的 8 个关键位,并结合初始化与调优场景说明其用法。

寄存器基础信息:USBSTS 为 32 位只读寄存器(部分位写 1 清除),基地址由 USB 基地址寄存器(USB Base Address Register, USBBA)偏移 4 字节得到。复位值为 0x0020(仅 HCHalted 位为 1)。

4.1 USBSTS 位布局总览

下表列出 USBSTS 各状态位的位号、名称、类型及简要描述。所有中断使能位位于 USB 中断使能寄存器(USBINTR)中,USBSTS 仅反映状态。

位号 名称 类型 描述
31:6 Reserved RO 保留位,始终读回 0
5 HCHalted RO 主机控制器已停止
4 HCPE R/WC 主机控制器进程错误
3 HCSE R/WC 主机控制器系统错误
2 RD R/WC 恢复检测
1 UEI R/WC USB 错误中断
0 USBINT R/WC USB 中断
写 1 清除(R/WC)说明:对于 HCPE、HCSE、RD、UEI、USBINT 位,软件写入 1 可清除该位;写入 0 无影响。HCHalted 为只读位,不可通过软件清除。

4.2 各状态位详解

4.2.1 HCHalted(位 5)——主机控制器已停止

HCHalted 是 USBSTS 中最重要的状态位之一。当该位为 1 时,表示主机控制器已进入停止状态,不再处理任何帧列表或队列头。该位在以下条件下被置位:

  • 硬件复位或软件复位后自动置位。
  • 软件向 USBCMD 的 Run/Stop(RS)位写 0 后,控制器完成当前帧事务后置位。
  • 发生致命错误(如 HCPE 或 HCSE)导致控制器自动停止。

软件在初始化流程中必须轮询 HCHalted 位,确认控制器已停止后才能安全配置帧列表基地址、设置寄存器等操作。在启动控制器前,软件应确保 HCHalted 为 1,然后写 USBCMD.RS = 1 并等待 HCHalted 变为 0。

常见陷阱:某些 UHCI 控制器在写 RS = 1 后需要等待至少一个帧周期(1 ms)HCHalted 才会清零。软件应实现超时机制(建议 10 ms),避免死循环。

4.2.2 HCPE(位 4)——主机控制器进程错误

HCPE 表示主机控制器在解析或执行链表(帧列表、队列头、传输描述符)时检测到不可恢复的结构错误。典型触发场景包括:

  • 队列头或传输描述符中的指针指向非法地址(如未对齐或超出系统内存范围)。
  • 传输描述符的 Active 位为 1 但格式错误(如长度字段为 0 且无数据阶段)。
  • 链表形成环路或深度超过控制器硬件限制。

当 HCPE 置位时,控制器会同时将 HCHalted 置位并停止运行。软件必须读取 USBSTS 判断错误来源,然后执行控制器复位并修正链表错误后重新启动。

4.2.3 HCSE(位 3)——主机控制器系统错误

HCSE 指示主机控制器在访问系统内存时发生了总线错误(如 PCI 总线错误、内存奇偶校验错误、目标设备终止等)。该错误通常由硬件系统层面引起,而非软件链表逻辑错误。

HCSE 与 HCPE 的区别在于:HCPE 是控制器内部解析链表时发现的协议/结构错误;HCSE 是控制器与系统内存交互时发生的总线级错误。两者都会导致控制器停止,但 HCSE 往往需要更彻底的复位(包括 PCI 配置空间复位)。

错误类型 触发原因 恢复方式
HCPE(进程错误) 链表结构错误、非法指针、格式错误 修正链表后复位控制器
HCSE(系统错误) PCI 总线错误、内存访问异常 PCI 复位或系统级复位

4.2.4 RD(位 2)——恢复检测

RD 位用于全局挂起(Global Suspend)后的唤醒检测。当主机控制器处于挂起状态时,检测到 USB 总线上的恢复信号(Resume Signaling)时,RD 位被置位。软件可通过该位判断是否有设备触发了远程唤醒。

在电源管理场景中,软件在挂起前应清除 RD 位(写 1),然后在唤醒中断服务程序中读取 RD 位确认唤醒源。如果 RD 为 1,则软件应执行恢复序列并将控制器重新置为运行状态。

4.2.5 UEI(位 1)——USB 错误中断

UEI 位在以下条件之一满足时置位:

  • 任何传输描述符完成时其 Error 位被置位(如 Stall、Babble、CRC 错误等)。
  • 控制器检测到 USB 协议错误(如帧格式错误、SOF 丢失等)。

UEI 是 USB 错误中断的汇总状态位。软件在中断服务程序中应首先读取 USBSTS,如果 UEI 为 1,则遍历所有活动队列头,检查传输描述符的错误状态,记录错误信息并决定是否重试传输。

4.2.6 USBINT(位 0)——USB 中断

USBINT 是最常用的中断位。当任何传输描述符完成且满足以下条件时,USBINT 被置位:

  • 传输描述符的 IOC(Interrupt On Complete)位为 1。
  • 传输描述符完成时无错误(Error 位为 0)。

软件通常将 USBINT 作为批量传输和中断传输的完成通知。在中断服务程序中,软件应读取 USBSTS,如果 USBINT 为 1,则遍历完成队列,处理已完成的传输描述符并释放相关资源。

4.2.7 SPD(位 ?)——短包检测

UHCI 规范中 USBSTS 寄存器并未定义独立的 SPD 位。短包检测(Short Packet Detect)功能通过传输描述符(TD)的 SPD 位实现,而非 USBSTS 寄存器。为避免混淆,此处澄清:

勘误说明:部分 UHCI 文档将 SPD 列为 USBSTS 位,但 UHCI 1.0/1.1 规范中 USBSTS 位 6 为保留位。短包检测功能由 TD 的 Short Packet Detect(SPD)位控制,位于传输描述符的状态字段中。软件应在 TD 层面处理短包检测,而非 USBSTS。

4.2.8 IOC(I/O Completion)

IOC 并非 USBSTS 的独立位,而是传输描述符(TD)控制字段中的一个标志位。当 TD 的 IOC 位为 1 且该 TD 完成时,USBSTS 的 USBINT 位会被置位。因此,IOC 是触发 USBINT 的条件之一,而非独立状态位。

软件通过在关键 TD 上设置 IOC 位来控制中断频率。例如,在批量传输中,软件可以在每 10 个 TD 上设置 IOC,以减少中断次数,提高吞吐量。

4.3 USBSTS 与中断服务流程

下图展示软件在中断服务程序中读取 USBSTS 并分发处理的典型流程:

USBSTS 中断服务程序处理流程 读取 USBSTS USBINT == 1 ? 遍历完成 TD 队列 UEI == 1 ? 记录错误并重试 HCPE/HCSE == 1 ? 执行控制器复位 RD == 1 ? 执行恢复序列 写 1 清除 USBSTS 中断位

4.4 初始化阶段 USBSTS 轮询示例

以下代码展示 UHCI 初始化过程中如何轮询 HCHalted 位,确保控制器已停止后再进行寄存器配置:

// UHCI 初始化:等待控制器停止
void uhci_wait_halted(uint32_t base_addr) {
    uint32_t timeout = 10000;  // 超时计数
    uint32_t usbsts;

    do {
        usbsts = readl(base_addr + 0x04);  // 读取 USBSTS
        if (usbsts & (1 << 5)) {          // 检查 HCHalted 位
            break;                          // 控制器已停止
        }
        udelay(100);                        // 等待 100 微秒
        timeout--;
    } while (timeout > 0);

    if (timeout == 0) {
        // 超时处理:执行复位
        writel(0x02, base_addr + 0x00);     // 写 USBCMD 复位位
        mdelay(10);
    }
}

// 启动控制器
void uhci_start(uint32_t base_addr) {
    uint32_t usbsts;

    // 确认控制器已停止
    usbsts = readl(base_addr + 0x04);
    if (!(usbsts & (1 << 5))) {
        // 如果未停止,先停止
        writel(0x00, base_addr + 0x00);     // 写 USBCMD.RS = 0
        uhci_wait_halted(base_addr);
    }

    // 配置帧列表基地址等寄存器
    // ...

    // 启动运行
    writel(0x01, base_addr + 0x00);         // 写 USBCMD.RS = 1

    // 等待 HCHalted 清零
    timeout = 1000;
    do {
        usbsts = readl(base_addr + 0x04);
        if (!(usbsts & (1 << 5))) {
            break;                          // 控制器已运行
        }
        udelay(100);
        timeout--;
    } while (timeout > 0);
}

4.5 性能调优:中断频率控制

USBINT 位的置位频率直接影响 CPU 占用率。通过合理设置 TD 的 IOC 位,软件可以控制中断频率,实现性能调优:

场景 IOC 设置策略 效果
批量传输(高吞吐) 每 10~20 个 TD 设置一次 IOC 减少中断次数,提高吞吐量
中断传输(低延迟) 每个 TD 都设置 IOC 保证及时响应,降低延迟
等时传输 每帧最后一个 TD 设置 IOC 平衡延迟与 CPU 负载
调优建议:在初始化阶段,软件应清除 USBSTS 所有中断位(写 0x3E),确保无残留中断状态。在运行过程中,中断服务程序应尽快读取 USBSTS 并清除已处理的中断位,避免丢失后续中断。

4.6 本章小结

USBSTS 寄存器是 UHCI 控制器状态的核心窗口。HCHalted 位控制初始化与停止流程;HCPE 和 HCSE 位指示不同层次的错误;RD 位用于电源管理唤醒;UEI 和 USBINT 位驱动中断服务程序。软件开发者必须深入理解每个状态位的置位条件和清除方式,才能编写健壮的 UHCI 驱动并实现性能调优。