记得有次面试一位嵌入式同行的时候,问到了他在工作中是否遇到了比较棘手的问题,他答道:“公司有一款跳绳产品,可以把跳绳的个数记录在手柄里面,通过IIC总线访问EEPROM实现。在测试过程中没有问题,但是在客户使用的时候出现无法计数的情况,必须得断电再上电才行,始终也找不到问题的原因,因为这个问题导致这款产品下架了”
我问他是否有了解过“IIC死锁”相关,他摇了摇头......
IIC协议从文字表达比较简单
起始信号:时钟线SCL在高电平的时候,数据线SDA由高电平变成低电平
结束信号:时钟线SCL在高电平的时候,数据线SDA由低电平变成高电平
通信信号:时钟线SCL在高电平的时候,数据线SDA保持稳定;时钟线SCL在低电平的时候,数据线SDA可以变化
SDA不会死锁场景:
当主机控制数据线SDA时(时钟线SCL由主机控制),在任意时刻主机意外复位或者断电重启,此时不会产生IIC死锁。
SDA死锁场景:
当从机控制数据线SDA时,并且将SDA拉低时候,有2种可能,
① 从机给主机发送数据bit"0"
② 从机回复给主机应答ACK信号,此时主机意外复位或者断电重启。
主机重启后时钟线SCL会被拉高(开漏/上拉电阻),根据IIC协议通信信号规则,SCL在高电平时,数据线SDA保持稳定,因此,从机会一直将SDA保持拉低状态,直到识别到SCL拉低。
主机IIC硬件识别到SDA处于低电平状态,认为IIC总线处于busy状态,则会死等IIC总线空闲,因此产生了IIC死锁。
规避SDA死锁方法:
① 硬件电路上从机供电由主机IO控制,主机一旦识别到IIC死锁,复位从机。
② 主机识别到IIC死锁后,将SCL/SDA管脚配置成GPIO输出模式,一边输出高低电平(模拟IIC时钟),一边读取SDA IO电平状态,一旦SDA IO为高电平后,模拟IIC结束信号,通知从机结束通信,该方式称之为“最多发送9个clock回复IIC总线”,也是最常用的软件恢复机制。
③ 选择带有看门狗复位的IIC器件,比如一些陀螺仪IMU的IIC器件,具备该功能。
进阶篇:
以上IIC死锁均是从机将SDA拉低状态,即SDA死锁。其实也存在SCL死锁状态,如下图所示
当主机和从机(从机IIC内部有接收数据FIFO)通信过程中,主机发送的数据过快或者过多,导致从机接收不过来的时候(从机接收数据FIFO满),从机会主动将SCL拉低(通常SCL由主机控制),以通知主机停止继续发送数据,从机收完数据后,又会释放SCL,以便主机继续发送数据,该方式称之为“IIC时钟延展”。
一旦从机程序因为软件设计问题,导致无法读取接收数据FIFO时,此时就导致了IIC死锁之SCL死锁,有且仅有唯一解决方法,“复位从机”。
从信号的角度分析,SDA为开漏电路,是为了方便主/从分时控制,SCL也为开漏电路,也是为了方便主/从分时控制。
关注公众号,加星标,回复1024获取学习资料,每天进步一点点。
声明:
本号原创、转载的文章、图片等版权归原作者所有,如有侵权,请联系删除。