嵌入式 - IIC被锁死的问题处理

I2C其实不是一个很稳定的通讯协议。

一方面,它是一个多设备通讯协议,各个通讯节点都在操作总线,只是各自设备的I2C地址不同。整个总线的状态和各个总线上的设备都是有关的。

当一个设备出现问题,就有可能影响到整个总线,使总线出问题,严重会导致整个总线通讯失败。

另一方面,使用I2C处理的通讯,大多是外设芯片的寄存器读写操作(比如charge IC,NFC芯片,EEPROM等),这种应用层通讯协议较为简单,关键是没有对数据帧进行校验,发出的数据被接收后就生效了。

而在物理通讯层,I2C只有ACK机制,也没有数据有效性的验证功能,一旦传输波形受到影响,就会造成数据错误,但发送和接收方都不知道。

也就是说,I2C总线通讯是很容易被干扰的。常见的情况,就是如果I2C的引脚暴露在外,比如接到连接器(connector)上,然后连接器的频繁插拔操作,就可能造成I2C总线通讯据错误;还有产品做ESD测试时,也会造成I2C总线通讯错误。

可能出现的错误包括,I2C控制器电路错误、I2C驱动程序错误、软件应用层错误等。而软件应用层错误可能是外设芯片工作状态异常,也可能是主控芯片工作状态异常。

比如我就遇到过I2C控制的charger IC,和主控芯片之间的连接,是通过一个底座上的connector。当设备频繁在底座上插拔,触发充电和停充时,就容易出现问题。因为SCL和SDA接触不是同时断开或接上,这两个pin放在了两排,这两排顶针不是平的,放下或抠开时,会一个先接触或断开,一个后接触或断开。尤其是断开连接时,可能对正在进行的I2C通信造成影响,出现充电错误。

对这个问题,后来降低了I2C通信的数据量,并在通信中加了保护,数据发送前先判断连接稳定性,发送中出现错误立刻停止发送。

还有一个问题,也是I2C连接charger、gauge IC的问题,这个是没有断开连接,而是在drop test中,因为震动,造成了I2C总线出现错误,SDA一直被拉低,无法通讯,影响充电功能。

当出现问题时,也尝试进行了一些恢复操作,比如使用GPIO拉高SDA,没有效果。后来根据其他项目出过类似的问题,发现是因为电池里使用了美信 gauge IC,由于机械震动、连接不良等导致I2C传输被中断, SDA会被一直拉低。就借鉴了过来。

===分割线===

I2C总线出问题的解决方案

I2C协议就是NXP的前身Philip发明的。

在I2C总线通信出现错误时,I2C SDA被锁定,强制拉低,

查看I2C Spec: https://www.nxp.com/docs/en/user-guide/UM10204.pdf

章节:

3.1.16 Bus clear

In the unlikely event where the clock (SCL) is stuck LOW, the preferential  procedure is to reset the bus using the HW reset signal if your I2C devices have HW reset inputs. If the I2C devices do not have HW reset inputs, cycle power to the devices to  activate the mandatory internal Power-On Reset (POR) circuit.

If the data line (SDA) is stuck LOW, the controller should send nine clock pulses. The device that held the bus LOW should release it sometime within those nine clocks.  If not, then use the HW reset or cycle power to clear the bus.

3.1.16 总线复位

在不太可能发生的情况下,clock(SCL)信号被卡在低电平,如果你的I2C设备有HW复位输入,最好的方法是使用HW复位信号来复位总线。如果I2C设备没有HW复位输入,对设备进行断电再上电的操作,来激活强制性的内部上电复位(Power-On Reset / POR)电路。

如果数据线(SDA)被卡在低电平,I2C主控制器应该发送9个时钟脉冲。把SDA信号拉低的设备,就应该在这9个时钟内的某个时间释放SDA信号。 如果没有,则使用HW复位或电源掉电上电来清除总线错误。

所以,当I2C的SDA被某个设备强制拉低了,就可以使用上面的办法,通过I2C master 设备,发送9个时钟周期,来清除I2C总线错误。

当然,这是个治标的办法,从源头上,可以降低I2C通信频率,减少发送数据量,提高I2C电路的电气稳定性,用这些措施来降低I2C总线出问题的机率。

你可能感兴趣的:(嵌入式,单片机)