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.

AM2434: I2C timeout - busy bit stuck - how to clear?

Part Number: AM2434

Hello,

I'm using I2C0 on a LP-AM2434 to read the status of an I2C peripheral (AD9542) in a lazy loop.

Periodically, the I2C transfer is timing-out: the I2CControllerBusBusy function, which appears to be checking the I2C busy bit, always returns busy.

How can I clear this bit and/or reset the bus? I don't care about prior transactions - I just want to perform a new transaction.

FYI, I am calling I2C_recoverBus followed by a 100 us delay at the start of the loop but this does not help.

Thanks, Steve

  • Hi Steve,

    This I2C handle getting stuck in the busy mode is not expected behavior. It can be some issue with the I2C configurations, if done incorrectly.

    Can you help me reproduce the issue on my end by sharing the example and MCU_PLUS_SDK version you are on.

    The 12th bit of I2C_IRQSTATUS_RAW gives the bus busy status but it is a Read only type and writing to it will have no effect so the bit cannot be cleared directly

    Also, can you try increasing the delay time to something like 250-500 us.

    Regards.

    ~Shaunak

  • Hi Shaunak,

    I am using SDK 8.06 and CLang 3.0.0 (although the issue has existed with SDKs 8.04 & 8.05).

    The (simplified) pseudo code is:

    device.I2cHandle = I2cHandle;
    I2C_Transaction_init(&device.i2cTransaction);
    device.i2cTransaction.targetAddress = targetAddress;

    device.i2cTransaction.timeout = 10000U;

    while(1)

    {

    I2C_recoverBus(I2cHandle, I2C_DELAY_SMALL);

    ClockP_usleep(500);

    pDevice->i2cTransaction.writeBuf = &txBytes[0U];
    pDevice->i2cTransaction.writeCount = 2U;
    pDevice->i2cTransaction.readBuf = pValue;
    pDevice->i2cTransaction.readCount = 1U;

    I2C_transfer(pDevice->I2cHandle, &pDevice->i2cTransaction);

    ClockP_usleep(10000);

    }

    I have increased the sleep after the recover to 500 us.

    FYI, I have added a PCA9517A I2C buffer between the AM2434 I2C0 and the AD9542 as we understand that the I2C edges from the AM are non-compliant with I2C ('too fast'). Below is a typical I2C transaction trace (either side of PCA9517A) of both analog and digital signal integrity. 

    Thanks, Steve

  • Hi Steve,

    Based on your pseudocode, I tried to reproduce this issue on my end, but I wasn't able to observe the same behavior, can you share your debug.out file? 

    Meanwhile could you try performing a I2C software reset?

     /* Put i2c in reset/disabled state */
        I2CControllerDisable(object->baseAddr);

     /* Do a software reset */
        I2CSoftReset(object->baseAddr);

     /* Enable i2c module */
      I2CControllerEnable(object->baseAddr);

    Regards,

    Shaunak

  • Hi Shaunak,

    Sadly, adding those calls caused an 'arbitration lost' error.

    Steve

  • Hi Steve,

    Can you please share your project.c file? I would like to work around it to try and find a solution since there is no direct way to clear the Bus Busy bit.

    Regards,

    Shaunak

  • Hi Shaunak,

    Unfortunately, I can't share the source for complexity and confidentiality reasons.

    What would cause the busy bit of the I2C controller to become stuck?

    Thanks, Steve

  • Hi Steve,

    It is difficult to come to a solid conclusion without reproducing the issue, I tried reproducing it based on your pseudocode, but couldn't find the bus busy bit stuck.

    You could follow a safer approach if you only care about the next transactions.

    if(I2CControllerBusBusy(baseAddr) == 1) /* check if bus is busy */
    {
        /* If busy, Wait for the transaction to complete */
        status = I2C_waitForBb(baseAddr, timeout);
    }
    else
    {
        /* If timeout, then reset the I2C IP */
        status = I2C_resetCtrl(I2C_Handle)
    }

    I am still looking into what could cause the bit to be stuck in busy mode. I'll get back to you if I have any update.

    Regards,
    Shaunak

  • Hi Steve,

    1. Can you share a scope shot of the I2C bus when the failing condition occurs?

    2. Can you draw the connection between the board and the AD9542, would help us understand the setup better?

    3. What version of AM243x LP are you using, like E3A or E3B?

    4. If you could remove the proprietary portions of the code and reduce it down only to the I2C code that would help me reproduce the issue, I will be able to support you better.

    Regards,
    Shaunak

  • Hi Shaunak,

    Oh, I based my code on the SDK documentation:

    However, I have now refactored it and will retry:

    int32_t AD9542_ReadRegister(AD9542_Device *pDevice, uint16_t registerAddress, uint8_t *pValue)
    {
        int32_t         status = SystemP_SUCCESS;
        int32_t         count = 5; // If there is an I2C Transfer error then retry 5 times
        uint8_t         txBytes[sizeof(registerAddress)];
    
        // address is high byte, low byte order
        txBytes[1U] = registerAddress & 0xFF;
        txBytes[0U] = registerAddress >> 8;
    
        // prepare to write
        pDevice->i2cTransaction.writeBuf = &txBytes[0U];
        pDevice->i2cTransaction.writeCount = sizeof(registerAddress);
        pDevice->i2cTransaction.readCount = 0U;
    
        // write
        status = I2C_transfer(pDevice->I2cHandle, &pDevice->i2cTransaction);
    
        if (SystemP_SUCCESS == status)
        {
            // prepare to read
            pDevice->i2cTransaction.writeCount = 0U;
            pDevice->i2cTransaction.readBuf = pValue;
            pDevice->i2cTransaction.readCount = sizeof(*pValue);
    
            // read
            status = I2C_transfer(pDevice->I2cHandle, &pDevice->i2cTransaction);
        }
    
        if (SystemP_SUCCESS != status)
        {
            // I2C not successful, print error
            AD9542_DebugPrintI2CStatus("AD9542_ReadRegister", registerAddress, status);
        }
    
        return status;
    }
    

    Steve

  • Hi Steve,

    Did the above refactoring resolve the issue?

    If not, can you please answer the questions in my previous reply.

    Regards
    Shaunak

  • Hi Shaunak,

    The refactored code ran overnight (with about 30-40 transactions per second). Although not conclusive, this is the longest it has run without timing-out by an order of magnitude so this is very encouraging.

    However, I only did it this way as this is 'what the SDK told me to do'. Please kindly amend as required.

    Thanks,

    Steve