一个让人抓狂的现场故障
去年冬天,有个做分布式传感网络的朋友找我帮忙看一个问题。他们的设备部署在野外,节点靠电池供电,大部分时间处于深度休眠,每隔几分钟唤醒一次,通过广播方式把采集的数据传给汇聚节点。问题出在:设备在实验室跑得好好的,一到现场,运行几天后就有节点彻底失联,重启才能恢复。
他们最初怀疑是电池电压跌落、天线接触不良、甚至怀疑是低温导致晶振停振。换了一批硬件、加了大电容、改了唤醒周期,问题依旧。更诡异的是,失联的节点位置不固定,时间也不固定,有时候一天出两三个,有时候一周都不出。他们抓了串口日志,发现节点最后打印的一条信息是“准备进入休眠”,然后就再也没有然后了。
这个现象最折磨人的地方在于:它不可稳定复现。你在实验室用电源供电、常温、短距离通信,怎么跑都不出问题。一到现场,电池供电、温度变化、距离拉远、周围干扰增多,它就偶尔来一下。你改一个参数,好像好了几天,然后又复发,你根本不知道是改对了还是运气好。
我拿到他们的代码和日志后,花了大概三天时间,用逻辑分析仪和可控电源反复模拟现场条件,终于把这个问题稳定复现出来了。根因说出来简单得让人想骂人:休眠和广播切换的时序配合上,状态机有一个极窄的窗口,在这个窗口里如果收到一个特定长度的广播包,状态机会卡在一个中间态,既进不了休眠,也回不到正常接收,最终看门狗复位,但复位后如果再次落入同一个窗口,就形成死循环。
这篇文章就把这个坑完整拆开讲清楚。市面上讲低功耗状态机的资料,大多只讲“休眠前要关外设、要保存上下文”,但很少有人讲休眠和广播切换时那个微妙的时序窗口,以及为什么这个窗口在现场环境下会被放大。我会把复现方法、观察手段、权衡取舍都写出来,这些都是付费课程里才会细讲的东西。


