STM32's I2C hardware bug caused a murder

Publisher:咖啡狐狸Latest update time:2018-06-03 Source: eefocusKeywords:I2C Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

There is a BUG in the function below, that is, SR2 cannot be polled using WHILE, but should be read directly. As shown in the following code segment, Therefore, what I say here is a BUG of STM32 is actually an error in my code:
    I2C2->DR = inerAddress[1];
    while( (I2C2->SR1&Q_I2C_SR1_BIT_BTF)==0 );
    I2C2->SR2; // Correct answer

2010-4-1 1:44, I never believed that there would be problems with the I2C interface of STM32, because my work experience has told me countless times that 99.999% of the problems in embedded system design are not caused by the design problems of the MCU itself, but most of them are caused by a design defect of hardware engineers or software engineers. This design experience is no exception.

Since I can finally spare more time to design the software interface of STM32's I2C, I decided to reconstruct the I2C module (based on I2C interrupt + state machine transceiver) used for master-slave STM32 communication. The I2C interrupt transmission module was quickly reconstructed and the error handling and I2C bus hang self-recovery function code modules were strengthened (I2C BUS Hang: that is, SDA and SCL are both pulled low by a slave device. Most of the cases occur when the host receives the last byte of the data packet from the slave without sending P (stop bit). At this time, the slave device (EEPROM) cannot receive P, so it will send data to the host in a DEAD LOOP. From the host's perspective, the I2C bus is equivalent to being in a BUSY state. This is the most frequently asked question about I2C on the Internet - why does the I2C bus TMD suddenly die, BUSY, or HANG.).

I thought that the I2C interrupt read module would be completed smoothly, but I was stuck for a whole day. It didn't matter if I added a breakpoint in most of the code. The read FUN was executed correctly every time, but as long as it was run at full speed, it could only run once and then it would not pass. The place where it could not pass was not fixed. Because I couldn't concentrate on the DUBEG, I made a note of the problem's Brainstorm, put it aside, and went on a business trip to Shenzhen at night to discuss system requirements with the customer, mainly the host computer part. Then I rushed back the next night and let my subconscious mind think in a half-asleep in the car. After returning home, I chose the best time for my biological clock, 10 o'clock in the evening. I started to DUBGE again at the problem's Brainstorm. The WORK PLAN is as follows:
(1) Restore the program to the test case state written for testing I2C, PASS.

(2) A step-by-step approach of debugging a small section of code. Following the previous idea, add the code to the read module (ignore the defense code and only add the necessary functional code). After everything is OK, run at full speed. XXX, it is stuck again. Go through a section of the read module. PASS. Then proceed to the planned (3)

(3) Run at full speed, then add breakpoints where the program might get stuck, instead of adding breakpoints first and then running (this method has been confirmed to pass):
After adding a few breakpoints, it was found that the program got stuck at the following code:
image

But strangely, every time I add a breakpoint after the statement pointed by the arrow, it will pass every time. So I know that I can find the cause of the problem in the I2C_CheckEvent function, so I do the following steps, the purpose is to exclude the stm32f10x_i2c.o in the link library containing I2C_CheckEvent Fun, and add stm32f10x_i2c.c to the project, so that I can enter I2C_CheckEvent Fun when debugging.

image

image

So I ran it at full speed, and then added breakpoints in stm32f10x_i2c.c, and finally caught the problem. The analysis is shown in the following figure:

image

/* Read the I2Cx status register */
// flag1 = I2Cx->SR1; // Original code
// flag2 = I2Cx->SR2; // Original code
// flag2 = flag2 << 16; // Original code

  /* Get the last event value from I2C status register */
  //lastevent = (flag1 | flag2) & FLAG_Mask; //Original code
  lastevent = (vu32)( (vu32)(I2Cx->SR1) | ((vu32)(I2Cx->SR2) << (vu32)16) ); //qzm is added for confirmation, the actual effect is the same as using the library.
  lastevent &= (vu32)FLAG_Mask; //qzm is added for confirmation, the actual effect is the same as using the library.

To confirm, I also changed all variables in Fun to start with v to ensure that they are not optimized by the compiler, and the compiled code is not optimized. However, at full speed, the events obtained by I2C will have an extra BTF bit. At the beginning, if you enter DEBUG, add a breakpoint, and then run, lastevent == 0x30001 (which also shows that there is no BUG in the library code), as shown in the following figure:

image





