3. UHCI 命令寄存器(USBCMD)详解

UHCI 命令寄存器(USBCMD)是主机控制器初始化与运行控制的核心寄存器,位于 I/O 空间偏移地址 0x00,宽度为 16 位。该寄存器中的每一位都直接控制着控制器的运行状态、复位行为、电源管理以及调试模式。本章将逐一解析 USBCMD 的各个字段,并结合实战场景说明其编程要点与性能调优策略。

3.1 USBCMD 寄存器位域总览

下表列出了 USBCMD 寄存器中所有有效位的名称、位号、访问属性及功能简述。理解这些位域是进行 UHCI 初始化的第一步。

位号 名称 访问 功能描述
15:7 Reserved R 保留位,必须写 0
6 CF R/W Configure Flag(配置标志)
5 SWDBG R/W SW Debug(软件调试模式)
4 FGR R/W Force Global Resume(强制全局唤醒)
3 EGSM R/W Enter Global Suspend Mode(进入全局挂起)
2 GRESET R/W Global Reset(全局复位)
1 HCRESET R/W Host Controller Reset(主机控制器复位)
0 RS R/W Run/Stop(运行/停止)
编程提示: 在初始化流程中,建议先配置好 USBCMD 的低 7 位(0x7F),再通过一次 16 位写操作写入寄存器,以避免中间状态导致控制器行为异常。

3.2 Run/Stop(RS)位 —— 控制器的启停开关

位号:0
访问:R/W
默认值:0(停止状态)

RS 位是 UHCI 控制器运行状态的总开关。当该位被置为 1 时,控制器开始按照帧列表(Frame List)的调度执行 USB 事务处理;当该位被清 0 时,控制器在完成当前帧的所有事务后停止运行,进入空闲状态。

编程要点

  • 启动控制器: 在完成所有初始化配置(如设置帧列表基地址、配置端口、设置中断使能等)后,最后一步将 RS 位置 1。
  • 停止控制器: 在系统休眠、挂起或卸载驱动前,先将 RS 位清 0,并轮询等待控制器状态寄存器(USBSTS)中的 HCHalted 位变为 1,确认控制器已安全停止。
  • 性能调优: 频繁启停 RS 位会增加调度延迟。在批量传输场景中,建议保持 RS 位为 1,仅在电源管理或错误恢复时操作该位。
实战代码片段: 启动 UHCI 控制器
// 假设 USBCMD 寄存器 I/O 地址为 0xC000
// 1. 设置帧列表基地址(略)
// 2. 设置端口配置(略)
// 3. 启动控制器
outw(inw(0xC000) | 0x0001, 0xC000);  // 将 RS 位置 1
// 4. 等待控制器进入运行状态
while (!(inw(0xC004) & 0x0001));     // 轮询 USBSTS 的 HCHalted 位为 0

3.3 Host Controller Reset(HCRESET)位 —— 软件复位

位号:1
访问:R/W
默认值:0

HCRESET 位用于对 UHCI 主机控制器执行软件复位。当该位被置 1 时,控制器内部状态机、寄存器(除 USBCMD 本身和 USBSTS 的某些位外)以及所有端口逻辑都会被复位到默认状态。该位由硬件在复位完成后自动清 0。

使用场景

  • 驱动加载初始化: 在 BIOS 或系统引导后,驱动应首先通过 HCRESET 确保控制器处于已知的初始状态。
  • 错误恢复: 当检测到控制器挂起或传输超时等不可恢复错误时,使用 HCRESET 复位控制器,然后重新初始化。
  • 热插拔处理: 在设备拔出后,可选择性复位控制器以清理残留状态。
注意事项: HCRESET 复位后,所有端口寄存器、帧列表指针、中断使能等配置都会丢失。复位后必须重新执行完整的初始化流程,包括设置帧列表基地址、配置端口、设置中断使能等。

编程流程

  1. 将 USBCMD 的 HCRESET 位置 1。
  2. 轮询等待 HCRESET 位被硬件自动清 0(通常需要 10~50 微秒)。
  3. 确认 USBSTS 中的 HCHalted 位为 1,表示控制器已进入停止状态。
  4. 重新进行完整的初始化配置。

3.4 Global Reset(GRESET)位 —— 全局复位

位号:2
访问:R/W
默认值:0

GRESET 位用于对 USB 总线上的所有下游设备执行全局复位。当该位被置 1 时,UHCI 控制器会驱动 D+ 和 D- 信号线进入复位状态(SE0 状态),持续时间由硬件控制(通常为 10~50 毫秒)。该位由硬件在复位完成后自动清 0。

与 HCRESET 的区别

特性 HCRESET GRESET
复位目标 主机控制器内部逻辑 USB 总线上的所有设备
持续时间 微秒级(10~50 µs) 毫秒级(10~50 ms)
对端口影响 端口寄存器复位 端口状态机复位,设备断开重连
使用场景 驱动初始化、错误恢复 系统级复位、电源管理
性能调优: GRESET 操作会中断所有正在进行的 USB 传输,且耗时较长。在正常运行时不应使用 GRESET。仅在系统进入深度休眠或需要完全重置 USB 子系统时使用。

3.5 Enter Global Suspend Mode(EGSM)与 Force Global Resume(FGR)

EGSM 位号:3
FGR 位号:4
访问:R/W
默认值:0

