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 ...
随机推荐
- Pwnable-random
ssh连接,输入密码查看目录下的文件 看看random.c的源码 #include <stdio.h> int main(){ unsigned int random; random = ...
- day49_9_10jQuery剩余
一.表单筛选器. 在jQuery中有,专门对表单中的元素,进行筛选的表单筛选器. 其实使用基本筛选器也可以筛选出相应的元素,但是,为了jQuery的简便性,以及对表单操作的频繁,这里可以使用专门的筛选 ...
- LeetCode 676. Implement Magic Dictionary实现一个魔法字典 (C++/Java)
题目: Implement a magic directory with buildDict, and search methods. For the method buildDict, you'll ...
- BootStrap、jQuery UI、bxSlider组件使用
组件的使用 首先需要将组件下载下来放在统同级目录下 导入组件 使用组件 BootStrap 示例: <!DOCTYPE html> <html lang="en" ...
- Python进阶-XVII 非python的接口类、多态、python自己的封装
1.python模拟java中的接口类 python中是没有接口类的概念的,因为它支持多继承,但是java不能,所以就提出一个接口类的概念 java : 面向对象编程 设计模式 —— 接口 接口类 : ...
- Python Dataframe 分组排序和 Modin
Python Dataframe 分组排序和 Modin 1.按照其中一列进行排序 在dataframe中,按照其中的一列排序:比如q值倒排 (1)rank方法 data['new_rank'] = ...
- [ZJOI2019] 开关 (一种扩展性较高的做法)
[ZJOI2019] 开关 (一种扩展性较高的做法) 题意: 有n个开关,一开始状态都为关闭.每次随机选出一个开关将其状态改变,选出第i个开关的概率为${ p_i \over \sum_{i=1}^n ...
- 安装更新时出现一些问题,但我们稍后会重试。如果你继续看到此错误,并且想要搜索 Web 或联系支持人员以获取相关信息,以下信息可能会对你有帮助: (0x80070426)
安装更新时出现一些问题,但我们稍后会重试.如果你继续看到此错误,并且想要搜索 Web 或联系支持人员以获取相关信息,以下信息可能会对你有帮助: (0x80070426) https://answers ...
- 【Linux命令】at、crontab定时任务
crontab定时任务(周期性) 一.简介 通过crontab命令可以在固定的间隔执行系统指令或shell脚本 二.crontab配置文件: Linux下的任务调度分为两类:系统任务调度和用户任务调度 ...
- OC 字典dictionaryWithObjectsAndKeys报错
字典dictionaryWithObjectsAndKeys crash,也没有控制台打印输出: 解决方案!! 1.检查dictionaryWithObjectsAndKeys中的object key ...