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.

TMS320C6678: I2C_transfer() can block the task forever when NACK raised.

Part Number: TMS320C6678


Hi,

My customer has a problem with I2C_transfer() delivered in PDK I2C driver. When NACK error is raised in I2C master transfer mode, I2C_transfer() can block the SYS/BIOS Task context permanently. 
For example, if you do I2C_transfer in Task function on C6678 EVM, the latter use case will block the current TSK context permanently even if I do it with timeout value.

//Should Be OK
i2cTransaction.writeBuf = writebuf;
i2cTransaction.writeCount = sizeof writebuf;
i2cTransaction.readBuf = readbuf;
i2cTransaction.readCount = sizeof readbuf;
i2cTransaction.slaveAddress = 0x50;  // Correct slave address
i2cTransaction.arg = NULL;
i2cTransaction.nextPtr = NULL;
i2cTransaction.timeout = 1000; 
res = I2C_transfer(i2c, &i2cTransaction); //1 will be returned (success)

//Error
i2cTransaction.writeBuf = writebuf;
i2cTransaction.writeCount = sizeof writebuf;
i2cTransaction.readBuf = readbuf;
i2cTransaction.readCount = sizeof readbuf;
i2cTransaction.slaveAddress = 0x60;  // In correct slave address. This will invoke NACK interrupt.
i2cTransaction.arg = NULL;
i2cTransaction.nextPtr = NULL;
i2cTransaction.timeout = 1000;  
res = I2C_transfer(i2c, &i2cTransaction);// This will block this context forever. No error returned.

The problem is that the driver code is using hard-codeed timeout value with FOREVER for its transfer completion semaphore. I just modify like this (see, #if 1) , and it seems the problem does not happen.
The latter code returns 0 (timeout failure).

C:\ti\pdk_c667x_2_0_3\packages\ti\drv\i2c\src\v0\I2C_v0.c

            if (object->operMode == I2C_OPER_MODE_BLOCKING) {
                I2C_drv_log1("\n I2C:(0x%x) Pending on transferComplete semaphore \n",
                    hwAttrs->baseAddr);

                /*
                 * Wait for the transfer to complete here.
                 * It's OK to block from here because the I2C's Hwi will unblock
                 * upon errors
                 */
#if 1
                SemaphoreP_Status semStatus;

                semStatus = I2C_osalPendLock(object->transferComplete, transaction->timeout);
#else
                I2C_osalPendLock(object->transferComplete, SemaphoreP_WAIT_FOREVER);
#endif
                I2C_drv_log1("\n I2C:(0x%x) Transaction completed \n", hwAttrs->baseAddr);

                /* Hwi handle has posted a 'transferComplete' check for Errors */
                if (object->mode == I2C_IDLE_MODE) {
                    I2C_drv_log1("\n I2C:(0x%x) Transfer OK \n", hwAttrs->baseAddr);
                    ret = (int16_t)I2C_STS_SUCCESS;
                }
#if 1
                if (semStatus == SemaphoreP_TIMEOUT) {
                 ret = (int16_t)I2C_STS_ERR;
                }
#endif
            }

Please note the above driver code is delivered from pdk_c667x_2_0_3 and as you know it is not latest version of PDK. But even in the latest PDK, I believe the same issue is present and the code should be fixed in the future release. Please confirm this is relevent fix and give it to your code base for the future release.

Best Regards,
Naoki

  • Hi Naoki,

    From what I understand from the code & I2C specification for C66x devices (www.ti.com/.../sprugv3.pdf), Section 2.9, the when NACK is sent the I2C should send an IRQ and the hwi should unblock the task, see the comment in I2C_transfer_v0():

    /*
    * Wait for the transfer to complete here.
    * It's OK to block from here because the I2C's Hwi will unblock
    * upon errors
    */

    Best Regards,
    Yordan
  • Yordan,

    The problem is NACK ISR can happen but it never handle NACK error and in fact, it does not invoke callback function from the ISR when NACK interrupt is raised. So, the transfer completion semaphore will not be posted. 
    Timeout can be given as I2C_transfer() parameter, so in software deign perspective, this problem should be fixed at your end. Thanks for your consideration.

    Best Regards,
    Naoki

  • Hi Naoki,

    I've notified the team about this.

    Best Regards,
    Yordan
  • Naoki,

    Yes, we are able to reproduce this error condition and have been able to analyze the driver code. We acknowledge this issue in the I2C_v0 version of the driver. If you look at the I2C_v1 implementation of the driver then you will see that the timeouts have been implemented exactly as you specified in the work around.

    I have filed a bug report for this issue which you can track using PRSDK-2207 in the Release notes. The code freeze for 1Q17 release was 2 weeks back so this will not be fixed in current update. You can track this issue to be resolved in Processor SDK RTOS release in 2Q17.

    Appreciate your due diligence in providing us a way to reproduce the issue and provide suggested work around on this issue.

    Regards,
    Rahul
  • Hello Rahul,

    Ok, thank you for your response. I close the thread.

    Best Regards,
    Naoki