1. OHCI 协议概述:标准历史、核心设计思想与对比
OHCI(Open Host Controller Interface)是 USB 主机控制器接口标准之一,由 Compaq、Microsoft 和 National Semiconductor 联合制定,于 1996 年发布 1.0 规范。它定义了 USB 主机控制器硬件与软件驱动之间的标准接口,旨在降低驱动开发复杂度,提升跨平台兼容性。
1.1 OHCI 标准的历史演进
USB 1.x 时代,主机控制器接口存在两大阵营:Intel 主导的 UHCI(Universal Host Controller Interface)和开放联盟主导的 OHCI。OHCI 的设计目标是将更多控制逻辑交给硬件,减少软件干预,从而简化驱动开发。
| 时间 | 事件 | 影响 |
|---|---|---|
| 1995 | USB 1.0 规范发布 | 定义物理层和协议层,但未统一主机控制器接口 |
| 1996 | OHCI 1.0 规范发布 | Compaq/Microsoft/National Semiconductor 联合推出 |
| 1998 | UHCI 规范发布 | Intel 推出,硬件更简单,软件负担更重 |
| 2000 | USB 2.0 / EHCI 规范发布 | EHCI 兼容 OHCI/UHCI,通过 Companion Controller 实现 |
| 2008 | USB 3.0 / xHCI 规范发布 | 统一所有速度等级,逐步取代 OHCI/UHCI/EHCI |
驱动开发提示: OHCI 在嵌入式领域(如 ARM SoC、早期 PowerPC 平台)仍有广泛应用。理解 OHCI 的硬件自动调度机制,对调试中断延迟和控制传输超时问题至关重要。
1.2 核心设计思想
OHCI 的核心设计哲学是 “硬件辅助,软件轻量”。与 UHCI 将大部分调度工作交给软件不同,OHCI 在硬件层面实现了以下关键机制:
- 周期性列表(Periodic List): 硬件自动遍历中断传输(Interrupt Transfer)和等时传输(Isochronous Transfer)的 ED(Endpoint Descriptor)链表,无需软件逐帧干预。
- 非周期性列表(Non-periodic List): 硬件在周期性列表空闲时,自动切换到控制传输(Control)和批量传输(Bulk)的 ED 链表,实现带宽复用。
- HCCA(Host Controller Communication Area): 一块共享内存区域,硬件将帧完成状态、中断状态等信息写入 HCCA,驱动通过轮询或中断读取。
- 帧周期固定为 1ms: 硬件以 1ms 为帧周期,每帧开始发送 SOF(Start of Frame)包,驱动基于帧号(Frame Number)进行时间管理。
关键概念: OHCI 的 ED(Endpoint Descriptor)和 TD(Transfer Descriptor)是驱动与硬件交互的核心数据结构。ED 描述端点属性(方向、速度、格式),TD 描述具体传输请求(数据缓冲区、传输长度、完成状态)。硬件自动遍历 ED 链表,从对应 TD 队列中取出待处理传输。
1.3 OHCI 与 UHCI / EHCI 的对比
三种主机控制器接口在设计理念、硬件复杂度、软件负担和适用场景上存在显著差异。下表从驱动开发角度进行对比:
| 对比维度 | OHCI | UHCI | EHCI |
|---|---|---|---|
| 制定者 | Compaq / Microsoft / National Semi | Intel | Intel 主导的 USB-IF |
| USB 版本 | USB 1.1 | USB 1.1 | USB 2.0 |
| 速度 | Full/Low Speed | Full/Low Speed | High Speed (480 Mbps) |
| 硬件复杂度 | 高(硬件自动调度) | 低(硬件简单) | 高(高速传输引擎) |
| 软件负担 | 低(驱动较简单) | 高(驱动需手动调度) | 中(需处理高速协议) |
| 帧周期 | 1ms 固定 | 1ms 固定 | 125μs(微帧) |
| 调度方式 | 硬件遍历 ED/TD 链表 | 软件构建帧列表(Frame List) | 硬件异步列表 + 周期性列表 |
| 中断处理 | HCCA 记录中断状态,驱动读取 | 中断寄存器直接映射 | 中断寄存器 + 异步中断消息 |
| 控制传输 | 硬件自动重试,软件设置 TD | 软件需手动管理控制阶段 | 硬件支持高速控制传输 |
| 典型平台 | 嵌入式 ARM / PowerPC / 早期 PC | Intel 芯片组 PC | USB 2.0 PC / 嵌入式 |
调试陷阱: OHCI 的硬件自动重试机制在控制传输阶段可能导致“死循环”现象——当设备无响应时,硬件会无限重试 SETUP 阶段,直到软件干预。驱动开发时必须设置 TD 的“重试计数”或“超时控制”位,否则调试时会出现总线挂起。
1.4 OHCI 在驱动开发中的关键数据结构
驱动开发者必须理解以下三个核心数据结构,它们直接映射到硬件寄存器或共享内存:
- HcControl(控制寄存器): 控制主机控制器的运行状态(运行/停止/复位)、周期性列表使能、非周期性列表使能等。
- HcInterruptStatus(中断状态寄存器): 反映写回完成、帧号溢出、根集线器状态变化、传输完成等中断事件。
- Hcca(Host Controller Communication Area): 256 字节对齐的共享内存区域,包含帧号、完成状态字、中断状态字等。
/* OHCI HCCA 结构定义(简化) */
struct ohci_hcca {
uint32_t frame_number; /* 当前帧号,每帧递增 */
uint32_t done_head; /* 已完成 TD 链表头指针 */
uint8_t reserved[116]; /* 保留 */
uint32_t interrupt_status; /* 中断状态位图 */
uint8_t pad[120]; /* 填充至 256 字节 */
} __attribute__((aligned(256)));
驱动开发要点: OHCI 驱动初始化时,必须将 HCCA 分配在 256 字节对齐的内存地址上,并将物理地址写入 HcHCCA 寄存器。中断处理函数中,驱动通过读取 HCCA 的 done_head 字段获取已完成 TD 链表,而非直接遍历硬件链表——这是 OHCI 与 UHCI 在中断处理上的核心差异。
1.5 控制传输在 OHCI 中的实现特点
控制传输是 USB 设备枚举和配置的基础,在 OHCI 中具有以下特点:
- 三个阶段: SETUP(建立)、DATA(数据,可选)、STATUS(状态)。每个阶段对应一个或多个 TD。
- 硬件自动重试: 当设备返回 NAK 时,OHCI 硬件会自动重试当前 TD,无需软件干预。但重试次数过多会导致帧时间超限。
- 控制 ED 位于非周期性列表: 控制传输的 ED 被挂接到非周期性列表,硬件在周期性列表空闲时处理。
- TD 完成中断: 每个 TD 完成后,硬件将其加入 HCCA.done_head 链表,并触发中断(如果使能)。
调试建议: 在控制传输调试中,建议在驱动中记录每个 TD 的完成状态和帧号。如果发现 SETUP 阶段反复重试但无 STATUS 阶段,通常是设备未正确解析 SETUP 包,或硬件重试计数未设置导致无限循环。