偶发bug排查实战:串口、蓝牙、烧录三类问题三板斧
过去这一个月我被三个偶发 bug 磨掉了半层皮串口打印偶尔顿住、蓝牙连着连着就断、还有一批板子在烧录时随机失败。三个问题看起来毫无关联但真查下来用的都是同一套思路——先别急着改代码先把“偶发”变成“必现”再用换机、录屏、对照批次的手段固定证据。这篇就聊聊我在这三类问题上的完整排查过程包括那些走不通的路和最后真正有效的做法。1. 偶发 bug 的底层逻辑先让“鬼”现形再谈定位1.1 为什么偶发 bug 总是“重启就好”复现率才是第一突破口干嵌入式这行的八成都被“偶发 bug”坑过。产品交到客户手里一个星期崩一次测试那边复现了一到研发手里就装乖你盯着串口日志盯了半天它偏偏在你转身倒水的瞬间跑出一个异常然后一切恢复正常。最气人的是这种问题你拿去问领导领导只会说“再观察观察”问测试测试说“概率很低”问硬件硬件说“波形没问题”。我的经验是偶发 bug 之所以难搞不是因为原因藏得深而是因为触发条件太多像一团乱麻。你不知道它在什么电压、什么温度、什么操作序列下才会跑出来所以每次复现都像抽奖。这时候最忌讳的就是“猜”猜是看门狗复位猜是蓝牙天线干扰猜是 Flash 烧录参数不对。猜十次能猜中一次都算运气好绝大多数时候是改了一版代码问题还在原地等你。所以我的第一步永远是同一件事把复现率提上去。复现率上去了才有资格谈定位。怎么提三个老办法压测、降频、记录环境变化。比如串口问题就加大通信频率、长时间跑压力脚本蓝牙问题就缩短连接间隔、在模块旁边反复开关手机蓝牙烧录问题就连续烧几百次把概率从“千分之一”放大到“几十分之一”。压测的目的不是折磨设备而是让随机性暴露到肉眼可见的程度。1.2 建档立卡时间、环境、操作序列一个都不能少在开始任何手段之前我强烈建议先建一份“问题档案”。别嫌麻烦这份档案是后面所有排查的锚点。具体记什么四点时间现象发生的确切时间点持续多长时间多久恢复。环境当时的供电方式USB 供电还是适配器、温度、设备摆放位置、附近有没有其他无线设备。操作序列用户或测试人员在这个现象出现前做了什么动作精确到“打开某个 App”“插入某个 USB 口”“按下某个按键”。记录方式串口日志存没存录屏有没有拍照拍了没有这套东西看着简单但能救命。我曾经排查一个蓝牙偶发断开用户一口咬定是“什么都没干自己断的”。结果回看操作序列发现他每次都是先打开微信语音通话再戴上蓝牙耳机断开都发生在语音通话切换听筒的瞬间。这个现象如果不建档根本不可能从聊天记录里挖出来。建档之后问题就从“偶发”变成了“有条件复现”方位立刻缩小了。1.3 从“偶发”到“必现”的常见杠杆压力、温度、时序除了压低复现率还要学会用“杠杆”撬开问题的壳。我见过太多工程师一上来就查代码其实是方向错了。偶发 bug 常见的三个杠杆是压力、温度、时序。压力杠杆通信就加长数据包、提高波特率蓝牙就增大数据吞吐、缩短广播间隔烧录就取消校验重试、强行降速。压力能放大临界状态比如电源纹波在低速时无所谓高速一拉就原形毕露。温度杠杆有些批次问题就是低温下 Flash 读写出错、高温下蓝牙射频失锁。用热风枪吹一吹、用冰袋贴一贴看现象是否跟着温度走。不用精确控温能看出趋势就行。时序杠杆上电时序、复位时序、使能引脚时序这一块最容易出问题。比如 STM32 的 BOOT0 引脚在烧录瞬间被拉高但上电顺序不对就导致偶尔进不了 Bootloader。这种问题只有靠反复上下电、插拔 USB 来诱发。杠杆的作用不是“修复问题”而是把问题逼到墙角。等你能做到“只要做某个动作现象必现”后面的换机、录屏、对照批次才有意义。2. 串口假故障换机排除的第一步不是查固件而是查工具链2.1 什么是串口假故障它为什么能骗过所有人串口是嵌入式调试的“眼睛”可有时候这双眼睛本身就有白内障。所谓“假故障”指的是产品实际工作正常但因为调试链路坏了让你误以为设备出了问题。最典型的表现串口打印突然中断几秒钟后自己恢复打印内容出现乱码一插上 USB 转串口模块电脑就开始丢 COM 口数据收发时有大量超时。你会下意识地怀疑固件是不是跑飞了DMA 配置是不是有问题结果反复查代码查不出任何毛病。问题不在产品而在你手里那根线、那个调试小板、那台电脑的 USB 控制器。为什么它能骗过所有人因为调试链路是“隐形的”。你会默认 USB 线是好的默认 CH340 驱动是好的默认串口助手的缓冲区设置是对的。而这些默认恰恰是假故障的温床。尤其当你的测试工装用了非常便宜的 USB 转串口模块时问题更多——不是不能用而是偶发丢数、偶发断流让你以为是设备端的稳定性问题。2.2 换机排除的标准剧本USB转串口模块、线材、驱动、电平“换机排除”这个词听起来很土但它是消除调试链路变量的金标准。我通常按下面顺序执行每一步都只改变一个变量换 USB 转串口模块。把 CH340 换成 FT232或者换成 CP2102再跑一遍压力测试。不同芯片的缓冲策略、驱动稳定性差异很大。便宜的 PL2303 在某些电脑上一旦 CPU 休眠醒来后串口直接挂死这种情况换模块立刻见分晓。换 USB 线。优先换短而粗的线最好是带屏蔽磁环的。长线在高速通信时线间串扰会放大尤其是 115200 以上波特率时更明显。USB 供电也受线阻影响线太长会导致模块供电不足。换 USB 口。台式机后面的 USB 口和前面板的 USB 口供电质量完全不同笔记本左侧和右侧的口也可能出自不同的控制器。串口偶尔断换到另一个口就好了这种我碰到过不止一次。换驱动版本。CH340 的驱动在不同 Windows 版本上表现差异很大有些版本的驱动在收到大量数据时会疯狂报警。官方驱动和系统自动安装的驱动也可能行为不同。检查电平匹配。如果你的设备是 3.3V 逻辑而调试小板是 5V 的偶尔能通但长时间跑就会不稳。尤其是引脚没有做电平转换直接硬连的时候可能出现边缘过冲、波形畸变。这时候不是换机而是得加转接板。这套流程做完如果现象消失那基本可以断定是调试链路的问题产品固件可以暂时放手。2.3 一次串口乱码的完整排查记录换到第三个小板才真相大白说个真实案例。一个设备在产线上测试时串口打印末级信息偶尔出现乱码几秒钟后恢复正常。硬件同事拿示波器打波形说 UART 波形没问题肯定是我们固件的问题。我一个一个模块换前两个 USB 转串口模块都复现换到第三个旧款 FT232 小板之后乱码消失了。当时我也觉得奇怪同样是 USB 转串口为什么前两个会乱码后来把两个模块拆了发现都用的是 CH340G但一个是某宝上一块多钱的裸片焊的晶振旁边滤波电容都省了另一个是正规封装但板子布线很差。第三个是原装 FT232RL 小板电源和地处理得干净。再用示波器看 CH340 的 TX 脚波形发现高电平幅度只有 2.4V 左右而且有振铃到了设备端的 RX 引脚时已经被削得不成样子。FT232 模块输出 3.3V 干净方波一发入魂。这件事给我的教训是串口乱码、偶尔断流的优先级永远是先换物理链路再动软件。不是固件工程师不自信而是调试工具的可信度远没有你想象得那么高。那之后我给测试工装定了规矩串口调试一律用带隔离的 FT232 或 CP2102USB 线长度不超过 1 米驱动统一安装官方版本。3. 蓝牙断开的录屏取证用时间戳把责任钉死在链路的某一端3.1 蓝牙问题为什么最容易扯皮应用层、协议栈、射频谁都可能蓝牙问题排在偶发 bug 排行榜前三名不是没道理的。因为链路长环节多而且看不见。手机这边有系统蓝牙协议栈有 App 处理逻辑设备那边有射频前端、协议栈、应用层回调中间还有空中接口受干扰、距离、遮挡影响。任何一个环节出问题表现都是“蓝牙断了”但你根本不知道是哪一环先动手的。这种问题一旦到了团队内部大概率演变成“软件说射频不行硬件说 App 乱发指令测试说你们别吵了”。如果拿不出硬证据最后只能谁声音大谁有理。所以我处理蓝牙问题第一个原则就是先把证据固定下来再开讨论会。证据最有效的形式不是截图不是测试报告而是带时间戳的录屏加日志。3.2 录屏取证的正确姿势屏幕、串口日志、协议日志三路对齐具体怎么做我推荐“三路对齐”第一路录屏。手机端开系统录屏把蓝牙设置页、App 界面、系统通知栏都录进去。重点记录断开瞬间的 UI 状态是 App 提示“设备已断开”还是系统蓝牙列表里设备消失还是根本没有任何提示只是功能没反应了。这三种现象指向的问题层次完全不同。第二路设备端串口日志。设备通过 UART 输出蓝牙事件包括连接建立、断连回调、重连开始。断开瞬间设备端打印了什么是收到了远端断连请求还是自己这边触发了超时这能直接区分是哪一端主动断的。第三路系统蓝牙日志。Android 可以打开开发者选项里的 Bluetooth HCI snoop log抓下来的日志能分析空中包的收发情况iOS 也可以通过 Profile 抓包。如果不想搞得这么深至少也要用系统自带的功能导出一份日志记录底层连接状态变化。三路数据最关键的是时间戳对齐。录屏里的时间、串口日志打印的时间、HCI 日志的时间可能各自用不同的时钟源。我的做法是开始测试前先用手机拍一下电脑屏幕上的串口日志窗口让录屏画面里同时出现系统时间和串口打印的时间戳制造一个“时间锚点”。后面分析时根据这个锚点把三路数据的时间轴对齐。不要相信任何人“感觉上是先怎么样”的说法时间戳对不上一切结论作废。3.3 我踩过的坑没有录屏的“听用户说”都是盲人摸象我之前处理过一个蓝牙耳机项目用户反馈“听音乐的时候声音断断续续然后连接就消失了”。研发那边怀疑是 A2DP 切换到 SCO 模式导致的音频异常。因为没有录屏只能靠用户描述大家补了各种代码防范问题还是复现。后来我让用户开着录屏复现回看录像才发现声音其实是先卡顿然后手机顶部状态栏的蓝牙图标跳了一下再过两秒 App 才提示断开。关键点在于“蓝牙图标跳了一下”这个瞬间恰好是手机来了一通骚扰电话系统把音频链路从 A2DP 强制切到了 SCO。挂断电话后链路没有正确恢复才触发了后续的断开。这个触发源如果不是看录屏根本不可能从日志里单独读出来——因为日志里只有链路断开的结果没有电话事件的记录。录屏把用户在干什么、系统在干什么、App 在干什么全部串起来了问题的根因立刻就清楚了。所以我现在做蓝牙问题有个不成文的规定复现时必须录屏宁可多录三分钟垃圾也不要漏掉关键的三秒。录屏不是给领导交差的是给分析器用的。很多偶发问题的触发条件恰恰藏在你以为“什么也没发生”的那几秒里。4. “新旧批次对照”的烧录排查固件没变为什么这批板子不行4.1 同一份 hex不同批次表现不同先分清物料、烧录配置、芯片版本“新旧批次对照”是我在烧录问题上最常用的一招。现象通常很统一老批次板子烧录一切正常新批次板子偶尔烧录失败或者烧录成功但运行一段时间后程序行为不对。代码是同一份编译产物是同一个 hex问题就只能出在“为烧录和运行提供基础环境的那些变量”上。首先要把“批次差异”拆清楚。常见差异来源有四类主控芯片版本同一型号的芯片硅片版本可能更新。比如 GD32、APM32 这类国产芯片不同批次丝印可能一样但 Flash 特性可能微调过。老的烧录算法参数不一定适合新批次。外部物料批次Flash、晶振、复位芯片、电源芯片任何一颗换料都可能影响烧录时序。PCB 工艺变化板厂做了阻抗调整、焊盘改动、元器件位置微调都可能让烧录接口的走线特性发生变化。烧录环境变化产线换了烧录器、换了电脑、换了下线软件版本甚至换了烧录治具的线长都会导致结果不同。注意这四类不是互斥的可能同时存在。所以不要一上来就断定是芯片批次问题先用排除法筛掉最容易混淆的“烧录配置差异”。4.2 设计一张批次对照表不用猜直接比我习惯把新旧批次所有相关参数列成一张表做单向差异对比。表格大致长这样对比项老批次正常新批次异常差异影响评估烧录工具J-Link V9J-Link V9无差异烧录软件Keil MDK 5.30Keil MDK 5.31烧录算法版本变了SWD 接口线长10cm30cm时钟频率高时可能不稳定烧录时钟4MHz2MHz暂时降低问题依旧目标芯片批次丝印 A 批次丝印 B 批次重点怀疑对象供电电压3.30V3.28V在规格范围内Flash 校验结果通过偶尔失败可能擦除/写入不稳定复位电路上电复位上电复位无差异这张表的价值不在于列得多全而在于把“谈感觉”变成“看差异”。你会发现很多以前没注意的变量比如 Keil 自动升级后烧录算法变了、产线换了批新线导致 SWD 信号质量下降。把表列完至少能排除掉一半无意义的争论。4.3 烧录环节的隐藏变量速度、供电、复位时序、驱动版本具体到烧录动作本身有几个变量特别容易被人忽略烧录速度。SWD 接口不是越慢越好但太快确实容易在走线不理想时翻车。老批次 4MHz 没问题新批次可能因为引脚走线变化需要降到 1MHz 才能稳定烧录。这不是“治标不治本”而是确认硬件余量的一个手段。供电稳定性。烧录器通过目标板取电时如果电源是 LDO 且负载刚好接近极限Flash 写操作瞬间电流拉高电压跌落就会导致写失败。用示波器抓一下烧录瞬间的 VDD 波形这种问题一眼就能看出来。复位时序。很多 MCU 在 SWD 烧录时要求复位引脚时序配合。新批次如果换了复位电容容值上电复位时间变长烧录器连接时芯片还卡在复位状态握手就会失败。这种偶发失败很符合“随机失败”的特征。烧录器驱动和软件版本。J-Link 的 DLL 版本、Keil 的 pack 版本、串口 ISP 软件的版本都可能影响烧录算法生成。新批次正好赶上软件升级很容易背锅。把老版本装回去试试是最快的验证方式。我曾经遇到一次新批次 ESP32 烧录失败率陡增经验做法都试了一圈没用最后发现是产线的烧录工具参数里默认勾了“加密烧录”新批次芯片的 eFuse 区域和旧批次不一样加密流程额外多花了时间导致上位机超时。这种问题如果不做新旧对照光看代码永远找不出来。4.4 烧录工具与驱动的坑不要忽略“烧录器兼容性清单”还有一个容易被甩锅的点是烧录器本身。同型号不同批次的烧录器比如某宝的 J-Link 兼容版固件可以被重新刷写有的版本对某些芯片的时序兼容性极差。我见过一个产线用“J-Link clone”烧 STM32G0老批次正常新批次偶尔找不到核心换一个正版 J-Link PLUS 后稳定烧了两千片。不是所有“同型号”都真的“同性能”。我的建议是一旦确认是烧录问题先把烧录器列进“嫌疑名单”不要默认它没问题。测试方法很简单用同一个烧录器分别烧老批次和新批次各五十片记录成功率再换一个不同品牌的烧录器重复同样测试。如果换烧录器后新旧批次的差异消失那问题就在烧录器、线缆或上位机软件而不是芯片或 PCB。5. 三板斧怎么组合用一套能让团队停止“互甩锅”的排查流程5.1 三类问题的边界与先后顺序把三招摆在一起看它们其实分别对应不同层级串口假故障的换机排除解决的是“调试工具引入了假信号”的问题属于链路症状。蓝牙断开的录屏取证解决的是“多方接口模糊、责任不清”的问题属于现场重建。新旧批次对照的烧录排查解决的是“生产变量导致行为差异”的问题属于横向对比。它们的共同点是先用最可控的手段清理变量再用独立证据固定现场最后用横向对比锁定批次差异。所以实际项目里我建议的顺序永远是从“工具不可靠”开始排除再到“现场不可信”的取证最后才是“批次不一致”的对照。如果一上来就做新旧批次对照而实际只是调试链路坏了那相当于把很好查的问题复杂化。5.2 排查记录模板与团队协作的“接口约定”最后分享一个很实用的协作模板我称之为“单问题单页报告”。无论谁在排查偶发 bug都要求用一页 PPT 回答五个问题现象是什么尽量附录屏或串口日志片段复现条件是什么时间、环境、操作序列我们已经排除了哪些变量换过什么、测过什么、对比过什么目前最可疑的两个方向是什么不许超过两个下一步计划做什么由谁做预期什么时候完成这个模板救了我不止一次。因为它强制把所有信息收敛到一页纸上避免了群里几十条语音、十几张截图来回轰炸的混乱。测试、固件、硬件、产线大家围绕同一份报告做更新和评审谁也不会跑偏。5.3 一点个人体会偶发 bug 是“确定性”藏在“混沌”里做了这么多年调试我越来越觉得偶发 bug 并不“偶发”只是我们还没找到它的边界条件。每一个看起来随机的现象背后都有一套确定的物理过程只是变量太多、交互太复杂暂时超出了直觉能跟踪的范围。所以每次遇到“随机抽风”的 bug我不再急着改代码而是先问自己三句话我的调试工具是不是可信的我的现场证据是不是完整的我有没有做过批次或环境的横向对比这三句话问完方向通常就清晰了一大半。写这篇文章的初衷也是希望大家少走一点弯路。换机排除、录屏取证、新旧批次对照这三招表面上是三种技术本质上是一种态度先信证据再信感觉先控制变量再谈修改。偶发 bug 最怕的不是难查而是那句“算了重启一下就好了”。每一次重启都是在掩盖一次真相。下一次再遇到莫名其妙的故障不妨先停下来把链条上的每个环节都摆在桌上一个一个地换、一遍一遍地录、一版一版地比。你会发现的真相往往比想象中朴素得多。
上一篇/下一篇内容由系统自动关联
返回资讯列表 →