Stuck I2C peripheral
Posted: Fri Jul 17, 2015 11:22 am
I have a feature suggestion - it would be handy if the API provided a function to free up a stuck I2C peripheral. I was seeing a seemingly random problem where MultiChannel_I2CStart on the MOD54415 would occasionally return I2C_BUS_NOT_AVAIL. When this occurred, it would not clear up until a power cycle of the slave device (an MS5611 barometer). I was able to narrow it down to a reset (or program download) in the middle of an I2C operation which was leaving the slave in a bad state. I don't have a way to reset the device or remotely cycle power on it.
This previous post touches on the problem:
http://forum.embeddedethernet.com/viewt ... =i2c+stuck
And some related vendor documentation:
NXP spec:
http://www.nxp.com/documents/user_manual/UM10204.pdf
See section 3.1.16 for Bus clear - it says to send 9 clock pulses
MicroChip AN1028:
http://ww1.microchip.com/downloads/en/A ... 01028B.pdf
See the Software Reset Sequence - it says to send a Start bit, 9 bits of '1', another Start bit, and then a Stop bit
I tried using parts of the MultiChannel API to accomplish but I think it has to be done with bit banging because of the error checking built in to the API and the I2C hardware. This sequence seems to work:
There probably should be some delays in between to work with slower devices.
There are a couple of other issues I noticed when debugging this. The high-level routines (MultiChannel_I2CSendBuf, etc.) are really easy to use but they don't accept a timeout and default to using 20 ticks of wait time so when the error (I2C_BUS_NOT_AVAIL) occurs, the task blocks for 1 second. It would be nice if the high-level routines accepted a timeout. Also, I discovered the I2C driver uses IRQ3 - can that kind of information be documented in the Runtime Library manual? I can switch to another IRQ but that might have taken a while to figure out.
Thanks,
-Bob
This previous post touches on the problem:
http://forum.embeddedethernet.com/viewt ... =i2c+stuck
And some related vendor documentation:
NXP spec:
http://www.nxp.com/documents/user_manual/UM10204.pdf
See section 3.1.16 for Bus clear - it says to send 9 clock pulses
MicroChip AN1028:
http://ww1.microchip.com/downloads/en/A ... 01028B.pdf
See the Software Reset Sequence - it says to send a Start bit, 9 bits of '1', another Start bit, and then a Stop bit
I tried using parts of the MultiChannel API to accomplish but I think it has to be done with bit banging because of the error checking built in to the API and the I2C hardware. This sequence seems to work:
Code: Select all
enum
{
sda = 39,
scl = 42
};
J2[39].function( PINJ2_39_GPIO); // sda
J2[42].function( PINJ2_42_GPIO); // scl
// Start bit
J2[sda] = 1;
J2[scl] = 1;
J2[sda] = 0;
// 9 clock pulses
J2[scl] = 0;
for (int i = 0; i < 9; i++)
{
J2[scl] = 1;
J2[scl] = 0;
}
// Start bit
J2[sda] = 1;
J2[scl] = 1;
J2[sda] = 0;
// Stop bit
J2[sda] = 0;
J2[scl] = 1;
J2[sda] = 1;
MultiChannel_I2CInit (0, 0x08, 0x3c); // continue with normal initialization
There are a couple of other issues I noticed when debugging this. The high-level routines (MultiChannel_I2CSendBuf, etc.) are really easy to use but they don't accept a timeout and default to using 20 ticks of wait time so when the error (I2C_BUS_NOT_AVAIL) occurs, the task blocks for 1 second. It would be nice if the high-level routines accepted a timeout. Also, I discovered the I2C driver uses IRQ3 - can that kind of information be documented in the Runtime Library manual? I can switch to another IRQ but that might have taken a while to figure out.
Thanks,
-Bob