STM32’s I2C 硬件BUG引发的血案

发布者:咖啡狐狸最新更新时间:2018-06-03 来源: eefocus关键字:STM32’s  I2C  硬件BUG 手机看文章 扫描二维码
随时随地手机看文章

下面的函数中有一个BUG, 也就是SR2不能用WHILE来轮询,而应直接读出.如下面代码段, 因此,在这里说的这是STM32的BUG其实是我的代码的错误:
    I2C2->DR = inerAddress[1];
    while( (I2C2->SR1&Q_I2C_SR1_BIT_BTF)==0 );
    I2C2->SR2;   // 正解

2010-4-1 1:44,一直都不相信STM32 的I2C接口会存在问题,因为工作经验无数次告诉我,嵌入式系统设计中的99.999%的问题不会是由于MCU本身的设计问题所引起,绝大部分都是硬件工程师或软件工程师的某个设计缺陷所造成的. 这次的设计经历也不例外.

由于终于可以抽多点时间用于设计STM32的I2C的软件接口, 因此, 决定重构之前用于主从STM32通讯所用的I2C模块(基于I2C中断+状态机收发)。I2C的中断发送模块很快就重构完毕并且强化了错误处理和I2C总线hang的自恢复功能代码模块(I2C BUS Hang:也就是SDA 和SCL都被某Slave DEVICE拉低,大部分发生在主机接收从机传过来的数据包的最后一个字节的数据时,没有发送P(停止位)所造成的,这时Slave device (EEPROM)因为接收不到P,从而会DEAD LOOP地发送数据给主机,在主机方向看,I2C总线就相当于一直处于BUSY的状态,也就是网上问得最多的关于I2C的问题-I2C总线TMD的怎么会突然间死掉了、BUSY了、HANG的原因。)。

本以为I2C中断读模块也会很顺利地完成,但是却被卡住了一整天,只要加一个断点,在大部份代码处加无所谓,读FUN每次都正确执行,但只要全速运行,就只能运行一次,然后就过不去了,而且过不去的地方并不固定。由于DUBEG得有点集中不了精力,于是就做好问题的Brainstrom的笔记,放了下,晚上出差到深圳,到客户处做系统需求的讨论会,主要是上位机部分的。然后第二天晚上又赶回来,在车上的半梦半觉中让潜意思去思考。回到家后,选择在我的生物钟的最佳的时侯,晚上10点。开始重新在问题的Brainstorm处接着DUBGE。WORK PLAN如下:
(1)把程序恢复到测试I2C写的测试用例状态,PASS。

(2)一小段代码就DEBUG一次的步步为营方法,按之前的思路把代码加入到读的模块(忽略防守代码,只加入必需的功能代码)。都OK后,全速运行,XXX,又卡住了。细过了一片读模块。PASS。于是进入计划中的(3)

(3)全速运行,然后在可能卡住的地方加上断点,而不是之前的先加断点,然后运行的方式(这种方式,已确认PASS):
加了几处后,发现程序是在下面代码处卡住的:
image

但是奇怪了,每次我只要在箭头指向的语句后加上断点,每次都能PASS。于是知道要到 I2C_CheckEvent 函数中就能找到问题的原因了,于是做下面的几步,目的是把包含I2C_CheckEvent Fun的链接库中的stm32f10x_i2c.o排除掉,而把stm32f10x_i2c.c加入到项目中,使得DEBUG时能进入到 I2C_CheckEvent Fun 中去.

image

image

于是全速运行,然后在 stm32f10x_i2c.c中加上断点,终于捕捉到问题点了,分析如下图所示:

image

