Hi. I have a I2C network with slaves. My problem is that periodically Arduino Freezes. This bug can be also forced if you put a screewdriver on I2C Analog Pins 4 or 5 during a moment. Arduino freezes and it is in unrecoverable state until next reset.
Investigating, the problem is <twi.c> blocking behavior without timeouts. (endless loops "while")
I have "solved" it with a counter timeout in all "while" loops. Now Arduino doesn't freezes, but I cannot found, there is no way to initialize or recover again the I2C Network without Reset Arduino.
Investigating more, the reason is in Interrupt Vector Code:
SIGNAL(TWI_vect)
switch(TW_STATUS){
...
case TW_MT_SLA_NACK: // address sent, nack received
twi_stop();
...
it it always entering with TW_MT_SLA_NACK code an then twi_stop, and from here I don't know how to continue.
I think this is a severe problem with Arduino and I2C networks, because any bus problem freezes arduino by code, or if you avoid freezing I2C network is unrecoverable.
A good analysis of some hidden bug..
I think you should not just leave the wait loops, but rather re-initialize the TWI hardware completly in that time-out case. This might need more changes in the library...
I have "solved" it with a counter timeout in all "while" loops. Now Arduino doesn't freezes, but I cannot found, there is no way to initialize or recover again the I2C Network without Reset Arduino.
I handle this pretty much the way you suggest (using a 5000 microseconds timeout), but when a state timeout is detected (assuming a bus issue), I call twi_init. For this to be effective, you also need to add the following statement to the top of twi_init:
void twi_init(void)
{
// disable twi module (to allow for reinitialize)
TWCR = 0;
// ... original code follows
// initialize state
twi_state = TWI_READY;