I2C 挂死,SDA一直为低问题分析【转】
转自:https://blog.csdn.net/winitz/article/details/72460775
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/winitz/article/details/72460775
问题
调试中遇到过这样一个问题,主芯片访问外部I2C设备时,市场出现I2C读写time out,而且一旦出现这个问题后,I2C访问会一直失败。
现象
1) 从log看,第一次出现time out是在发送end命令时,之后一直访问失败
2) 出错后I2C的SCL一直为高,SDA一直为低
分析
1) 从现象上看,I2C主设备发送命令后,SCL一直为高,而SDA一直被外设拉低。对于I2C主设备来说,由于检测到SDA信号为低电平,则会认为I2C总线被占用,I2C主设备等待从设备释放SDA信号,而同时I2C从设备又在等待主设备将SCL信号拉低以释放应答信号,两者相互等待,I2C总线进入死锁状态。
2) 从现象上看很可能由主从设备的时序不匹配导致。查看I2C驱动程序,在等待从设备应答的函数里,看到最多等待0x100000个时钟周期,而主设备主频为1.2GHz。可以算出最多的等待时间为:
t=16^5/(1.2*10^12)=870(ns)
该时间很可能小于从设备响应所需要的时间。
解决
根据从设备I2C的时序要求,增加驱动程序里等待响应的时间解决该问题。
相关知识
注:以下转载自http://www.cnblogs.com/zym0805/archive/2011/07/31/2122890.html
I2C是由Philips公司发明的一种串行数据通信协议,仅使用两根信号线:SerialClock(简称SCL)和SerialData(简称SDA)。I2C是总线结构,1个Master,1个或多个Slave,各Slave设备以7位地址区分,地址后面再跟1位读写位,表示读(=1)或者写(=0),所以我们有时也可看到8位形式的设备地址,此时每个设备有读、写两个地址,高7位地址其实是相同的。
I2C数据格式如下:
无数据:SCL=1,SDA=1;
开始位(Start):当SCL=1时,SDA由1向0跳变;
停止位(Stop):当SCL=1时,SDA由0向1跳变;
数据位:当SCL由0向1跳变时,由发送方控制SDA,此时SDA为有效数据,不可随意改变SDA;
当SCL保持为0时,SDA上的数据可随意改变;
地址位:定义同数据位,但只由Master发给Slave;
应答位(ACK):当发送方传送完8位时,发送方释放SDA,由接收方控制SDA,且SDA=0;
否应答位(NACK):当发送方传送完8位时,发送方释放SDA,由接收方控制SDA,且SDA=1。
当数据为单字节传送时,格式为:
开始位,8位地址位(含1位读写位),应答,8位数据,应答,停止位。
当数据为一串字节传送时,格式为:
开始位,8位地址位(含1位读写位),应答,8位数据,应答,8位数据,应答,……,8位数据,应答,停止位。
需要注意的是:
1,SCL一直由Master控制,SDA依照数据传送的方向,读数据时由Slave控制SDA,写数据时由Master控制SDA。当8位数据传送完毕之后,应答位或者否应答位的SDA控制权与数据位传送时相反。
2,开始位“Start”和停止位“Stop”,只能由Master来发出。
3,地址的8位传送完毕后,成功配置地址的Slave设备必须发送“ACK”。否则否则一定时间之后Master视为超时,将放弃数据传送,发送“Stop”。
4,当写数据的时候,Master每发送完8个数据位,Slave设备如果还有空间接受下一个字节应该回答“ACK”,Slave设备如果没有空间接受更多的字节应该回答“NACK”,Master当收到“NACK”或者一定时间之后没收到任何数据将视为超时,此时Master放弃数据传送,发送“Stop”。
5,当读数据的时候,Slave设备每发送完8个数据位,如果Master希望继续读下一个字节,Master应该回答“ACK”以提示Slave准备下一个数据,如果Master不希望读取更多字节,Master应该回答“NACK”以提示Slave设备准备接收Stop信号。
6,当Master速度过快Slave端来不及处理时,Slave设备可以拉低SCL不放(SCL=0将发生“线与”)以阻止Master发送更多的数据。此时Master将视情况减慢或结束数据传送。
在实际应用中,并没有强制规定数据接收方必须对于发送的8位数据做出回应,尤其是在Master和Slave端都是用GPIO软件模拟的方法来实现的情况下,编程者可以事先约定数据传送的长度,slave不检查NACK,有时可以起到减少系统开销的效果。但是如果slave方是硬件i2c要求一定要标准的NACK,master方是GPIO软件模拟i2c并没有正确的发送NACK,就会出现“slave收不到stop”导致i2c挂死。
在正常情况下,I2C总线协议能够保证总线正常的读写操作。但是,当I2C主设备异常复位时(看门狗动作,板上电源异常导致复位芯片动作,手动按钮复位等等)有可能导致I2C总线死锁产生。下面详细说明一下总线死锁产生的原因。
在I2C主设备进行读写操作的过程中.主设备在开始信号后控制SCL产生8个时钟脉冲,然后拉低SCL信号为低电平,在这个时候,从设备输出应答信号,将SDA信号拉为低电平。如果这个时候主设备异常复位,SCL就会被释放为高电平。此时,如果从设备没有复位,就会继续I2C的应答,将SDA一直拉为低电平,直到SCL变为低电平,才会结束应答信号。而对于I2C主设备来说.复位后检测SCL和SDA信号,如果发现SDA信号为低电平,则会认为I2C总线被占用,会一直等待SCL和SDA信号变为高电平。这样,I2C主设备等待从设备释放SDA信号,而同时I2C从设备又在等待主设备将SCL信号拉低以释放应答信号,两者相互等待,I2C总线进人一种死锁状态。同样,当I2C进行读操作,I2C从设备应答后输出数据,如果在这个时刻I2C主设备异常复位而此时I2C从设备输出的数据位正好为0,也会导致I2C总线进入死锁状态。
方法
尽量选用带复位输人的I2C从器件。
将所有的从I2C设备的电源连接在一起,通过MOS管连接到主电源,而MOS管的导通关断由I2C主设备来实现。
在I2C从设备设计看门狗的功能。
在I2C主设备中增加I2C总线恢复程序。
每次I2C主设备复位后,如果检测到SDA数据线被拉低,则控制I2C中的SCL时钟线产生9个时钟脉冲(针对8位数据的情况,“9个clk可以激活”的方法来自NXP的文档,NXP(Philips)作为I2C总线的鼻祖,这样的说法是可信的),这样I2C从设备就可以完成被挂起的读操作,从死锁状态中恢复过来。
这种方法有很大的局限性,因为大部分主设备的I2C模块由内置的硬件电路来实现,软件并不能够直接控制SCL信号模拟产生需要时钟脉冲。
或者,发送I2C_Stop条件也能让从设备释放总线。如果是GPIO模拟I2C总线实现,那么在I2C操作之前,加入I2C总线状态检测 I2C_Probe ,如果总线被占用,则可尝试恢复总线,待总线释放后,再进行操作。要保证I2C操作最小单元的完整性,不被其他事件(中断、高优先级线程,等)打断。
在I2C总线上增加一个额外的总线恢复设备。这个设备监视I2C总线。当设备检测到SDA信号被拉低超过指定时间时,就在SCL总线上产生9个时钟脉冲,使I2C从设备完成读操作,从死锁状态上恢复出来。总线恢复设备需要有具有编程功能,一般可以用单片机或CPLD实现这一功能。
在I2C上串人一个具有死锁恢复的I2C缓冲器,如Linear公司的LTC4307是一个双向的I2C总线缓冲器,并且具有I2C总线死锁恢复的功能。LTC4307总线输入侧连接主设备,总线输出侧连接所有从设备。当LTC4307检测到输出侧SDA或SCL信号被拉低30ms时,就自动断开I2C总线输入侧与输出侧的连接.并且在输出侧SCL信号上产生16个时钟脉冲来释放总线。当总线成功恢复后,LTC4307会再次连接输入输出侧,使总线能够正常工作。
---------------------
作者:winitz
来源:CSDN
原文:https://blog.csdn.net/winitz/article/details/72460775
版权声明:本文为博主原创文章,转载请附上博文链接!
I2C 挂死,SDA一直为低问题分析【转】的更多相关文章
- 浅谈STM32L071硬件I2C挂死
STM32的IIC问题一直存在,在网上也被很多人吐槽,然而FAE告诉我,硬件IIC的问题在F1,F3,F4系列单片机存在,而在L0上已经解决了,然而这几天调试加密芯片和显示芯片,都是IIC芯片,却再一 ...
- 记一次 .NET 某上市工业智造 CPU+内存+挂死 三高分析
一:背景 1. 讲故事 上个月有位朋友加wx告知他的程序有挂死现象,询问如何进一步分析,截图如下: 看这位朋友还是有一定的分析基础,可能玩的少,缺乏一定的分析经验,当我简单分析之后,我发现这个dump ...
- 应用程序出现挂死,.NET Runtime at IP 791F7E06 (79140000) with exit code 80131506.
工具出现挂死问题 1.问题描述 工具出现挂死问题,巡检IIS发现以下异常日志 现网系统日志: 事件类型: 错误 事件来源: .NET Runtime 描述: Application: Di ...
- java多线程解决应用挂死的问题
这两天为了定位JBOSS老是挂死的问题,学习了一下JAVA多线程方面的知识,在此总结一下 1.在Java程序中,JVM负责线程的调度.线程调度是指按照特定的机制为多个线程分配CPU的使用权. 调度的模 ...
- MySQL 连接为什么挂死了?
摘要:本次分享的是一次关于 MySQL 高可用问题的定位过程,其中曲折颇多但问题本身却比较有些代表性,遂将其记录以供参考. 一.背景 近期由测试反馈的问题有点多,其中关于系统可靠性测试提出的问题令人感 ...
- MySQL 连接为什么挂死了
声明:本文为博主原创文章,由于已授权部分平台发表该文章(知乎.云社区),可能造成发布时间方面的困扰. 一.背景 近期由测试反馈的问题有点多,其中关于系统可靠性测试提出的问题令人感到头疼,一来这类问题有 ...
- NFS Server宕机后,NFS Client主机上df命令挂死
方法1: 使用root用户:Oracle@NDMCDB05:~> su -Password: NDMCDB05:~ # cat /etc/mtab /dev/sda2 / reiserfs rw ...
- 关于用strace工具定位vrrpd进程有时会挂死的bug
只做工作总结备忘之用. 正在烧镜像,稍总结一下进来改bug遇到的问题. 一个项目里要用到L3 switch的nat,vrrp功能,但实地测试中偶然出现write file挂死的情况,但不是必现.交付在 ...
- Redis主从同步之主库挂死解决方案
Redis实现了主从同步,但是主库挂死了,如何处理 方案:切换主库的身份 # 连接从库 [root@localhost redis-]# redis-cli -p # 取消从库身份 > slav ...
随机推荐
- 安装npm install app-inspector -g 提示错误
问题1: npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@^ (node_modules\app-inspector\node_mod ...
- 再次体会wireshark的威力!
今天一位同学给我打电话,说是重启了客户机房里的一台服务器A,重启之后此台服务器不能与B服务器通信了,要命的是A台服务器上有关键数据需要与B服务器进行通信交互.客户大发雷霆,同学的老板也发火一再催促要尽 ...
- 攻防世界Web-bug
一直误以为是二次注入,看了别人wp,自己梳理了一遍 首先打开题目页面 先注册一个账号 注册成功(注意这个UID) 然后注意下包,发现cookie中的user很可疑,是一串md5值,我们可以推测是我们注 ...
- MySQL实战45讲学习笔记:第四十四讲
一.引子 这是我们专栏的最后一篇答疑文章,今天我们来说说一些好问题. 在我看来,能够帮我们扩展一个逻辑的边界的问题,就是好问题.因为通过解决这样的问题,能够加深我们对这个逻辑的理解,或者帮我们关联到另 ...
- [NewLife.XCode]角色权限
NewLife.XCode是一个有10多年历史的开源数据中间件,支持nfx/netcore,由新生命团队(2002~2019)开发完成并维护至今,以下简称XCode. 整个系列教程会大量结合示例代码和 ...
- Chrome保存整个网页为图片
打开需要保存为图片的网页 然后按F12,接着按Ctrl+Shift+P 在红框内输入full 点击下面的“Capture full size screenshot”就可以保存整个网页为图片了 原文出处 ...
- 解决office365无法登录以及同步的问题
解决office365无法登录以及同步的问题 You better need to test them one by one. You better need to test them one by ...
- idea修改svn地址
1.不能直接修改idea中的svn路径 2.需要先修改小乌龟地址,先找到本地的项目文件右键
- 队列和 BFS —— 栈和 DFS
队列和 BFS: 广度优先搜索(BFS)的一个常见应用是找出从根结点到目标结点的最短路径. 示例 这里我们提供一个示例来说明如何使用 BFS 来找出根结点 A 和目标结点 G 之间的最短路径. 洞悉 ...
- SQLyog 图形化数据库的操作教程
首先SQLyog作为mysql的图形化操作工具,是一款非常好用的工具. 操作说明 1.打开工具,点击[新建]输入名称.用户名:root,密码是安装时自己设置的(一定要记住的),端口号默认是:3306, ...