This should be a BUG of the STM32 I2C hardware interface. The solution is as follows:


image

The idea of ​​combining the I2C interrupt event judgment in the library with SR1 and SR2 is the opposite. I clearly separate the reading of SR1 and SR2, and confirm and pass them. I add defense code to the module and do a good job of documentation. At this point, the life cycle of the module enters the white box test and black box test stage.


Keywords:I2C Reference address:STM32's I2C hardware bug caused a murder

Previous article:A brief discussion on the use of STM32 hardware I2C (interrupt mode without DMA and without the highest priority)
Next article:STM32 I2C Hardware

Recommended ReadingLatest update time:2024-11-16 14:33

Logic Analyzer Provides Complete Solution for I2C Signal Measurement
  The I2C bus is a very common bus in electronic products. Its advantage is that it only needs two lines to connect many ICs in parallel for control. However, due to the multi-device and open drain architecture, it is often difficult to troubleshoot the I2C bus. This article will present some practical application case
[Test Measurement]
s3c2440 bare metal - i2c programming - 3 - i2c program framework
1. Functions of iiC devices Obviously, the IIC controller provides the ability to transmit data, but the IIC controller does not know what the data means. The meaning of the data is from the external I2C slave device. We need to read the chip manual to know what data the IIC controller should send. The fol
[Microcontroller]
s3c2440 bare metal - i2c programming - 3 - i2c program framework
STM8L drives I2C type 12864
principle I have never used a 12864 screen before, but I have used other types, and the principles are the same. 12864 is the name of a screen with 128x64 pixels. The screen has 64 rows and 128 columns; each Chinese character is 16x16, so such a screen can display up to 4x8 Chinese characters or 8x16 characters. I
[Microcontroller]
Design and implementation of OSD display driver based on I2C
With the development of the automobile industry, in-vehicle navigation equipment has been used more and more. Now mainstream in-vehicle navigation equipment is integrated with DVD function, which puts forward high requirements for video processing. Choosing high-performance platform and high-performance video proces
[Power Management]
Design and implementation of OSD display driver based on I2C
STM32 simulates i2c driver ht16c22
The iic.h file is as follows: #ifndef _stm32f103_myi2c_h_ #define _stm32f103_myi2c_h_ //IO direction setting #define SDA_IN() {GPIOB- CRH&=0XFFFF0FFF;GPIOB- CRH|=8 12;} #define SDA_OUT() {GPIOB- CRH&=0XFFFF0FFF;GPIOB- CRH|=3 12;} //IO operation function #define IIC_SCL PBout(10) //SCL #define IIC_SDA PB
[Microcontroller]
I2C bus AT24C02 reading and writing program
pre //**************************************************** /* Function of the program: write data into AT24C02, then read it back and assign it to port P2 to display the running light. Chip involved: AT24C02 */ //******************************************************** #include reg52.
[Microcontroller]
Realization of Audio Processing System Based on I2C Serial Bus Using Single Chip Microcomputer
At present, the diversified functions of consumer electronic products (such as color TVs, stereos, etc.) make the control circuit more complicated. The I2CBUS (Inter ICBUS) bus introduced by Philips is the most concise, effective and widely used bus format among many buses. The I2C bus is usually implemented in hard
[Microcontroller]
Latest Microcontroller Articles
  • Download from the Internet--ARM Getting Started Notes
    A brief introduction: From today on, the ARM notebook of the rookie is open, and it can be regarded as a place to store these notes. Why publish it? Maybe you are interested in it. In fact, the reason for these notes is ...
  • Learn ARM development(22)
    Turning off and on interrupts Interrupts are an efficient dialogue mechanism, but sometimes you don't want to interrupt the program while it is running. For example, when you are printing something, the program suddenly interrupts and another ...
  • Learn ARM development(21)
    First, declare the task pointer, because it will be used later. Task pointer volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • Learn ARM development(20)
    With the previous Tick interrupt, the basic task switching conditions are ready. However, this "easterly" is also difficult to understand. Only through continuous practice can we understand it. ...
  • Learn ARM development(19)
    After many days of hard work, I finally got the interrupt working. But in order to allow RTOS to use timer interrupts, what kind of interrupts can be implemented in S3C44B0? There are two methods in S3C44B0. ...
  • Learn ARM development(14)
  • Learn ARM development(15)
  • Learn ARM development(16)
  • Learn ARM development(17)
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号