[U-Boot-Users] I2C Initialization, important Update!!

Joakim Tjernlund joakim.tjernlund at lumentis.se
Fri Mar 14 14:38:50 CET 2003


> > For I2C Reset it is adviseable to cause at least a sequence of eight STOP
> > one START and another STOP condition. Some Manufacturers (Microchip when I
> > remember correctly) require that because in violation of the I2C Spec they
> > do not recognize a STOP condition while expecting the Bits of a Byte.

So does the DS1337 also, but I don't think this is a bug. When you are
reading FROM a I2C device, it owns the SDA signal and all you can do is
set the master SDA to high and generate clocks util the slave wants ACK/NACK.
When the slave sees the masters high SDA during the ACK/NACK cycle it will
look for a START or STOP condition. If the slave sees a STOP, it will go
into "passive"(release the bus) mode and listen for a new transmision.  

> > Otherwise you might end up writing an arbitrary value the last addressed
> > location in your I2C memory if the previous transfer has been interrupted in
> > an unfortunate state... (see also I2C Edge Conditions, which addresses a
> > part of the Problem).
> 
> Hi 
> 
> I have a DS1337 RTC which hangs if you press the reset button while doing
> hwclock. To "unhang" the DS1337 I have to remove the battery :-(.
> I figured the above I2C reset trick would help, but so far nothing helps.

[SNIP]

I managed to fix my problem, by coping the latest soft I2C code u-boot,
but I had to do some some changes to make it work reliably. I think this
is something all 8xx(possibly 82xx too) suffer from.

On my boards(862, B0 rev.) I2C_ACTIVE will pull SDA low initially whatever
I do(verified with a scope)!! 
This messes up the DS1337 so it wont recover(sometimes), no matter how
many times I run the loop. By modifying the code to avoid activate, see #if 1
below, SDA is kept high until I do stop(as it should). 

I think the I2C_ACTIVE behaviour is a CPU bug, possibly in other 8xx PUs as well.
Can anybody confirm this?

This is what I run now:

void myi2c_reset(void)
{
	volatile immap_t *immr = (immap_t *)CFG_IMMR;
	int j;

	immr->im_cpm.cp_pbpar &= ~(PB_SCL | PB_SDA);	/* GPIO */
	immr->im_cpm.cp_pbodr |=  PB_SDA;	/* Open Drain Output */

	if(getenv("noi2cres")){
	  printf("No I2C reset!\n");
	  return;
	}
if 1
	I2C_SCL(1);
	I2C_SDA(1);
	I2C_INIT;
	I2C_TRISTATE;
#else
	I2C_SCL(1);
	I2C_SDA(1);
	I2C_INIT;
	I2C_ACTIVE; /* Buggy, will pull SDA low! */
#endif
	for(j = 0; j < 9; j++) {
		I2C_SCL(0);
		I2C_DELAY;
		I2C_DELAY;
		I2C_SCL(1);
		I2C_DELAY;
		I2C_DELAY;
	}
	send_stop();
}





More information about the U-Boot mailing list