ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

从BSP视角看USB调试:T527平台枚举失败与VBUS电源排查实战

从BSP视角看USB调试:T527平台枚举失败与VBUS电源排查实战 写BSP调试这个系列写到第13篇今天终于轮到了USB。说实话在我手头的全志T527板子上USB是让我加班最狠、也最能练基本功的模块——插个U盘能跑大家都觉得理所当然一旦插上不识别、识别了掉线、或者只能跑USB 1.1速度问题可能藏在设备树配置、PHY校准参数、VBUS电源纹波、甚至一根线缆的阻抗里。这篇就基于T527平台把我在USB调试过程中用过的方法、踩过的坑、以及沉淀下来的排查思路完整过一遍适合正在做BSP的兄弟参考也适合刚入行想搞懂USB底层到底怎么回事的朋友读一读。这里先说明一下前提不同方案商拿T527做的板卡USB口数量、接口形态和引脚分配会有差异我这里拿的是常见工控板布局——一路USB0做Type-C DRD支持OTG一路USB2.0 Host一路USB3.0 Host。设备树节点、控制器名称以你实际拿到的BSP包为准但排查思路和方法论是通用的。这篇不打算写成一册USB协议科普重点放在“真出了问题怎么下手”毕竟BSP调试永远是问题驱动的。1. 先把T527上的USB家底盘点清楚1.1 硬件接口与控制器分配T527这颗芯片在做工控和车机方案时很常见USB部分一般会引出三路独立接口典型接法如下表所示。别看都是USB它们的角色、速率和调试关注点其实完全不同一开始就把家底摸清楚后面能省大量时间。接口形态速率典型角色调试关注点USB0Type-CUSB 2.0 OTG / DRD烧录、ADB、U盘兼用角色切换、CC逻辑、VBUS检测USB1USB-AUSB 2.0 High-Speed键鼠、U盘、低速外设枚举稳定性、供电能力USB2USB-AUSB 3.0 Gen1高速存储、USB网卡、采集设备信号完整性、SuperSpeed协商很多板卡上的USB3.0口为了扩展更多下游设备会先在板内接一颗USB 3.0 HUB芯片再引出多个USB-A口。这种情况下调试时还要额外关心HUB的复位时序、电源管理和过流保护。我一直跟硬件同事强调一句话BSP工程师拿到板子第一件事不是看代码而是对着原理图把每个USB口的供电来源、CC/ID引脚连接方式、ESD保护器件位置全部确认一遍。别等到插上设备跑不起来才开始怀疑是驱动写错了。1.2 内核与设备树里的USB框架在Linux内核里USB协议栈自下而上大致是PHY层负责电气信号→ 控制器驱动DWC3/XHCI→ USB Core枚举、设备管理→ 各种Class驱动存储、HID、CDC等。全志平台把USB控制器和PHY的配置都放在设备树里T527这一代基本走标准DTS不再像早期方案那样依赖sys_config.fex。下面是一段简化后的设备树节点示意属性名以你拿到的BSP源码为准usb0 { dr_mode otg; phys usb2phy0 0; phy-names usb2-phy; vbus-supply reg_usb0_vbus; usb-role-switch; status okay; }; usb2 { dr_mode host; phys usb3phy0; phy-names usb3-phy; vbus-supply reg_usb2_vbus; status okay; };看到这个结构很多新手容易忽略两个东西。第一是phys属性它决定了控制器绑定到哪一颗PHY如果这里和实际硬件接法对不上典型现象就是“设备能识别到控制器但插上U盘后完全没有枚举动作”。第二是vbus-supply它对应控制VBUS输出的稳压器节点。全志平台通常在PMIC或外部DC-DC上接一个GPIO控制VBUS的使能如果设备树里没有正确关联或者GPIO默认状态不对就可能出现“量VBUS有5V但插入瞬间被拉垮”之类的电源问题。后面我会用实际案例证明USB调试里一大半的疑难杂症根因都在电源。1.3 调试前先建立基线在动任何代码之前我强烈建议先把当前板子的“正常状态”完整记录一遍。说白了就是建立基线哪些口能识别、识别速度是多少、设备树里显示的是哪个控制器、连接某个外设时dmesg打印长什么样。没有基线出了问题你连“现在和之前哪里不一样”都不知道。我的基线检查清单一般是这几条启动后执行dmesg | grep -i usb看控制器注册是否成功有没有“failed to initialize”字样。执行lsusb和lsusb -t确认总线拓扑和已连接设备。插入一个已知没问题的U盘观察dmesg里枚举过程是否完整记录下“new high-speed USB device number x”这一行的设备编号规律。对USB3.0口用lsusb -t确认设备是接在“5000M”还是“480M”速率上这能直接告诉你SuperSpeed链路是否协商成功。跑一遍文件读写验证数据传输稳定用dd if/dev/sda of/dev/null bs1M count100看速度是否符合该接口预期。这一套流程走完正常板子的“画像”就出来了。后面所有异常排查本质上都是拿异常现象和这个基线做对比。别嫌麻烦我见过很多同事一上来就改驱动、调设备树结果折腾半天发现是某个U盘本身兼容性问题浪费时间不说还容易把问题越改越乱。2. 从日志、节点到抓包USB调试三板斧2.1 dmesg里那些错误码到底什么意思USB枚举过程中一旦出错内核会通过dmesg往外抛信息。最常见的几种错误码我直接整理成一张速查表排查时对照着看非常方便错误码含义典型诱因-71EPROTO 协议错误设备返回了无法解析的数据D/D-信号质量差、干扰大-110ETIMEDOUT 超时设备对控制传输没有响应常伴随设备瞬间掉电-84EILSEQ 字节序列错误数据CRC校验失败物理链路损耗过大-62ETIME 定时器超时比较少用通常也指向设备侧无响应-32EPIPE 端点停止设备端主动STALL命令不支持或异常看到usb 2-1: device descriptor read/64, error -71这种日志很多新手会直接慌。我的经验是先别急着查USB协议先去量一下设备插入瞬间VBUS电压有没有跌落再用手摸一下接插件是否松动最后才考虑信号完整性问题。原因很简单——如果VBUS在枚举过程中出现几百毫秒的欠压设备会瞬间掉电重启主机这一侧看到的就是“读到一半设备没响应了”然后报一个超时或协议错误。换句话说错误码只是结果不是原因。还有一个高频日志是reset high-speed USB device number x using xhci-hcd如果这句话反复出现说明链路建立了但不太稳设备在运行过程中频繁复位。这种情况优先怀疑电源波动、线缆过长、或者设备自身功耗过大导致热插拔瞬间供电不足。日志里如果能捕捉到Cannot enable. Maybe the USB cable is bad?这类提示那基本就是物理层问题了。2.2 用lsusb和设备节点读懂设备状态lsusb是每个搞USB的人都应该用熟的工具。基础用法大家都知道我补充几个容易被忽略的lsusb -t输出的是总线拓扑能直接看到每个接口的速率。比如下面这行5000M表示设备已经协商到了SuperSpeed速率480M则是USB2.0 High-Speed/: Bus 02.Port 1: Dev 1, Classhub, Driverxhci-hcd/4p, 5000M |__ Port 2: Dev 2, If 0, ClassMass Storage, Driverusb-storage, 5000Mlsusb -v会打印非常详细的描述符信息包括设备厂商、产品、序列号、端点配置等。注意这个命令要求root权限。在BSP调试时我经常用lsusb -v对比“正常设备”和“异常设备”的描述符差异。比如某些杂牌U盘在设备描述符里的bcdUSB字段写得不对主机就可能拒绝识别这时候日志和抓包里看不出问题但描述符对比一眼就能发现蹊跷。另外/sys/bus/usb/devices/目录下每个设备都有一个子目录里面藏着大量运行期状态信息。idVendor、idProduct、speed、bConfigurationValue这些文件都能直接cat出来。我遇到过一种情况设备在系统里偶尔“消失”查dmesg没打印lsusb也看不到但/sys/bus/usb/devices/下设备目录还在——这说明设备在主机侧还没被移除但物理连接已经断了。这种“半死”状态其实很有价值至少能帮你区分是硬件断连还是软件逻辑把它踢掉了。2.3 usbmon抓包给USB总线装个探针如果说网络调试用tcpdump抓包是基本功那USB调试的对应工具就是usbmon。usbmon是内核提供的USB总线抓包机制可以把主机和设备之间传输的URBUSB Request Block全部记录下来然后用Wireshark分析。我愿称之为“给USB总线装了一根逻辑探针”。启用方法很简单# 挂载debugfs mount -t debugfs none /sys/kernel/debug # 加载usbmon模块 modprobe usbmon # 查看可用总线号 ls /sys/kernel/debug/usb/usbmon # 抓取总线1的流量并保存 tcpdump -i usbmon1 -w usb.pcap抓完的pcap文件直接拖到Wireshark里打开能看到完整的枚举流程主机发送GET_DESCRIPTOR、设备返回设备描述符、主机再发送SET_ADDRESS、后续继续读取配置描述符……一个典型的USB设备枚举大概会经历20多个URB交互。如果某个请求超时或返回错误对照Wireshark里标红的部分就能精确定位到哪一步出了问题。有一件事必须提醒usbmon抓的是“协议逻辑层面”的数据它只能证明“数据包有没有正确交互”不能反映“电信号质量怎么样”。比如D信号上升沿太缓导致误码usbmon里完全看不出来只能看到CRC错误或者设备无响应。所以usbmon和示波器是互补关系不是替代关系。我在实际调试中线上有同事用USB转串口线看log以为这也是“抓USB包”——不是一回事那只是把console输出送到串口而已千万别混。2.4 示波器与协议分析仪物理层绕不开到了这一步如果usbmon抓包显示协议交互正常但设备还是枚举失败那就是物理层问题了。USB2.0高速信号和USB3.0超高速信号对信号完整性要求都很高这时必须上示波器。对USB2.0重点看三样东西VBUS电压插入瞬间跌落幅度是否超过5%USB规范要求4.75V-5.25V跌落恢复时间是否过长。D/D-差分波形检查高速握手过程中的Chirp K、Chirp J序列是否清晰眼图是否满足模板要求。ESD保护器件很多板子为了过EMC测试在D/D-上挂了TVS管。TVS管结电容如果太大超过3pF高速信号会被严重劣化表现为设备时好时坏。对USB3.0还需要关注SuperSpeed差分对的交流耦合电容标准是0.1uF是否放置正确以及信号路径上有没有重定时器/Redriver芯片它们的配置寄存器有没有正确初始化。USB3.0跑不起来或者速率不稳很大概率出在高速信号路径上而不是软件逻辑。如果公司有USB协议分析仪比如Teledyne LeCroy的Voyager系列那调试体验会好很多它能同时抓逻辑层和物理层还能做电源纹波分析。但这种设备不是每个小团队都有我的建议是没有分析仪也能干活usbmon 示波器 万用表三件套已经能解决95%的问题。3. 一次USB 3.0枚举不稳的完整排查3.1 故障现象与初步判断下面用我第一次在T527上调USB3.0口时遇到的实际问题完整走一遍排查流程这个案例基本覆盖了“日志-抓包-硬件”三个层面的方法。故障现象USB3.0口接一个移动固态硬盘冷启动后插入10次里有3到4次完全无反应如果插入后等几秒再拔出重插大概率又能正常识别。正常识别后跑大文件拷贝偶尔会中断dmesg里出现反复的reset high-speed USB device number 9 using xhci-hcd。同一块移动硬盘插到PC上反复插拔几百次都稳定。初步判断这个现象有两个关键特征。第一是“概率性失败”如果问题出在软件逻辑或者设备树配置通常是100%稳定失败不会时好时坏。第二是“插入后等待片刻再重插能好”这往往说明第一次插入时供电或信号建立过程不稳定设备没能完成初始枚举而重插时有些条件已经改变了。所以我的第一直觉就是不是驱动问题优先怀疑电源和物理连接质量。3.2 日志、抓包、波形三步锁定根因第一步看dmesg。失败时的日志反复出现device descriptor read/64, error -71和unable to enumerate USB device。-71是EPROTO说明主机确实收到了设备的响应但响应数据解析失败或者设备响应到一半就断了。第二步用usbmon抓包。在失败场景下抓到的数据包里主机发起了GET_DESCRIPTOR请求但设备侧没有返回完整的设备描述符交互在数据阶段就中断了。这就把问题范围缩小到“设备在枚举初期就异常掉线或者信号严重劣化”。第三步上示波器重点测VBUS和D/D-。结果发现了两个问题一是移动硬盘插入瞬间VBUS电压从5.02V跌到4.31V持续了大约几十毫秒才恢复这个跌落幅度已经超过了USB规范允许的范围二是D/D-波形上叠加了明显的噪声眼图边界已经碰触到模板边缘余量很小。VBUS跌落解释了为什么设备在枚举时突然掉电——设备控制器在读到一半时因欠压复位主机看到的自然就是EPROTO。而D/D-信号余量不足则解释了为什么偶尔能识别成功后传输也不稳定。继续深挖VBUS跌落的原因。把原理图翻出来一看这个USB3.0口的VBUS是从一颗PMIC内置LDO直接拉出来的LDO的输出能力本身就不高而且板子在外围只放了两颗10uF的陶瓷电容作为储能。移动硬盘启动瞬间电流可以达到1A以上LDO扛不住这个冲击输出电压就被拉垮了。对比PC端为什么会稳定PC的USB口供电来自开关电源并且USB口附近通常有大量储能电容瞬态响应能力完全不是一个级别。3.3 改硬件还是改软件这次我改了板子问题定位清楚后软件上其实没有什么可改的。设备树里vbus-supply虽然关联到了那颗LDO但软件再怎么能耐也改变不了物理电源的带载能力。唯一的正确解法是改硬件。具体改法把VBUS供电从PMIC的LDO切换到外部DC-DC降压电路并在USB3.0接口附近补齐储能电容至少4颗22uF如果是电解电容就选低ESR的。改完之后重新上电测试插入瞬间VBUS跌落控制在0.1V以内D/D-波形余量也明显提升移动硬盘连续插拔100次不再出现失败大文件拷贝中断问题随之消失。这个案例给我最大的教训是BSP调试时软件工程师往往第一个怀疑自己写的设备树和驱动但USB这类涉及高速信号和功率输出的接口硬件设计缺陷导致的故障率非常高。排查顺序千万不能先软件后硬件而应该是“先确认电源、再确认信号、最后才动代码”。我后来凡是接到“USB不稳”的bug单第一句话永远是让硬件同事先量一下插入瞬间的VBUS波形这招十次有八次能直接命中问题。4. 常见问题速查表与避坑要点4.1 八类高频问题的诊断方向在T527上折腾USB这么久我把遇到过并整理过的常见问题汇总成一张速查表每类问题都附上优先排查方向。这张表同样适用于大部分Linux平台建议收藏。症状优先排查方向解决思路插U盘完全无反应VBUS有无输出过流保护是否触发控制器有没有注册成功检查vbus-supply、GPIO状态、控制器dmesg枚举反复失败dmesg报-71/-110插入瞬间VBUS跌落D/D-信号质量接插件松动测量电源瞬态检查TVS/共模电感选型加固插座只能识别为USB1.1全速D上拉检测异常设备不支持高速PHY配置有误查chirp握手过程检查PHY驱动是否加载USB3.0设备降级成USB2.0SuperSpeed差分对阻抗不连续交流耦合电容缺失Redriver未初始化量差分波形检查0.1uF耦合电容配置重定时器OTG/DRD角色切换异常Type-C CC逻辑、usb-role-switch配置检查CC引脚状态换支持CC的线缆核对dts的role-switch节点特定U盘不识别其余正常设备描述符不规范兼容性问题用usb-storage.quirks添加兼容参数设备休眠唤醒后掉线USB autosuspend导致设备断电禁用autosuspend或调整电源管理策略拷贝大文件时中断电源供电能力不足线缆压降大设备过热测VBUS带载波形换短线粗线改善散热4.2 几个值得单独说的坑第一个坑是usb-storage.quirks。有些U盘的主控对标准协议支持得不够好主机识别它就是不稳定但U盘在Windows上却一切正常。这种问题不用改内核可以直接给usb-storage驱动传兼容参数。比如某U盘的VID是1234、PID是5678想跳过它的自动识别逻辑可以在内核启动参数里加usb-storage.quirks1234:5678:kk代表Quirks里的IGNORE_RESIDUE意思是“忽略传输剩余字节数”。不同厂商出问题的地方不一样u不要自动挂载、m最大扇区数限制等标记含义不一样具体可以去内核文档Documentation/admin-guide/kernel-parameters.txt里查usb-storage.quirks的说明。BSP开发时这个参数是兼容性问题的利器不用改一行代码就能让原本不认的U盘跑起来。第二个坑是USB autosuspend。默认配置下系统在USB设备空闲一段时间后会把设备切到挂起状态。这在PC上很节能但在嵌入式工控板上经常惹麻烦——设备确实空闲了但外部硬件可能没按规范处理挂起/唤醒信号导致设备直接掉线而且唤醒不回来。如果你发现设备长时间不操作后再访问就找不到盘符了多半就是它。最快的验证方法是临时关掉autosuspendecho on /sys/bus/usb/devices/2-1/power/control如果验证有效再决定是写个systemd服务统一设置还是在内核启动参数里加usbcore.autosuspend-1直接全局禁用。对于工控场景我倾向直接禁用省电收益远小于设备掉线造成的损失。第三个坑是HUB级联后的过流保护。很多T527板卡会在USB3.0口后面接一颗HUB芯片扩展出4个口HUB每个端口都有自己的过流检测引脚。如果你发现某个扩展出来的口一插入大功率设备就“噗”一下整个HUB掉线先查过流检测电阻和限流开关的设置别一上来就怀疑HUB驱动。另外注意HUB的复位引脚要用RC延时电路接好不能直接和主芯片复位连在一起否则主芯片复位期间HUB上电时序不对就会出现开机时HUB枚举失败重启一次又正常这种恼人的问题。4.3 兼容性测试治“玄学问题”的标准姿势USB兼容性问题最让人头疼的地方在于“没有规律”。同型号U盘这个批次有问题下个批次又好了同一个设备在这块板子上有问题在另一块板子上完全正常。面对这种问题抱怨没有用最有效的做法是把测试变成量化的流程。我给自己定的规矩是每次硬件改版后都要拿一套固定的外设组合完整跑一遍兼容性测试。这套组合包括至少3个不同主控方案的U盘、1个USB3.0移动硬盘、1个USB有线网卡、1个蓝牙适配器、1个USB键盘鼠标套装、1个USB转串口调试线。测试时记录每个设备在不同端口上的枚举结果、速率、读写稳定性整理成一张表。任何一轮改版后这张表和上一轮有差异就说明改动引入了回归无论差异看起来多轻微都不能轻易放过。这个方法听起来很笨但实际效果极好。因为USB兼容性问题往往是多种因素叠加的结果没有一张覆盖全部外设的测试表你根本无法判断某个改动到底是修好了一个问题还是引入了新的问题。我把这套测试表和测试记录放到公司的共享文档里硬件同事改版之后也会主动跑一遍省掉了大量“你来帮我看看为什么又不识别了”的来回扯皮。5. 给BSP新手的USB调试工具箱5.1 软件与硬件工具清单调试USB工具不在多在于每一件都要发挥价值。我平时最常用的工具清单如下按“必备”和“进阶”分个层软件工具dmesg、lsusb、lsusb -t、lsusb -v基础三件套看状态和拓扑。usbmon tcpdump Wireshark免费、轻量、信息量最大的逻辑分析组合。usbview图形化查看USB拓扑读起来比命令行直观。USBlyzerWindows平台Windows下的USB协议分析软件方便对比PC和板卡行为差异。硬件工具一台带宽1GHz以上的示波器配无源探头和差分探头。一台电流表或USB电流电压测试表用于观察设备实际功耗和VBUS稳定性。一套质量可靠的USB延长线、转接头用来排除线缆本身的问题。有条件的话一台USB协议分析仪逻辑物理一把抓。这里想多说一句很多新手看到USB抓包第一反应是去找那种“USB串口调试助手”。你要搞清楚USB转TTL、USB转串口线是用来连console口的不是用来抓USB总线数据的。USB总线是差分对协议串口是异步单端协议两者完全不是一个东西。买一堆USB转串口模块不如先把usbmon吃透。5.2 我自己沉淀的调试顺序最后把我这次T527 USB调试中稳定下来的工作流写出来照着走至少不会在方向上跑偏。第一步确认“能不能识别”。看dmesg看lsusb看设备节点是否创建。这一步如果失败进入第二步如果成功直接跳到第四步验证稳定性。第二步区分“软件问题还是硬件问题”。用usbmon在主机侧抓包看枚举交互在哪一步中断。如果包交互正常但设备没起来重点查信号完整性如果包交互本身就出错再进一步查设备树、驱动配置和电源。第三步物理层验证。测VBUS瞬态响应测D/D-波形测USB3.0差分对信号质量。这一步最好和硬件工程师一起做因为很多时候结论直接指向改板。第四步功能与稳定性回归。枚举稳定不代表数据链路稳定做dd读写、长时间压力拷贝、反复热插拔测试。这个过程里如果出现reset日志通常是电源余量不足不是协议问题。第五步兼容性测试。把手头所有外设挨个插一遍记录每个设备的枚举和传输状态。出现个别设备异常时先用usb-storage.quirks这类手段快速绕过问题积累多了再统一分析。这套流程不会让问题“自动消失”但能保证你每一步都有据可查改了什么、验证了什么、结论是什么都清清楚楚。USB调试最忌讳的就是“东改一下西试一下”最后连自己都不知道哪一步起效了。再分享一个习惯我会在板子上留一个USB转串口调试脚单独引出一路console用来随时看内核日志。调试USB协议问题的时候用独立的console口输出日志避免串口工具本身抢占USB资源造成二次干扰。很多兄弟图省事用同一个口一边挂console一边插U盘结果日志刷屏时U盘就掉线了自己还以为是USB控制器不稳定——这种低级干扰排查起来最浪费时间。关于T527这颗芯片的USB调试这次就分享到这里。我自己的体会是USB在整个BSP体系里是个“麻雀虽小五脏俱全”的模块它同时涉及电源、时钟、信号完整性、协议栈、设备模型和驱动框架能把USB调得明明白白其他很多模块的调试思路都会一通百通。后面如果继续在这块板子上做文章我打算把USB gadget方向整理出来特别是UVC和RNDIS的调试记录。继续调板子去了。
返回列表