Skip to content

ESP-IDF v5.3 I2C Old driver working, new driver not. (IDFGH-13508) #14401

Closed
@western-hoolock

Description

Answers checklist.

  • I have read the documentation ESP-IDF Programming Guide and the issue is not addressed there.
  • I have updated my IDF branch (master or release) to the latest version and checked that the issue is present there.
  • I have searched the issue tracker for a similar issue and not found a similar issue.

General issue report

Environment: PlatformIO with v5.3 and an ESP32-WROVER-E on a custom board and a Texas Instruments BQ27441 Fuel Gauge and external 4.7k SCL/SDA pull-up resistors.

I wrote some code that uses the deprecated I2C <i2c.h> driver, which works fine at 400kHz:

#define P_I2C_SDA 22
#define P_I2C_SCL 23
#define BQ27441_ADDRESS 0x55

i2c_config_t i2c_conf = 
{
    .mode             = I2C_MODE_MASTER,
    .sda_io_num       = P_I2C_SDA,
    .sda_pullup_en    = GPIO_PULLUP_DISABLE,
    .scl_io_num       = P_I2C_SCL,
    .scl_pullup_en    = GPIO_PULLUP_DISABLE,
    .master.clk_speed = 400000,
};

i2c_param_config(I2C_NUM_0, &i2c_conf);
i2c_driver_install(I2C_NUM_0, i2c_conf.mode, 0, 0, 0);

i2c_set_timeout(I2C_NUM_0, 400000); // ~5ms

i2c_master_write_to_device(I2C_NUM_0, BQ27441_ADDRESS, (uint8_t []){ 0x00, 0x01 }, 2, portMAX_DELAY);
i2c_master_write_to_device(I2C_NUM_0, BQ27441_ADDRESS, (uint8_t []){ 0x01, 0x00 }, 2, portMAX_DELAY);

i2c_master_write_to_device(I2C_NUM_0, BQ27441_ADDRESS, (uint8_t []){ 0x00 }, 1, portMAX_DELAY);
uint8_t val[2];
i2c_master_read_from_device(I2C_NUM_0, BQ27441_ADDRESS, val, sizeof(val), portMAX_DELAY);

printf("Device Type: %04X\r\n", (val[1] << 8) | val[0]);

Then I decided to rewrite this to use the new I2C driver in <i2c_master.h> like so:

#define P_I2C_SDA 22
#define P_I2C_SCL 23
#define BQ27441_ADDRESS 0x55

i2c_master_bus_config_t master_cfg = {
    .clk_source = I2C_CLK_SRC_DEFAULT,
    .i2c_port = I2C_NUM_0,
    .scl_io_num = P_I2C_SCL,
    .sda_io_num = P_I2C_SDA,
    .glitch_ignore_cnt = 7,
    .flags.enable_internal_pullup = 0,
};

i2c_master_bus_handle_t bus_handle;

i2c_new_master_bus(&master_cfg, &bus_handle);

i2c_device_config_t bq27441_cfg = {
    .dev_addr_length = I2C_ADDR_BIT_LEN_7,
    .device_address = BQ27441_ADDRESS,
    .scl_speed_hz = 400000,
    .scl_wait_us = 5 * 1000, // BQ27441 can stretch up to 4ms, use 5ms to be safe.
};

i2c_master_dev_handle_t device_handle;
i2c_master_bus_add_device(bus_handle, &bq27441_cfg, &device_handle);

// This call returns ESP_ERR_INVALID_STATE.
i2c_master_transmit(device_handle, (uint8_t []){ 0x00, 0x01 }, 2, -1);
esp_rom_delay_us(100); // Per BQ27441 datasheet.

i2c_master_transmit(device_handle, (uint8_t []){ 0x01, 0x00 }, 2, -1);
esp_rom_delay_us(100); // Per BQ27441 datasheet.

uint8_t val[2];

i2c_master_transmit(device_handle, (uint8_t []){ 0x00 }, 1, -1);
esp_rom_delay_us(100); // Per BQ27441 datasheet.
i2c_master_receive(device_handle, val, 1, -1);
i2c_master_receive(device_handle, val + 1, 1, -1);

printf("Device Type: %04X\r\n", (val[1] << 8) | val[0]);

This code however works only at 100kHz, not at 400kHz. At 400kHz the line:
i2c_master_transmit(device_handle, (uint8_t []){ 0x00, 0x01 }, 2, -1); fails with ESP_ERR_INVALID_STATE and the logs show:

E (510) i2c.master: I2C hardware timeout detected
E (520) i2c.master: s_i2c_synchronous_transaction(870): I2C transaction failed
E (550) i2c.master: i2c_master_transmit(1072): I2C transaction failed

Thoughts on why the new i2c driver doesn't work at 400kHz while the old one does?

Metadata

Assignees

Labels

Resolution: NAIssue resolution is unavailableStatus: DoneIssue is done internally

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions