ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

全志T527平台USB BSP调试实战:枚举、抓包与OTG排查指南

全志T527平台USB BSP调试实战:枚举、抓包与OTG排查指南 做BSP调试这个系列我在全志T527平台上已经写了十几期这期主题是USB。老实说调USB比调网口、串口都让人头大——它不是单一层面的问题网口调不通查PHY、查MDIO、查链路基本就能收敛USB一个“枚举失败”背后可能同时藏着电源、信号完整性、PHY时钟、驱动时序、协议栈、设备端固件六七个方向的账哪一环都能让现象一模一样。我这段时间在T527板子上把USB Host、OTG、USB转串口三条线都跑了一遍踩了不少坑也沉淀出一套相对固定的排查套路。这篇文章就把过程原原本本写出来适合正在做T527或其他全志系平台BSP/驱动开发的兄弟参考刚入门的朋友也可以按我写的命令一步步复现很多排查步骤在别的SoC上同样适用。1. T527上的USB资源盘点这期的战场长什么样1.1 先理清板子上每个USB口归谁管拿到一块T527的板子第一件事绝对是对着原理图把USB口画个清单。全志T527这颗平台的USB控制器数量不算少有些口支持USB 2.0有些带USB 3.0能力其中一个口通常还支持OTG。但“SoC支持几个”不等于“板子上几个都好用”做底板的硬件工程师往往只引出一部分或者把某个OTG口强制当成Host用。我这次调试的工控底板实际分配大概是这样端口工作模式实际用途调试中最高频的问题USB0OTG/Device烧录、ADB、U盘扩展角色切换识别不到ID脚与VBUS检测闹脾气USB1Host外接U盘、4G模组、键盘VBUS供电时序不对导致枚举失败USB2HostUSB转串口、调试工具驱动匹配不上、设备节点消失注意具体板子的端口编号和模式一定会有差异必须以自己手上的原理图和设备树为准。全志Linux内核的设备树里USB控制器节点一般比较好找主要看这几个属性status是否打开、dr_mode是host还是peripheral还是otg、vbus-supply指向哪个regulator。我第一次拿到这块板时没看原理图就开调结果在一路本来就被硬件强制为Device模式的口上查了半天Host枚举问题纯属浪费生命。先把资源归属摸清楚后面排错才不会张冠李戴。1.2 为什么USB的BSP问题很难“一锤子定位”USB的协议栈分层非常多物理层有D/D-差分信号、上拉/下拉电阻、信号眼图链路层有包结构、CRC校验、握手响应事务层有控制、批量、中断、等时四种传输类型再往上还有各种类协议比如MSC、CDC、HID。BSP调试过程中任何一个报错都可能是上面某一层出了问题但症状往往是同一个——设备不被识别。打个比方USB枚举就像两个人第一次见面握手。A伸出手Host发送复位信号B要回握设备响应SETUP包。如果B根本没听到、听错了、或者回握的力度不对A的判断都是“这人没理我”。但问题是你完全不知道是B耳朵不好、手没力气还是两个人隔得太远。所以排查不能从一个点硬钻而是要从物理层、电源时序、协议层、驱动代码一层层做隔离。这期文章最核心想传递的思路就是USB的BSP调试本质上是分层隔离的排查。2. U盘枚举失败从PHY供电到控制传输的完整排错链条先讲一个我在T527板子上实际反复出现的问题U盘插Host口不识别。这类问题在BSP调试中出现频率极高我把它完整拆开从现象到根因一步步还原这套思路大家可以直接套用。2.1 现象记录插上去“毫无反应”Linux启动完成后插入U盘正常预期下dmesg会输出类似下面的日志usb 1-1: new high-speed USB device number 3 using xxx usb 1-1: New USB device found, idVendorxxxx, idProductxxxx usb 1-1: New USB device strings: Mfr1, Product2, SerialNumber3 usb-storage 1-1:1.0: USB Mass Storage device detected但当时我看到的是日志完全不动连hub端口变化的消息都没有就好像物理上根本没插过一样。我的第一反应不能乱来。先用肉眼观察硬件层面的动静发现U盘指示灯没亮。这初步说明VBUS可能没供上或者供电能力严重不足。但也别急着下结论有的U盘没有灯有的U盘灯要等控制器初始化之后才亮。所以还得按链路一层层确认。2.2 第一层确认连接事件到底有没有传到Hub插入U盘那一刻设备端的D上拉电阻会把D拉高Host侧的hub通过检测这个电平变化感知到“有设备插入”。如果hub连这个事件都没有收到问题基本就定位在物理层或hub本身。怎么确认我习惯用两个手段第一是dmesg过滤hub相关日志第二是看 /sys/bus/usb/devices/ 下有没有新增目录。dmesg | grep -i usb ls /sys/bus/usb/devices/正常插入后 /sys/bus/usb/devices/ 下会多出像 1-1 这样的目录。如果目录完全没出现说明usbcore根本没收到连接事件。这时候就别再去翻usb-storage的驱动代码了方向错了。继续往底层查。2.3 第二层PHY时钟、复位和VBUS供电的“时序账”全志平台的USB控制器都配了独立的USB PHY。PHY正常工作的前提有三个供电正常、时钟正常、复位释放而且三个条件的先后顺序不能乱。当时我检查设备树发现Host口的vbus-supply指向了一个由GPIO控制的regulator这就是关键线索。问题出在时序这个regulator的enable ramp delay配置得太小VBUS电压还在缓慢爬升的时候控制器已经开始采样D/D-电平了设备端根本没进入稳定工作状态第一次握手自然失败。但因为驱动通常有重试机制所以表现出来的症状非常经典——第一次插没反应拔掉重插就识别了。这种“一次成功一次失败”的现象九成跟协议栈无关就是电源和复位的先后顺序没写对。我当时的处理办法是在设备树里把vbus regulator的regulator-enable-ramp-delay调大同时在驱动侧调整初始化顺序保证先复位PHY再拉VBUS等电压稳定之后再去使能连接检测。顺序改对之后问题就不再复现了。提示碰到“第一次识别失败、第二次成功”这种典型症状优先怀疑电源/复位时序别急着改协议栈。2.4 第三层示波器看波形验证物理链路软件时序改好之后我还会用示波器实测一遍关键点确保不是硬件设计本身的坑。重点看三个位置一是VBUS电平插入设备瞬间是否有明显跌落二是D/D-接入时的电平状态设备上拉是否正常、Host侧下拉是否正常三是PHY参考时钟的频率和幅度是否在规格内。实测下来这块底板的D/D-走线偏长高速模式下信号质量不是很好偶尔会冒出一个位错误。这种问题不是纯软件能解决的只能通过调整端接电阻、或者修改PHY驱动里的信号摆幅参数去补偿。这一步极其重要因为很多“枚举失败”的真实原因是眼图不过关跟代码没有半毛钱关系。如果你手上没有示波器至少也用一个逻辑分析仪去抓一下D/D-的电平翻转别全靠猜。2.5 修复验证与一套可复用的排查框架修复后的验证方式不能是“插一次能识别”就完事。我通常做压力测试反复插拔50次换不同厂商的U盘轮换测再通过Hub下挂设备去测拓扑扩展场景确认枚举仍然稳定。这套压力测试在T527板子上帮我筛出了另外两个U盘的兼容性问题。把这次排查的框架总结一下顺序非常重要不能跳先确认连接事件是否到达hub层再检查PHY供电、时钟和复位时序然后用示波器验证物理信号最后才轮到协议栈和驱动代码。很多人一上来就装抓包工具、翻usb-storage代码方向错了越查越糊涂。我踩过这种坑所以现在习惯把“分层隔离”四个字贴在工位上。3. 抓包说话USB分析仪如何帮我锁定GET_DESCRIPTOR死穴有些USB问题靠dmesg和示波器是定位不了的。比如物理连接正常、hub也检测到了设备但设备就是枚举失败。这种时候USB协议分析仪就该上场了把总线上真实的包数据还原出来比对着代码猜靠谱一百倍。3.1 什么时候必须上分析仪我的判断标准很直接只要涉及“设备到底有没有响应”这类协议层疑问靠猜是浪费时间直接抓包。典型场景有三个设备端固件是自己写的枚举到某一步就没下文怀疑Host发出的请求本身有问题比如描述符请求长度不对或者设备返回的端点配置和驱动预期不一致。抓包工具的选择上有条件就上台式协议分析仪这类设备能完整记录每一笔事务和时序。没有的话支持USB解码的逻辑分析仪也能应付大部分场景。还有一种省钱玩法在Host和被测设备之间串一个监控用Hub配合总线监控工具抓包。抓包不是为了炫技而是为了把总线上真实发生的事情原原本本还原出来。3.2 一次枚举失败抓包实录有一次我在T527上调试一个自研外设现象是设备在系统里显示为“unknown device”dmesg能看到插入事件但紧接着报错“device descriptor read/64, error -71”。我把分析仪串在Host和设备之间抓到的过程整理成了下面这个表格顺序总线动作抓包结果说明1总线复位正常完成Host拉低总线并释放2GET_DESCRIPTOR请求Host发出设备描述符请求请求长度64字节3设备响应阶段总线上无ACK无数据返回设备端没有回应4Host超时重试重试两次均失败最终枚举中止先补一下标准枚举流程很多刚接触USB的读者需要这张对照表Host检测到设备插入D被上拉Host发送总线复位信号Host发GET_DESCRIPTOR请求设备返回描述符此时通常只回前8字节或完整18字节Host发SET_ADDRESS为设备分配唯一地址Host重新GET_DESCRIPTOR取完整设备描述符Host读取配置描述符和端点信息Host根据接口类型加载对应class驱动。抓包显示失败点在第3步到第4步之间GET_DESCRIPTOR发出去之后总线上始终没有来自设备的响应。也就是说Host在等设备回包但设备端要么没收到要么收到了却没能形成合法的ACK。结合设备固件代码分析真正原因是它的USB控制器在收到复位中断后还没完成内部状态初始化就开始响应请求时序上没来得及。3.3 把抓包和内核日志对应起来抓包的价值不只在分析仪屏幕上的波形它给出的时间戳和包序号可以和Host端dmesg里的报错逐条对应。上面那个error -71在内核里的含义是协议传输层错误对应的是数据传输阶段STALL或超时。配合抓包看到的“设备未响应”基本可以确认问题出在设备端固件的状态机而不是T527这边的驱动。我还在T527上遇到过一个更刁钻的情况同一个设备在PC上能正常枚举在T527的Host口上就失败。用分析仪一看才发现设备在收到GET_DESCRIPTOR之后返回的数据包长度和Host请求的长度不匹配严格说设备端固件有合规性问题只是PC端的驱动做了容错。面对这种外部设备BSP侧能做的是在usb core或class驱动层面加容忍逻辑但更靠谱的办法是推动设备端把描述符按规范修好。从这期调试经验看USB抓包应该是BSP工程师的基本功。不需要天天用但遇到协议层疑难杂症时它比翻十个小时代码高效得多。我在T527上把抓包流程跑通之后很多以前需要反复试错的枚举问题现在基本都是十分钟内定位。4. USB转串口通道BSP调试场景里的隐形“生命线”4.1 为什么我说USB转串口是BSP的“生命线”做BSP调试时串口console就是最后的救命稻草。有些板子出于体积和接口成本考虑不引出标准UART调试口只在面板上留一个USB-A座子让用户插USB转串口线进console。这时候USB转串口的稳定性直接决定你能不能继续往下调系统。我甚至会在调USB Host本身的时候故意把USB转串口接到Host口上当“探针”用因为它枚举流程比U盘简单、受供电影响小而且驱动栈非常成熟很适合验证Host控制器本身是否正常。系统起不来、网口没配好、显示没起来的时候只有这条USB转串口通道能让你看到内核到底死在哪里。另外提一句网上关于USB转串口线的型号讨论特别多比如FT231X、CH340、CP2102这些实际用起来最关键的不是芯片品牌而是内核驱动是否覆盖了对应VID/PID。我手里几根线里FT231X的在T527上的稳定度最好长时间跑console不会掉线这个在选择调试线材时可以优先考虑。4.2 内核里该开哪些配置一个都不能少在T527的Linux内核里配置USB转串口支持有几个Kconfig项很容易漏列出来给大家对照CONFIG_USB_SERIALyUSB串口设备的基础框架CONFIG_USB_SERIAL_FTDI_SIOyFTDI芯片支持对应FT232、FT231X这一族CONFIG_USB_SERIAL_PL2303yPL2303系列支持CONFIG_USB_ACMy支持CDC-ACM设备很多免驱的USB转串口芯片走这个类。有一个特别容易踩的坑CH340芯片在主线内核里对应的配置是CONFIG_USB_SERIAL_CH341但很多默认配置没开。如果你拿到一根CH340的线插上后lsusb能看到设备但就是没有串口节点多半就是漏了这个。配完之后插上线应该能在 /dev 下看到ttyUSB0或者ttyACM0具体名字取决于芯片走的是串口类驱动还是ACM类驱动。4.3 lsusb、dmesg、udevadm三步定位驱动问题设备节点不出现时我的排查顺序固定三步。第一步lsusb确认USB层是否识别到设备如果这一步都过不了说明问题在Host口或枚举层回到前面章节的排查框架去查。第二步dmesg过滤usb相关日志看驱动绑定过程是否发生。第三步用udevadm查看设备节点属性lsusb dmesg | grep -i usb udevadm info /sys/bus/usb-serial/devices/ttyUSB0我遇到最高频的问题是USB转串口芯片能被lsusb识别但 /dev/ttyUSB0 就是不存在。原因一般是内核里对应serial驱动没编译进去或者模块没被自动加载。这种情况下先确认CONFIG_USB_SERIAL_*有没有开成y或者m再检查驱动表里是不是缺了这个芯片的VID/PID。有些芯片版本很多VID/PID列表不全时需要手动往驱动里补一条。4.4 波特率乱码和重启丢节点两个高频坑还有两个小问题在T527上特别常见。第一个是console输出乱码。先别怀疑驱动先确认波特率和bootloader是否一致。T527上我常用的Kernel cmdline配置是consolettyS0,1152008N1的默认参数。如果bootloader实际用的是别的波特率或者cmdline里没写对就会出现终端上半个字能读半个字乱码的诡异现象。第二个是设备重启后节点丢失。原因是部分USB转串口芯片枚举速度比较慢systemd的serial-getty服务可能在设备节点出现之前已经启动之后就没能再绑定上。解法是给serial-getty加udev规则或After依赖用延迟启动兜底。这两个坑都不难解决但第一次遇到时确实能卡住很久。5. OTG与Gadget模式切换T527上最绕的几个配置点5.1 先分清T527的OTG角色是怎么决定的OTG口在Linux里一般有三种角色host、peripheral、otg由运行时检测决定。全志平台的实现里dr_mode属性决定基本工作模式otg模式则依赖硬件上的ID引脚和VBUS检测做动态切换。按照我的实际经验如果板子上的ID引脚悬空或者接错OTG工作在otg模式下时会识别不到外部设备切到host方向也一样看不到设备。排查时最快的二分法就是把dr_mode临时改成固定的host或peripheral分头验证。比如你要烧录就先把角色固定成peripheral排查gadget相关配置要插U盘就先固定成host排查Host侧问题。动态切换的问题放到两边都通了之后再去处理。5.2 用configfs把Device侧功能跑起来把OTG口当Device用是烧录和调试Android系统时的核心需求。很多初学者会问“ADB驱动是不是要开USB调试模式”这个问题在PC端是软件设置但在BSP侧你得先把设备端的gadget功能跑起来PC端才有机会弹窗。在主线Linux上我习惯用ConfigFS组织gadget。流程大致是挂载configfs创建gadget目录并写入厂商ID和产品ID创建function目录把function链接到配置目录最后绑定UDC控制器。这里给一个简化脚本模板mount -t configfs configfs /config mkdir /config/usb_gadget/g1 cd /config/usb_gadget/g1 echo 0x1234 idVendor echo 0x5678 idProduct mkdir functions/ffs.adb mkdir configs/c.1 ln -s functions/ffs.adb configs/c.1/ echo musb-hdrc.0 UDC脚本里的UDC控制器名称要按实际来通过 /sys/class/udc/ 目录可以查到。写完后有两个检查点UDC节点是否存在以及function目录名是否跟内核编译进去的gadget驱动对应。我遇到最典型的问题是内核开了CONFIG_USB_CONFIGFS但没开对应的function模块结果创建function目录直接失败报错。遇到先回头查内核配置别在脚本里死磕。5.3 ID引脚、Type-C与role switch机制OTG动态切换失败绝大多数出在检测机制上。T527这类平台硬件上通过ID引脚的电气状态判断角色ID接地通常是HostA端ID悬空或拉高通常是DeviceB端。但很多底板根本没有接标准的mini/micro AB插座直接用Type-C。Type-C的CC检测和传统ID引脚不是一回事如果驱动还在傻等ID信号它就会一直卡在错误的角色上。这种情况有两招可以解决。第一招如果产品形态不需要动态切换直接改设备树把dr_mode固定为peripheral或host不做otg模式省心又稳定。第二招如果确实需要动态切换就让驱动使用外部的USB role switch驱动把Type-C的CC状态正确上报给控制器。从BSP角度讲能用固定模式解决就不要硬刚动态切换除非产品定义上确实需要一块口子既烧录又能插U盘。5.4 Host切Device瞬间的供电与枚举顺序最后分享一个我在T527上实际遇到、而且藏得特别深的问题OTG口从Host切到Device之后第一次插到PC上PC端提示“无法识别的USB设备设备描述符请求失败”。一开始我以为是gadget配置有问题反复检查configfs配置、VID/PID、function链接全部正常。后来才发现真正的原因是切换角色时这个口的VBUS还在保持Host模式下的输出状态导致PC侧的VBUS检测和D/D-上拉状态对不上。修复方式是在角色切换时先把该口的VBUS输出关掉然后让PHY进入peripheral模式再等待外部VBUS供给。这个顺序写在usb_role_switch的notifier回调里代码量不大但先后顺序错了就是不行。如果你在别的平台上切换角色也遇到过类似“第一次插上失败拔掉重插就好”的情况先复盘一下电源和角色切换的先后顺序多半能省下一个通宵。串口、网络、显示这种外设的BSP问题大多数是单点故障查到一个层面就能收工。只有USB这种协议栈又深又宽的外设逼着我养成了“分层隔离”的排查习惯先物理层、再时序电源、再协议层、最后才碰驱动代码。T527这块平台的USB控制器整体算稳定真正耗时间的不是控制器本身而是它和底板供电、外部设备固件之间的配合问题。如果你现在也在调T527或者类似平台的USB被“插上没反应”折磨的时候建议先按这篇文章的框架走一遍别急着改代码。我的经验是USB的坑多半不在你想的那个地方。
返回列表