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.

CCS/TM4C1294NCPDT: I2C gets stuck in I2CMasterBusy(ui32Base) function

Part Number: TM4C1294NCPDT

Tool/software: Code Composer Studio

We are communicating a sensor with TM4C1294 controller on I2C bus. It is working fine for a few minutes and after that code stuck in while(I2CMasterBusy(ui32Base)); function. We have checked the SDA, SCL line on logic analyzer and found that some times controller responds with a NACK and after that code hanging problems starts. We have used a 20ms timeout condition in while(I2CMasterBusy(ui32Base)); function to come out of the function and resend the command to the sensor. This is also working for a while but after some time controller stops sending the read command to the sensor even if it is going in the I2C function.

Please guide me how to resolve this issue.

I am not getting why controller stops sending the read command even if it is going in the I2C function.

Is there any way to reset the I2C in controller?

For the reference purpose, i have attached screenshots of the logic analyzer.

Thanks

  • Hello Amit,

    You may need an additional check in your code for TM4C129x MCUs:

        //
        // Setup for first read.  Use I2C_MASTER_CMD_BURST_RECEIVE_START
        // to start a burst mode read.  The I2C master continues to own
        // the bus at the end of this transaction.
        //
        MAP_I2CMasterControl(I2C7_BASE, I2C_MASTER_CMD_BURST_RECEIVE_START);
    
        //
        // Wait until master module is done transferring.
        // The I2C module has a delay in setting the Busy flag in the register so
        // there needs to be a delay before checking the Busy bit.  The below loops
        // wait until the Busy flag is set, and then wait until it is cleared to
        // indicate that the transaction is complete.  This can take up to 633 CPU
        // cycles @ 100 kbit I2C Baud Rate and 120 MHz System Clock.  Therefore, a
        // while loop is used instead of SysCtlDelay.
        //
        while(!MAP_I2CMasterBusy(I2C7_BASE))
        {
        }
        while(MAP_I2CMasterBusy(I2C7_BASE))
        {
        }

    If you do not have both while loop checks for I2CMasterBusy then that may explain your behavior here. Please try and adjust your code to reflect that and see if it solves your issue.

  • Hello Ralph,

    Thanks for the reply.

    I already have the both while() statements in my function. For the reference please find the i2c read function below. please let me know if you found anything wrong in my code.


    uint32_t i2c_read(uint32_t ui32Base, uint8_t ui8SlaveAddr, uint8_t* ui8Data, uint8_t ui8Length){
       
        uint8_t data = 0;
        uint8_t i = 0;

        i2cTimeoutCounter = 0; //  global variable used in timer function of 1 ms to come out of the while() functions. Increment by 1 at every 1 ms.


        while ( I2CMasterBusy(ui32Base) && (i2cTimeoutCounter < 20) ); // will come out of the while() after 20 ms
        I2CMasterSlaveAddrSet(ui32Base, ui8SlaveAddr, true);

        // Whait until I2C bus is not busy
        while ( I2CMasterBusBusy(ui32Base) && (i2cTimeoutCounter < 20) );

        I2CMasterControl(ui32Base, I2C_MASTER_CMD_BURST_RECEIVE_START);
      
        while ( !(I2CMasterBusy(ui32Base)) && (i2cTimeoutCounter < 20));
        while (   I2CMasterBusy(ui32Base) && (i2cTimeoutCounter < 20) );

        data = I2CMasterDataGet(ui32Base);
       
        ui8Data[i++] = data;
       

        while(i < (ui8Length - 1)){
            I2CMasterControl(ui32Base, I2C_MASTER_CMD_BURST_RECEIVE_CONT);
           
            while ( !(I2CMasterBusy(ui32Base)) && (i2cTimeoutCounter < 20));
            while (   I2CMasterBusy(ui32Base)  && (i2cTimeoutCounter < 20));


            data = I2CMasterDataGet(ui32Base);
            ui8Data[i++] = data;
        }

        I2CMasterControl(ui32Base, I2C_MASTER_CMD_BURST_RECEIVE_FINISH);
      
        while ( !(I2CMasterBusy(ui32Base)) && (i2cTimeoutCounter < 20));
        while (   I2CMasterBusy(ui32Base) && (i2cTimeoutCounter < 20) );
        

        data = I2CMasterDataGet(ui32Base);
      
        ui8Data[i] = data;
    }

  • Hello Amit,

    Are you sure that the timeout hasn't been hit during the while loop? Can you reproduce the behavior without the timeout being used?

    Have you checked for any I2C status indicators? Maybe if the bus lost arbitration that could explain what is going on.

    You can do this with the I2CMasterErr API.