diff --git a/components/esp_driver_i2c/i2c_master.c b/components/esp_driver_i2c/i2c_master.c index a0fadc64d5..1b4e9d0c8a 100644 --- a/components/esp_driver_i2c/i2c_master.c +++ b/components/esp_driver_i2c/i2c_master.c @@ -1290,6 +1290,34 @@ esp_err_t i2c_master_probe(i2c_master_bus_handle_t bus_handle, uint16_t address, return ret; } +esp_err_t i2c_master_device_change_address(i2c_master_dev_handle_t i2c_dev, uint16_t new_device_address, int timeout_ms) +{ + ESP_RETURN_ON_FALSE(i2c_dev != NULL, ESP_ERR_INVALID_ARG, TAG, "i2c handle not initialized"); + + TickType_t ticks_to_wait = (timeout_ms == -1) ? portMAX_DELAY : pdMS_TO_TICKS(timeout_ms); + if (xSemaphoreTake(i2c_dev->master_bus->bus_lock_mux, ticks_to_wait) != pdTRUE) { + ESP_LOGE(TAG, "change address take semaphore timeout"); + return ESP_ERR_TIMEOUT; + } + + if (i2c_dev->addr_10bits == I2C_ADDR_BIT_LEN_7) { + if (new_device_address > 0x7f) { + ESP_LOGE(TAG, "The address is now 7 bit address mode, new address is larger than 7 bits"); + return ESP_ERR_INVALID_ARG; + } + } else { + if (new_device_address <= 0x7f) { + ESP_LOGE(TAG, "The address is now 10 bit address mode, new address is smaller than 10 bits"); + return ESP_ERR_INVALID_ARG; + } + } + + i2c_dev->device_address = new_device_address; + + xSemaphoreGive(i2c_dev->master_bus->bus_lock_mux); + return ESP_OK; +} + esp_err_t i2c_master_register_event_callbacks(i2c_master_dev_handle_t i2c_dev, const i2c_master_event_callbacks_t *cbs, void *user_data) { ESP_RETURN_ON_FALSE(i2c_dev != NULL, ESP_ERR_INVALID_ARG, TAG, "i2c handle not initialized"); diff --git a/components/esp_driver_i2c/include/driver/i2c_master.h b/components/esp_driver_i2c/include/driver/i2c_master.h index 8518a45d0c..d5c18fb123 100644 --- a/components/esp_driver_i2c/include/driver/i2c_master.h +++ b/components/esp_driver_i2c/include/driver/i2c_master.h @@ -247,6 +247,29 @@ esp_err_t i2c_master_register_event_callbacks(i2c_master_dev_handle_t i2c_dev, c */ esp_err_t i2c_master_bus_reset(i2c_master_bus_handle_t bus_handle); +/** + * @brief Change the I2C device address at runtime. + * + * This function updates the device address of an existing I2C device handle. + * It is useful for devices that support dynamic address assignment or when + * switching communication to a device with a different address on the same bus. + * + * @param[in] i2c_dev I2C device handle. + * @param[in] new_device_address The new device address. + * @param[in] timeout_ms Timeout for the address change operation, in milliseconds. + * + * @return + * - ESP_OK: Address successfully changed. + * - ESP_ERR_INVALID_ARG: Invalid arguments (e.g., NULL handle or invalid address). + * - ESP_ERR_TIMEOUT: Operation timed out. + * + * @note + * - This function does not send commands to the I2C device. It only updates + * the address used in subsequent transactions through the I2C handle. + * - Ensure that the new address is valid and does not conflict with other devices on the bus. + */ +esp_err_t i2c_master_device_change_address(i2c_master_dev_handle_t i2c_dev, uint16_t new_device_address, int timeout_ms); + /** * @brief Wait for all pending I2C transactions done *