diff --git a/components/driver/i2c/i2c.c b/components/driver/i2c/i2c.c index e8b6353935..b8e4ea2ada 100644 --- a/components/driver/i2c/i2c.c +++ b/components/driver/i2c/i2c.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -64,6 +64,7 @@ static const char *I2C_TAG = "i2c"; #define I2C_CMD_USER_ALLOC_ERR_STR "i2c command link allocation error: the buffer provided is too small." #define I2C_TRANS_MODE_ERR_STR "i2c trans mode error" #define I2C_MODE_ERR_STR "i2c mode error" +#define I2C_CLEAR_BUS_ERR_STR "clear bus error" #define I2C_SDA_IO_ERR_STR "sda gpio number error" #define I2C_SCL_IO_ERR_STR "scl gpio number error" #define I2C_SCL_SDA_EQUAL_ERR_STR "scl and sda gpio numbers are the same" @@ -122,6 +123,8 @@ static const char *I2C_TAG = "i2c"; #define I2C_RCC_ATOMIC() #endif +#define I2C_CLR_BUS_TIMEOUT_MS (50) // 50ms is sufficient for clearing the bus + /** * I2C bus are defined in the header files, let's check that the values are correct */ @@ -626,6 +629,7 @@ esp_err_t i2c_get_data_mode(i2c_port_t i2c_num, i2c_trans_mode_t *tx_trans_mode, **/ static esp_err_t i2c_master_clear_bus(i2c_port_t i2c_num) { + esp_err_t ret = ESP_OK; #if !SOC_I2C_SUPPORT_HW_CLR_BUS const int scl_half_period = I2C_CLR_BUS_HALF_PERIOD_US; // use standard 100kHz data rate int i = 0; @@ -654,11 +658,22 @@ static esp_err_t i2c_master_clear_bus(i2c_port_t i2c_num) i2c_set_pin(i2c_num, sda_io, scl_io, 1, 1, I2C_MODE_MASTER); #else i2c_ll_master_clr_bus(i2c_context[i2c_num].hal.dev, I2C_CLR_BUS_SCL_NUM, true); + // If the i2c master clear bus state machine got disturbed when working, it would go into error state. + // The solution here is to use freertos tick counter to set a timeout threshold. If it doesn't return on time, + // return invalid state and turn off the state machine as its always wrong. + TickType_t start_tick = xTaskGetTickCount(); + const TickType_t timeout_ticks = pdMS_TO_TICKS(I2C_CLR_BUS_TIMEOUT_MS); while (i2c_ll_master_is_bus_clear_done(i2c_context[i2c_num].hal.dev)) { + if ((xTaskGetTickCount() - start_tick) > timeout_ticks) { + ESP_LOGE(I2C_TAG, I2C_CLEAR_BUS_ERR_STR); + i2c_ll_master_clr_bus(i2c_context[i2c_num].hal.dev, 0, false); + ret = ESP_ERR_INVALID_STATE; + break; + } } i2c_ll_update(i2c_context[i2c_num].hal.dev); #endif - return ESP_OK; + return ret; } /**if the power and SDA/SCL wires are in proper condition, everything works find with reading the slave. diff --git a/components/driver/i2c/i2c_master.c b/components/driver/i2c/i2c_master.c index cfb8842963..261dd031f3 100644 --- a/components/driver/i2c/i2c_master.c +++ b/components/driver/i2c/i2c_master.c @@ -105,7 +105,7 @@ static esp_err_t s_i2c_master_clear_bus(i2c_bus_handle_t handle) * * @param[in] i2c_master I2C master handle */ -static esp_err_t s_i2c_hw_fsm_reset(i2c_master_bus_handle_t i2c_master) +static esp_err_t s_i2c_hw_fsm_reset(i2c_master_bus_handle_t i2c_master, bool clear_bus) { esp_err_t ret = ESP_OK; i2c_hal_context_t *hal = &i2c_master->base->hal; @@ -117,19 +117,27 @@ static esp_err_t s_i2c_hw_fsm_reset(i2c_master_bus_handle_t i2c_master) i2c_ll_master_get_filter(hal->dev, &filter_cfg); //to reset the I2C hw module, we need re-enable the hw - ret = s_i2c_master_clear_bus(i2c_master->base); + if (clear_bus) { + ret = s_i2c_master_clear_bus(i2c_master->base); + } I2C_RCC_ATOMIC() { i2c_ll_reset_register(i2c_master->base->port_num); } i2c_hal_master_init(hal); + // Restore the clock source here. + I2C_CLOCK_SRC_ATOMIC() { + i2c_ll_set_source_clk(hal->dev, i2c_master->base->clk_src); + } i2c_ll_disable_intr_mask(hal->dev, I2C_LL_INTR_MASK); i2c_ll_clear_intr_mask(hal->dev, I2C_LL_INTR_MASK); i2c_hal_set_timing_config(hal, &timing_config); i2c_ll_master_set_filter(hal->dev, filter_cfg); #else i2c_ll_master_fsm_rst(hal->dev); - ret = s_i2c_master_clear_bus(i2c_master->base); + if (clear_bus) { + ret = s_i2c_master_clear_bus(i2c_master->base); + } #endif return ret; } @@ -213,14 +221,30 @@ static bool s_i2c_write_command(i2c_master_bus_handle_t i2c_master, i2c_operatio i2c_master->async_break = true; } } else { - i2c_master->cmd_idx++; - i2c_master->trans_idx++; - i2c_master->i2c_trans.cmd_count--; - if (i2c_master->async_trans == false) { - if (xPortInIsrContext()) { - xSemaphoreGiveFromISR(i2c_master->cmd_semphr, do_yield); + // Handle consecutive i2c write operations + i2c_operation_t next_transaction = i2c_master->i2c_trans.ops[i2c_master->trans_idx + 1]; + if (next_transaction.hw_cmd.op_code == I2C_LL_CMD_WRITE) { + portENTER_CRITICAL_SAFE(&handle->spinlock); + i2c_ll_master_write_cmd_reg(hal->dev, hw_end_cmd, i2c_master->cmd_idx + 1); + portEXIT_CRITICAL_SAFE(&handle->spinlock); + i2c_master->cmd_idx = 0; + i2c_master->trans_idx++; + i2c_master->i2c_trans.cmd_count--; + if (i2c_master->async_trans == false) { + i2c_hal_master_trans_start(hal); } else { - xSemaphoreGive(i2c_master->cmd_semphr); + i2c_master->async_break = true; + } + } else { + i2c_master->cmd_idx++; + i2c_master->trans_idx++; + i2c_master->i2c_trans.cmd_count--; + if (i2c_master->async_trans == false) { + if (xPortInIsrContext()) { + xSemaphoreGiveFromISR(i2c_master->cmd_semphr, do_yield); + } else { + xSemaphoreGive(i2c_master->cmd_semphr); + } } } } @@ -314,7 +338,7 @@ static bool s_i2c_read_command(i2c_master_bus_handle_t i2c_master, i2c_operation i2c_ll_master_write_cmd_reg(hal->dev, hw_cmd, i2c_master->cmd_idx); i2c_ll_master_write_cmd_reg(hal->dev, hw_end_cmd, i2c_master->cmd_idx + 1); portEXIT_CRITICAL_SAFE(&handle->spinlock); - i2c_master->status = I2C_STATUS_READ; + atomic_store(&i2c_master->status, I2C_STATUS_READ); portENTER_CRITICAL_SAFE(&handle->spinlock); if (i2c_master->async_trans == false) { i2c_hal_master_trans_start(hal); @@ -354,6 +378,8 @@ static void s_i2c_start_end_command(i2c_master_bus_handle_t i2c_master, i2c_oper } uint8_t addr_write[addr_byte]; uint8_t addr_read[addr_byte]; + memset(addr_write, 0, sizeof(addr_write)); + memset(addr_read, 0, sizeof(addr_read)); if (addr_byte != 0) { addr_write[0] = I2C_ADDRESS_TRANS_WRITE(cmd_address); @@ -455,16 +481,16 @@ static void s_i2c_send_commands(i2c_master_bus_handle_t i2c_master, TickType_t t while (i2c_master->i2c_trans.cmd_count) { if (xSemaphoreTake(i2c_master->cmd_semphr, ticks_to_wait) != pdTRUE) { // Software timeout, clear the command link and finish this transaction. + atomic_store(&i2c_master->status, I2C_STATUS_TIMEOUT); i2c_master->cmd_idx = 0; i2c_master->trans_idx = 0; - atomic_store(&i2c_master->status, I2C_STATUS_TIMEOUT); ESP_LOGE(TAG, "I2C software timeout"); xSemaphoreGive(i2c_master->cmd_semphr); return; } - if (i2c_master->status == I2C_STATUS_TIMEOUT) { - s_i2c_hw_fsm_reset(i2c_master); + if (atomic_load(&i2c_master->status) == I2C_STATUS_TIMEOUT) { + s_i2c_hw_fsm_reset(i2c_master, true); i2c_master->cmd_idx = 0; i2c_master->trans_idx = 0; ESP_LOGE(TAG, "I2C hardware timeout detected"); @@ -472,7 +498,7 @@ static void s_i2c_send_commands(i2c_master_bus_handle_t i2c_master, TickType_t t return; } - if (i2c_master->status == I2C_STATUS_ACK_ERROR) { + if (atomic_load(&i2c_master->status) == I2C_STATUS_ACK_ERROR) { ESP_LOGE(TAG, "I2C hardware NACK detected"); const i2c_ll_hw_cmd_t hw_stop_cmd = { .op_code = I2C_LL_CMD_STOP, @@ -572,8 +598,8 @@ static esp_err_t s_i2c_transaction_start(i2c_master_dev_handle_t i2c_dev, int xf TickType_t ticks_to_wait = (xfer_timeout_ms == -1) ? portMAX_DELAY : pdMS_TO_TICKS(xfer_timeout_ms); // Sometimes when the FSM get stuck, the ACK_ERR interrupt will occur endlessly until we reset the FSM and clear bus. esp_err_t ret = ESP_OK; - if (i2c_master->status == I2C_STATUS_TIMEOUT || i2c_ll_is_bus_busy(hal->dev)) { - ESP_RETURN_ON_ERROR(s_i2c_hw_fsm_reset(i2c_master), TAG, "reset hardware failed"); + if (atomic_load(&i2c_master->status) == I2C_STATUS_TIMEOUT || i2c_ll_is_bus_busy(hal->dev)) { + ESP_RETURN_ON_ERROR(s_i2c_hw_fsm_reset(i2c_master, true), TAG, "reset hardware failed"); } if (i2c_master->base->pm_lock) { @@ -607,7 +633,7 @@ static esp_err_t s_i2c_transaction_start(i2c_master_dev_handle_t i2c_dev, int xf } else { s_i2c_send_commands(i2c_master, ticks_to_wait); // Wait event bits - if (i2c_master->status != I2C_STATUS_DONE) { + if (atomic_load(&i2c_master->status) != I2C_STATUS_DONE) { ret = ESP_ERR_INVALID_STATE; } // Interrupt can be disabled when on transaction finishes. @@ -627,7 +653,8 @@ static esp_err_t s_i2c_transaction_start(i2c_master_dev_handle_t i2c_dev, int xf IRAM_ATTR static void i2c_isr_receive_handler(i2c_master_bus_t *i2c_master) { i2c_hal_context_t *hal = &i2c_master->base->hal; - if (i2c_master->status == I2C_STATUS_READ) { + + if (atomic_load(&i2c_master->status) == I2C_STATUS_READ) { i2c_operation_t *i2c_operation = &i2c_master->i2c_trans.ops[i2c_master->trans_idx]; portENTER_CRITICAL_ISR(&i2c_master->base->spinlock); i2c_ll_read_rxfifo(hal->dev, i2c_operation->data + i2c_operation->bytes_used, i2c_master->rx_cnt); @@ -901,7 +928,7 @@ static esp_err_t s_i2c_synchronous_transaction(i2c_master_dev_handle_t i2c_dev, err: // When error occurs, reset hardware fsm in case not influence following transactions. - s_i2c_hw_fsm_reset(i2c_dev->master_bus); + s_i2c_hw_fsm_reset(i2c_dev->master_bus, false); xSemaphoreGive(i2c_dev->master_bus->bus_lock_mux); return ret; } @@ -1084,7 +1111,7 @@ esp_err_t i2c_master_bus_reset(i2c_master_bus_handle_t bus_handle) { ESP_RETURN_ON_FALSE((bus_handle != NULL), ESP_ERR_INVALID_ARG, TAG, "This bus is not initialized"); // Reset I2C master bus - ESP_RETURN_ON_ERROR(s_i2c_hw_fsm_reset(bus_handle), TAG, "I2C master bus reset failed"); + ESP_RETURN_ON_ERROR(s_i2c_hw_fsm_reset(bus_handle, true), TAG, "I2C master bus reset failed"); // Reset I2C status state atomic_store(&bus_handle->status, I2C_STATUS_IDLE); return ESP_OK; @@ -1196,8 +1223,12 @@ esp_err_t i2c_master_probe(i2c_master_bus_handle_t bus_handle, uint16_t address, i2c_ll_set_source_clk(hal->dev, bus_handle->base->clk_src); i2c_hal_set_bus_timing(hal, 100000, bus_handle->base->clk_src, bus_handle->base->clk_src_freq_hz); } + i2c_ll_txfifo_rst(hal->dev); + i2c_ll_rxfifo_rst(hal->dev); i2c_ll_master_set_fractional_divider(hal->dev, 0, 0); i2c_ll_enable_intr_mask(hal->dev, I2C_LL_MASTER_EVENT_INTR); + // 20ms is sufficient for stretch, since there is no device config on probe operation. + i2c_hal_master_set_scl_timeout_val(hal, 20 * 1000, bus_handle->base->clk_src_freq_hz); i2c_ll_update(hal->dev); s_i2c_send_commands(bus_handle, ticks_to_wait); @@ -1223,7 +1254,7 @@ esp_err_t i2c_master_execute_defined_operations(i2c_master_dev_handle_t i2c_dev, ESP_RETURN_ON_FALSE(operation_list_num <= (SOC_I2C_CMD_REG_NUM), ESP_ERR_INVALID_ARG, TAG, "i2c command list cannot contain so many commands"); i2c_operation_t i2c_ops[operation_list_num]; - memset(i2c_ops, 0, sizeof(i2c_ops)/sizeof(i2c_operation_t)); + memset(i2c_ops, 0, sizeof(i2c_ops)); for (int i = 0; i < operation_list_num; i++) { switch (i2c_operation[i].command) { case I2C_MASTER_CMD_START: diff --git a/components/driver/i2c/i2c_private.h b/components/driver/i2c/i2c_private.h index 0d0e6cea20..9d623c8090 100644 --- a/components/driver/i2c/i2c_private.h +++ b/components/driver/i2c/i2c_private.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -52,7 +52,7 @@ extern "C" { #define I2C_ALLOW_INTR_PRIORITY_MASK ESP_INTR_FLAG_LOWMED #define I2C_PM_LOCK_NAME_LEN_MAX 16 -#define I2C_STATIC_OPERATION_ARRAY_MAX 6 +#define I2C_STATIC_OPERATION_ARRAY_MAX SOC_I2C_CMD_REG_NUM #define I2C_TRANS_READ_COMMAND(ack_value) {.ack_val = (ack_value), .op_code = I2C_LL_CMD_READ} #define I2C_TRANS_WRITE_COMMAND(ack_check) {.ack_en = (ack_check), .op_code = I2C_LL_CMD_WRITE} @@ -65,11 +65,6 @@ typedef struct i2c_bus_t *i2c_bus_handle_t; typedef struct i2c_master_dev_t i2c_master_dev_t; typedef struct i2c_slave_dev_t i2c_slave_dev_t; -typedef enum { - I2C_BUS_MODE_MASTER = 0, - I2C_BUS_MODE_SLAVE = 1, -} i2c_bus_mode_t; - typedef enum { I2C_SLAVE_FIFO = 0, I2C_SLAVE_NONFIFO = 1, diff --git a/components/driver/i2c/i2c_slave.c b/components/driver/i2c/i2c_slave.c index 8134908d2f..855d207866 100644 --- a/components/driver/i2c/i2c_slave.c +++ b/components/driver/i2c/i2c_slave.c @@ -199,6 +199,7 @@ esp_err_t i2c_new_slave_device(const i2c_slave_config_t *slave_config, i2c_slave ESP_RETURN_ON_FALSE(i2c_slave, ESP_ERR_NO_MEM, TAG, "no memory for i2c slave bus"); ESP_GOTO_ON_ERROR(i2c_acquire_bus_handle(i2c_port_num, &i2c_slave->base, I2C_BUS_MODE_SLAVE), err, TAG, "I2C bus acquire failed"); + i2c_port_num = i2c_slave->base->port_num; i2c_hal_context_t *hal = &i2c_slave->base->hal; i2c_slave->base->scl_num = slave_config->scl_io_num; diff --git a/components/driver/test_apps/i2c_test_apps/main/test_i2c_multi.c b/components/driver/test_apps/i2c_test_apps/main/test_i2c_multi.c index 87e206cee9..a9cb9493ef 100644 --- a/components/driver/test_apps/i2c_test_apps/main/test_i2c_multi.c +++ b/components/driver/test_apps/i2c_test_apps/main/test_i2c_multi.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -788,3 +788,94 @@ static void uart_test_i2c_master_freq(void) TEST_CASE_MULTIPLE_DEVICES("I2C master clock frequency test", "[i2c][test_env=generic_multi_device][timeout=150]", uart_test_i2c_master_freq, i2c_master_write_fsm_reset); #endif // CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 + +static void i2c_master_write_test_with_customize_api(void) +{ + uint8_t data_wr[DATA_LENGTH] = { 0 }; + int i; + + i2c_master_bus_config_t i2c_mst_config = { + .clk_source = I2C_CLK_SRC_DEFAULT, + .i2c_port = TEST_I2C_PORT, + .scl_io_num = I2C_MASTER_SCL_IO, + .sda_io_num = I2C_MASTER_SDA_IO, + .flags.enable_internal_pullup = true, + }; + i2c_master_bus_handle_t bus_handle; + + TEST_ESP_OK(i2c_new_master_bus(&i2c_mst_config, &bus_handle)); + + i2c_device_config_t dev_cfg = { + .dev_addr_length = I2C_ADDR_BIT_LEN_7, + .device_address = 0xFFFF, + .scl_speed_hz = 100000, + }; + + i2c_master_dev_handle_t dev_handle; + TEST_ESP_OK(i2c_master_bus_add_device(bus_handle, &dev_cfg, &dev_handle)); + + unity_wait_for_signal("i2c slave init finish"); + + unity_send_signal("master write"); + for (i = 0; i < DATA_LENGTH; i++) { + data_wr[i] = i; + } + + disp_buf(data_wr, i); + + uint8_t address = (0x58 << 1 | 0); + + i2c_operation_job_t i2c_ops[] = { + { .command = I2C_MASTER_CMD_START }, + { .command = I2C_MASTER_CMD_WRITE, .write = { .ack_check = true, .data = (uint8_t *) &address, .total_bytes = 1 } }, + { .command = I2C_MASTER_CMD_WRITE, .write = { .ack_check = true, .data = (uint8_t *) data_wr, .total_bytes = DATA_LENGTH } }, + { .command = I2C_MASTER_CMD_STOP }, + }; + + TEST_ESP_OK(i2c_master_execute_defined_operations(dev_handle, i2c_ops, sizeof(i2c_ops) / sizeof(i2c_operation_job_t), -1)); + unity_wait_for_signal("ready to delete"); + TEST_ESP_OK(i2c_master_bus_rm_device(dev_handle)); + + TEST_ESP_OK(i2c_del_master_bus(bus_handle)); +} + +static void i2c_slave_read_test_v1(void) +{ + uint8_t data_rd[DATA_LENGTH] = {0}; + + i2c_slave_config_t i2c_slv_config = { + .addr_bit_len = I2C_ADDR_BIT_LEN_7, + .clk_source = I2C_CLK_SRC_DEFAULT, + .i2c_port = TEST_I2C_PORT, + .send_buf_depth = 256, + .scl_io_num = I2C_SLAVE_SCL_IO, + .sda_io_num = I2C_SLAVE_SDA_IO, + .slave_addr = 0x58, + }; + + i2c_slave_dev_handle_t slave_handle; + TEST_ESP_OK(i2c_new_slave_device(&i2c_slv_config, &slave_handle)); + + s_receive_queue = xQueueCreate(1, sizeof(i2c_slave_rx_done_event_data_t)); + i2c_slave_event_callbacks_t cbs = { + .on_recv_done = test_i2c_rx_done_callback, + }; + ESP_ERROR_CHECK(i2c_slave_register_event_callbacks(slave_handle, &cbs, s_receive_queue)); + + i2c_slave_rx_done_event_data_t rx_data; + TEST_ESP_OK(i2c_slave_receive(slave_handle, data_rd, DATA_LENGTH)); + + unity_send_signal("i2c slave init finish"); + + unity_wait_for_signal("master write"); + xQueueReceive(s_receive_queue, &rx_data, pdMS_TO_TICKS(10000)); + disp_buf(data_rd, DATA_LENGTH); + for (int i = 0; i < DATA_LENGTH; i++) { + TEST_ASSERT(data_rd[i] == i); + } + vQueueDelete(s_receive_queue); + unity_send_signal("ready to delete"); + TEST_ESP_OK(i2c_del_slave_device(slave_handle)); +} + +TEST_CASE_MULTIPLE_DEVICES("I2C master write slave with customize api", "[i2c][test_env=generic_multi_device][timeout=150]", i2c_master_write_test_with_customize_api, i2c_slave_read_test_v1); diff --git a/components/hal/esp32/include/hal/i2c_ll.h b/components/hal/esp32/include/hal/i2c_ll.h index 4a97017c37..3f700155fa 100644 --- a/components/hal/esp32/include/hal/i2c_ll.h +++ b/components/hal/esp32/include/hal/i2c_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -652,6 +652,20 @@ static inline bool i2c_ll_master_is_bus_clear_done(i2c_dev_t *hw) return false; } +/** + * @brief Set the ACK level that the I2C master must send when the Rx FIFO count has reached the threshold value. + * ack_level: 1 (NACK) + * ack_level: 0 (ACK) + * + * @param hw Beginning address of the peripheral registers + * + * @return None + */ +static inline void i2c_ll_master_rx_full_ack_level(i2c_dev_t *hw, int ack_level) +{ + // Not supported on esp32 +} + /** * @brief Set I2C source clock * @@ -678,37 +692,37 @@ static inline void i2c_ll_enable_controller_clock(i2c_dev_t *hw, bool en) } /** - * @brief Init I2C master + * @brief Set the I2C bus mode (Master or Slave) * - * @param hw Beginning address of the peripheral registers - * - * @return None + * @param hw Pointer to the I2C hardware register structure. + * @param mode The desired I2C bus mode (Master or Slave). */ -static inline void i2c_ll_master_init(i2c_dev_t *hw) +static inline void i2c_ll_set_mode(i2c_dev_t *hw, i2c_bus_mode_t mode) { - typeof(hw->ctr) ctrl_reg; - ctrl_reg.val = 0; - ctrl_reg.ms_mode = 1; - ctrl_reg.sda_force_out = 1; - ctrl_reg.scl_force_out = 1; - hw->ctr.val = ctrl_reg.val; + hw->ctr.ms_mode = (mode == I2C_BUS_MODE_MASTER) ? 1 : 0; } /** - * @brief Init I2C slave + * @brief Enable or disable open-drain mode for I2C pins * - * @param hw Beginning address of the peripheral registers - * - * @return None + * @param hw Pointer to the I2C hardware register structure. + * @param enable_od Boolean flag to enable or disable open-drain mode: */ -static inline void i2c_ll_slave_init(i2c_dev_t *hw) +static inline void i2c_ll_enable_pins_open_drain(i2c_dev_t *hw, bool enable_od) { - typeof(hw->ctr) ctrl_reg; - ctrl_reg.val = 0; - ctrl_reg.sda_force_out = 1; - ctrl_reg.scl_force_out = 1; - hw->ctr.val = ctrl_reg.val; - hw->fifo_conf.fifo_addr_cfg_en = 0; + hw->ctr.sda_force_out = enable_od; + hw->ctr.scl_force_out = enable_od; +} + +/** + * @brief Enable or disable arbitration for I2C communication. + * + * @param hw Pointer to the I2C hardware instance. + * @param enable_arbi Boolean flag to enable (true) or disable (false) arbitration. + */ +static inline void i2c_ll_enable_arbitration(i2c_dev_t *hw, bool enable_arbi) +{ + ;// ESP32 do not support } /** diff --git a/components/hal/esp32c2/include/hal/i2c_ll.h b/components/hal/esp32c2/include/hal/i2c_ll.h index 170b8a2d45..5cc967554b 100644 --- a/components/hal/esp32c2/include/hal/i2c_ll.h +++ b/components/hal/esp32c2/include/hal/i2c_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -692,6 +692,20 @@ static inline bool i2c_ll_master_is_bus_clear_done(i2c_dev_t *hw) return hw->scl_sp_conf.scl_rst_slv_en; } +/** + * @brief Set the ACK level that the I2C master must send when the Rx FIFO count has reached the threshold value. + * ack_level: 1 (NACK) + * ack_level: 0 (ACK) + * + * @param hw Beginning address of the peripheral registers + * + * @return None + */ +static inline void i2c_ll_master_rx_full_ack_level(i2c_dev_t *hw, int ack_level) +{ + hw->ctr.rx_full_ack_level = ack_level; +} + /** * @brief Set I2C source clock * @@ -718,21 +732,37 @@ static inline void i2c_ll_enable_controller_clock(i2c_dev_t *hw, bool en) } /** - * @brief Init I2C master + * @brief Set the I2C bus mode (Master or Slave) * - * @param hw Beginning address of the peripheral registers - * - * @return None + * @param hw Pointer to the I2C hardware register structure. + * @param mode The desired I2C bus mode (Master or Slave). */ -static inline void i2c_ll_master_init(i2c_dev_t *hw) +static inline void i2c_ll_set_mode(i2c_dev_t *hw, i2c_bus_mode_t mode) { - typeof(hw->ctr) ctrl_reg; - ctrl_reg.val = 0; - ctrl_reg.ms_mode = 1; - ctrl_reg.clk_en = 1; - ctrl_reg.sda_force_out = 1; - ctrl_reg.scl_force_out = 1; - hw->ctr.val = ctrl_reg.val; + hw->ctr.ms_mode = (mode == I2C_BUS_MODE_MASTER) ? 1 : 0; +} + +/** + * @brief Enable or disable open-drain mode for I2C pins + * + * @param hw Pointer to the I2C hardware register structure. + * @param enable_od Boolean flag to enable or disable open-drain mode: + */ +static inline void i2c_ll_enable_pins_open_drain(i2c_dev_t *hw, bool enable_od) +{ + hw->ctr.sda_force_out = enable_od; + hw->ctr.scl_force_out = enable_od; +} + +/** + * @brief Enable or disable arbitration for I2C communication. + * + * @param hw Pointer to the I2C hardware instance. + * @param enable_arbi Boolean flag to enable (true) or disable (false) arbitration. + */ +static inline void i2c_ll_enable_arbitration(i2c_dev_t *hw, bool enable_arbi) +{ + hw->ctr.arbitration_en = enable_arbi; } /** diff --git a/components/hal/esp32c3/include/hal/i2c_ll.h b/components/hal/esp32c3/include/hal/i2c_ll.h index ea216a2a43..8d90b44d5e 100644 --- a/components/hal/esp32c3/include/hal/i2c_ll.h +++ b/components/hal/esp32c3/include/hal/i2c_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -815,6 +815,20 @@ static inline bool i2c_ll_master_is_bus_clear_done(i2c_dev_t *hw) return hw->scl_sp_conf.scl_rst_slv_en; } +/** + * @brief Set the ACK level that the I2C master must send when the Rx FIFO count has reached the threshold value. + * ack_level: 1 (NACK) + * ack_level: 0 (ACK) + * + * @param hw Beginning address of the peripheral registers + * + * @return None + */ +static inline void i2c_ll_master_rx_full_ack_level(i2c_dev_t *hw, int ack_level) +{ + hw->ctr.rx_full_ack_level = ack_level; +} + /** * @brief Set I2C source clock * @@ -841,38 +855,37 @@ static inline void i2c_ll_enable_controller_clock(i2c_dev_t *hw, bool en) } /** - * @brief Init I2C master + * @brief Set the I2C bus mode (Master or Slave) * - * @param hw Beginning address of the peripheral registers - * - * @return None + * @param hw Pointer to the I2C hardware register structure. + * @param mode The desired I2C bus mode (Master or Slave). */ -static inline void i2c_ll_master_init(i2c_dev_t *hw) +static inline void i2c_ll_set_mode(i2c_dev_t *hw, i2c_bus_mode_t mode) { - typeof(hw->ctr) ctrl_reg; - ctrl_reg.val = 0; - ctrl_reg.ms_mode = 1; - ctrl_reg.clk_en = 1; - ctrl_reg.sda_force_out = 1; - ctrl_reg.scl_force_out = 1; - hw->ctr.val = ctrl_reg.val; + hw->ctr.ms_mode = (mode == I2C_BUS_MODE_MASTER) ? 1 : 0; } /** - * @brief Init I2C slave + * @brief Enable or disable open-drain mode for I2C pins * - * @param hw Beginning address of the peripheral registers - * - * @return None + * @param hw Pointer to the I2C hardware register structure. + * @param enable_od Boolean flag to enable or disable open-drain mode: */ -static inline void i2c_ll_slave_init(i2c_dev_t *hw) +static inline void i2c_ll_enable_pins_open_drain(i2c_dev_t *hw, bool enable_od) { - typeof(hw->ctr) ctrl_reg; - ctrl_reg.val = 0; - ctrl_reg.sda_force_out = 1; - ctrl_reg.scl_force_out = 1; - hw->ctr.val = ctrl_reg.val; - hw->fifo_conf.fifo_addr_cfg_en = 0; + hw->ctr.sda_force_out = enable_od; + hw->ctr.scl_force_out = enable_od; +} + +/** + * @brief Enable or disable arbitration for I2C communication. + * + * @param hw Pointer to the I2C hardware instance. + * @param enable_arbi Boolean flag to enable (true) or disable (false) arbitration. + */ +static inline void i2c_ll_enable_arbitration(i2c_dev_t *hw, bool enable_arbi) +{ + hw->ctr.arbitration_en = enable_arbi; } /** diff --git a/components/hal/esp32c6/include/hal/i2c_ll.h b/components/hal/esp32c6/include/hal/i2c_ll.h index 944c8d3bcf..6e85e746bb 100644 --- a/components/hal/esp32c6/include/hal/i2c_ll.h +++ b/components/hal/esp32c6/include/hal/i2c_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -874,37 +874,37 @@ static inline void i2c_ll_enable_controller_clock(i2c_dev_t *hw, bool en) } /** - * @brief Init I2C master + * @brief Set the I2C bus mode (Master or Slave) * - * @param hw Beginning address of the peripheral registers - * - * @return None + * @param hw Pointer to the I2C hardware register structure. + * @param mode The desired I2C bus mode (Master or Slave). */ -static inline void i2c_ll_master_init(i2c_dev_t *hw) +static inline void i2c_ll_set_mode(i2c_dev_t *hw, i2c_bus_mode_t mode) { - typeof(hw->ctr) ctrl_reg; - ctrl_reg.val = 0; - ctrl_reg.ms_mode = 1; - ctrl_reg.sda_force_out = 0; - ctrl_reg.scl_force_out = 0; - hw->ctr.val = ctrl_reg.val; + hw->ctr.ms_mode = (mode == I2C_BUS_MODE_MASTER) ? 1 : 0; } /** - * @brief Init I2C slave + * @brief Enable or disable open-drain mode for I2C pins * - * @param hw Beginning address of the peripheral registers - * - * @return None + * @param hw Pointer to the I2C hardware register structure. + * @param enable_od Boolean flag to enable or disable open-drain mode: */ -static inline void i2c_ll_slave_init(i2c_dev_t *hw) +static inline void i2c_ll_enable_pins_open_drain(i2c_dev_t *hw, bool enable_od) { - typeof(hw->ctr) ctrl_reg; - ctrl_reg.val = 0; - ctrl_reg.sda_force_out = 0; - ctrl_reg.scl_force_out = 0; - hw->ctr.val = ctrl_reg.val; - hw->fifo_conf.fifo_addr_cfg_en = 0; + hw->ctr.sda_force_out = !enable_od; + hw->ctr.scl_force_out = !enable_od; +} + +/** + * @brief Enable or disable arbitration for I2C communication. + * + * @param hw Pointer to the I2C hardware instance. + * @param enable_arbi Boolean flag to enable (true) or disable (false) arbitration. + */ +static inline void i2c_ll_enable_arbitration(i2c_dev_t *hw, bool enable_arbi) +{ + hw->ctr.arbitration_en = enable_arbi; } /** diff --git a/components/hal/esp32h2/include/hal/i2c_ll.h b/components/hal/esp32h2/include/hal/i2c_ll.h index c73dc8ef08..7927c61b81 100644 --- a/components/hal/esp32h2/include/hal/i2c_ll.h +++ b/components/hal/esp32h2/include/hal/i2c_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -762,6 +762,20 @@ static inline bool i2c_ll_master_is_bus_clear_done(i2c_dev_t *hw) return hw->scl_sp_conf.scl_rst_slv_en; } +/** + * @brief Set the ACK level that the I2C master must send when the Rx FIFO count has reached the threshold value. + * ack_level: 1 (NACK) + * ack_level: 0 (ACK) + * + * @param hw Beginning address of the peripheral registers + * + * @return None + */ +static inline void i2c_ll_master_rx_full_ack_level(i2c_dev_t *hw, int ack_level) +{ + hw->ctr.rx_full_ack_level = ack_level; +} + /** * @brief Set I2C source clock * @@ -789,37 +803,37 @@ static inline void i2c_ll_enable_controller_clock(i2c_dev_t *hw, bool en) } /** - * @brief Init I2C master + * @brief Set the I2C bus mode (Master or Slave) * - * @param hw Beginning address of the peripheral registers - * - * @return None + * @param hw Pointer to the I2C hardware register structure. + * @param mode The desired I2C bus mode (Master or Slave). */ -static inline void i2c_ll_master_init(i2c_dev_t *hw) +static inline void i2c_ll_set_mode(i2c_dev_t *hw, i2c_bus_mode_t mode) { - typeof(hw->ctr) ctrl_reg; - ctrl_reg.val = 0; - ctrl_reg.ms_mode = 1; - ctrl_reg.sda_force_out = 0; - ctrl_reg.scl_force_out = 0; - hw->ctr.val = ctrl_reg.val; + hw->ctr.ms_mode = (mode == I2C_BUS_MODE_MASTER) ? 1 : 0; } /** - * @brief Init I2C slave + * @brief Enable or disable open-drain mode for I2C pins * - * @param hw Beginning address of the peripheral registers - * - * @return None + * @param hw Pointer to the I2C hardware register structure. + * @param enable_od Boolean flag to enable or disable open-drain mode: */ -static inline void i2c_ll_slave_init(i2c_dev_t *hw) +static inline void i2c_ll_enable_pins_open_drain(i2c_dev_t *hw, bool enable_od) { - typeof(hw->ctr) ctrl_reg; - ctrl_reg.val = 0; - ctrl_reg.sda_force_out = 0; - ctrl_reg.scl_force_out = 0; - hw->ctr.val = ctrl_reg.val; - hw->fifo_conf.fifo_addr_cfg_en = 0; + hw->ctr.sda_force_out = !enable_od; + hw->ctr.scl_force_out = !enable_od; +} + +/** + * @brief Enable or disable arbitration for I2C communication. + * + * @param hw Pointer to the I2C hardware instance. + * @param enable_arbi Boolean flag to enable (true) or disable (false) arbitration. + */ +static inline void i2c_ll_enable_arbitration(i2c_dev_t *hw, bool enable_arbi) +{ + hw->ctr.arbitration_en = enable_arbi; } /** diff --git a/components/hal/esp32p4/include/hal/i2c_ll.h b/components/hal/esp32p4/include/hal/i2c_ll.h index 065a92be37..dbfb7b5dba 100644 --- a/components/hal/esp32p4/include/hal/i2c_ll.h +++ b/components/hal/esp32p4/include/hal/i2c_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -829,37 +829,37 @@ static inline void i2c_ll_enable_controller_clock(i2c_dev_t *hw, bool en) } /** - * @brief Init I2C master + * @brief Set the I2C bus mode (Master or Slave) * - * @param hw Beginning address of the peripheral registers - * - * @return None + * @param hw Pointer to the I2C hardware register structure. + * @param mode The desired I2C bus mode (Master or Slave). */ -static inline void i2c_ll_master_init(i2c_dev_t *hw) +static inline void i2c_ll_set_mode(i2c_dev_t *hw, i2c_bus_mode_t mode) { - typeof(hw->ctr) ctrl_reg; - ctrl_reg.val = 0; - ctrl_reg.ms_mode = 1; - ctrl_reg.sda_force_out = 0; - ctrl_reg.scl_force_out = 0; - hw->ctr.val = ctrl_reg.val; + hw->ctr.ms_mode = (mode == I2C_BUS_MODE_MASTER) ? 1 : 0; } /** - * @brief Init I2C slave + * @brief Enable or disable open-drain mode for I2C pins * - * @param hw Beginning address of the peripheral registers - * - * @return None + * @param hw Pointer to the I2C hardware register structure. + * @param enable_od Boolean flag to enable or disable open-drain mode: */ -static inline void i2c_ll_slave_init(i2c_dev_t *hw) +static inline void i2c_ll_enable_pins_open_drain(i2c_dev_t *hw, bool enable_od) { - typeof(hw->ctr) ctrl_reg; - ctrl_reg.val = 0; - ctrl_reg.sda_force_out = 0; - ctrl_reg.scl_force_out = 0; - hw->ctr.val = ctrl_reg.val; - hw->fifo_conf.fifo_addr_cfg_en = 0; + hw->ctr.sda_force_out = !enable_od; + hw->ctr.scl_force_out = !enable_od; +} + +/** + * @brief Enable or disable arbitration for I2C communication. + * + * @param hw Pointer to the I2C hardware instance. + * @param enable_arbi Boolean flag to enable (true) or disable (false) arbitration. + */ +static inline void i2c_ll_enable_arbitration(i2c_dev_t *hw, bool enable_arbi) +{ + hw->ctr.arbitration_en = enable_arbi; } /** diff --git a/components/hal/esp32s2/include/hal/i2c_ll.h b/components/hal/esp32s2/include/hal/i2c_ll.h index 163e1e7c74..266c796b60 100644 --- a/components/hal/esp32s2/include/hal/i2c_ll.h +++ b/components/hal/esp32s2/include/hal/i2c_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -681,6 +681,20 @@ static inline bool i2c_ll_master_is_bus_clear_done(i2c_dev_t *hw) return false; // not supported on esp32s2 } +/** + * @brief Set the ACK level that the I2C master must send when the Rx FIFO count has reached the threshold value. + * ack_level: 1 (NACK) + * ack_level: 0 (ACK) + * + * @param hw Beginning address of the peripheral registers + * + * @return None + */ +static inline void i2c_ll_master_rx_full_ack_level(i2c_dev_t *hw, int ack_level) +{ + hw->ctr.rx_full_ack_level = ack_level; +} + /** * @brief Set I2C source clock * @@ -708,36 +722,37 @@ static inline void i2c_ll_enable_controller_clock(i2c_dev_t *hw, bool en) } /** - * @brief Init I2C master + * @brief Set the I2C bus mode (Master or Slave) * - * @param hw Beginning address of the peripheral registers - * - * @return None + * @param hw Pointer to the I2C hardware register structure. + * @param mode The desired I2C bus mode (Master or Slave). */ -static inline void i2c_ll_master_init(i2c_dev_t *hw) +static inline void i2c_ll_set_mode(i2c_dev_t *hw, i2c_bus_mode_t mode) { - typeof(hw->ctr) ctrl_reg; - ctrl_reg.val = 0; - ctrl_reg.ms_mode = 1; - ctrl_reg.sda_force_out = 1; - ctrl_reg.scl_force_out = 1; - hw->ctr.val = ctrl_reg.val; + hw->ctr.ms_mode = (mode == I2C_BUS_MODE_MASTER) ? 1 : 0; } /** - * @brief Enable I2C internal open-drain mode - * If internal open-drain of the I2C module is disabled, scl and sda gpio should be configured in open-drain mode. - * Otherwise it is not needed. + * @brief Enable or disable open-drain mode for I2C pins * - * @param hw Beginning address of the peripheral registers - * @param internal_od_ena Set true to enable internal open-drain, otherwise, set it false. - * - * @return None + * @param hw Pointer to the I2C hardware register structure. + * @param enable_od Boolean flag to enable or disable open-drain mode: */ -static inline void i2c_ll_internal_od_enable(i2c_dev_t *hw, bool internal_od_ena) +static inline void i2c_ll_enable_pins_open_drain(i2c_dev_t *hw, bool enable_od) { - hw->ctr.sda_force_out = (internal_od_ena == false); - hw->ctr.scl_force_out = (internal_od_ena == false); + hw->ctr.sda_force_out = enable_od; + hw->ctr.scl_force_out = enable_od; +} + +/** + * @brief Enable or disable arbitration for I2C communication. + * + * @param hw Pointer to the I2C hardware instance. + * @param enable_arbi Boolean flag to enable (true) or disable (false) arbitration. + */ +static inline void i2c_ll_enable_arbitration(i2c_dev_t *hw, bool enable_arbi) +{ + hw->ctr.arbitration_en = enable_arbi; } /** diff --git a/components/hal/esp32s3/include/hal/i2c_ll.h b/components/hal/esp32s3/include/hal/i2c_ll.h index 0b877b95c4..418086073b 100644 --- a/components/hal/esp32s3/include/hal/i2c_ll.h +++ b/components/hal/esp32s3/include/hal/i2c_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -820,6 +820,20 @@ static inline bool i2c_ll_master_is_bus_clear_done(i2c_dev_t *hw) return false; // not supported on esp32s3 } +/** + * @brief Set the ACK level that the I2C master must send when the Rx FIFO count has reached the threshold value. + * ack_level: 1 (NACK) + * ack_level: 0 (ACK) + * + * @param hw Beginning address of the peripheral registers + * + * @return None + */ +static inline void i2c_ll_master_rx_full_ack_level(i2c_dev_t *hw, int ack_level) +{ + hw->ctr.rx_full_ack_level = ack_level; +} + /** * @brief Set I2C source clock * @@ -845,38 +859,37 @@ static inline void i2c_ll_enable_controller_clock(i2c_dev_t *hw, bool en) } /** - * @brief Init I2C master + * @brief Set the I2C bus mode (Master or Slave) * - * @param hw Beginning address of the peripheral registers - * - * @return None + * @param hw Pointer to the I2C hardware register structure. + * @param mode The desired I2C bus mode (Master or Slave). */ -static inline void i2c_ll_master_init(i2c_dev_t *hw) +static inline void i2c_ll_set_mode(i2c_dev_t *hw, i2c_bus_mode_t mode) { - typeof(hw->ctr) ctrl_reg; - ctrl_reg.val = 0; - ctrl_reg.ms_mode = 1; - ctrl_reg.clk_en = 1; - ctrl_reg.sda_force_out = 1; - ctrl_reg.scl_force_out = 1; - hw->ctr.val = ctrl_reg.val; + hw->ctr.ms_mode = (mode == I2C_BUS_MODE_MASTER) ? 1 : 0; } /** - * @brief Init I2C slave + * @brief Enable or disable open-drain mode for I2C pins * - * @param hw Beginning address of the peripheral registers - * - * @return None + * @param hw Pointer to the I2C hardware register structure. + * @param enable_od Boolean flag to enable or disable open-drain mode: */ -static inline void i2c_ll_slave_init(i2c_dev_t *hw) +static inline void i2c_ll_enable_pins_open_drain(i2c_dev_t *hw, bool enable_od) { - typeof(hw->ctr) ctrl_reg; - ctrl_reg.val = 0; - ctrl_reg.sda_force_out = 1; - ctrl_reg.scl_force_out = 1; - hw->ctr.val = ctrl_reg.val; - hw->fifo_conf.fifo_addr_cfg_en = 0; + hw->ctr.sda_force_out = enable_od; + hw->ctr.scl_force_out = enable_od; +} + +/** + * @brief Enable or disable arbitration for I2C communication. + * + * @param hw Pointer to the I2C hardware instance. + * @param enable_arbi Boolean flag to enable (true) or disable (false) arbitration. + */ +static inline void i2c_ll_enable_arbitration(i2c_dev_t *hw, bool enable_arbi) +{ + hw->ctr.arbitration_en = enable_arbi; } /** diff --git a/components/hal/i2c_hal.c b/components/hal/i2c_hal.c index 2daa902bb7..f73154b1df 100644 --- a/components/hal/i2c_hal.c +++ b/components/hal/i2c_hal.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -13,7 +13,9 @@ void i2c_hal_slave_init(i2c_hal_context_t *hal) { - i2c_ll_slave_init(hal->dev); + i2c_ll_set_mode(hal->dev, I2C_BUS_MODE_SLAVE); + i2c_ll_enable_pins_open_drain(hal->dev, true); + i2c_ll_enable_arbitration(hal->dev, false); //MSB i2c_ll_set_data_mode(hal->dev, I2C_DATA_MODE_MSB_FIRST, I2C_DATA_MODE_MSB_FIRST); //Reset fifo @@ -36,7 +38,10 @@ void i2c_hal_master_fsm_rst(i2c_hal_context_t *hal) void i2c_hal_master_init(i2c_hal_context_t *hal) { - i2c_ll_master_init(hal->dev); + i2c_ll_set_mode(hal->dev, I2C_BUS_MODE_MASTER); + i2c_ll_enable_pins_open_drain(hal->dev, true); + i2c_ll_enable_arbitration(hal->dev, false); + i2c_ll_master_rx_full_ack_level(hal->dev, false); //MSB i2c_ll_set_data_mode(hal->dev, I2C_DATA_MODE_MSB_FIRST, I2C_DATA_MODE_MSB_FIRST); //Reset fifo diff --git a/components/hal/include/hal/i2c_types.h b/components/hal/include/hal/i2c_types.h index e264b2aff2..b928019520 100644 --- a/components/hal/include/hal/i2c_types.h +++ b/components/hal/include/hal/i2c_types.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -98,6 +98,19 @@ typedef enum { I2C_SLAVE_STRETCH_CAUSE_SENDING_ACK = 3, /*!< Stretching SCL low when slave sending ACK */ } i2c_slave_stretch_cause_t; +typedef enum { + I2C_SLAVE_WRITE_BY_MASTER = 0, + I2C_SLAVE_READ_BY_MASTER = 1, +} i2c_slave_read_write_status_t; + +/** + * @brief Enum for i2c working modes. + */ +typedef enum { + I2C_BUS_MODE_MASTER = 0, /*!< I2C works under master mode */ + I2C_BUS_MODE_SLAVE = 1, /*!< I2C works under slave mode */ +} i2c_bus_mode_t; + #if SOC_I2C_SUPPORTED /** * @brief I2C group clock source