Eric Thrall

I2C issue on 521x

Discussion created by Eric Thrall on Sep 20, 2007
Latest reply on Oct 15, 2007 by Eric Thrall
Hi - I am running into an I2C issue on an MCF5212.  Using the sample code from Freescale for an I2C solution using interrupts, I get stuck in infinite loops.  It happens sometimes (not every time, but more than a third of the time) and only with the first message I try to transmit.  Here's the sample code fragment:

        /* Make sure bus is idle */
        while (MCF_I2C_I2SR & MCF_I2C_I2SR_IBB)
        ;
        /* Put module in master TX mode (generates START) */
        MCF_I2C_I2CR |= (0 | MCF_I2C_I2CR_MSTA | MCF_I2C_I2CR_MTX);
        /* Put target address into I2DR */
        MCF_I2C_I2DR = (uint8)( 0 | slave_address | mode);
        /* Wait for I2SR[IBB] (bus busy) to be set */
        while (!(MCF_I2C_I2SR & MCF_I2C_I2SR_IBB))
        ;
   
        /* Wait for bus to become free before continuing */
        while (MCF_I2C_I2SR & MCF_I2C_I2SR_IBB)
        ;

OK, here, we first make sure the bus is idle, then we put ourselves in master transmit mode, and write the address and read/write mode to the data register.  Then we wait until the bus gets busy (meaning that we are transmitting) and then wait for the bus to free up, indicating that the address has been successfully transmitted.

I have run into problems with getting stuck at all three of those while loops, especially the second one where I wait until the bus becomes busy after writing the address to the data register.  I am running at 100KHz, so I am using an appropriate speed.  I have had a scope hooked up when it got stuck in that second while loop and at that point and the busy bit (IBB) is clear, meaning that the bus is not busy, but the scope showed that SDA was high while SCL was low, which by definition means that the bus is busy, right?  If the bus is idle, both of them should be high.  Therefore, I wonder how much I can trust IBB.

I've also tried to use ICF (I can't use IIF because I am using interrupts, right?) in place of the last two uses of IBB - after all, it makes much more sense to me to key on a bit telling me that a transfer is in progress rather than just checking whether the bus is idle or not.  However, ICF doesn't seem to work at all.

Is there something subtle that I don't know that would make those two bits behave properly?  This problem has been very frustrating.

First of all, has anyone else seen something similar and found a way around it?

Outcomes