6月份时,公司的产品要求增加TCPIP协议栈,以便完成以太网的通讯功能,接入上层管理系统。作为一名业余“救火”程序员,用三天时间完成了TCPIP的协议栈移植,然后又与现有的RS485通讯程序整合。兴冲冲的去现场为用户更新软件,带着悠闲地心情回到公司。三个月后,现场打电话说,“装置通讯时,出现反覆的重启现象,但是过段时间又好了”。对于工业产品来说,通讯可以没有,但不能无故重启,否则会有事故发生的可能。为了确认问题的出现原为,让现场人员分多次观测装置,发现中午12点至16点之间,装置重启的可能性最大。面对这种情况,我的第一反映是温度导致以太网芯片过热,由于MCU与以太网芯片是使用SPI方式连接,怀疑是SPI通讯没有复位,导致MCU卡在在某个whille中,WatchDog将MCU硬复位了。

这个地方有一些疑点:

  1. 不加以太网程序时,装置并没有重复重启情况发生

  2. 增加以太网程序时,在常温下没有出现类似问题

  3. 以太网的程序是由MicroChip公司提供的MicrochipLibraryApplication套件,这个里面有实现TCPIP协议栈处理和SPI通讯

TCPIP的库是由官网提供的不应该有问题,但装置本身也是没有重启现象。早些时候觉得可能是TCPIP处理中有while卡死,所有就在主循环一定时间后把以太网芯片复位,可问题依旧。这个时候,决定再做一些测试,期间没有把局域网的网线接在交换机,只有交换机与装置以太网接口相连,发现高温持续很长时间后长会有重启现象。

这里突然想到,会不会是上层处理数据包时卡死。代码跟踪一圈后,在TCP处理时,有对数据包的校验,发现里面竟然直接有Reset()这种函数的调用,最终发现了下面的东东:

#define Reset() asm("reset")

我嘞个去啊,大哥,不带这么玩我呢。你校验个TCP头,觉得有问题,可以扔掉或者复位以太网芯片呢。为什么要把MCU都Reset掉,这绝对是个坑呢。我以为一切都结束呢,结果高温测试时,以太网一直在重启中。

这时想到了个问题,高温对SPI线上的数据还是有影响的,导致数据包有问题,所以以太网芯片就一直在重启,因为每个包都有问题么。郁闷之迹,看到校验判断前有注释,可能还比较多(我为了查看方便把Folding功能是打开的,只能看见一行),打开后有很长一段,其中说明了为什么会有校验判断这片代码,还提到了可能会出现这种情况的原因,其中说如果MCU的SPI总线与以太网芯片通讯速率太快,数据包可能会不完整。

难道是配置的通讯速率太快了么??

最大16MHz,我使用12MHz,那就换5MHz吧。接下来就是见证奇迹的时候,果然高温测试时,不再有重启现象。问题是解决了,但个中原因还是不详啊。硬件工程师给出了一个满意的答案:

12MHz来通讯是很快,但是MCU与以太网芯片比较远,SPI总线就很长了,速度快肯定是要衰减的,
同时速度快就会很容易受外界的影响,高温就导致你的MAC数据帧有错乱,上面又是Reset,所以就会出现这种问题了。

很多时候,我在通讯时都尽量避免使用最大速率通讯,但是还有一些外界的情况没有考虑到。所以,没有最快速率,只有最合适的。