I2C freezes arduino

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")

uint8_t twi_writeTo(...
...
while(TWI_READY != twi_state){
    continue;
  }
...
while(wait && (TWI_MTX == twi_state)){
    continue;
  }
...

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.

Any trail or solution?

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;

OK with your solution, TWCR = 0 is the key. Now I2C autorecover after failure.

These are my "final" twi.c and twi.h:

http://liken.otsoa.net/pub/ntwi/twi.h
http://liken.otsoa.net/pub/ntwi/twi.c

Expecting for a better and elegant solution...