/* Read the I2Cx status register */
//  flag1 = I2Cx->SR1;             // 原代码
//  flag2 = I2Cx->SR2;            //原代码
//  flag2 = flag2 << 16;           //原代码

  /* Get the last event value from I2C status register */
  //lastevent = (flag1 | flag2) & FLAG_Mask; //原代码
  lastevent = (vu32)( (vu32)(I2Cx->SR1) | ((vu32)(I2Cx->SR2) << (vu32)16) ); //qzm为了确认而加入的,实际效果和用库的是一样的结果。
  lastevent &= (vu32)FLAG_Mask; //qzm为了确认而加入的,实际效果和用库的是一样的结果。

为了确认,我也把 Fun中的所有变量改为以v开头的,以确保不被编译器所优化掉,编译代码也不作任何的优化。但是全速时I2C获得的事件会多出个BTF位,而在一开始时如果先进入DEBUG,加上断点,然后运行,lastevent == 0x30001(之也说明了库代码是不存在BUG的),如下图所示:

image





这应该是STM32 I2C硬件接口的BUG,解决方法如下:


image

把库中的I2C中断事件判定结合SR1和SR2的思路相反,我把读SR1和SR2明确地分了出现,并进行确认, PASS, 给模块加上防守代码,做好文档, 至此,模块的生命周期进入到白盒测试和黑盒测试阶段.


关键字:STM32’s  I2C  硬件BUG 引用地址:STM32’s I2C 硬件BUG引发的血案

上一篇:浅谈 STM32 硬件I2C的使用 (中断方式 无DMA 无最高优先级)
下一篇:STM32 I2C硬件

推荐阅读最新更新时间:2024-03-16 16:04

