3. 设备枚举失败分析:复位与速度检测

枚举失败,是USB调试里最常见的坑。我见过不少工程师,拿着示波器一脸茫然——明明D+、D-都有波形,为什么主机就是认不出设备?

说白了,枚举的第一步就是复位和速度检测。这一步要是没过,后面全是白搭。咱们今天就把这块掰开揉碎了讲清楚。

3.1 复位信号与速度检测波形

主机检测到设备插入后,会先做一件事:拉低D+和D-至少10ms。这就是复位信号(Reset)。

复位结束后,主机开始检测速度。怎么检测?看终端电阻的位置:

  • 全速(FS)设备:D+线上有1.5kΩ上拉电阻
  • 低速(LS)设备:D-线上有1.5kΩ上拉电阻
  • 高速(HS)设备:先以FS模式启动,再通过Chirp握手切换到高速

我建议你用示波器抓一下复位后的D+、D-波形。正常情况应该是:复位结束后,D+或D-被拉高,主机检测到电平变化,就知道设备速度了。

关键波形特征:

  • 复位:D+和D-同时为低,持续≥10ms
  • FS设备:复位结束后D+被拉高(约3.3V)
  • LS设备:复位结束后D-被拉高(约3.3V)
  • HS设备:复位结束后D+先拉高(FS模式),然后主机发送Chirp K信号

我在项目中遇到过一个问题:设备插上后,主机偶尔能识别,偶尔不行。抓波形发现,复位时间只有8ms,刚好卡在临界值上。后来把复位时间改到12ms,问题就解决了。嗯,这里要注意——有些主机的时序要求比规范更严格。

3.2 速度检测失败常见原因

速度检测失败,通常逃不出这几个原因:

故障现象 可能原因 排查方法
复位后D+无上拉 终端电阻虚焊、电阻值错误 万用表测量D+对地电阻
D+上拉电压偏低 上拉电阻供电不足、PCB走线过长 示波器测量上拉电压幅值
HS设备无法握手 Chirp信号时序异常、PHY未正确初始化 抓取Chirp K/J序列波形
主机反复复位 设备响应超时、VBUS电压跌落 检查VBUS电容、电源纹波

你想想看,如果D+上拉电阻没焊好,主机复位后根本看不到电平变化,那它就会认为总线上没有设备。我曾经排查过一个案子,折腾了两天,最后发现是1.5kΩ电阻被贴成了15kΩ——颜色环看走眼了。

注意:HS设备的Chirp握手必须在复位结束后100μs内开始。如果设备响应慢了,主机会认为它是FS设备,直接跳过高速模式。

3.3 获取描述符阶段常见错误

速度检测通过后,主机开始获取设备描述符。这一步最容易出问题的是Stall和CRC错误。

3.3.1 Stall错误

Stall,说白了就是设备对主机说“我不支持这个请求”。但很多时候,Stall是因为设备固件没处理好。

  • 设备描述符请求(0x80 0x06 0x00 0x01):如果设备返回Stall,说明USB外设根本没初始化
  • 配置描述符请求(0x80 0x06 0x00 0x02):Stall通常是因为描述符长度填错了
  • 字符串描述符请求:Stall可能是因为语言ID不支持

我建议你在固件里加个调试打印,把主机发来的Setup包内容都打出来。这样一眼就能看出是哪个请求出了问题。

小技巧:用USB分析仪抓包时,注意看Stall包的PID。如果设备连续Stall三次,主机会认为设备不可用,直接断开连接。

3.3.2 CRC错误

CRC错误,说明数据在传输过程中被破坏了。原因通常是:

  1. 时钟抖动:晶振精度不够,导致位采样出错
  2. 信号完整性:PCB走线过长、阻抗不匹配
  3. 电源噪声:VBUS纹波太大,影响收发器工作

我记得有一次,客户反馈设备偶尔枚举失败。抓包发现CRC错误率高达5%。最后定位到是D+走线绕了个大圈,长度超过30cm。改板后把走线控制在15cm以内,CRC错误就消失了。

3.4 地址分配失败原因排查

主机获取描述符后,会发Set Address请求给设备分配地址。这一步失败,通常是因为:

错误类型 典型现象 根因分析
设备无响应 主机发Set Address后收不到ACK 设备未正确解析Setup包、地址寄存器未更新
地址冲突 主机分配地址后,设备用新地址通信失败 设备固件未切换地址、PHY未重新配置
超时重试 主机反复发Set Address 设备响应延迟、USB时钟不稳定

这里有个容易忽略的点:Set Address请求成功后,设备必须在2ms内切换到新地址。如果固件里处理得太慢,主机会认为设备没响应,重新复位总线。

我曾经踩过这个坑——固件里在Set Address处理函数中加了个延时,结果超时了。去掉延时后,地址分配就正常了。

3.5 枚举失败排查流程图

下面这张图,是我自己总结的枚举失败排查流程。每次遇到枚举问题,我都会按这个思路走一遍。

USB设备枚举失败排查流程图 USB设备枚举失败排查流程图 设备插入 步骤1:检测复位信号 D+、D-同时为低≥10ms? 步骤2:速度检测 D+或D-被拉高? 步骤3:获取描述符 是否返回Stall或CRC错误? 步骤4:地址分配 Set Address是否成功? 枚举成功 检查VBUS、终端电阻 复位时间是否≥10ms 检查上拉电阻、PHY配置 HS设备Chirp时序 检查描述符长度、内容 CRC错误查时钟/走线 检查固件地址切换逻辑 2ms超时限制 排查要点 1. 示波器抓取D+、D-波形,确认复位和速度检测是否正常 2. USB分析仪抓包,定位Stall或CRC错误的具体阶段 3. 检查固件中描述符内容、地址切换逻辑、超时处理

3.6 实战排查建议

最后,我分享几个实战中总结的排查建议:

我的排查工具箱:

  • 示波器:抓D+、D-波形,看复位、速度检测、Chirp握手
  • USB分析仪:抓协议包,看Stall、CRC错误、地址分配
  • 万用表:测量终端电阻、VBUS电压、上拉电阻供电
  • 调试串口:打印固件中USB中断、Setup包内容

我个人习惯,遇到枚举问题先抓波形。波形能告诉你80%的问题——是复位没到位,还是速度检测失败,还是Chirp握手没完成。剩下的20%,再用分析仪和调试串口去定位。

记住一句话:枚举失败,90%是硬件问题,10%是固件问题。先查硬件,再查固件,别搞反了。