I2C freezes ATmega

For Adafruit customers who seek help with microcontrollers

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
uhe
 
Posts: 178
Joined: Mon Sep 03, 2007 4:50 pm

I2C freezes ATmega

Post by uhe »

I'm trying to read some data out of an i2c IO-expander but sometimes the ATmega freezes completely.
I was able to trak the cause of this down to the point where it waits for a read to be finished.

Code: Select all

while(!(TWCR & (1<<TWINT)));
Does that ring a bell? Are there some known errors with this?

mwilson
 
Posts: 46
Joined: Sun Oct 23, 2011 11:17 am

Re: I2C freezes ATmega

Post by mwilson »

That by itself won't cause a problem. It's meant to wait until TWI has finished the operation it's doing. Is it doing an operation? Going into your wait code twice in a row without starting an operation in between will hang.

In my own code I prefer to wrap things in a way that's still pretty hardware-centric, but structured enough to prevent the problem I've described:

Code: Select all

static unsigned char twi_op (unsigned char op)
{
	TWCR = op;
	while (! bit_tst (TWCR, TWINT)) ;	// wait for TWINT
	return TWSR & 0xF8;
} // twi_op

#define TWI_OP	(1<<TWINT | 1<<TWEN)

static void ds1307_read_buf (unsigned char addr, unsigned char *buf, unsigned char n)
{
	int j;
	if (twi_op (TWI_OP | 1<<TWSTA) != 0x08)	// START condition
		goto bailout;
	
	TWDR = DS1307_W;		// WRITE command
	if (twi_op (TWI_OP) != 0x18)	goto bailout;

	TWDR = addr;	// DS1307 address
	if (twi_op (TWI_OP) != 0x28)	goto bailout;

	if (twi_op (TWI_OP | 1<<TWSTA) != 0x10)	// Repeated START
		goto bailout;
	TWDR = DS1307_R;			// READ command
	if (twi_op (TWI_OP) != 0x40)	goto bailout;
	
	for (j=0; j < n-1; j++) {		// read all bytes except the last with following ACK
		if (twi_op (TWI_OP | 1<<TWEA) != 0x50)	goto bailout;
		buf[j] = TWDR;
	}
	if (twi_op (TWI_OP) != 0x50)	goto bailout;	// read the last byte without ACK
	buf[n-1] = TWDR;
bailout:	
	TWCR = TWI_OP | 1<<TWSTO;
} // ds1307_read_buf
(bit_tst is a macro that does the

Code: Select all

(REGISTER & (1 << BIT_NUMBER))
)
Also, the above is AVR-only because of all the 0x?? status constants that come straight from the datasheet.

Barring that, which port expander are you using?

mwilson
 
Posts: 46
Joined: Sun Oct 23, 2011 11:17 am

Re: I2C freezes ATmega

Post by mwilson »

Actually, this is nonsense, isn't it? My code is very interesting and all, but my discussion of the hanging thing is flat-out wrong. Have you got the TWI interface turned on? What IS the device you're dealing with?

uhe
 
Posts: 178
Joined: Mon Sep 03, 2007 4:50 pm

Re: I2C freezes ATmega

Post by uhe »

I'm using a ATmega168 connected to an MAX7318 (IO expander with interrupt) which has two MAX6818 (debouncer and ESD protection) at it's 16 I/O pins. The IRQ output of the MAX7318 is connected to INT0. For I2C I'm using the I2C lib from Peter Fleury.
I have a bunch of buttons connected to the MAX6818 and most of the time everything is working but sometimes the whole thing freezes.

My code goes like:

Code: Select all

while(1) {
  someADCstuff();
  if((IRQ_0 & 0x1)){
    IRQ_0 &= ~0x1; 
    readIOexpander();
  }
}

uint8_t readIOexpander(){
  GPIOR1 = 0;
  INT_0_OFF;                                            // macro to disable the INT0
  i2c_start_wait(addr+I2C_WRITE); 	        // set device address and write mode
  i2c_write(reg);   
  i2c_start(addr+I2C_READ); 	              // restart
  GPIOR1 = i2c_readNak();
  i2c_stop();
  INT_0_ON;
  return GPIOR1;
}

unsigned char i2c_readNak(void) {
	TWCR = (1<<TWINT) | (1<<TWEN); // | (1<<TWIE);
  PORTB |=  _BV(PB0);                             // DEBUG LED ON
	while(!(TWCR & (1<<TWINT)));
  PORTB &= ~_BV(PB0);                             // DEBUG LED OFF
    return TWDR;
}/* i2c_readNak */



ISR(INT0_vect) {
  IRQ_1 |= 0x1;
}
*i2c_*-stuff is from the library and when I'm able to trigger the freeze the debug LED stuff tells me it's the while() in i2c_readNak() where it hangs.


CAPTCHAS FOR LOGGED IN USERES ARE PRETTY ANNOYING BTW!!!

mwilson
 
Posts: 46
Joined: Sun Oct 23, 2011 11:17 am

Re: I2C freezes ATmega

Post by mwilson »

Fascinating. Is that Peter Fleury's library you're using? I've never tried to bit-bang an I2C interface; always used the on-chip peripheral. Two things off the top of my head -- no guarantee they're any righter than my old reply:

1) should your repeated start use i2c_rep_start instead of i2c_start ?
2) since Fleury's library never seems to go anywhere near the on-chip interface, the TWSR register isn't affected by anything the library does. As far as the on-chip TWI interface is concenred nothing is happening. If you're using Fleury's other functions then you'll have to use or mimic his i2c_readNak. Assuming I understand this correctly.

CAPTCHAS -- yeah. just had a great comment shot down from the blog because I got the captcha wrong on the first pass, and when I re-entered it, BANNED killed me for commenting too frequently. Little logic glitch there.

adafruit
 
Posts: 12151
Joined: Thu Apr 06, 2006 4:21 pm

Re: I2C freezes ATmega

Post by adafruit »

mwilson wrote:CAPTCHAS -- yeah. just had a great comment shot down from the blog because I got the captcha wrong on the first pass, and when I re-entered it, BANNED killed me for commenting too frequently. Little logic glitch there.
hiya! can you email [email protected] we'd like to see which post that was on.

thanks!
adafruit support, phil

uhe
 
Posts: 178
Joined: Mon Sep 03, 2007 4:50 pm

Re: I2C freezes ATmega

Post by uhe »

Is there any alternative to Fleury's lib?

1) one line summary of rep_start: unsigned char i2c_rep_start(unsigned char address){ return i2c_start( address ); }
The datasheet says the same ;)
2) TWSR... may I cite?
These 5 bits reflect the status of the TWI logic and the 2-wire Serial Bus. The different status codes are described
later in this section.
Has anyone found a description of theese status bits anywhere?

At this point I this I'll switch to SPI an polling instead of IRQ driven I2C.

tldr
 
Posts: 466
Joined: Thu Aug 30, 2012 1:34 am

Re: I2C freezes ATmega

Post by tldr »

uhe wrote:
These 5 bits reflect the status of the TWI logic and the 2-wire Serial Bus. The different status codes are described
later in this section.
Has anyone found a description of theese status bits anywhere?
later, earlier, what difference does it make when you're writing data sheets in trondheim in the dead of winter.

see tables 22-2, 22-3, 22-4 and 22-5.

Locked
Please be positive and constructive with your questions and comments.

Return to “Microcontrollers”