1. USB OTG 概述与基础概念
做嵌入式这么多年,USB OTG 这块确实坑不少。每次驱动加载失败,工程师们第一反应往往是怀疑硬件,但很多时候问题出在对 OTG 基础概念的理解上。今天我们就从根儿上捋一捋。
1.1 什么是 USB OTG?
USB OTG,全称 USB On-The-Go,是 USB 2.0 规范的一个补充协议。它解决了一个很实际的问题:设备间的直接数据交换。
传统 USB 架构里,主机(Host)只有一个,外设(Peripheral)也只有一个。手机连电脑,电脑是 Host,手机是 Device。但如果两个手机想互传文件呢?没门儿。OTG 就是来打破这个僵局的。
我记得最早接触 OTG 是在 2012 年做的一款平板电脑项目。客户要求平板能接 U 盘,也能当 U 盘被电脑识别。当时我就想,这不就是让一个设备动态切换角色吗?对的,OTG 的核心就是角色动态协商。
关键定义: USB OTG 允许设备在 Host 和 Device 之间动态切换,通过 ID 引脚和主机协商协议(HNP)来实现。它兼容 USB 2.0,但并非所有 USB 设备都支持 OTG。
1.2 OTG 的演进路线
技术总是向前走的。USB OTG 从诞生到现在,经历了几个版本。我给你们列个表,这样一目了然。
| 版本 | 发布时间 | 核心变化 | 我的实际感受 |
|---|---|---|---|
| USB OTG 1.0 | 2001 | 定义 ID 引脚、主机协商协议(HNP) | 初次引入,硬件设计复杂,很多芯片不支持 |
| USB OTG 2.0 | 2006 | 增加 A-device、B-device 概念,优化 HNP 流程 | 兼容性好了不少,但功耗控制仍是痛点 |
| USB OTG 3.0 | 2008 | 支持 SuperSpeed,加入无缝切换 | 性能提升明显,但驱动协议复杂度大增 |
简单说,从 OTG 1.0 到 3.0,主要解决三个问题:连接兼容、角色切换、高速支持。你在实际项目中遇到的大部分加载失败,往往卡在第一个版本的定义上——硬件没焊 ID 引脚,或者 ID 引脚电平不对。
1.3 核心硬件结构
USB OTG 在传统 USB 四根线(VBUS、D+、D-、GND)的基础上,特意加了第五根线——ID 引脚。这根引脚干啥用?简单说就是给设备一个“身份牌”。
- ID 引脚接地(低电平):设备默认为 Host(A-device),负责供电和枚举。
- ID 引脚悬空或拉高(高电平):设备默认为 Device(B-device),等待 Host 枚举。
我见过一个坑:有工程师为了省成本,直接把 ID 引脚悬空,结果插上 U 盘后系统识别不出。后来查了半天,发现芯片内部弱上拉,导致 ID 引脚状态不确定。嗯,这地方一定要加硬性的下拉或上拉电阻,不能用软件配置糊弄。
除了 ID 引脚,还有一个非常重要的概念:VBUS 供电能力。OTG Host 必须提供至少 8mA 的 VBUS 电流,而标准 Host 是 100mA 或 500mA。你想想看,如果一个 OTG 设备驱动能力不够,插上功耗大的外设(比如移动硬盘),VBUS 就会跌落,驱动加载直接失败。我在项目中就遇到过这种“驱动加载失败”,调了三天才发现是供电不足。
1.4 角色协商协议(HNP)
HNP 全称 Host Negotiation Protocol,是 OTG 的灵魂。它负责让两个设备在物理连接后,动态决定谁当 Host,谁当 Device。
过程其实不复杂:
- 默认情况下,A-device(ID 引脚接地)先做 Host,提供 VBUS。
- 如果 A-device 觉得没必要继续做 Host,它可以挂起总线的同时,释放 VBUS 使用权。
- B-device 检测到 VBUS 变化,如果它想做 Host,就通过拉低 D+ 或 D- 来发出请求。
- A-device 收到请求,同意切换,两者交换角色。
听起来很顺畅对不对?但实际执行时,时序要求非常严。我调过一家的 OTG 控制器,HNP 切换时如果 D+ 线毛刺过多,芯片会误判成双重角色冲突,驱动直接报错码 -ENOTSUPP。后来我们在 D+/D- 线上加了 22pF 对地电容,问题就消失了。这就是实战。
避坑指南: HNP 过程中,软件层面的“角色切换超时”最常见。我曾经用逻辑分析仪抓到过,某个芯片在释放 VBUS 后,B-device 要等 100ms 才能发起请求,驱动里没加这个延时,一切换就崩。记得加 msleep(100)。
1.5 驱动加载失败的常见宏观原因
在深入每个代码细节前,我们先从整体上看看为什么 OTG 驱动加载会失败。这部分是理论框架,后面几章会逐一深挖。
- 硬件层面: ID 引脚没有正确连接或电平错误;VBUS 供电不足;D+/D- 线阻抗不匹配。
- 软件层面: OTG 驱动没有注册 HNP 回调;角色状态机未初始化;时钟或电源管理未正确配置。
- 协议层面: HNP 时序超时;不支持 SRP(会话请求协议);控制器硬件版本与驱动不匹配。
你仔细看就会发现,很多失败其实都围绕着一个核心:ID 引脚的状态。我见过最离谱的案例是,客户的原理图上 ID 引脚标了上拉,实际上 BOM 里电阻没焊,导致设备永远觉得自己是 Host,插到电脑上电脑就报“无法识别的USB设备”。
1.6 知识体系总览
为了让你对本章有个全局印象,我画了一张结构图。它展示了 USB OTG 的整体知识脉络:从物理层到协议层再到应用层,每层的关键要素。
这张图里,物理层、协议层、驱动层、应用层层层递进。大部分驱动加载失败都发生在驱动层和协议层的接口上。比如驱动没注册 HNP 回调,或者 HNP 中断处理不正确。理解了这个架构,再看后面的代码分析,心里就有谱了。
1.7 本章小结
USB OTG 说穿了就是一句话:让设备身兼两职,通过一根 ID 引脚和一套协议来切换身份。但在实际落地时,硬件设计、软件状态机、协议时序任何一个环节疏忽,都会导致驱动加载失败。
我个人习惯在项目初期先确认两件事:一是 ID 引脚电平是否在预期范围,二是 VBUS 供电能否驱动目标外设。这两点对了,至少一半的坑就避开了。