esp-idf: [TW#13148] i2c timeout error

I’m polling a i2c device every half second and after a while (sometimes 4 minutes, sometimes half an hour). The i2c_master_cmd_begin function returns ESP_ERR_TIMEOUT, and every next call to i2c_master_cmd_begin returns ESP_ERR_TIMEOUT.

I tried deleting the driver using i2c_driver_delete and then i2c_driver_install but it keeps giving the error.

At this time the SDA line remains low and the SCL line remains high. I also tried to delete the driver and then change the pins to output and change to no avail.

The device I am communicating with is a battery monitor (LC709203F). But I have the same problem with an accelerometer.

init code

    i2c_config_t conf;
    conf.mode = I2C_MODE_MASTER;
    conf.sda_io_num = I2C_MASTER_SDA_IO;
    conf.sda_pullup_en = GPIO_PULLUP_DISABLE;
    conf.scl_io_num = I2C_MASTER_SCL_IO;
    conf.scl_pullup_en = GPIO_PULLUP_DISABLE;
    conf.master.clk_speed = I2C_MASTER_FREQ_HZ;
    i2c_param_config(I2C_MASTER_NUM, &conf);
    i2c_driver_install(I2C_MASTER_NUM, conf.mode, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0);

communication code

    int ret = 0;
    uint8_t crc = 0, crc_read, valh, vall;
    i2c_cmd_handle_t cmd;

    cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, ( FG_SLAVE_ADDR << 1 ) | WRITE_BIT, ACK_CHECK_EN);
    i2c_master_write_byte(cmd, command, ACK_CHECK_EN);
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, ( FG_SLAVE_ADDR << 1 ) | READ_BIT, ACK_CHECK_EN);
    i2c_master_read_byte(cmd, &vall, ACK_VAL);
    i2c_master_read_byte(cmd, &valh, ACK_VAL);
    i2c_master_read_byte(cmd, &crc_read, NACK_VAL);
    i2c_master_stop(cmd);
    ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 1000 / portTICK_RATE_MS);
    i2c_cmd_link_delete(cmd);

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Comments: 20 (4 by maintainers)

Commits related to this issue

Most upvoted comments

@AmrutaCh You’ll need to modify components/driver/i2c.c…I’m not up-to-date with the latest version so I’ll just walk you through the change:

In esp_err_t i2c_param_config(i2c_port_t i2c_num, const i2c_config_t* i2c_conf) there is an if block…something like:

if (i2c_conf->mode == I2C_MODE_SLAVE) {  //slave mode
...    
} else {
...        
}

You’ll need to modify the else clause changing

I2C[i2c_num]->timeout.tout = cycle * I2C_MASTER_TOUT_CNUM_DEFAULT;

To

I2C[i2c_num]->timeout.tout = 1048575;

That number was picked because, to the best of my knowledge, it’s the largest supported by the hardware.

That being said there is a “newer” function that may help: i2c_set_timeout

When first introduced I found that it did not resolve my issue, but I should really give it another try.

I think I have the same problem but with a DS3231 / DS1307. The interesting thing is, that I have exactly your behavior using the ESP-IDF. But if I use the ESP-Arduino SDK (as a component in IDF) it works without any problems.