RS485 的蹊跷
出现的问题
某个产品的 485 在客户那里翻了船,机器在现象发生后不再响应任何指令。
在实验室反复测试,短路,全抢占乱发帧,长高长低异常,都没办法复现,机器的通信相当稳健。找了两天我对自己的这部分处理越来越自信,但是客户那里又确实存在问题,只能去现场看一下,此时我已经认定是现场的差分线有问题了。
还真不是,确实是我的问题。总的来说,排查后发现机器卡在了 485 IC 拉到发送态的情况。
什么造成的
当存在数据需要发送时,先切到发送态,发送结束后,再切回接收态。
看起来很合理,其实不然。这台机没有使用 DMA 进行 UART 管理,所以收发数据都依赖于外设中断,而切换 IC 状态也由中断负责。当某种情况,物理世界千奇百怪的干扰阻碍了中断的产生/处理,或许是某个特殊的异常引起了外设的重启,反正就是无法通过中断检测到发送结束这个事情的发生,此时 IC 卡在发送态。而设备又不会主动产生任何发送数据,导致也无法接收数据,也不发送,同时把总线发送抢占掉了。

正常的波形

异常发生时主动端的波形
通道的思维
半双工的通信与 DMA 其实是有相似性的,都需要将杂乱而来的数据集合起来,建立一段通道统一进行传输。
此前已知大批量出货的机器都采用 DMA+485 的方式,而 DMA 的中断与外设无关,无论物理世界发生什么,DMA 的通道结束都会发生中断。所以没有发生过这样的问题。
这次由于是后加的 485 功能,偷懒以及考虑到稳定性改动尽量小,没用 DMA,又长姿势了。
非通道的思维
既然使用中断+手写寄存器来管理一个流式数据的接口,那这个方案是非通道的。但是物理层 485 又是通道形式,那怎么办呢?
我认为不能依赖非通道的方案来管理通道,例如将 IC 拉高低事件放在非通道中断中产生就是不合理的。应该由一个轮询来专门管理通道方向,周期性监测是否处于发送状态,使用诸如发送buffer是否为空、总线是否空闲等条件综合检测,如果未处于发送态已有一段事件,强制将通道转为接收。
(别说用外设流控脚,这个时间不可控并不是 IC 通用)
后续会在数据流控库中加入这个机制,以供非通道的应用。
stbanana/Dataflow: Dataflow middleware. Enhanced use of DMA and half-duplex.