USB OTG 概述
USB OTG,全称 USB On-The-Go,是 USB 2.0 规范的一个重要补充。它解决了传统 USB 只能固定主从关系的问题。说白了,就是让一个 USB 接口既能当主机,也能当设备。我个人认为,这是嵌入式系统中灵活度最高的接口之一。
OTG 协议简介
OTG 是 2001 年由 USB-IF 推出的。它定义了两种新型设备:OTG A-device(初始 Host)和 OTG B-device(初始 Peripheral)。A-device 供电,B-device 受电。但关键来了——它们可以在运行时通过 HNP(主机协商协议)和 SRP(会话请求协议)互换角色。
我在一个智能硬件项目里遇到过这种情况:一台平板通过 USB 口连接一个 U 盘,突然又想把这个平板再接到另一台电脑上当 U 盘拷贝数据。按照传统 USB 规范,这根本不可能。但 OTG 可以做到——只需要一根 OTG 线,系统就能自动切换。
| 协议 | 全称 | 作用 |
|---|---|---|
| HNP | Host Negotiation Protocol | 让 B-device 发起请求,变为主机 |
| SRP | Session Request Protocol | 让 B-device 唤醒暂停的主机,开始通信 |
主机与设备角色切换
角色切换的触发条件有两个:一是 ID 引脚的电平变化,二是上层软件发出切换指令。硬件上靠 ID 引脚决定初始角色,软件上靠 HNP 实现动态切换。
举个实际例子:一台手机(B-device)通过 OTG 线连一个鼠标(A-device)。鼠标是 Host,手机是 Device。但如果你拔掉鼠标,换上一个 U 盘,此时手机想变成 Host 去读写 U 盘。怎么做的?HNP 会介入:手机通过 D+ 线拉低一段时间,向对方发出角色切换请求。鼠标(或 U 盘本身不支持 HNP)可能拒绝,但如果是真·OTG 外设,就会完成切换。
我记得调试一个 Linux 平台时,最坑的是 HNP 状态机驱动不对,导致切换后 USB 总线报错。我用的是 usbmon 抓包,发现角色切换后设备描述符请求超时。最后发现是 host 侧没有及时释放端点资源。这类问题很隐蔽,你想想看,硬件连接没问题,但软件状态机挂死在中间状态。
ID 引脚检测原理
这是 OTG 最基础的硬件识别手段。标准 mini-USB / micro-USB 的 5 个引脚中,第 4 脚就是 ID。它内部上拉到 3.3V。当插入 OTG 线时:
- ID 引脚接地(GND):设备被识别为 A-device(Host),负责供电。
- ID 引脚悬空(或接高电平):设备被识别为 B-device(Peripheral),默认受电。
这里有一个常见的误区。我在刚入职时就踩过:以为 ID 接地就是永远 Host,悬空就是永远 Device。但实际上,很多嵌入式 SoC 的 USB 控制器在检测到 ID 接地后,只是初始化成 Host 模式,而后续 HNP 仍然可以把它切回 Peripheral。ID 引脚只决定“初始”角色,不是“永远”角色。
OTG 系统角色切换流程(附图)
下面这张图概括了 OTG 的初始角色分配和 ID 检测逻辑。注意两个设备都有 OTG 双角色能力时,流程才完整。如果一端是标准 USB 主机或设备,则只能从事先固定的角色通信。
图中展示了 ID 引脚决定初始角色,以及 HNP 协商后的可互换性。实际调试中,我建议重点关注三个关键点:ID 引脚电平检测时序、HNP 超时时间、以及切换后端点的重新配置。把这三点搞明白了,大多数 OTG 角色切换问题都能定位。
小结(工程视角)
- OTG 的核心价值:一根线,两种身份,免去额外的 Host 芯片。
- ID 引脚是硬线逻辑,但不要把它当成“永久角色锁”——它只是初始化的提示。
- 角色切换的失败,十有八九出在软件状态机实现上,而不是硬件本身。
好了,这一章我们大致理清了 OTG 的框架。后面的章节会深入驱动代码和具体调试工具。做好准备,后面的内容会更硬核。