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.

TMS320F28388D: I2C Multi-byte Read Issue (Works in Debug, Fails in Normal Run)

Part Number: TMS320F28388D

Hi everyone,

I’m working on implementing a multi-byte I2C register read without using FIFO. I’ve written the following function to read multiple bytes from a slave device:

#define CMI2C_DELAY_IN_US = 50;

//
// cmi2c single register read
//
uint8_t cmi2c_ReadReg(uint8_t slave, uint8_t reg, uint8_t data[], uint8_t len)
{
    uint8_t d = 1, err;

    // Wait until bus free
    err = cmi2c_isMasterBusy();
    if (I2C_OK != err)
    {
        return err;
    }

    // Send Slave address
    I2C_setSlaveAddress(I2C0_BASE, slave, I2C_MASTER_WRITE);

    I2C_putMasterData(I2C0_BASE, reg);
    I2C_setMasterConfig(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_START);

    // Wait until bus free
    err = cmi2c_isMasterBusy();
    if (I2C_OK != err)
    {
        return err;
    }
    DEVICE_DELAY_US(CMI2C_DELAY_IN_US);
    // Read First Byte
    I2C_setSlaveAddress(I2C0_BASE, slave, I2C_MASTER_READ);
    I2C_setMasterConfig(I2C0_BASE, I2C_MASTER_CMD_BURST_RECEIVE_START);

    // Wait until bus free
    err = cmi2c_isMasterBusy();
    if (I2C_OK != err)
    {
        return err;
    }

    data[0] = I2C_getMasterData(I2C0_BASE);
    DEVICE_DELAY_US(CMI2C_DELAY_IN_US);

    for (; d < len - 1; d++)
    {
        I2C_setMasterConfig(I2C0_BASE, I2C_MASTER_CMD_BURST_RECEIVE_CONT);

        // Wait until bus free
        err = cmi2c_isMasterBusy();
        if (I2C_OK != err)
        {
            return err;
        }

        data[d] = I2C_getMasterData(I2C0_BASE);
        DEVICE_DELAY_US(CMI2C_DELAY_IN_US);
    }
    DEVICE_DELAY_US(CMI2C_DELAY_IN_US);
    // Read Last Byte
    I2C_setMasterConfig(I2C0_BASE, I2C_MASTER_CMD_BURST_RECEIVE_FINISH);

    // Wait until bus free
    err = cmi2c_isMasterBusy();
    if (I2C_OK != err)
    {
        return err;
    }

    data[len - 1] = I2C_getMasterData(I2C0_BASE);
    return I2C_OK;
}

Issue:

  • On the logic analyzer, the I2C transaction looks correct (start, address, repeated start, and data bytes are all proper).

  • However, the data stored in the buffer (data[]) is not properly organized or sometimes incorrect.

  • Interestingly, the code works perfectly in debug mode, but fails or gives inconsistent results in normal run mode.

 

what is the problem in this code kindly guide me.

 

 

 

  • Hi Savan,

    Let me take a look at this and get back to you tomorrow on this.

    Best Regards,

    Aishwarya

  • Savan,

    Especially when doing burst read operations, it's important to wait for the data to be ready before reading it. In debug mode, you are introducing natural delays that allow the I2C module to complete the receive operation, but there is a chance it is stale data. Knowing that, can you add a DEVICE_DELAY_US before the reading the data as well. You can use the datasheet/scope shots as a reference point of how much delay to start with. 

    BTW the "CMI2C_DELAY_IN_US" macro should not have an equal sign in it. 

    Best Regards,

    Aishwarya

  • I solved this problem by reading the document, and there is one note. 

                                                                                        Note

    When reading the I2CMCS register to check the BUSY bit, also read the ADRACK and DATACK bits, because these are cleared on register read, and status may be lost if they are not checked on every read of the register.

    So, I accidentally cleared all I2CMCS bits and gave mismatched data. So, I changed the code, and it worked.