lucullusTheOnly / TinyWire

Composite Master and Slave I2C library for Atmels ATTiny microcontrollers
108 stars 26 forks source link

Rarely stuck SCL in multi master setup #10

Open lucullusTheOnly opened 6 years ago

lucullusTheOnly commented 6 years ago

When working in a multi master setup, I sometimes get a blocked bus. It was not easy reproducing this, because it seems to happen only very rarely (I had to do about 50 multi master transactions to let it happen again). So I could capture it on my scope. The reason for the blocking is that one of the masters holds the SCL line at LOW.

I investigated further and found the problematic code in the master function USI_TWI_Master_Transfer() in twi.cpp. Here the SCL line is controlled by writing a 1 to the USITC bit in the USICR register. By doing so the USI hardware should toggle the SCL line. It seems, that some action on the SCL line, due to other masters, can prevent the hardware from doing so. Directly after this line, the code waits in a while loop, until the toggling has taken place. This never happens, so the code gets stuck there until reset.

After long thought I may have found the overlying problem with the master code: The I2C specification states, that all lines have to be connected open drain, so that every circuit on the bus can drive them low, but not high. The code I used from the TinyWireM library sets both lines as OUTPUT at the initialization. So, when one circuit drives the SCL line low, while the library is driving it high, providing a powerfull output and not a high impedance pullup, there is a high current flowing between the circuits. The corresponding voltage on the SCL line depends on somewhat race conditions (how much current the one can drain in relation to how much the other can source). This may lead to circuit destruction, since it is basically a short.

I'm currently investigating, how to rewrite the master code as pure open drain and if this would solve the problem. Also this seems to be the reason, why using the library as a pure master blocks the bus for other masters.

j-protex commented 6 years ago

Hello lucullus, did you progress on this issue? I feel like I have a similar problem, but not sure. I use 2 masters to communicate with one I2C device, where both should access it on after the other. But the one who is using the TinyWire library (ATtiny85) seems to have problem with accessing the I2C device (an FRAM chip), and does not seem to write the values to it that it is supposed to..