Stuck I2C peripheral

Discussion to talk about software related topics only.
Post Reply
Watzlavick
Posts: 22
Joined: Mon Jan 27, 2014 7:19 pm

Stuck I2C peripheral

Post by Watzlavick »

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:

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 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
Post Reply