1. Introduction: When the “Two Wires” Suddenly “Stop Working“
In the daily work of embedded engineers, the I2C bus, with its two-wire communication feature, is a prime example of “minimalist aesthetics“. However, this seemingly simple two-wire system can suddenly fall into a “deadlock“—the clock line (SCL) stubbornly remains high, while the data line (SDA) is firmly pulled low, causing the entire system to seem as if it has been paused. This is the I2C deadlock issue. This article will combine principle analysis with practical experience to unveil the mystery of deadlocks and master the complete process from diagnosis to recovery solutions.

Figure 1: I2C Communication Architecture Diagram, connecting multiple master and slave devices with two wires
2. Deadlock Scene: Characteristics and Causes Uncovered
(1) Typical Symptoms: Identifying Deadlocks at a Glance
Abnormal Signals: The SCL high level and SDA low level “weird combination“ breaks the I2C protocol’s “data must be stable when the clock is high” rule.
Communication Stagnation: The master device cannot initiate new transactions, and the slave device remains silent, causing the system to fall into an “infinite loop of master waiting for slave response and slave waiting for master action“.

Figure 2: Typical waveform during I2C deadlock, with SCL high and SDA continuously low
(2) The Four Major “Causes“
Inconsistent Timing between Master and Slave Devices: The master device suddenly “restarts“ due to a watchdog reset or power fluctuation, while the slave device remains “immersed” in unfinished communication, stubbornly pulling SDA low, preventing the master device from regaining control of the bus.Scenario Recreation: When the master device sends the 9th clock pulse and resets, the slave device has not yet completed its response, and SDA is “locked” low.
Slave Device’s “Rebellious Moment“: The slave device, due to hardware failure or program runaway, erroneously continues to pull SDA low.Typical Case: When the acknowledgment signal is output, SDA unexpectedly becomes 0, causing the master device to mistakenly believe the bus is occupied, leading both parties into a “standstill“.
Physical Layer’s “Subtle Interference“
◦Short Circuit Trap: SCL/SDA accidentally shorted to GND, directly crippling the bus signal.
◦Electromagnetic Interference: Noise in complex environments causes signal “transition distortion“, leading master and slave devices to misinterpret commands and cause chaos.
Contradiction between Speed and Stability: Pursuing high-speed communication highlights the bus capacitance effect: SCL cannot be released in time due to charge and discharge delays, causing SDA to be “dragged” into a low-level abyss.
3. Officially Certified “First Aid Manual“: Practical Recovery Strategies
(1) Software Fix: A “Gentle Wake-Up“
Nine Pulse “Wake-Up Technique“ Principle: The master device forcibly generates 9 clock cycles on SCL, akin to “gently shaking” the sleeping slave device, forcing it to release SDA.Practical Case: Tests on the STM32F103 platform show that this method can quickly resolve deadlocks and revive the bus.
Below is an example of I2C deadlock recovery code for the STM32 platform:
int32_t i2c_dev_io_reset(char *name){ struct iic_priv_data *priv; struct iic_dev_t *pdev = get_iic_dev(name); GPIO_InitTypeDef GPIO_InitStruct = {0}; if (pdev == NULL || pdev->priv_data == NULL) { return BMS_ERROR_NULL; } priv = pdev->priv_data; /* check sda line */ if (HAL_GPIO_ReadPin(priv->port, (priv->pin_sda)) == GPIO_PIN_RESET) { if (priv->handle != NULL) { /* release i2c bus */ HAL_I2C_DeInit(priv->handle); /* unlock i2c pin */ LL_IOP_GRP1_EnableClock(priv->port_clk_en); GPIO_InitStruct.Pin = (priv->pin_scl) | (priv->pin_sda); GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(priv->port, &GPIO_InitStruct); HAL_GPIO_WritePin(priv->port, (priv->pin_scl) | (priv->pin_sda), GPIO_PIN_SET); i2c_dev_delay(10); /* toggle the i2c scl pin */ for (int i = 0; i < 18; i++) { HAL_GPIO_TogglePin(priv->port, priv->pin_scl); i2c_dev_delay(10); } /* init i2c bus */ priv->priv_iic_init(); } } return BMS_SUCCESS;}
The above code releases SDA by waiting for the bus to be idle, sending 9 clock pulses, and reinitializing I2C to achieve deadlock recovery.
(2) Hardware Intervention: A Simple and Direct “Physical Therapy“
Power Cycling: The Most Direct “System Reset“ Disconnect the power from the master/slave devices, wait for the capacitors to discharge, and then power back on. Although it interrupts the system, it is highly effective for stubborn deadlocks.
Reset Pin Control: Precisely Targeting Faulty DevicesIf the slave device is equipped with a reset pin (such as an EEPROM or sensor), it can be forcibly reset through the MCU’s GPIO, such as directly controlling the slave device’s reset signal with STM32 for “targeted repair“.
I2C Switch: Isolating Faulty Devices with a “Firewall“ Deploy I2C switches (such as certain chips from TI) on the bus, which can quickly isolate the faulty branch when a device deadlocks, ensuring normal communication for other devices and enhancing system robustness.
4. Preventive Measures: Nipping Deadlock Risks in the Bud
(1) Hardware Design as a “Defense Fortress“
Strong Pull-Up Resistors: Choose pull-up resistors below 4.7kΩ to ensure the bus defaults to high level, enhancing anti-interference capability.
Isolation Design: Integrate I2C switches or buffers to “quarantine” faulty devices in a safe area.
Slave Devices with Reset Capability: Prefer chips that support hardware reset (such as sensors with RST pins) to leave a “backdoor” for future maintenance.
(2) Software Programming as a “Discipline Manual“
Avoid Interruptions Mid-Process: Disable non-essential interrupts during communication to prevent accidental modification of bus status.
Initiate Recovery Sequence: Perform an empty transmission or pulse sending at system initialization to clear residual bus states.
Simulate I2C as a Safety Net: For devices with strict timing requirements, simulate I2C timing in software to avoid hardware defects through precise control of pin levels.
5. Conclusion: The Ultimate Rule for Making Peace with Deadlocks
I2C deadlocks may seem tricky, but they are a microcosm of the interplay between embedded systems and the physical world. Through “hardware-software collaborative defense + precise recovery strategies“, we can build strong defenses during the development phase with strong pull-up resistors and timeout mechanisms, and quickly mitigate losses during operation with nine pulse wake-ups and hardware resets. Remember: there is no perfect system, but there are continuously evolving solutions—next time when SCL and SDA are again in a “standoff“, you will be the one who can break the deadlock as the “mediator“.