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.

LAUNCHXL-F280049C: Repeated start not working in I2C normal mode

Part Number: LAUNCHXL-F280049C
Other Parts Discussed in Thread: BQ76952, C2000WARE

I am using a slightly modified version of the I2C master receiver function in C2000Ware_4_00_00_00\driverlib\f28004x\examples\i2c\i2cLib_FIFO_polling.c. to read registers from the BQ76952 battery monitor IC.

The original function uses the repeat mode but sometimes ends up reading 3 bytes of data instead of two.

I modified the function to use normal mode with a data count of two. After the register address byte is sent, I switch to normal, master-receive mode. I then set the data count to 2 and further set the start and stop bits in the I2C mode register. I expect a repeated start to be generated followed by the slave address and two byte read, but I don't see anything on the scope or the logic analyzer. 

Please suggest if anything is wrong with the code.

uint16_t I2C_ReadReg(uint16_t reg_addr, uint16_t *reg_data, uint16_t NumOfDataBytes)
{
    uint16_t status;
    uint16_t attemptCount;

    I2C_disableFIFO(MY_I2C_BASE);  //Reset FIFOs
    I2C_enableFIFO(MY_I2C_BASE);

    // Write register address
    status = I2C_TransmitSlaveAddress_ControlBytes(reg_addr);
    if(status) {
        return status;
    }

    uint16_t numofSixteenByte  = NumOfDataBytes / I2C_FIFO_DEPTH; //FIFO is 16 bytes deep
    uint16_t remainingBytes    = NumOfDataBytes % I2C_FIFO_DEPTH;

    // Switch to master receiver mode
    //I2C_setConfig(MY_I2C_BASE, (I2C_MASTER_RECEIVE_MODE|I2C_REPEAT_MODE));

    I2C_setConfig(MY_I2C_BASE, I2C_MASTER_RECEIVE_MODE);
    I2C_setDataCount(MY_I2C_BASE, NumOfDataBytes+1);

    I2C_sendStartCondition(MY_I2C_BASE);

    I2C_sendStopCondition(MY_I2C_BASE);

    uint16_t i, count = 0, buff_pos=0;

    //for(count=0; count < numofSixteenByte; ++count) { //Read 16 bytes at a time from RX FIFO
    while(count < numofSixteenByte) {
        status = handleNACK(MY_I2C_BASE);
        if(status) {
          return status;
        }

        count++;

        attemptCount = 1;
        while(!(I2C_getRxFIFOStatus(MY_I2C_BASE) == I2C_FIFO_RXFULL) && attemptCount <= 9 * (I2C_FIFO_RXFULL + 2U)) {
            DEVICE_DELAY_US(I2C_DELAY_US);
            attemptCount++;
        }

        for(i=0; i<I2C_FIFO_RXFULL; ++i) { // Transfer RX FIFO contents to RX buffer
            reg_data[buff_pos] = I2C_getData(MY_I2C_BASE);
            buff_pos++;
        }
    }

    attemptCount = 1;
    while(!(I2C_getRxFIFOStatus(MY_I2C_BASE) == remainingBytes) && attemptCount <= 9 * (remainingBytes + 2U)) {
       DEVICE_DELAY_US(I2C_DELAY_US);
       attemptCount++;
    }

    //I2C_sendStopCondition(MY_I2C_BASE);

    for(i=0; i<remainingBytes; ++i) {     // Transfer RX FIFO contents to RX buffer
        reg_data[buff_pos] = I2C_getData(MY_I2C_BASE);
        buff_pos++;
    }

    status = handleNACK(MY_I2C_BASE);
    if(status) {
      return status;
    }

    //I2C_disableFIFO(MY_I2C_BASE);

    attemptCount = 1;
    while(I2C_getStopConditionStatus(MY_I2C_BASE) && attemptCount <= 3U) {
        DEVICE_DELAY_US(I2C_DELAY_US);
        attemptCount++;
    }

    return SUCCESS;
}

/** Private Function Definitions **/
/*==============================================================================
Function Name:
--------------------------------------------------------------------------------
Scope:         Private
--------------------------------------------------------------------------------
Description:
--------------------------------------------------------------------------------
Input Data:
--------------------------------------------------------------------------------
Return Value:
==============================================================================*/
uint16_t I2C_TransmitSlaveAddress_ControlBytes(uint16_t ControlAddr)
{
    uint16_t status;
    uint16_t attemptCount = 1;
    uint16_t NumOfAddrBytes = 1U;

    do {
        status = checkBusStatus(MY_I2C_BASE);
        attemptCount++;
        DEVICE_DELAY_US(I2C_DELAY_US);
    } while(status & (attemptCount <= I2C_RETRIES));

    if(status) {
        return status;  //Fail; Return bus busy or stop not ready error
    }

    I2C_setConfig(MY_I2C_BASE, (I2C_MASTER_SEND_MODE|I2C_REPEAT_MODE));
    I2C_setSlaveAddress(MY_I2C_BASE, DEV_ADDR);     // Setup slave address

    I2C_putData(MY_I2C_BASE, ControlAddr);   // Put control address in transmit buffer
    I2C_sendStartCondition(MY_I2C_BASE);     // Send start condition

//    DEVICE_DELAY_US(150U);
//
//    status = handleNACK(MY_I2C_BASE);
//    if(status) { // Retry once
//      if(attemptCount <= I2C_RETRIES) {
//          attemptCount++;
//          I2C_setConfig(MY_I2C_BASE, (I2C_MASTER_SEND_MODE));
//          I2C_sendStartCondition(MY_I2C_BASE);
//          DEVICE_DELAY_US(I2C_DELAY_US);
//      }
//      else {
//          return status;    // Fail
//      }
//    }

    attemptCount = 1;
    while(I2C_getTxFIFOStatus(MY_I2C_BASE) && attemptCount <= 9 * (1U + NumOfAddrBytes + 2U))
    {
       status = handleNACK(MY_I2C_BASE);
       if(status) {
          return status;
       }
       attemptCount++;
       DEVICE_DELAY_US(I2C_DELAY_US);
    }

    return SUCCESS;
}

/*==============================================================================
Function Name:
--------------------------------------------------------------------------------
Scope:         Private
--------------------------------------------------------------------------------
Description:
--------------------------------------------------------------------------------
Input Data:
--------------------------------------------------------------------------------
Return Value:
==============================================================================*/
uint16_t checkBusStatus(uint32_t base)
{
    if(I2C_isBusBusy(base)) {
        return ERR_BUS_BUSY;
    }
    if(I2C_getStopConditionStatus(base)) { // Check if the stop condition has not been already generated
        return ERR_STOP_NOT_RDY;
    }
    return SUCCESS;
}

/*==============================================================================
Function Name:
--------------------------------------------------------------------------------
Scope:         Private
--------------------------------------------------------------------------------
Description:
--------------------------------------------------------------------------------
Input Data:
--------------------------------------------------------------------------------
Return Value:
==============================================================================*/
uint16_t handleNACK(uint32_t base)
{
    if(I2C_getStatus(base) & I2C_STS_NO_ACK) {    //Status is NACK
        I2C_clearStatus(base, I2C_STS_NO_ACK);  //Clear NACK flag
        I2C_sendStopCondition(base);            //Set STP bit
        return ERR_NACK_RCVD;
    }
    return SUCCESS;
}