tiny-i2c icon indicating copy to clipboard operation
tiny-i2c copied to clipboard

SCL release?

Open rscheff opened this issue 2 years ago • 5 comments

Hi,

Line 95 is supposed to "release" SCL (that is, make it an input pin, and validate that no other device pulls it down).

However, the code keeps this as an output (PORTB PIN is set, rather than unset)...

Unless I am mistaken, this should be a PORT_USI_CL &= ~(1<<PIN_USI_SCL);

What am I missing?

https://github.com/technoblogy/tiny-i2c/blob/1029f6fca7c297eb887b601e3b0e352f71e60d1c/TinyI2CMaster.cpp#L95

rscheff avatar Dec 14 '21 09:12 rscheff

Thanks - I'll have a look.

technoblogy avatar Dec 14 '21 09:12 technoblogy

Should have written

/* Release SCL to ensure that (repeated) Start can be performed */ DDR_USI_CL &= ~(1<<PIN_USI_SCL); // Release SCL. while (!(PIN_USI_CL & 1<<PIN_USI_SCL)); // Verify that SCL becomes high. DDR_USI_CL |= (1<<PIN_USI_SCL);

(make SCL an input, validate that the pull up still keeps SCL high, and make it a driven output again).

See https://www.i2c-bus.org/clock-stretching/

Unless I am mistaken, SCL "High" should normally be done not by driving it as an output high, but making it an input and rely on the pull-up resistor to pull SCL high (or a client keeping it low, if it needs more processing time).

rscheff avatar Dec 14 '21 09:12 rscheff

Thanks for your comment. From the datasheet:

The Serial Data (SDA) and the Serial Clock (SCL) pins are bi- directional and use open-collector output drives. The output drivers are enabled by setting the corresponding bit for SDA and SCL in the DDR Register.

As I understand it, because they are open-collector, setting SCL low leaves the slave free to pull it high, so it's OK the way it's written.

Was this a theoretical point, or have you encountered problems with the library as it's written?

technoblogy avatar Feb 16 '22 17:02 technoblogy

Well, if you keep the PORT as output and set it high, the PIN will most likely read one - as you are injecting current not only via the (high resistance, 1-22kOhm) pull up, but a low-resistance (0.1-10Ohm) MOS driver. Especially if the slave is some line resistance away and not able to pull down the 50 or 100 mA the MOS PIN driver can inject. Therefore you can not actually observe, if a I2C slave is pulling the SCL low to extend the clock cycle - the code will just "mostly" work as extendning the clock is not very often done.

IIRC the SDA is doing it correct, as NACK/ACK is a more common pattern, where pull form the pull-up resistor (a few kOhm) has to work properly - and a MOS high output (few milliohms to few ohms - depending on the MCU) would be too strong driving the line.

rscheff avatar Feb 16 '22 18:02 rscheff

I believe that putting the USI into two-wire mode changes the SCL and SDA output pins to open-collector. I based my code on the Atmel example code; I assume they knew what they were doing.

Have you done any testing to compare both approaches in practice?

technoblogy avatar Feb 16 '22 18:02 technoblogy