Problem
If another component (e.g. espressif/esp_lcd, espressif/i2c_bus, or
application code) has already called i2c_new_master_bus for a given port
before i2cdev touches it, i2c_setup_port will attempt a second
i2c_new_master_bus on the same port and return ESP_ERR_INVALID_STATE.
This makes i2cdev fragile in any project where the bus lifetime is managed
outside of i2cdev — which is a common pattern when multiple components share
a single I2C bus.
Suggested fix
Call i2c_master_get_bus_handle(port, &handle) before i2c_new_master_bus.
If a handle already exists, adopt it and skip installation. This is exactly
the pattern espressif/i2c_bus already implements:
// From espressif/i2c_bus
esp_err_t ret = i2c_master_get_bus_handle(i2c_num, &p_i2c_bus->i2c_master_handle);
if (ret == ESP_ERR_INVALID_ARG) {
// No existing handle — install a new bus
ret = i2c_master_bus_init(i2c_num, conf, &p_i2c_bus->i2c_master_handle);
p_i2c_bus->bus_mode = I2C_BUS_MODE_OWNER;
} else {
// Reuse the existing handle
p_i2c_bus->bus_mode = I2C_BUS_MODE_REFERENCE;
}
A similar externally_owned flag could be tracked in i2cdev's port_state
so that i2cdev_done / the port teardown path knows not to call
i2c_del_master_bus on a handle it didn't create.
Context
This came up while working on LP_I2C support (see #12 / PR #13). Before the
clock-source fix landed we pre-installed the LP bus from application code to
work around the wrong clock source, which then caused i2cdev to fail with
ESP_ERR_INVALID_STATE on first use. The clock-source fix removes our need
for pre-installation, but the underlying fragility remains for any project
that shares bus ownership between i2cdev and another component.
Problem
If another component (e.g.
espressif/esp_lcd,espressif/i2c_bus, orapplication code) has already called
i2c_new_master_busfor a given portbefore i2cdev touches it,
i2c_setup_portwill attempt a secondi2c_new_master_buson the same port and returnESP_ERR_INVALID_STATE.This makes i2cdev fragile in any project where the bus lifetime is managed
outside of i2cdev — which is a common pattern when multiple components share
a single I2C bus.
Suggested fix
Call
i2c_master_get_bus_handle(port, &handle)beforei2c_new_master_bus.If a handle already exists, adopt it and skip installation. This is exactly
the pattern
espressif/i2c_busalready implements:A similar
externally_ownedflag could be tracked in i2cdev'sport_stateso that
i2cdev_done/ the port teardown path knows not to calli2c_del_master_buson a handle it didn't create.Context
This came up while working on LP_I2C support (see #12 / PR #13). Before the
clock-source fix landed we pre-installed the LP bus from application code to
work around the wrong clock source, which then caused i2cdev to fail with
ESP_ERR_INVALID_STATEon first use. The clock-source fix removes our needfor pre-installation, but the underlying fragility remains for any project
that shares bus ownership between i2cdev and another component.