This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TM4C123GH6PM I2C Master Busy Flag Latency

Other Parts Discussed in Thread: TM4C123GH6PM

I connected a 24AA01 memory chip to the Tiva LaunchPad to a TM4C123GH6PM through I2C1.  The read/write of the memory worked fine when I programmed it with CCS and driverlib in TivaWare.  

When I rewrote the program in Keil without using the driverlib, the program did not work.  I spent the whole weekend trying to track down the problem.  Finally with the following code:

uint8_t logger[10];
int i;

uint8_t M2401_byteWrite(I2C0_Type* I2C, int32_t slaveAddr, uint8_t memAddr, const uint8_t data)
{
uint8_t error;

// write: S-(addr+w)-ACK-addr-ACK-data-ACK-data-ACK- ... -data-ACK-P
I2C->MSA = slaveAddr << 1;
I2C->MDR = memAddr;
I2C->MCS = 3; // S-(addr+w)-ACK-addr-ACK

// busy does not come on for a few cycles
logger[0] = I2C->MCS;
logger[1] = I2C->MCS;
logger[2] = I2C->MCS;
logger[3] = I2C->MCS;
logger[4] = I2C->MCS;
logger[5] = I2C->MCS;
logger[6] = I2C->MCS;
logger[7] = I2C->MCS;
logger[8] = I2C->MCS;
logger[9] = I2C->MCS;

...

The MCS values in the logger[ ] were 0x20, 0x21, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01.  The onset of the busy bit (bit 0) was late.  Using the driverlib, the busy bit was checked in a function WaitI2CDone( ).  The overhead of the function call was long enough so the busy bit was set before MCS was checked for the first time.  

In my own implementation, the busy bit was check inline and it fell right through the first time.

I tried 16 MHz and 50 MHz system clock and 100 kHz I2C.

Did anyone see the same problem?

  • Taking the cue from:

    http://e2e.ti.com/support/microcontrollers/tiva_arm/f/908/p/306546/1068144.aspx#1068144

    I modified the program to include a read back of the register and it seems to work.

    uint8_t I2C1_byteWrite(I2C0_Type* I2C, int32_t slaveAddr, uint8_t memAddr, const uint8_t data)
    {
        uint8_t error;
        volatile uint32_t readback;
       
        // write: S-(addr+w)-ACK-addr-ACK-data-ACK-data-ACK- ... -data-ACK-P
        I2C->MSA = slaveAddr << 1;
        I2C->MDR = memAddr;
        I2C->MCS = 3;                       // S-(addr+w)-ACK-addr-ACK
        readback = I2C->MCS; // Ensure write has been drained from the write buffer

        // busy does not come on for a few cycles
        logger[0] = I2C->MCS;
        logger[1] = I2C->MCS;
        logger[2] = I2C->MCS;
        logger[3] = I2C->MCS;
        logger[4] = I2C->MCS;
        logger[5] = I2C->MCS;
        logger[6] = I2C->MCS;
        logger[7] = I2C->MCS;
        logger[8] = I2C->MCS;
        logger[9] = I2C->MCS;

  • Shujen,

    Glad to see you were able to resolve this issue using the readback as suggested in the link you took the cue from. This is a very good example of the effect of RMW nature of register writes in action in a pipelined architecture.

    Regards,

    Shashank