[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

I2C bus



Hi,
 
I've come across an interesting problem when trying to hook up the ETRAX 100LX to a peripheral via I2C.
 
I am writing a driver for the device, and was intending to use the functions in i2c.c and i2c.h in the /arch/cris/drivers directory. I thnk that the peripheral doesn't meet the I2C spec properly, as the peripheral does not correctly respond to i2c_readreg(). I hooked up a scope to the data pins, and following is what occurs. Our device has a 7 bit address of 0x21 (i.e. byte = 0x42 for write, 0x43 for read). START and STOP are the I2C start and stop conditions, NACK/ACK is the device response and I am trying to read register 0x1C
 
Data line -> START  0x42  ACK  0x1C ACK START 0x43 NACK 0xFF NACK
                                                                     ^          ^
                                         peripheral doesn't see this   peripheral tries to ACK here
 
The peripheral tries to send an ACK when the I2C bus sends the last bit (R/W) of the device address for the second time. I am fairly sure this is because it sees the second START as a data bit instead. Therefore it thinks that the value of the device address should be written to 0x1C, instead of reading from it.
 
To check this I made the following change to i2c_readreg(), I placed a STOP condition before the second START. (removed comments for brevity)
 
i2c_start();
i2c_outbyte((theSlave & 0xfe));
if(!i2c_getack())
error = 1;
i2c_dir_out();
i2c_outbyte(theReg);
if(!i2c_getack())
error = 1;
i2c_delay(CLOCK_LOW_TIME);
/* CHANGE MADE HERE */
    i2c_stop();
    i2c_delay(CLOCK_HIGH_TIME);
i2c_start();
i2c_outbyte(theSlave | 0x01);
/* etc */
 
The peripheral now works correctly, i.e. it returns data in the last byte, and all ACKs etc are performed correctly.
 
The question I have is will making this change break other I2C devices? If it does, then I will have to write a seperate I2C device driver for this peripheral. From my understanding of I2C, a repeated start condition, for example how i2c_readreg() originally works is supposed to be supported by devices. This doesn't seem the case for the peripheral I'm using.
 
Thanks
 
Jeremy Turner