serial-bench / I²C / msg #7
A temperature-and-pressure part on a 400 kHz segment read back correctly from a bench script but returned garbage from the product firmware, on the same board, through the same wires. The difference was not the wires and not the pull-ups - I had already been down that road. It was that the device expected to be allowed to pause the bus, and one master let it while the other did not.
After the master writes the address byte and the read bit, this device needs to run a conversion before it has a data byte to give back. Rather than return a stale value or make the master poll, it does what the I²C specification explicitly permits a slave to do: it holds SCL low after the acknowledgement, which freezes the master's clock until the device is ready. The master cannot drive the next clock high because the slave is pinning the line down.
On the logic analyser the pattern is unmistakable once you know it. SCL ticks normally for the address byte, the slave pulls SDA low for the ACK on the ninth clock, and then SCL simply stops - flat low - for 1.41 ms. It is not SDA that is stuck, which is what a wedged bus looks like; it is SCL, held down between the ACK and the first data bit, and then clocking resumes as if nothing happened.
At 400 kHz a bit is 2.5 µs. The conversion stalled the bus for 1.41 ms, which is 564 bit times - as if the device had inserted five hundred invisible clock cycles. The bench script was written against a driver that waits for SCL to actually go high before counting a clock, so it simply waited out the 1.41 ms. The product firmware used a hardware I²C block whose default clock-low timeout was 25 µs; after ten bit times of SCL not rising it declared a bus error, issued a stop, and read whatever was on SDA, which was nothing coherent.
| Operation | Stretch | in bit times | 25 µs timeout | 5 ms timeout |
|---|---|---|---|---|
| Register read, cached | 0 µs | 0 | survives | survives |
| ADC single-shot | 1.41 ms | 564 | aborts | survives |
| Temperature + pressure | 2.2 ms | 880 | aborts | survives |
| EEPROM page write-back | 4.8 ms | 1920 | aborts | survives |
The specification bounds how long a slave may stretch only in the sense that fast-mode-plus devices advertise a maximum; it does not promise the master a short one. A master with a fixed timeout shorter than the slowest device's longest stretch will eventually meet an operation it cannot complete. The honest fix is to match the timeout to the parts on the bus, not to assume a number.
Two things, in order of confidence. First, the hardware I²C block's clock-low timeout was raised from 25 µs to 5 ms, comfortably above the 4.8 ms worst case in the table and still short enough to catch a genuinely dead bus within a human-noticeable time. Second - and this is the part I would argue for even on a bus with no stretching device today - the driver now treats a clock-low timeout as a recoverable event that retries the transaction once, rather than as a fatal bus error, because a marginal pull-up occasionally produces a slow SCL rise that looks like a short stretch.
What I check first now when an I²C device «works from the script and not from the firmware»: put the analyser on SCL alone and look for flat-low gaps between a byte's ACK and the next byte. If they are there, it is clock stretching and the question is the master's timeout, not the wiring. If SCL keeps ticking and SDA is wrong, it is back to levels and rise time.