Go Down

Topic: I2C freezes arduino (Read 11912 times) previous topic - next topic

unaie

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

Code: [Select]

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:

Code: [Select]

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?








deSilva

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...

BenF

#2
Sep 08, 2010, 08:29 am Last Edit: Sep 08, 2010, 08:32 am by borref Reason: 1
Quote
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:

Code: [Select]

void twi_init(void)
{
 // disable twi module (to allow for reinitialize)
 TWCR = 0;

 // ... original code follows

 // initialize state
 twi_state = TWI_READY;



unaie

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...



Go Up
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy