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