DEV Community

jiahui dong
jiahui dong

Posted on Originally published at resume.tensorview.cc

Embedded Linux I2C Debugging: How a Register Dump Saved Me from an Invisible Timing Trap

This article was first published on my site: https://resume.tensorview.cc/blog/i2c-trise-ack-trap.html
CCR looked flawless. TRISE was the real trap.

Recently I worked on a layout where the host MCU needed more GPIOs, so we hung an I2C expander. Standard architecture — until intermittent EIO (-5) errors and missing slave ACKs showed up.

Instead of guessing at the driver, I took a structured path: scope the bus and dump physical I2C registers at the moment of failure.

The Illusion

The Clock Control Register (CCR) was calculated correctly for 100 kHz Standard Mode. On paper the baud rate looked flawless.

The Symptom

The oscilloscope showed a slight trailing edge on the SCL rise. The register snapshot at failure captured SR1.AF = 1 (Acknowledge Failure).

The Root Cause

TRISE (maximum rise time) was set too low. The I2C state machine jumped the gun — sampling before SCL had reached a valid high (Vih).

The Fix

I recomputed TRISE from PCLK and the I2C spec, updated Device Tree / driver init, and the bus stayed clean across a 10,000-cycle stress test.

Key Takeaway

High-level abstractions often mask physical reality. When a driver throws a generic error, dump the hardware registers. Registers do not lie.


Original post: https://resume.tensorview.cc/blog/i2c-trise-ack-trap.html

Top comments (0)