EGSM 和 FGR 位用于控制 UHCI 控制器的全局电源管理。EGSM 位使控制器进入全局挂起模式,此时控制器停止帧启动(SOF)包的发送,所有端口进入挂起状态。FGR 位用于强制唤醒,使控制器恢复 SOF 发送并唤醒所有挂起的设备。

电源管理状态转换

下图展示了 UHCI 控制器在正常运行、全局挂起和全局唤醒之间的状态转换关系。

UHCI 全局电源管理状态转换 正常运行 RS=1, EGSM=0 全局挂起 RS=1, EGSM=1 唤醒过渡 FGR=1 置位 EGSM 置位 FGR FGR 自动清 0 清 EGSM(不推荐)

编程注意事项

  • 进入挂起: 先确保所有 USB 设备已进入挂起状态(通过端口控制寄存器),再将 EGSM 位置 1。控制器将在当前帧结束后停止 SOF 发送。
  • 唤醒: 将 FGR 位置 1,控制器会立即恢复 SOF 发送并持续 20 毫秒,然后自动清 0 FGR 位。驱动应轮询等待 FGR 位清 0 后,再恢复正常操作。
  • 性能影响: 全局挂起/唤醒操作会引入 20~50 毫秒的延迟,不适合频繁使用。建议仅在系统进入 S3(挂起到内存)或 S4(休眠)状态时使用。

3.6 SW Debug(SWDBG)位 —— 软件调试模式

位号:5
访问:R/W
默认值:0

SWDBG 位用于启用 UHCI 控制器的软件调试模式。当该位被置 1 时,控制器会在每个帧结束后暂停,等待软件干预。调试模式允许驱动开发者单步执行帧调度,检查传输描述符(TD)和队列头(QH)的状态。

调试模式工作流程

  1. 将 SWDBG 位置 1,同时确保 RS 位为 1。
  2. 控制器执行完当前帧的所有事务后,暂停并设置 USBSTS 中的 Debug 状态位。
  3. 驱动读取帧列表、TD 和 QH 的状态,分析传输结果。
  4. 驱动清除 Debug 状态位,控制器继续执行下一帧。
性能警告: SWDBG 模式会显著降低 USB 传输吞吐量,仅用于开发和调试阶段。在生产环境或性能测试中,必须确保 SWDBG 位为 0。

3.7 Configure Flag(CF)位 —— 配置标志

位号:6
访问:R/W
默认值:0

CF 位是 UHCI 控制器的配置标志位。该位用于指示主机控制器驱动(HCD)已完成对控制器的配置。在 CF 位被置 1 之前,控制器不会开始处理任何 USB 传输请求。CF 位通常作为初始化完成的最后一步。

CF 位的使用规则

  • 置位时机: 在所有初始化步骤(包括 HCRESET、帧列表设置、端口配置、中断使能)完成后,最后将 CF 位置 1。
  • 清 0 时机: 在驱动卸载或系统进入休眠前,先将 CF 位清 0,再停止控制器(RS 位清 0)。
  • 多控制器协调: 在具有多个 UHCI 控制器的系统中,每个控制器的 CF 位独立管理,互不影响。

3.8 初始化流程整合:USBCMD 寄存器编程实战

以下是一个完整的 UHCI 控制器初始化流程,展示了 USBCMD 各字段的正确编程顺序。

UHCI 控制器初始化流程(USBCMD 编程顺序) 1. 置位 HCRESET 2. 轮询 HCRESET 自动清 0 3. 设置帧列表基地址 4. 配置端口寄存器 5. 设置中断使能 6. 置位 CF 7. 置位 RS(启动控制器)
完整初始化代码示例:
// 步骤 1: 复位主机控制器
outw(inw(0xC000) | 0x0002, 0xC000);  // 置位 HCRESET
// 步骤 2: 等待复位完成
while (inw(0xC000) & 0x0002);
// 步骤 3: 设置帧列表基地址(假设基地址为 0x100000)
outl(0x100000, 0xC008);
// 步骤 4: 配置端口 1(启用端口)
outw(inw(0xC010) | 0x0001, 0xC010);
// 步骤 5: 设置中断使能(启用完成中断)
outw(0x0001, 0xC006);
// 步骤 6: 置位 CF
outw(inw(0xC000) | 0x0040, 0xC000);
// 步骤 7: 启动控制器
outw(inw(0xC000) | 0x0001, 0xC000);
// 等待控制器运行
while (inw(0xC004) & 0x0001);

3.9 性能调优建议

场景 USBCMD 配置建议 性能影响
高吞吐量传输 RS=1, SWDBG=0, CF=1 最大化帧调度效率
低功耗待机 RS=1, EGSM=1, CF=1 减少功耗,唤醒延迟约 20ms
调试阶段 RS=1, SWDBG=1, CF=1 单帧执行,吞吐量下降 90% 以上
错误恢复 先 HCRESET=1,再重新初始化 完全重置,恢复时间约 50µs
调优总结: USBCMD 寄存器的配置直接影响 UHCI 控制器的运行模式与性能。在正常运行时,保持 RS=1、SWDBG=0、CF=1 是最优配置。电源管理场景下,合理使用 EGSM/FGR 可以在功耗与响应时间之间取得平衡。调试时,SWDBG 模式提供了强大的单步跟踪能力,但务必在性能测试前关闭。