用高压I2C电流和电压监视器进行测量
引言   由于今天电子产品设计的复杂性不断提高,所以管理功耗和优化总体效率变得更加重要。从工业和电信应用到汽车和消费电子产品的所有产品中,准确的电源电压和电流监视对节省功率和保证可靠性都是至关重要的。   监视至一个系统的电源输入需要多种组件。为了测量电流,需要一个检测电阻和放大器,而且如果放大器共模范围扩展到正的电源轨并将其输出转换到地是最方便的。需要精确电阻分压器来测量电压,而且如果有多于 1 个电压要监视,那么还必须给这个组件表增加一个多路复用器。下一个是具有精确基准和一些与微处理器连接途径的模数转换器 (ADC),同时也许与相邻 IC 共享 I/O 线。由于找到合适组件的总体复杂性和困难,电源监视最好的方法就是集成式解
[测试测量]
用高压<font color='red'>I2C</font>电流和电压监视器进行测量
基于51单片机i2c多字节的读写
使用Keil的编译环境下载,确实能够下载,但是入口的地址是如下黄色的那行显示所示,如果单步执行(F11)或全速运行(F5),程序始终在原位置不动(0x1FFF4252),如果强制的将PC指针的值和SP的值修改为0x8000000与0x2000000,然后在点击运行,则能够跑到main()函数,再全速运行,能够看到客户板子上的LED灯的闪烁。 但是如果不强制修改PC和SP指针的值,则程序不执行。 所以问题就变成为什么程序下载进去后的地址是0x1FFF4252?0x1FFF4252又是什么地址呢?查阅相应的手册,发现0x1FFF4252是处在了Systemmemory区域。 用万用表测量了客户板上的Boot0引脚的电平,发
[单片机]
基于51单片机<font color='red'>i2c</font>多字节的读写
按平台模式设计的虚拟I2C总线软件包VIIC
摘要:VIIC是主方式下的虚拟I2C总线软件包,用于80C51系列单片机的单主系统中。只需两根普通I/O口线就可随时扩展I2C总线外围器件。将VIIC1.0装入程序存储器中,对其中的符号单元赋值后,使用三条通用操作命令就可实现任何I2C总线外围器件的应用程序设计。本文以VIIC为例,介绍应用软件形式的广义平台设计方法,给出VIIC1.0程序文本。按照这一思路,也可移植到其他系列的嵌入式系统中。 关键词:平台模式虚拟I2C总线VIIC应用程序设计 一、I2C总线及其虚拟应用 1. I2C总线应用呼唤平台模式 目前,单片机应用系统的外围扩展已从并行方式为主过渡到以串行方式为主的时代。许多新型外围器件都带有串行扩展接口。通常的串
[应用]
STM8S003的GPIO模拟I2C切换输入输出的解决办法
刚开始学STM8,很多东西刚了解,正在做一个温湿度显示小板,就是使用I2C驱动SHT20传感器,并显示到数码管,数码管用的四位一体共阴数码管,STM8管脚有限,添加了一片TM1650做驱动,不过SHT20和TM1650都是用的I2C接口,由于对STM8硬件I2C还不了解,先打算用软件模拟,这就涉及到需要对GPIO做输入输出切换处理来检测ACK响应,刚开始,直接操作DDR寄存器,但是出现从输出切换到输入就会出现单片机死机,不解,查资料,得到一个解决办法,在输出状态时,可以不用切换到输入,我使用管脚D4,D5这两个管脚,这两个管脚比较特殊,就是真正开漏,在管脚描述为T,其它描述为HS(高吸收电流)。 解决办法,将IO设置为开漏输出
[单片机]
伍尔特电子发布干扰抑制应用说明 I2C 总线的滤波和浪涌保护
瓦尔登堡(德国), 2023 年 11 月 07 日 — 伍尔特电子 发布新的应用说明: 《 ANP121 - I 2 C 总线的滤波和浪涌保护》 。在 这篇 新的应用说明中,这家电子和机电元件供应商为在跨电路板方案中使用 I ² C 总线(集成电路总线)的开发人员提供了 宝贵 的支持。通过连接器或电缆扩展接口可 能会导致 I ² C 总线易受外部干扰,如静电放电 (ESD) 、 瞬态干扰 和辐射射频。这份应用说明旨在介绍一种 合适 的滤波和保护电路 ,以 提高 I ² C 总线的抗噪能力同时又不会 影响数据线和时钟线信号质量 。 伍尔特电子支持网站上最新增加的应用特定说明包括《I 2 C 总线
[电源管理]
伍尔特电子发布干扰抑制应用说明  <font color='red'>I2C</font> 总线的滤波和浪涌保护
mini2440-i2c驱动分析
在s3c2440的i2c驱动框架中, 分2个部分的内容, 一部分是i2c-adapter初始化, 一部分是i2c-driver的初始化. 针对s3c2440自带的eeprom, 走读一下代码, 看看哪些东西值的我们学习和借鉴. s3c2440上有若干个i2c-adapter, 每一个对应一条i2c总线, 每个总线上可以挂多个i2c 设备, 读写这些设备的方式是操作i2c-adapter的寄存器.挂在同一个i2c-adapter下的i2c设备通过同一个 adapter的发送算法对数据进行操作. 换言之: 一个adapter对应一条总线, 对应一组算法, 操作这条总线下的设备. 那么很容易理解, 要操作i2c设备, ada
[单片机]
mini2440-i2c驱动分析
STM32 I2C Slave(SMBUS)模式软件参考设计
I2C大家都很熟悉,总共2根线,CLK和DATA,stm32的I2C相信大家就更熟悉了,采用写控制器的方式,直接由控制器去完成I2C时序操作,用户无需关心具体产生的逻辑。然而,大部分情况下,使用的都是I2C Master模式,即主设备模式,很少当成slave模式即从设备模式来用,这篇文章讲的是如何把stm32 I2C当成slave模式来使用,更严格来说,本篇讲的是smbus模式。 从官网stm32手册上我们发现了smbus和I2C区别,大家自行理解: 真正使用时,可以把smbus等同于I2C来设置和使用,从代码上看,除了I2C Clock设置为20K之外,其它暂无明显区别。以下为I2C smbus模式的设置: v
[单片机]
<font color='red'>STM32</font> <font color='red'>I2C</font> Slave(SMBUS)模式软件参考设计
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
随便看看
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved