Hi Team,
Below function returns error code as -5 and unable to write and read data from I2C peripheral.
Hi Team,
Below function returns error code as -5 and unable to write and read data from I2C peripheral.
Hello Sravan,
What NCS version are you using?
Is there a way for me to reproduce what you are seeing on a DK?
Best regards,
Edvin
Hi Edvin,
We are using SDK 3.1.0, we are using our custom board.
Regards,
Sravan Rikka
Thank you!
Have you tried reproducing the issue on a DK? Or stepped into the i2c_nrfx_twim_transfer() in v3.1.1\zephyr\drivers\i2c\i2c_nrfx_twim.c, which is ultimately called from i2c_write_read() to see why it returns -5 (-EIO)?
This is the full function:
static int i2c_nrfx_twim_transfer(const struct device *dev,
struct i2c_msg *msgs,
uint8_t num_msgs, uint16_t addr)
{
struct i2c_nrfx_twim_data *dev_data = dev->data;
const struct i2c_nrfx_twim_common_config *dev_config = dev->config;
int ret = 0;
uint8_t *msg_buf = dev_config->msg_buf;
uint16_t msg_buf_used = 0;
uint16_t msg_buf_size = dev_config->msg_buf_size;
uint8_t *buf;
uint16_t buf_len;
(void)i2c_nrfx_twim_exclusive_access_acquire(dev, K_FOREVER);
/* Dummy take on completion_sync sem to be sure that it is empty */
k_sem_take(&dev_data->completion_sync, K_NO_WAIT);
for (size_t i = 0; i < num_msgs; i++) {
if (I2C_MSG_ADDR_10_BITS & msgs[i].flags) {
ret = -ENOTSUP;
break;
}
bool dma_accessible = nrf_dma_accessible_check(&dev_config->twim, msgs[i].buf);
/* This fragment needs to be merged with the next one if:
* - it is not the last fragment
* - it does not end a bus transaction
* - the next fragment does not start a bus transaction
* - the direction of the next fragment is the same as this one
*/
bool concat_next = ((i + 1) < num_msgs)
&& !(msgs[i].flags & I2C_MSG_STOP)
&& !(msgs[i + 1].flags & I2C_MSG_RESTART)
&& ((msgs[i].flags & I2C_MSG_READ)
== (msgs[i + 1].flags & I2C_MSG_READ));
/* If we need to concatenate the next message, or we've
* already committed to concatenate this message, or its buffer
* is not accessible by DMA, add it to the internal driver
* buffer after verifying there's room.
*/
if (concat_next || (msg_buf_used != 0) || !dma_accessible) {
if ((msg_buf_used + msgs[i].len) > msg_buf_size) {
LOG_ERR("Need to use the internal driver "
"buffer but its size is insufficient "
"(%u + %u > %u). "
"Adjust the zephyr,concat-buf-size or "
"zephyr,flash-buf-max-size property "
"(the one with greater value) in the "
"\"%s\" node.",
msg_buf_used, msgs[i].len,
msg_buf_size, dev->name);
ret = -ENOSPC;
break;
}
if (!(msgs[i].flags & I2C_MSG_READ)) {
memcpy(msg_buf + msg_buf_used,
msgs[i].buf,
msgs[i].len);
}
msg_buf_used += msgs[i].len;
}
if (concat_next) {
continue;
}
if (msg_buf_used == 0) {
buf = msgs[i].buf;
buf_len = msgs[i].len;
} else {
buf = msg_buf;
buf_len = msg_buf_used;
}
ret = i2c_nrfx_twim_msg_transfer(dev, msgs[i].flags, buf, buf_len, addr);
if (ret < 0) {
break;
}
ret = k_sem_take(&dev_data->completion_sync,
I2C_TRANSFER_TIMEOUT_MSEC);
if (ret != 0) {
/* Whatever the frequency, completion_sync should have
* been given by the event handler.
*
* If it hasn't, it's probably due to an hardware issue
* on the I2C line, for example a short between SDA and
* GND.
* This is issue has also been when trying to use the
* I2C bus during MCU internal flash erase.
*
* In many situation, a retry is sufficient.
* However, some time the I2C device get stuck and need
* help to recover.
* Therefore we always call i2c_nrfx_twim_recover_bus()
* to make sure everything has been done to restore the
* bus from this error.
*/
(void)i2c_nrfx_twim_recover_bus(dev);
ret = -EIO;
break;
}
if (dev_data->res != NRFX_SUCCESS) {
ret = -EIO;
break;
}
/* If concatenated messages were I2C_MSG_READ type, then
* content of concatenation buffer has to be copied back into
* buffers provided by user. */
if ((msgs[i].flags & I2C_MSG_READ) && (buf == msg_buf)) {
int j = i;
while (msg_buf_used >= msgs[j].len) {
msg_buf_used -= msgs[j].len;
memcpy(msgs[j].buf,
msg_buf + msg_buf_used,
msgs[j].len);
j--;
}
}
msg_buf_used = 0;
}
i2c_nrfx_twim_exclusive_access_release(dev);
return ret;
}
and as you can see, there are several possible routes to return -EIO. Either k_sem_take(&dev_data->completion_sync, I2C_TRANSFER_TIMEOUT_MSEC); returned an error, or dev_data->res != NRFX_SUCCESS, or possibly i2c_nrfx_twim_msg_transfer() returned -EIO.
Are you able to see which one it is?
Best regards,
Edvin
Hi Edvin,
Have you tried reproducing the issue on a DK?
No, we don't have DK boards.
We are using 'i2c_write_read()' function and getting -5 from this function. Attached our test code.
Please provide your inputs to resolve this. We are stuck up in board bring up activity.
We have 5 I2C slave on board. We are able to communicate successfully and getting data from the 3 slaves but getting -5 error from two slaves. We are using 10K pullup resistor.

Regards,
Sravan Rikka
Can you upload the full application that you are testing?
And have you checked whether there is any I2C activity on the I2C pins at all using a logic analyzer? Can you upload the logic trace as well?
Best regards,
Edvin