I2C is almost the most universal serial bus in embedded systems. All devices around MCU can use it as long as the speed requirement is not high. The advantages are good compatibility (almost all MCUs have I2C host controllers, and IO simulation can be used if they don't), small pin occupancy, and simple chip implementation. Although the I2C protocol is simple, there are still many minor problems in actual use. Today, let's take a look at one of the most common problems in daily life: I2C slave hangs up.
Many things are not difficult and often happen. Every time I think I understand something, but when you finally ask me to explain it, I always can't justify myself. It's very uncomfortable. So when I decided to write a blog, I wanted to write the content as clear, detailed and even thorough as possible, hoping that every student who reads the blog can understand it clearly and learn a little knowledge. If you still don't understand something, please leave a message to communicate.
I2C Specifications and Features
What is I2C? I believe that 99% of the students who clicked on this blog have a certain understanding of I2C. Here is an authoritative manual from NXP (formerly Philips Semiconductor), the originator of I2C: I2C-bus specification and user manual v.6
This section describes the most important features of I2C to lay the foundation for describing the problems and solutions later.
I2C is a multi-master and multi-slave serial synchronous communication bus consisting of two lines (clock SCL + data SDA).
The specification requires that the SCL clock and SDA data lines of devices connected to I2C must be bidirectional open-drain structures, and pulled to a logic high level through pull-up resistors on the bus. Such a structure can realize the line AND (&) function.
Generally, the SDA of I2C can only change when SCL is at a low level, and needs to be maintained when it is at a high level. Corresponding to the chip design, it is sampled on the rising edge and changes on the falling edge.
The two exceptions are the bus start condition START (SDA changes from high to low when SCL is high) and the stop condition STOP (SDA changes from low to high when SCL is high) issued by the master.
Hang = hang + freeze
The word "挂死" probably comes from the English word "hangs": To cause (a computer system) to halt so that input devices, such as the keyboard or the mouse, do not function.
As mentioned earlier, the wire-AND structure is the most critical feature of the I2C bus design. This structure can be used to achieve
Multi-host arbitration synchronization
Slow slave synchronizes with fast master
Because of this feature, as long as any device on the bus pulls down SDA or SCL, other devices cannot pull them up, and all they see are low levels. If a device does not release the bus, the communication on the entire bus will be suspended, which we call I2C bus hangs: I2C bus hangs
Because the I2C host is generally a programmable device under our control, if the host actively pulls down the bus, we can understand the reason through debugging code, and we can also easily exit this state by resetting the I2C peripheral or resetting the chip. However, the I2C slave often does not have a RESET pin. If the bus is hung, even if the entire system is reset, it cannot be released, and it can only be restored by powering on and off again. This is unacceptable in many systems, so we need to be more careful in handling the situation where the I2C slave is hung. The following analysis is also written for the I2C slave hanging.
SDA hangs
Let's first look at the situations in which the I2C slave needs to pull the SDA line low.
When the master writes data or address to the slave, if the slave sends an ACK response, it will pull down SDA during the 9th CLK.
When the host reads data, the slave will pull down SDA during the CLK period corresponding to the bit being 0.
Then, in what circumstances can an I2C slave clamp the SDA line? Let's first look at a typical I2C master initiating a read operation on a device address. The data read is 10011000b, with the MSB first, which is 0x98. In the figure, during the 9th CLK of the address byte, the slave pulls down SDA to indicate a response to the address. During the 2nd, 3rd, 6th, 7th, and 8th CLKs of the returned data byte, the slave pulls down SDA to output a logic 0 level.
According to the I2C protocol mentioned above, when SCL is high, the SDA level should be maintained, and it can only change after SCL is low (that is, after the falling edge). What if the host does not pull SCL low after SCL is pulled high in the first half of the above CLK cycles? What will the slave do? YES, the slave will continue to pull SDA low until it sees the next falling edge that it should output a high level.
The most common situation is that the host generates a reset during the communication process. Since the reset action is usually executed immediately, the peripheral state machine is restored to the default state, and the complete CLK cannot be sent. Then when the host completes the reset and returns, SCL is high and SDA is pulled low by the slave. The host cannot initiate the START condition and cannot start the next communication with the slave. This is called SDA hanging.
To find a way to recover, we first need to know when the slave will release SDA. Since the falling edge of SCL just now was not given, the first thing to do to recover the bus is to find a way to use GPIO to simulate a falling edge on the SCL line to let the slave state machine continue. Sending only a falling edge does not necessarily release SDA, because we don't know which state the slave is in when the host reset exception occurs. So we need to detect CLK by CLK until we see SDA is released. Then we terminate and send a STOP condition to tell the slave that this terrible communication is over.
The method commonly taught on the Internet is to simulate 9 consecutive CLKs, but I prefer the above method because it is fast and deterministic. When sending 9 CLKs, I am mainly worried that the slave will pull down SDA again at the last CLK, so I still need to use the above method to release it.
Let's experience it by simulating several situations (the operation of the slave on SDA is shown in red):
If the host is reset after the 9th CLK of the address byte is pulled high, the release of SDA can be seen during the first simulated clock low level period, and then the host pulls SDA low first, and then simulates a STOP end condition.
The host is reset after the second CLK is pulled high in the data byte, and the SDA is released during the second simulated clock low period.
The host is reset after the sixth CLK is pulled high in the data byte, and the SDA is released during the third simulated clock low period.
Through the analysis of the above three situations, I believe you have already known very well how to deal with it. Finally, a program processing flow chart is attached:
SCL hangs
It is a legal behavior for the I2C slave to actively pull down the SCL line in the specification, which is called Clock Stretching (I usually call it clock synchronization). Usually, after the host requests data (receive or send), the slave needs some time to process it, and there is no extra buffer to receive or provide the next data. The slave will pull down the SCL line for a while until new data is ready.
SCL hangs (that is, the SCL is pulled low all the time as mentioned above) and this situation will not occur in standard I2C slave devices, because as long as the chip is still working normally and the buffer is finally ready, SCL will be released naturally. It is often caused by programming problems when users use MCU as I2C slave, which makes MCU unable to read & fill buffer. The focus is on analyzing MCU I2C interrupt service program.
I2C interrupt service routine is accidentally blocked
The interrupt service program is stuck in a while(flag != xxx) infinite loop of some flag bit query
The I2C function system was unexpectedly disabled
Previous article:Calculate the transfer rate of analog I2C
Next article:I2C deadlock causes and solutions
- Popular Resources
- Popular amplifiers
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- LED chemical incompatibility test to see which chemicals LEDs can be used with
- Application of ARM9 hardware coprocessor on WinCE embedded motherboard
- What are the key points for selecting rotor flowmeter?
- LM317 high power charger circuit
- A brief analysis of Embest's application and development of embedded medical devices
- Single-phase RC protection circuit
- stm32 PVD programmable voltage monitor
- Introduction and measurement of edge trigger and level trigger of 51 single chip microcomputer
- Improved design of Linux system software shell protection technology
- What to do if the ABB robot protection device stops
- Huawei's Strategic Department Director Gai Gang: The cumulative installed base of open source Euler operating system exceeds 10 million sets
- Download from the Internet--ARM Getting Started Notes
- Learn ARM development(22)
- Learn ARM development(21)
- Learn ARM development(20)
- Learn ARM development(19)
- Learn ARM development(14)
- Learn ARM development(15)
- Analysis of the application of several common contact parts in high-voltage connectors of new energy vehicles
- Wiring harness durability test and contact voltage drop test method
- 15 "Wanli" Raspberry Pi car - photoelectric encoder learning (forward and reverse judgment)
- A TOF "image" sensor that is worth playing with, VL53L5CX
- ARM immediate number explanation--the difference between LDR and MOV
- TI C5000 compiler error message list
- TI Award-winning Live Broadcast: Talking about "packaged antenna" smart millimeter wave sensors, even novices can handle industrial robots
- The voltage of the TPS73033 buck chip drops to 0.7V after the load is connected
- Wi-Fi 6 is here to provide network coverage for the entire home. Will you adopt it?
- Common APDU instruction error codes for CPU cards
- [GigaDevice GD32F310 Review] +ADC Data Collection
- [Mill Edge AI Computing Box FZ5 Review] Development Board Target Classification Demo