STM32’s I2C 硬件BUG引发的血案
2010-4-8 1: 45?下面的函數中有一個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的筆記,放了下,晚上出差到深圳,到客戶處做系統需求的討論會,主要是上位機部分的。然后第二天晚上又趕回來,在車上的半夢半覺中讓潛意思去思考?;氐郊液?#xff0c;選擇在我的生物鐘的最佳的時侯,晚上10點。開始重新在問題的Brainstorm處接著DUBGE。WORK PLAN如下:
(1)把程序恢復到測試I2C寫的測試用例狀態,PASS。
(2)一小段代碼就DEBUG一次的步步為營方法,按之前的思路把代碼加入到讀的模塊(忽略防守代碼,只加入必需的功能代碼)。都OK后,全速運行,XXX,又卡住了。細過了一片讀模塊。PASS。于是進入計劃中的(3)
(3)全速運行,然后在可能卡住的地方加上斷點,而不是之前的先加斷點,然后運行的方式(這種方式,已確認PASS):
加了幾處后,發現程序是在下面代碼處卡住的:
但是奇怪了,每次我只要在箭頭指向的語句后加上斷點,每次都能PASS。于是知道要到 I2C_CheckEvent 函數中就能找到問題的原因了,于是做下面的幾步,目的是把包含I2C_CheckEvent Fun的鏈接庫中的stm32f10x_i2c.o排除掉,而把stm32f10x_i2c.c加入到項目中,使得DEBUG時能進入到 I2C_CheckEvent Fun 中去.
于是全速運行,然后在 stm32f10x_i2c.c中加上斷點,終于捕捉到問題點了,分析如下圖所示:
/* 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的),如下圖所示:
這應該是STM32 I2C硬件接口的BUG,解決方法如下:
把庫中的I2C中斷事件判定結合SR1和SR2的思路相反,我把讀SR1和SR2明確地分了出現,并進行確認,?PASS, 給模塊加上防守代碼,做好文檔,?至此,模塊的生命周期進入到白盒測試和黑盒測試階段.
總結
以上是生活随笔為你收集整理的STM32’s I2C 硬件BUG引发的血案的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: stm32启动文件ld md hd cl
- 下一篇: 关于IO模式(浮空、推挽、开漏...)描