From 803fc3fbe0d659aeb1bdc6eea4fb6cfafe72c6e1 Mon Sep 17 00:00:00 2001 From: Cao Sen Miao Date: Wed, 2 Nov 2022 18:09:22 +0800 Subject: [PATCH] I2C: Add i2c support for ESP32C6 --- components/driver/i2c.c | 8 +- components/hal/esp32/include/hal/i2c_ll.h | 22 +- components/hal/esp32c2/include/hal/i2c_ll.h | 24 +- components/hal/esp32c3/include/hal/i2c_ll.h | 23 +- components/hal/esp32c6/include/hal/i2c_ll.h | 948 ++++++++++++++++++ components/hal/esp32h2/include/hal/i2c_ll.h | 21 +- components/hal/esp32s2/include/hal/i2c_ll.h | 21 +- components/hal/esp32s3/include/hal/i2c_ll.h | 27 +- components/hal/i2c_hal.c | 8 + components/hal/include/hal/i2c_hal.h | 7 + components/soc/esp32c6/CMakeLists.txt | 1 - .../esp32c6/include/soc/Kconfig.soc_caps.in | 4 + components/soc/esp32c6/include/soc/soc_caps.h | 3 +- docs/docs_not_updated/esp32c6.txt | 1 - examples/peripherals/.build-test-rules.yml | 10 - .../peripherals/i2c/i2c_self_test/README.md | 4 +- .../i2c/i2c_self_test/main/Kconfig.projbuild | 11 +- examples/peripherals/i2c/i2c_simple/README.md | 4 +- .../i2c/i2c_simple/main/Kconfig.projbuild | 8 +- examples/peripherals/i2c/i2c_tools/README.md | 4 +- .../i2c_tools/main/i2ctools_example_main.c | 1 - tools/test_apps/.build-test-rules.yml | 6 - .../test_apps/peripherals/i2c_wifi/README.md | 4 +- .../i2c_wifi/main/Kconfig.projbuild | 12 +- 24 files changed, 1097 insertions(+), 85 deletions(-) create mode 100644 components/hal/esp32c6/include/hal/i2c_ll.h diff --git a/components/driver/i2c.c b/components/driver/i2c.c index 2889955ea4..0c2411acbb 100644 --- a/components/driver/i2c.c +++ b/components/driver/i2c.c @@ -112,7 +112,7 @@ _Static_assert(I2C_NUM_1 == 1, "I2C_NUM_1 must be equal to 1"); _Static_assert(I2C_NUM_MAX == SOC_I2C_NUM, "I2C_NUM_MAX must be equal to SOC_I2C_NUM"); typedef struct { - i2c_hw_cmd_t hw_cmd; + i2c_ll_hw_cmd_t hw_cmd; union { uint8_t* data; // When total_bytes > 1 uint8_t data_byte; //when total_byte == 1 @@ -373,6 +373,7 @@ esp_err_t i2c_driver_install(i2c_port_t i2c_num, i2c_mode_t mode, size_t slv_rx_ return ESP_FAIL; } i2c_hw_enable(i2c_num); + i2c_hal_init(&i2c_context[i2c_num].hal, i2c_num); //Disable I2C interrupt. i2c_ll_disable_intr_mask(i2c_context[i2c_num].hal.dev, I2C_LL_INTR_MASK); i2c_ll_clear_intr_mask(i2c_context[i2c_num].hal.dev, I2C_LL_INTR_MASK); @@ -487,6 +488,7 @@ esp_err_t i2c_driver_delete(i2c_port_t i2c_num) } #endif + i2c_hal_deinit(&i2c_context[i2c_num].hal); free(p_i2c_obj[i2c_num]); p_i2c_obj[i2c_num] = NULL; @@ -1382,14 +1384,14 @@ static void IRAM_ATTR i2c_master_cmd_begin_static(i2c_port_t i2c_num, portBASE_T p_i2c->status = I2C_STATUS_IDLE; return; } - const i2c_hw_cmd_t hw_end_cmd = { + const i2c_ll_hw_cmd_t hw_end_cmd = { .op_code = I2C_LL_CMD_END }; while (p_i2c->cmd_link.head) { i2c_cmd_t *cmd = &p_i2c->cmd_link.head->cmd; const size_t remaining_bytes = cmd->total_bytes - cmd->bytes_used; - i2c_hw_cmd_t hw_cmd = cmd->hw_cmd; + i2c_ll_hw_cmd_t hw_cmd = cmd->hw_cmd; uint8_t fifo_fill = 0; if (cmd->hw_cmd.op_code == I2C_LL_CMD_WRITE) { diff --git a/components/hal/esp32/include/hal/i2c_ll.h b/components/hal/esp32/include/hal/i2c_ll.h index 83b898b0dd..b8d1b67363 100644 --- a/components/hal/esp32/include/hal/i2c_ll.h +++ b/components/hal/esp32/include/hal/i2c_ll.h @@ -34,7 +34,7 @@ typedef union { done: 1; }; uint32_t val; -} i2c_hw_cmd_t; +} i2c_ll_hw_cmd_t; // I2C operation mode command #define I2C_LL_CMD_RESTART 0 /*!command[cmd_idx].val = cmd.val; } @@ -611,6 +613,18 @@ static inline void i2c_ll_set_source_clk(i2c_dev_t *hw, i2c_clock_source_t src_c ;//Not support on ESP32 } +/** + * @brief Enable I2C peripheral controller clock + * + * @param dev Peripheral instance address + * @param en True to enable, False to disable + */ +static inline void i2c_ll_enable_controller_clock(i2c_dev_t *hw, bool en) +{ + (void)hw; + (void)en; +} + /** * @brief Init I2C master * @@ -681,10 +695,6 @@ static inline volatile void *i2c_ll_get_interrupt_status_reg(i2c_dev_t *dev) /////////////////////////////They might be removed in the next major release (ESP-IDF 6.0)////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Get the I2C hardware instance -#define I2C_LL_GET_HW(i2c_num) (((i2c_num) == 0) ? &I2C0 : &I2C1) -// Get the I2C hardware FIFO address -#define I2C_LL_GET_FIFO_ADDR(i2c_num) (I2C_DATA_APB_REG(i2c_num)) // I2C master TX interrupt bitmap #define I2C_LL_MASTER_TX_INT (I2C_ACK_ERR_INT_ENA_M|I2C_TIME_OUT_INT_ENA_M|I2C_TRANS_COMPLETE_INT_ENA_M|I2C_ARBITRATION_LOST_INT_ENA_M|I2C_END_DETECT_INT_ENA_M) // I2C master RX interrupt bitmap diff --git a/components/hal/esp32c2/include/hal/i2c_ll.h b/components/hal/esp32c2/include/hal/i2c_ll.h index 5a8db8aba5..83837dab56 100644 --- a/components/hal/esp32c2/include/hal/i2c_ll.h +++ b/components/hal/esp32c2/include/hal/i2c_ll.h @@ -16,7 +16,6 @@ #include "hal/i2c_types.h" #include "soc/rtc_cntl_reg.h" #include "soc/clk_tree_defs.h" -#include "esp_rom_sys.h" #include "esp_attr.h" #ifdef __cplusplus @@ -37,7 +36,7 @@ typedef union { done: 1; }; uint32_t val; -} i2c_hw_cmd_t; +} i2c_ll_hw_cmd_t; // I2C operation mode command #define I2C_LL_CMD_RESTART 6 /*!command[cmd_idx].val = cmd.val; } @@ -643,6 +644,17 @@ static inline void i2c_ll_set_source_clk(i2c_dev_t *hw, i2c_clock_source_t src_c hw->clk_conf.sclk_sel = (src_clk == I2C_CLK_SRC_RC_FAST) ? 1 : 0; } +/** + * @brief Enable I2C peripheral controller clock + * + * @param dev Peripheral instance address + * @param en True to enable, False to disable + */ +static inline void i2c_ll_enable_controller_clock(i2c_dev_t *hw, bool en) +{ + hw->clk_conf.sclk_active = en; +} + /** * @brief Init I2C master * @@ -674,16 +686,10 @@ static inline volatile void *i2c_ll_get_interrupt_status_reg(i2c_dev_t *dev) /////////////////////////////They might be removed in the next major release (ESP-IDF 6.0)////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Get the I2C hardware instance -#define I2C_LL_GET_HW(i2c_num) (&I2C0) -// Get the I2C hardware FIFO address -#define I2C_LL_GET_FIFO_ADDR(i2c_num) (I2C_DATA_APB_REG(i2c_num)) // I2C master TX interrupt bitmap #define I2C_LL_MASTER_TX_INT (I2C_NACK_INT_ENA_M|I2C_TIME_OUT_INT_ENA_M|I2C_TRANS_COMPLETE_INT_ENA_M|I2C_ARBITRATION_LOST_INT_ENA_M|I2C_END_DETECT_INT_ENA_M) // I2C master RX interrupt bitmap #define I2C_LL_MASTER_RX_INT (I2C_TIME_OUT_INT_ENA_M|I2C_TRANS_COMPLETE_INT_ENA_M|I2C_ARBITRATION_LOST_INT_ENA_M|I2C_END_DETECT_INT_ENA_M) -// delay time after rtc_clk swiching on -#define DELAY_RTC_CLK_SWITCH (5) // I2C max timeout value #define I2C_LL_MAX_TIMEOUT I2C_TIME_OUT_VALUE diff --git a/components/hal/esp32c3/include/hal/i2c_ll.h b/components/hal/esp32c3/include/hal/i2c_ll.h index e0a8b69eea..c103594038 100644 --- a/components/hal/esp32c3/include/hal/i2c_ll.h +++ b/components/hal/esp32c3/include/hal/i2c_ll.h @@ -16,7 +16,6 @@ #include "hal/i2c_types.h" #include "soc/rtc_cntl_reg.h" #include "soc/clk_tree_defs.h" -#include "esp_rom_sys.h" #include "esp_attr.h" #ifdef __cplusplus @@ -38,7 +37,7 @@ typedef union { done: 1; }; uint32_t val; -} i2c_hw_cmd_t; +} i2c_ll_hw_cmd_t; // I2C operation mode command #define I2C_LL_CMD_RESTART 6 /*!command[cmd_idx].val = cmd.val; } @@ -662,7 +662,16 @@ static inline void i2c_ll_set_source_clk(i2c_dev_t *hw, i2c_clock_source_t src_c hw->clk_conf.sclk_sel = (src_clk == I2C_CLK_SRC_RC_FAST) ? 1 : 0; } - +/** + * @brief Enable I2C peripheral controller clock + * + * @param dev Peripheral instance address + * @param en True to enable, False to disable + */ +static inline void i2c_ll_enable_controller_clock(i2c_dev_t *hw, bool en) +{ + hw->clk_conf.sclk_active = en; +} /** * @brief Init I2C master @@ -723,10 +732,6 @@ static inline volatile void *i2c_ll_get_interrupt_status_reg(i2c_dev_t *dev) /////////////////////////////They might be removed in the next major release (ESP-IDF 6.0)////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Get the I2C hardware instance -#define I2C_LL_GET_HW(i2c_num) (&I2C0) -// Get the I2C hardware FIFO address -#define I2C_LL_GET_FIFO_ADDR(i2c_num) (I2C_DATA_APB_REG(i2c_num)) // I2C master TX interrupt bitmap #define I2C_LL_MASTER_TX_INT (I2C_NACK_INT_ENA_M|I2C_TIME_OUT_INT_ENA_M|I2C_TRANS_COMPLETE_INT_ENA_M|I2C_ARBITRATION_LOST_INT_ENA_M|I2C_END_DETECT_INT_ENA_M) // I2C master RX interrupt bitmap diff --git a/components/hal/esp32c6/include/hal/i2c_ll.h b/components/hal/esp32c6/include/hal/i2c_ll.h new file mode 100644 index 0000000000..c7bbc8f189 --- /dev/null +++ b/components/hal/esp32c6/include/hal/i2c_ll.h @@ -0,0 +1,948 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +// The LL layer for I2C register operations + +#pragma once + +#include +#include "hal/misc.h" +#include "soc/i2c_periph.h" +#include "soc/soc_caps.h" +#include "soc/i2c_struct.h" +#include "soc/pcr_struct.h" +#include "hal/i2c_types.h" +#include "soc/clk_tree_defs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief I2C hardware cmd register fields. + */ +typedef union { + struct { + uint32_t byte_num: 8, + ack_en: 1, + ack_exp: 1, + ack_val: 1, + op_code: 3, + reserved14: 17, + done: 1; + }; + uint32_t val; +} i2c_ll_hw_cmd_t; + +// I2C operation mode command +#define I2C_LL_CMD_RESTART 6 /*!clkm_div = clkm_div; + clk_cal->scl_low = half_cycle; + // default, scl_wait_high < scl_high + // Make 80KHz as a boundary here, because when working at lower frequency, too much scl_wait_high will faster the frequency + // according to some hardware behaviors. + clk_cal->scl_wait_high = (bus_freq >= 80*1000) ? (half_cycle / 2 - 2) : (half_cycle / 4); + clk_cal->scl_high = half_cycle - clk_cal->scl_wait_high; + clk_cal->sda_hold = half_cycle / 4; + clk_cal->sda_sample = half_cycle / 2 + clk_cal->scl_wait_high; + clk_cal->setup = half_cycle; + clk_cal->hold = half_cycle; + //default we set the timeout value to about 10 bus cycles + // log(20*half_cycle)/log(2) = log(half_cycle)/log(2) + log(20)/log(2) + clk_cal->tout = (int)(sizeof(half_cycle) * 8 - __builtin_clz(5 * half_cycle)) + 2; +} + +/** + * @brief Update I2C configuration + * + * @param hw Beginning address of the peripheral registers + * + * @return None + */ +__attribute__((always_inline)) +static inline void i2c_ll_update(i2c_dev_t *hw) +{ + hw->ctr.conf_upgate = 1; +} + +/** + * @brief Configure the I2C bus timing related register. + * + * @param hw Beginning address of the peripheral registers + * @param bus_cfg Pointer to the data structure holding the register configuration. + * + * @return None + */ +static inline void i2c_ll_set_bus_timing(i2c_dev_t *hw, i2c_hal_clk_config_t *bus_cfg) +{ + HAL_FORCE_MODIFY_U32_REG_FIELD(PCR.i2c_sclk_conf, i2c_sclk_div_num, bus_cfg->clkm_div - 1); + + /* Set div_a and div_b to 0, as it's not necessary to use them */ + HAL_FORCE_MODIFY_U32_REG_FIELD(PCR.i2c_sclk_conf, i2c_sclk_div_a, 0); + HAL_FORCE_MODIFY_U32_REG_FIELD(PCR.i2c_sclk_conf, i2c_sclk_div_b, 0); + /* According to the Technical Reference Manual, the following timings must be subtracted by 1. + * However, according to the practical measurement and some hardware behaviour, if wait_high_period and scl_high minus one. + * The SCL frequency would be a little higher than expected. Therefore, the solution + * here is not to minus scl_high as well as scl_wait high, and the frequency will be absolutely accurate to all frequency + * to some extent. */ + hw->scl_low_period.scl_low_period = bus_cfg->scl_low - 1; + hw->scl_high_period.scl_high_period = bus_cfg->scl_high; + hw->scl_high_period.scl_wait_high_period = bus_cfg->scl_wait_high; + //sda sample + hw->sda_hold.sda_hold_time = bus_cfg->sda_hold - 1; + hw->sda_sample.sda_sample_time = bus_cfg->sda_sample - 1; + //setup + hw->scl_rstart_setup.scl_rstart_setup_time = bus_cfg->setup - 1; + hw->scl_stop_setup.scl_stop_setup_time = bus_cfg->setup - 1; + //hold + hw->scl_start_hold.scl_start_hold_time = bus_cfg->hold - 1; + hw->scl_stop_hold.scl_stop_hold_time = bus_cfg->hold - 1; + hw->to.time_out_value = bus_cfg->tout; + hw->to.time_out_en = 1; +} + +/** + * @brief Reset I2C txFIFO + * + * @param hw Beginning address of the peripheral registers + * + * @return None + */ +static inline void i2c_ll_txfifo_rst(i2c_dev_t *hw) +{ + hw->fifo_conf.tx_fifo_rst = 1; + hw->fifo_conf.tx_fifo_rst = 0; +} + +/** + * @brief Reset I2C rxFIFO + * + * @param hw Beginning address of the peripheral registers + * + * @return None + */ +static inline void i2c_ll_rxfifo_rst(i2c_dev_t *hw) +{ + hw->fifo_conf.rx_fifo_rst = 1; + hw->fifo_conf.rx_fifo_rst = 0; +} + +/** + * @brief Configure I2C SCL timing + * + * @param hw Beginning address of the peripheral registers + * @param hight_period The I2C SCL hight period (in core clock cycle, hight_period > 2) + * @param low_period The I2C SCL low period (in core clock cycle, low_period > 1) + * + * @return None. + */ +static inline void i2c_ll_set_scl_timing(i2c_dev_t *hw, int hight_period, int low_period) +{ + hw->scl_low_period.scl_low_period = low_period - 1; + hw->scl_high_period.scl_high_period = hight_period - 10; + hw->scl_high_period.scl_wait_high_period = hight_period - hw->scl_high_period.scl_high_period; +} + +/** + * @brief Clear I2C interrupt status + * + * @param hw Beginning address of the peripheral registers + * @param mask Interrupt mask needs to be cleared + * + * @return None + */ +__attribute__((always_inline)) +static inline void i2c_ll_clear_intr_mask(i2c_dev_t *hw, uint32_t mask) +{ + hw->int_clr.val = mask; +} + +/** + * @brief Enable I2C interrupt + * + * @param hw Beginning address of the peripheral registers + * @param mask Interrupt mask needs to be enabled + * + * @return None + */ +static inline void i2c_ll_enable_intr_mask(i2c_dev_t *hw, uint32_t mask) +{ + hw->int_ena.val |= mask; +} + +/** + * @brief Disable I2C interrupt + * + * @param hw Beginning address of the peripheral registers + * @param mask Interrupt mask needs to be disabled + * + * @return None + */ +__attribute__((always_inline)) +static inline void i2c_ll_disable_intr_mask(i2c_dev_t *hw, uint32_t mask) +{ + hw->int_ena.val &= (~mask); +} + +/** + * @brief Get I2C interrupt status + * + * @param hw Beginning address of the peripheral registers + * + * @return I2C interrupt status + */ +__attribute__((always_inline)) +static inline void i2c_ll_get_intr_mask(i2c_dev_t *hw, uint32_t *intr_status) +{ + *intr_status = hw->int_status.val; +} + +/** + * @brief Configure I2C memory access mode, FIFO mode or non-FIFO mode + * + * @param hw Beginning address of the peripheral registers + * @param fifo_mode_en Set true to enable FIFO access mode, else, set it false + * + * @return None + */ +static inline void i2c_ll_set_fifo_mode(i2c_dev_t *hw, bool fifo_mode_en) +{ + hw->fifo_conf.nonfifo_en = fifo_mode_en ? 0 : 1; +} + +/** + * @brief Configure I2C timeout + * + * @param hw Beginning address of the peripheral registers + * @param tout_num The I2C timeout value needs to be set (2^tout in core clock cycle) + * + * @return None + */ +static inline void i2c_ll_set_tout(i2c_dev_t *hw, int tout) +{ + hw->to.time_out_value = tout; +} + +/** + * @brief Configure I2C slave address + * + * @param hw Beginning address of the peripheral registers + * @param slave_addr I2C slave address needs to be set + * @param addr_10bit_en Set true to enable 10-bit slave address mode, set false to enable 7-bit address mode + * + * @return None + */ +static inline void i2c_ll_set_slave_addr(i2c_dev_t *hw, uint16_t slave_addr, bool addr_10bit_en) +{ + hw->slave_addr.slave_addr = slave_addr; + hw->slave_addr.addr_10bit_en = addr_10bit_en; +} + +/** + * @brief Write I2C hardware command register + * + * @param hw Beginning address of the peripheral registers + * @param cmd I2C hardware command + * @param cmd_idx The index of the command register, should be less than 16 + * + * @return None + */ +static inline void i2c_ll_write_cmd_reg(i2c_dev_t *hw, i2c_ll_hw_cmd_t cmd, int cmd_idx) +{ + hw->command[cmd_idx].val = cmd.val; +} + +/** + * @brief Configure I2C start timing + * + * @param hw Beginning address of the peripheral registers + * @param start_setup The start condition setup period (in core clock cycle) + * @param start_hold The start condition hold period (in core clock cycle) + * + * @return None + */ +static inline void i2c_ll_set_start_timing(i2c_dev_t *hw, int start_setup, int start_hold) +{ + hw->scl_rstart_setup.scl_rstart_setup_time = start_setup; + hw->scl_start_hold.scl_start_hold_time = start_hold - 1; +} + +/** + * @brief Configure I2C stop timing + * + * @param hw Beginning address of the peripheral registers + * @param stop_setup The stop condition setup period (in core clock cycle) + * @param stop_hold The stop condition hold period (in core clock cycle) + * + * @return None + */ +static inline void i2c_ll_set_stop_timing(i2c_dev_t *hw, int stop_setup, int stop_hold) +{ + hw->scl_stop_setup.scl_stop_setup_time = stop_setup; + hw->scl_stop_hold.scl_stop_hold_time = stop_hold; +} + +/** + * @brief Configure I2C stop timing + * + * @param hw Beginning address of the peripheral registers + * @param sda_sample The SDA sample time (in core clock cycle) + * @param sda_hold The SDA hold time (in core clock cycle) + * + * @return None + */ +static inline void i2c_ll_set_sda_timing(i2c_dev_t *hw, int sda_sample, int sda_hold) +{ + hw->sda_hold.sda_hold_time = sda_hold; + hw->sda_sample.sda_sample_time = sda_sample; +} + +/** + * @brief Set I2C txFIFO empty threshold + * + * @param hw Beginning address of the peripheral registers + * @param empty_thr The txFIFO empty threshold + * + * @return None + */ +static inline void i2c_ll_set_txfifo_empty_thr(i2c_dev_t *hw, uint8_t empty_thr) +{ + hw->fifo_conf.txfifo_wm_thrhd = empty_thr; +} + +/** + * @brief Set I2C rxFIFO full threshold + * + * @param hw Beginning address of the peripheral registers + * @param full_thr The rxFIFO full threshold + * + * @return None + */ +static inline void i2c_ll_set_rxfifo_full_thr(i2c_dev_t *hw, uint8_t full_thr) +{ + hw->fifo_conf.rxfifo_wm_thrhd = full_thr; +} + +/** + * @brief Set the I2C data mode, LSB or MSB + * + * @param hw Beginning address of the peripheral registers + * @param tx_mode Tx data bit mode + * @param rx_mode Rx data bit mode + * + * @return None + */ +static inline void i2c_ll_set_data_mode(i2c_dev_t *hw, i2c_trans_mode_t tx_mode, i2c_trans_mode_t rx_mode) +{ + hw->ctr.tx_lsb_first = tx_mode; + hw->ctr.rx_lsb_first = rx_mode; +} + +/** + * @brief Get the I2C data mode + * + * @param hw Beginning address of the peripheral registers + * @param tx_mode Pointer to accept the received bytes mode + * @param rx_mode Pointer to accept the sended bytes mode + * + * @return None + */ +static inline void i2c_ll_get_data_mode(i2c_dev_t *hw, i2c_trans_mode_t *tx_mode, i2c_trans_mode_t *rx_mode) +{ + *tx_mode = hw->ctr.tx_lsb_first; + *rx_mode = hw->ctr.rx_lsb_first; +} + +/** + * @brief Get I2C sda timing configuration + * + * @param hw Beginning address of the peripheral registers + * @param sda_sample Pointer to accept the SDA sample timing configuration + * @param sda_hold Pointer to accept the SDA hold timing configuration + * + * @return None + */ +static inline void i2c_ll_get_sda_timing(i2c_dev_t *hw, int *sda_sample, int *sda_hold) +{ + *sda_hold = hw->sda_hold.sda_hold_time; + *sda_sample = hw->sda_sample.sda_sample_time; +} + +/** + * @brief Get the I2C hardware version + * + * @param hw Beginning address of the peripheral registers + * + * @return The I2C hardware version + */ +static inline uint32_t i2c_ll_get_hw_version(i2c_dev_t *hw) +{ + return hw->date.date; +} + +/** + * @brief Check if the I2C bus is busy + * + * @param hw Beginning address of the peripheral registers + * + * @return True if I2C state machine is busy, else false will be returned + */ +static inline bool i2c_ll_is_bus_busy(i2c_dev_t *hw) +{ + return hw->sr.bus_busy; +} + +/** + * @brief Check if I2C is master mode + * + * @param hw Beginning address of the peripheral registers + * + * @return True if I2C is master mode, else false will be returned + */ +static inline bool i2c_ll_is_master_mode(i2c_dev_t *hw) +{ + return hw->ctr.ms_mode; +} + +/** + * @brief Get the rxFIFO readable length + * + * @param hw Beginning address of the peripheral registers + * + * @return RxFIFO readable length + */ +__attribute__((always_inline)) +static inline void i2c_ll_get_rxfifo_cnt(i2c_dev_t *hw, uint32_t *length) +{ + *length = hw->sr.rxfifo_cnt; +} + +/** + * @brief Get I2C txFIFO writable length + * + * @param hw Beginning address of the peripheral registers + * + * @return TxFIFO writable length + */ +__attribute__((always_inline)) +static inline void i2c_ll_get_txfifo_len(i2c_dev_t *hw, uint32_t *length) +{ + *length = SOC_I2C_FIFO_LEN - hw->sr.txfifo_cnt; +} + +/** + * @brief Get I2C timeout configuration + * + * @param hw Beginning address of the peripheral registers + * + * @return The I2C timeout value + */ +static inline void i2c_ll_get_tout(i2c_dev_t *hw, int *timeout) +{ + *timeout = hw->to.time_out_value; +} + +/** + * @brief Start I2C transfer + * + * @param hw Beginning address of the peripheral registers + * + * @return None + */ +static inline void i2c_ll_trans_start(i2c_dev_t *hw) +{ + hw->ctr.trans_start = 1; +} + +/** + * @brief Get I2C start timing configuration + * + * @param hw Beginning address of the peripheral registers + * @param setup_time Pointer to accept the start condition setup period + * @param hold_time Pointer to accept the start condition hold period + * + * @return None + */ +static inline void i2c_ll_get_start_timing(i2c_dev_t *hw, int *setup_time, int *hold_time) +{ + *setup_time = hw->scl_rstart_setup.scl_rstart_setup_time; + *hold_time = hw->scl_start_hold.scl_start_hold_time + 1; +} + +/** + * @brief Get I2C stop timing configuration + * + * @param hw Beginning address of the peripheral registers + * @param setup_time Pointer to accept the stop condition setup period + * @param hold_time Pointer to accept the stop condition hold period + * + * @return None + */ +static inline void i2c_ll_get_stop_timing(i2c_dev_t *hw, int *setup_time, int *hold_time) +{ + *setup_time = hw->scl_stop_setup.scl_stop_setup_time; + *hold_time = hw->scl_stop_hold.scl_stop_hold_time; +} + +/** + * @brief Get I2C SCL timing configuration + * + * @param hw Beginning address of the peripheral registers + * @param high_period Pointer to accept the SCL high period + * @param low_period Pointer to accept the SCL low period + * + * @return None + */ +static inline void i2c_ll_get_scl_timing(i2c_dev_t *hw, int *high_period, int *low_period) +{ + *high_period = hw->scl_high_period.scl_high_period + hw->scl_high_period.scl_wait_high_period; + *low_period = hw->scl_low_period.scl_low_period + 1; +} + +/** + * @brief Write the I2C hardware txFIFO + * + * @param hw Beginning address of the peripheral registers + * @param ptr Pointer to data buffer + * @param len Amount of data needs to be writen + * + * @return None. + */ +__attribute__((always_inline)) +static inline void i2c_ll_write_txfifo(i2c_dev_t *hw, const uint8_t *ptr, uint8_t len) +{ + for (int i = 0; i< len; i++) { + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->data, fifo_rdata, ptr[i]); + } +} + +/** + * @brief Read the I2C hardware rxFIFO + * + * @param hw Beginning address of the peripheral registers + * @param ptr Pointer to data buffer + * @param len Amount of data needs read + * + * @return None + */ +__attribute__((always_inline)) +static inline void i2c_ll_read_rxfifo(i2c_dev_t *hw, uint8_t *ptr, uint8_t len) +{ + for(int i = 0; i < len; i++) { + ptr[i] = HAL_FORCE_READ_U32_REG_FIELD(hw->data, fifo_rdata); + } +} + +/** + * @brief Configure I2C hardware filter + * + * @param hw Beginning address of the peripheral registers + * @param filter_num If the glitch period on the line is less than this value, it can be filtered out + * If `filter_num == 0`, the filter will be disabled + * + * @return None + */ +static inline void i2c_ll_set_filter(i2c_dev_t *hw, uint8_t filter_num) +{ + if (filter_num > 0) { + hw->filter_cfg.scl_filter_thres = filter_num; + hw->filter_cfg.sda_filter_thres = filter_num; + hw->filter_cfg.scl_filter_en = 1; + hw->filter_cfg.sda_filter_en = 1; + } else { + hw->filter_cfg.scl_filter_en = 0; + hw->filter_cfg.sda_filter_en = 0; + } +} + +/** + * @brief Get I2C hardware filter configuration + * + * @param hw Beginning address of the peripheral registers + * + * @return The hardware filter configuration + */ +static inline void i2c_ll_get_filter(i2c_dev_t *hw, uint8_t *filter_conf) +{ + *filter_conf = hw->filter_cfg.scl_filter_thres; +} + +/** + * @brief Reste I2C master FSM. When the master FSM is stuck, call this function to reset the FSM + * + * @param hw Beginning address of the peripheral registers + * + * @return None + */ +static inline void i2c_ll_master_fsm_rst(i2c_dev_t *hw) +{ + // fsm_rst is a self cleared bit. + hw->ctr.fsm_rst = 1; +} + +/** + * @brief Clear I2C bus, when the slave is stuck in a deadlock and keeps pulling the bus low, + * master can controls the SCL bus to generate 9 CLKs. + * + * Note: The master cannot detect if deadlock happens, but when the scl_st_to interrupt is generated, a deadlock may occur. + * + * @param hw Beginning address of the peripheral registers + * + * @return None + */ +static inline void i2c_ll_master_clr_bus(i2c_dev_t *hw) +{ + hw->scl_sp_conf.scl_rst_slv_num = 9; + hw->scl_sp_conf.scl_rst_slv_en = 1; + hw->ctr.conf_upgate = 1; + // hardward will clear scl_rst_slv_en after sending SCL pulses, + // and we should set conf_upgate bit to synchronize register value. + while (hw->scl_sp_conf.scl_rst_slv_en); + hw->ctr.conf_upgate = 1; +} + +/** + * @brief Set I2C source clock + * + * @param hw Beginning address of the peripheral registers + * @param src_clk Source clock of the I2C + * + * @return None + */ +static inline void i2c_ll_set_source_clk(i2c_dev_t *hw, i2c_clock_source_t src_clk) +{ + (void)hw; + // src_clk : (1) for RTC_CLK, (0) for XTAL + PCR.i2c_sclk_conf.i2c_sclk_sel = (src_clk == I2C_CLK_SRC_RC_FAST) ? 1 : 0; +} + +/** + * @brief Enable I2C peripheral controller clock + * + * @param dev Peripheral instance address + * @param en True to enable, False to disable + */ +static inline void i2c_ll_enable_controller_clock(i2c_dev_t *hw, bool en) +{ + (void)hw; + PCR.i2c_sclk_conf.i2c_sclk_en = en; +} + +/** + * @brief Init I2C master + * + * @param hw Beginning address of the peripheral registers + * + * @return None + */ +static inline void i2c_ll_master_init(i2c_dev_t *hw) +{ + 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; +} + +/** + * @brief Init I2C slave + * + * @param hw Beginning address of the peripheral registers + * + * @return None + */ +static inline void i2c_ll_slave_init(i2c_dev_t *hw) +{ + 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; +} + +/** + * @brief Set whether slave should auto start, or only start with start signal from master + * + * @param hw Beginning address of the peripheral registers + * @param slv_ex_auto_en 1 if slave auto start data transaction, otherwise, 0. + */ +static inline void i2c_ll_slave_tx_auto_start_en(i2c_dev_t *hw, bool slv_ex_auto_en) +{ + hw->ctr.slv_tx_auto_start_en = slv_ex_auto_en; +} + +/** + * @brief Get I2C interrupt status register address + */ +static inline volatile void *i2c_ll_get_interrupt_status_reg(i2c_dev_t *dev) +{ + return &dev->int_status; +} + +//////////////////////////////////////////Deprecated Functions////////////////////////////////////////////////////////// +/////////////////////////////The following functions are only used by the legacy driver///////////////////////////////// +/////////////////////////////They might be removed in the next major release (ESP-IDF 6.0)////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +// I2C master TX interrupt bitmap +#define I2C_LL_MASTER_TX_INT (I2C_NACK_INT_ENA_M|I2C_TIME_OUT_INT_ENA_M|I2C_TRANS_COMPLETE_INT_ENA_M|I2C_ARBITRATION_LOST_INT_ENA_M|I2C_END_DETECT_INT_ENA_M) +// I2C master RX interrupt bitmap +#define I2C_LL_MASTER_RX_INT (I2C_TIME_OUT_INT_ENA_M|I2C_TRANS_COMPLETE_INT_ENA_M|I2C_ARBITRATION_LOST_INT_ENA_M|I2C_END_DETECT_INT_ENA_M) +// I2C slave TX interrupt bitmap +#define I2C_LL_SLAVE_TX_INT (I2C_TXFIFO_WM_INT_ENA_M) +// I2C slave RX interrupt bitmap +#define I2C_LL_SLAVE_RX_INT (I2C_RXFIFO_WM_INT_ENA_M | I2C_TRANS_COMPLETE_INT_ENA_M) +// I2C max timeout value +#define I2C_LL_MAX_TIMEOUT I2C_TIME_OUT_VALUE + +#define I2C_LL_INTR_MASK (0x3fff) /*!< I2C all interrupt bitmap */ + +/** + * @brief I2C interrupt event + */ +typedef enum { + I2C_INTR_EVENT_ERR, + I2C_INTR_EVENT_ARBIT_LOST, /*!< I2C arbition lost event */ + I2C_INTR_EVENT_NACK, /*!< I2C NACK event */ + I2C_INTR_EVENT_TOUT, /*!< I2C time out event */ + I2C_INTR_EVENT_END_DET, /*!< I2C end detected event */ + I2C_INTR_EVENT_TRANS_DONE, /*!< I2C trans done event */ + I2C_INTR_EVENT_RXFIFO_FULL, /*!< I2C rxfifo full event */ + I2C_INTR_EVENT_TXFIFO_EMPTY, /*!< I2C txfifo empty event */ +} i2c_intr_event_t; + +/** + * @brief Configure I2C SCL timing + * + * @param hw Beginning address of the peripheral registers + * @param high_period The I2C SCL hight period (in core clock cycle, hight_period > 2) + * @param low_period The I2C SCL low period (in core clock cycle, low_period > 1) + * @param wait_high_period The I2C SCL wait rising edge period. + * + * @return None. + */ +static inline void i2c_ll_set_scl_clk_timing(i2c_dev_t *hw, int high_period, int low_period, int wait_high_period) +{ + hw->scl_low_period.scl_low_period = low_period; + hw->scl_high_period.scl_high_period = high_period; + hw->scl_high_period.scl_wait_high_period = wait_high_period; +} + +/** + * @brief Get I2C SCL timing configuration + * + * @param hw Beginning address of the peripheral registers + * @param high_period Pointer to accept the SCL high period + * @param low_period Pointer to accept the SCL low period + * + * @return None + */ +static inline void i2c_ll_get_scl_clk_timing(i2c_dev_t *hw, int *high_period, int *low_period, int *wait_high_period) +{ + *high_period = hw->scl_high_period.scl_high_period; + *wait_high_period = hw->scl_high_period.scl_wait_high_period; + *low_period = hw->scl_low_period.scl_low_period; +} + +/** + * @brief Get I2C master interrupt event + * + * @param hw Beginning address of the peripheral registers + * @param event Pointer to accept the interrupt event + * + * @return None + */ +__attribute__((always_inline)) +static inline void i2c_ll_master_get_event(i2c_dev_t *hw, i2c_intr_event_t *event) +{ + i2c_int_status_reg_t int_sts = hw->int_status; + if (int_sts.arbitration_lost_int_st) { + *event = I2C_INTR_EVENT_ARBIT_LOST; + } else if (int_sts.nack_int_st) { + *event = I2C_INTR_EVENT_NACK; + } else if (int_sts.time_out_int_st) { + *event = I2C_INTR_EVENT_TOUT; + } else if (int_sts.end_detect_int_st) { + *event = I2C_INTR_EVENT_END_DET; + } else if (int_sts.trans_complete_int_st) { + *event = I2C_INTR_EVENT_TRANS_DONE; + } else { + *event = I2C_INTR_EVENT_ERR; + } +} + +/** + * @brief Get I2C slave interrupt event + * + * @param hw Beginning address of the peripheral registers + * @param event Pointer to accept the interrupt event + * + * @return None + */ +__attribute__((always_inline)) +static inline void i2c_ll_slave_get_event(i2c_dev_t *hw, i2c_intr_event_t *event) +{ + typeof(hw->int_status) int_sts = hw->int_status; + if (int_sts.txfifo_wm_int_st) { + *event = I2C_INTR_EVENT_TXFIFO_EMPTY; + } else if (int_sts.trans_complete_int_st) { + *event = I2C_INTR_EVENT_TRANS_DONE; + } else if (int_sts.rxfifo_wm_int_st) { + *event = I2C_INTR_EVENT_RXFIFO_FULL; + } else { + *event = I2C_INTR_EVENT_ERR; + } +} + +/** + * @brief Enable I2C master TX interrupt + * + * @param hw Beginning address of the peripheral registers + * + * @return None + */ +static inline void i2c_ll_master_enable_tx_it(i2c_dev_t *hw) +{ + hw->int_clr.val = UINT32_MAX; + hw->int_ena.val = I2C_LL_MASTER_TX_INT; +} + +/** + * @brief Enable I2C master RX interrupt + * + * @param hw Beginning address of the peripheral registers + * + * @return None + */ +static inline void i2c_ll_master_enable_rx_it(i2c_dev_t *hw) +{ + hw->int_clr.val = UINT32_MAX; + hw->int_ena.val = I2C_LL_MASTER_RX_INT; +} + +/** + * @brief Disable I2C master TX interrupt + * + * @param hw Beginning address of the peripheral registers + * + * @return None + */ +static inline void i2c_ll_master_disable_tx_it(i2c_dev_t *hw) +{ + hw->int_ena.val &= (~I2C_LL_MASTER_TX_INT); +} + +/** + * @brief Disable I2C master RX interrupt + * + * @param hw Beginning address of the peripheral registers + * + * @return None + */ +__attribute__((always_inline)) +static inline void i2c_ll_master_disable_rx_it(i2c_dev_t *hw) +{ + hw->int_ena.val &= (~I2C_LL_MASTER_RX_INT); +} + +/** + * @brief + * + * @param hw Beginning address of the peripheral registers + * + * @return None + */ +static inline void i2c_ll_slave_enable_tx_it(i2c_dev_t *hw) +{ + hw->int_ena.val |= I2C_LL_SLAVE_TX_INT; +} + +/** + * @brief Enable I2C slave RX interrupt + * + * @param hw Beginning address of the peripheral registers + * + * @return None + */ +static inline void i2c_ll_slave_enable_rx_it(i2c_dev_t *hw) +{ + hw->int_ena.val |= I2C_LL_SLAVE_RX_INT; +} + +/** + * @brief Disable I2C slave TX interrupt + * + * @param hw Beginning address of the peripheral registers + * + * @return None + */ +__attribute__((always_inline)) +static inline void i2c_ll_slave_disable_tx_it(i2c_dev_t *hw) +{ + hw->int_ena.val &= (~I2C_LL_SLAVE_TX_INT); +} + +/** + * @brief Disable I2C slave RX interrupt + * + * @param hw Beginning address of the peripheral registers + * + * @return None + */ +static inline void i2c_ll_slave_disable_rx_it(i2c_dev_t *hw) +{ + hw->int_ena.val &= (~I2C_LL_SLAVE_RX_INT); +} + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/esp32h2/include/hal/i2c_ll.h b/components/hal/esp32h2/include/hal/i2c_ll.h index 88668d2e35..f5af47eefc 100644 --- a/components/hal/esp32h2/include/hal/i2c_ll.h +++ b/components/hal/esp32h2/include/hal/i2c_ll.h @@ -37,7 +37,7 @@ typedef union { done: 1; }; uint32_t val; -} i2c_hw_cmd_t; +} i2c_ll_hw_cmd_t; // I2C operation mode command #define I2C_LL_CMD_RESTART 6 /*!command[cmd_idx].val = cmd.val; } @@ -659,6 +661,17 @@ static inline void i2c_ll_set_source_clk(i2c_dev_t *hw, i2c_clock_source_t src_c hw->clk_conf.sclk_sel = (src_clk == I2C_CLK_SRC_RC_FAST) ? 1 : 0; } +/** + * @brief Enable I2C peripheral controller clock + * + * @param dev Peripheral instance address + * @param en True to enable, False to disable + */ +static inline void i2c_ll_enable_controller_clock(i2c_dev_t *hw, bool en) +{ + hw->clk_conf.sclk_active = en; +} + /** * @brief Init I2C master * @@ -718,10 +731,6 @@ static inline volatile void *i2c_ll_get_interrupt_status_reg(i2c_dev_t *dev) /////////////////////////////They might be removed in the next major release (ESP-IDF 6.0)////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Get the I2C hardware instance -#define I2C_LL_GET_HW(i2c_num) (&I2C0) -// Get the I2C hardware FIFO address -#define I2C_LL_GET_FIFO_ADDR(i2c_num) (I2C_DATA_APB_REG(i2c_num)) // I2C master TX interrupt bitmap #define I2C_LL_MASTER_TX_INT (I2C_NACK_INT_ENA_M|I2C_TIME_OUT_INT_ENA_M|I2C_TRANS_COMPLETE_INT_ENA_M|I2C_ARBITRATION_LOST_INT_ENA_M|I2C_END_DETECT_INT_ENA_M) // I2C master RX interrupt bitmap diff --git a/components/hal/esp32s2/include/hal/i2c_ll.h b/components/hal/esp32s2/include/hal/i2c_ll.h index 19dd073f65..b695a5e4eb 100644 --- a/components/hal/esp32s2/include/hal/i2c_ll.h +++ b/components/hal/esp32s2/include/hal/i2c_ll.h @@ -34,7 +34,7 @@ typedef union { done: 1; }; uint32_t val; -} i2c_hw_cmd_t; +} i2c_ll_hw_cmd_t; // I2C operation mode command #define I2C_LL_CMD_RESTART 0 /*!command[cmd_idx].val = cmd.val; } @@ -627,6 +629,17 @@ static inline void i2c_ll_set_source_clk(i2c_dev_t *hw, i2c_clock_source_t src_c hw->ctr.ref_always_on = (src_clk == I2C_CLK_SRC_REF_TICK) ? 0 : 1; } +/** + * @brief Enable I2C peripheral controller clock + * + * @param dev Peripheral instance address + * @param en True to enable, False to disable + */ +static inline void i2c_ll_enable_controller_clock(i2c_dev_t *hw, bool en) +{ + (void)hw; + (void)en; +} /** * @brief Init I2C master @@ -717,10 +730,6 @@ static inline volatile void *i2c_ll_get_interrupt_status_reg(i2c_dev_t *dev) /////////////////////////////They might be removed in the next major release (ESP-IDF 6.0)////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Get the I2C hardware instance -#define I2C_LL_GET_HW(i2c_num) (((i2c_num) == 0) ? &I2C0 : &I2C1) -// Get the I2C hardware FIFO address -#define I2C_LL_GET_FIFO_ADDR(i2c_num) (I2C_DATA_APB_REG(i2c_num)) // I2C master TX interrupt bitmap #define I2C_LL_MASTER_TX_INT (I2C_NACK_INT_ENA_M|I2C_TIME_OUT_INT_ENA_M|I2C_TRANS_COMPLETE_INT_ENA_M|I2C_ARBITRATION_LOST_INT_ENA_M|I2C_END_DETECT_INT_ENA_M) // I2C master RX interrupt bitmap diff --git a/components/hal/esp32s3/include/hal/i2c_ll.h b/components/hal/esp32s3/include/hal/i2c_ll.h index 38bd0762ba..8b5d3ab7b4 100644 --- a/components/hal/esp32s3/include/hal/i2c_ll.h +++ b/components/hal/esp32s3/include/hal/i2c_ll.h @@ -35,7 +35,7 @@ typedef union { done: 1; }; uint32_t val; -} i2c_hw_cmd_t; +} i2c_ll_hw_cmd_t; // I2C operation mode command #define I2C_LL_CMD_RESTART 6 /*!comd0; + _Static_assert(sizeof(i2c_comd0_reg_t) == sizeof(i2c_ll_hw_cmd_t), + "i2c_comdX_reg_t structure size must be equal to i2c_ll_hw_cmd_t structure size"); + volatile i2c_ll_hw_cmd_t* commands = (volatile i2c_ll_hw_cmd_t*) &hw->comd0; commands[cmd_idx].val = cmd.val; } @@ -654,6 +656,17 @@ static inline void i2c_ll_set_source_clk(i2c_dev_t *hw, i2c_clock_source_t src_c hw->clk_conf.sclk_sel = (src_clk == I2C_CLK_SRC_RC_FAST) ? 1 : 0; } +/** + * @brief Enable I2C peripheral controller clock + * + * @param dev Peripheral instance address + * @param en True to enable, False to disable + */ +static inline void i2c_ll_enable_controller_clock(i2c_dev_t *hw, bool en) +{ + hw->clk_conf.sclk_active = en; +} + /** * @brief Init I2C master * @@ -713,10 +726,6 @@ static inline volatile void *i2c_ll_get_interrupt_status_reg(i2c_dev_t *dev) /////////////////////////////They might be removed in the next major release (ESP-IDF 6.0)////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Get the I2C hardware instance -#define I2C_LL_GET_HW(i2c_num) (((i2c_num) == 0) ? &I2C0 : &I2C1) -// Get the I2C hardware FIFO address -#define I2C_LL_GET_FIFO_ADDR(i2c_num) (I2C_DATA_APB_REG(i2c_num)) // I2C master TX interrupt bitmap #define I2C_LL_MASTER_TX_INT (I2C_NACK_INT_ENA_M|I2C_TIME_OUT_INT_ENA_M|I2C_TRANS_COMPLETE_INT_ENA_M|I2C_ARBITRATION_LOST_INT_ENA_M|I2C_END_DETECT_INT_ENA_M) // I2C master RX interrupt bitmap diff --git a/components/hal/i2c_hal.c b/components/hal/i2c_hal.c index 7497cb206c..567586ff93 100644 --- a/components/hal/i2c_hal.c +++ b/components/hal/i2c_hal.c @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include #include "hal/i2c_hal.h" #include "hal/i2c_ll.h" #include "hal/i2c_types.h" @@ -51,6 +52,13 @@ void i2c_hal_master_init(i2c_hal_context_t *hal) void i2c_hal_init(i2c_hal_context_t *hal, int i2c_port) { hal->dev = I2C_LL_GET_HW(i2c_port); + i2c_ll_enable_controller_clock(hal->dev, true); +} + +void i2c_hal_deinit(i2c_hal_context_t *hal) +{ + i2c_ll_enable_controller_clock(hal->dev, false); + hal->dev = NULL; } void i2c_hal_master_trans_start(i2c_hal_context_t *hal) diff --git a/components/hal/include/hal/i2c_hal.h b/components/hal/include/hal/i2c_hal.h index 2f3df91b10..dc308fbed7 100644 --- a/components/hal/include/hal/i2c_hal.h +++ b/components/hal/include/hal/i2c_hal.h @@ -101,6 +101,13 @@ void i2c_hal_master_handle_rx_event(i2c_hal_context_t *hal, i2c_intr_event_t *ev */ void i2c_hal_init(i2c_hal_context_t *hal, int i2c_port); +/** + * @brief Deinit I2C hal layer + * + * @param hal Context of the HAL + */ +void i2c_hal_deinit(i2c_hal_context_t *hal); + /** * @brief Start I2C master transaction * diff --git a/components/soc/esp32c6/CMakeLists.txt b/components/soc/esp32c6/CMakeLists.txt index 0eb7ac39a9..b5c8dfc2e5 100644 --- a/components/soc/esp32c6/CMakeLists.txt +++ b/components/soc/esp32c6/CMakeLists.txt @@ -20,7 +20,6 @@ set(srcs list(REMOVE_ITEM srcs "adc_periph.c" # TODO: IDF-5310 "ledc_periph.c" # TODO: IDF-5328 - "i2c_periph.c" # TODO: IDF-5326 "temperature_sensor_periph.c" # TODO: IDF-5322 ) diff --git a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in index 1493ebdc05..b978d689f5 100644 --- a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in @@ -59,6 +59,10 @@ config SOC_SDM_SUPPORTED bool default y +config SOC_I2C_SUPPORTED + bool + default y + config SOC_SYSTIMER_SUPPORTED bool default y diff --git a/components/soc/esp32c6/include/soc/soc_caps.h b/components/soc/esp32c6/include/soc/soc_caps.h index d87ad897c0..7c4b94c2da 100644 --- a/components/soc/esp32c6/include/soc/soc_caps.h +++ b/components/soc/esp32c6/include/soc/soc_caps.h @@ -45,7 +45,7 @@ #define SOC_RMT_SUPPORTED 1 #define SOC_SDM_SUPPORTED 1 // #define SOC_LEDC_SUPPORTED 1 // TODO: IDF-5328 -// #define SOC_I2C_SUPPORTED 1 // TODO: IDF-5326 +#define SOC_I2C_SUPPORTED 1 #define SOC_SYSTIMER_SUPPORTED 1 #define SOC_SUPPORT_COEXISTENCE 1 // #define SOC_AES_SUPPORTED 1 // TODO: IDF-5356 @@ -173,7 +173,6 @@ #define SOC_DEDIC_GPIO_IN_CHANNELS_NUM (8) /*!< 8 inward channels on each CPU core */ #define SOC_DEDIC_PERIPH_ALWAYS_ENABLE (1) /*!< The dedicated GPIO (a.k.a. fast GPIO) is featured by some customized CPU instructions, which is always enabled */ -// TODO: IDF-5326 (Copy from esp32c3, need check) /*-------------------------- I2C CAPS ----------------------------------------*/ // ESP32-C6 has 1 I2C #define SOC_I2C_NUM (1U) diff --git a/docs/docs_not_updated/esp32c6.txt b/docs/docs_not_updated/esp32c6.txt index d518487277..6aede90d0f 100644 --- a/docs/docs_not_updated/esp32c6.txt +++ b/docs/docs_not_updated/esp32c6.txt @@ -137,7 +137,6 @@ api-reference/peripherals/touch_pad api-reference/peripherals/adc_calibration api-reference/peripherals/spi_slave_hd api-reference/peripherals/ds -api-reference/peripherals/i2c api-reference/peripherals/dedic_gpio api-reference/peripherals/sd_pullup_requirements api-reference/peripherals/spi_master diff --git a/examples/peripherals/.build-test-rules.yml b/examples/peripherals/.build-test-rules.yml index ed9d3ea6ef..0b7386733e 100644 --- a/examples/peripherals/.build-test-rules.yml +++ b/examples/peripherals/.build-test-rules.yml @@ -24,23 +24,13 @@ examples/peripherals/i2c/i2c_self_test: disable: - if: SOC_I2C_SUPPORT_SLAVE != 1 reason: the test requires both master and slave - - if: IDF_TARGET == "esp32c6" - temporary: true - reason: target esp32c6 is not supported yet examples/peripherals/i2c/i2c_simple: disable: - if: SOC_I2C_SUPPORT_SLAVE != 1 reason: the test requires both master and slave - - if: IDF_TARGET == "esp32c6" - temporary: true - reason: target esp32c6 is not supported yet examples/peripherals/i2c/i2c_tools: - disable: - - if: IDF_TARGET == "esp32c6" - temporary: true - reason: target esp32c6 is not supported yet disable_test: - if: IDF_TARGET != "esp32" temporary: true diff --git a/examples/peripherals/i2c/i2c_self_test/README.md b/examples/peripherals/i2c/i2c_self_test/README.md index 192a9de504..edb09f7bda 100644 --- a/examples/peripherals/i2c/i2c_self_test/README.md +++ b/examples/peripherals/i2c/i2c_self_test/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C3 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C3 | ESP32-C6 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | # I2C Self-Test Example diff --git a/examples/peripherals/i2c/i2c_self_test/main/Kconfig.projbuild b/examples/peripherals/i2c/i2c_self_test/main/Kconfig.projbuild index 7772ab1a71..9d16b5386a 100644 --- a/examples/peripherals/i2c/i2c_self_test/main/Kconfig.projbuild +++ b/examples/peripherals/i2c/i2c_self_test/main/Kconfig.projbuild @@ -1,26 +1,31 @@ menu "Example Configuration" menu "I2C Master" + + orsource "$IDF_PATH/examples/common_components/env_caps/$IDF_TARGET/Kconfig.env_caps" + config I2C_MASTER_SCL int "SCL GPIO Num" - default 6 if IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32C2 || IDF_TARGET_ESP32H2 + range ENV_GPIO_RANGE_MIN ENV_GPIO_OUT_RANGE_MAX default 2 if IDF_TARGET_ESP32S3 default 19 if IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 + default 6 help GPIO number for I2C Master clock line. config I2C_MASTER_SDA int "SDA GPIO Num" - default 5 if IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32C2 || IDF_TARGET_ESP32H2 + range ENV_GPIO_RANGE_MIN ENV_GPIO_OUT_RANGE_MAX default 1 if IDF_TARGET_ESP32S3 default 18 if IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 + default 5 help GPIO number for I2C Master data line. config I2C_MASTER_PORT_NUM int "Port Number" default 1 if IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3 - default 0 if IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32C2 || IDF_TARGET_ESP32H2 + default 0 help Port number for I2C Master device. diff --git a/examples/peripherals/i2c/i2c_simple/README.md b/examples/peripherals/i2c/i2c_simple/README.md index 294edc2ead..f7904ac0d5 100644 --- a/examples/peripherals/i2c/i2c_simple/README.md +++ b/examples/peripherals/i2c/i2c_simple/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C3 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C3 | ESP32-C6 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | # I2C Simple Example diff --git a/examples/peripherals/i2c/i2c_simple/main/Kconfig.projbuild b/examples/peripherals/i2c/i2c_simple/main/Kconfig.projbuild index ce85352b02..62f89be8f9 100644 --- a/examples/peripherals/i2c/i2c_simple/main/Kconfig.projbuild +++ b/examples/peripherals/i2c/i2c_simple/main/Kconfig.projbuild @@ -1,16 +1,20 @@ menu "Example Configuration" + orsource "$IDF_PATH/examples/common_components/env_caps/$IDF_TARGET/Kconfig.env_caps" + config I2C_MASTER_SCL int "SCL GPIO Num" - default 6 if IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32C2 || IDF_TARGET_ESP32H2 + range ENV_GPIO_RANGE_MIN ENV_GPIO_OUT_RANGE_MAX default 19 if IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3 + default 6 help GPIO number for I2C Master clock line. config I2C_MASTER_SDA int "SDA GPIO Num" - default 5 if IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32C2 || IDF_TARGET_ESP32H2 + range ENV_GPIO_RANGE_MIN ENV_GPIO_OUT_RANGE_MAX default 18 if IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3 + default 5 help GPIO number for I2C Master data line. diff --git a/examples/peripherals/i2c/i2c_tools/README.md b/examples/peripherals/i2c/i2c_tools/README.md index c3425ff775..4b2be6cd50 100644 --- a/examples/peripherals/i2c/i2c_tools/README.md +++ b/examples/peripherals/i2c/i2c_tools/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | # I2C Tools Example diff --git a/examples/peripherals/i2c/i2c_tools/main/i2ctools_example_main.c b/examples/peripherals/i2c/i2c_tools/main/i2ctools_example_main.c index 5cb6a6e988..7374b0891c 100644 --- a/examples/peripherals/i2c/i2c_tools/main/i2ctools_example_main.c +++ b/examples/peripherals/i2c/i2c_tools/main/i2ctools_example_main.c @@ -62,7 +62,6 @@ void app_main(void) #endif register_i2ctools(); - register_system(); printf("\n ==============================================================\n"); printf(" | Steps to Use i2c-tools |\n"); diff --git a/tools/test_apps/.build-test-rules.yml b/tools/test_apps/.build-test-rules.yml index 4b2e501033..6c25a5fd5b 100644 --- a/tools/test_apps/.build-test-rules.yml +++ b/tools/test_apps/.build-test-rules.yml @@ -25,12 +25,6 @@ tools/test_apps/linux_compatible/hello_world_linux_compatible: temporary: true reason: pytest doesn't support linux target yet, hence, it's tested independenly in the host_tests stage -tools/test_apps/peripherals/i2c_wifi: - disable: - - if: IDF_TARGET == "esp32c6" - temporary: true - reason: target esp32c6 is not supported yet - tools/test_apps/peripherals/usb: enable: - if: IDF_TARGET in ["esp32s2", "esp32s3"] diff --git a/tools/test_apps/peripherals/i2c_wifi/README.md b/tools/test_apps/peripherals/i2c_wifi/README.md index 6707b6585e..a5412d113b 100644 --- a/tools/test_apps/peripherals/i2c_wifi/README.md +++ b/tools/test_apps/peripherals/i2c_wifi/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | # I2C-WIFI Test diff --git a/tools/test_apps/peripherals/i2c_wifi/main/Kconfig.projbuild b/tools/test_apps/peripherals/i2c_wifi/main/Kconfig.projbuild index a2c3de4afb..773a0ed916 100644 --- a/tools/test_apps/peripherals/i2c_wifi/main/Kconfig.projbuild +++ b/tools/test_apps/peripherals/i2c_wifi/main/Kconfig.projbuild @@ -11,19 +11,24 @@ menu "Test Configuration" endchoice menu "I2C Configuration" + + orsource "$IDF_PATH/examples/common_components/env_caps/$IDF_TARGET/Kconfig.env_caps" + config TEST_I2C_SCL_NUM int "SCL GPIO Num" - default 9 if IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32C2 + range ENV_GPIO_RANGE_MIN ENV_GPIO_OUT_RANGE_MAX default 2 if IDF_TARGET_ESP32S3 default 19 if IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 + default 9 help GPIO number for I2C Master clock line. config TEST_I2C_SDA_NUM int "SDA GPIO Num" - default 5 if IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32C2 + range ENV_GPIO_RANGE_MIN ENV_GPIO_OUT_RANGE_MAX default 1 if IDF_TARGET_ESP32S3 default 18 if IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 + default 5 help GPIO number for I2C Master data line. @@ -50,7 +55,8 @@ menu "Test Configuration" config TEST_I2C_WIFI_AP_ENABLE bool "Enable WIFI AP" default y - depends on TEST_I2C_MASTER_MODE && !IDF_TARGET_ESP32C2 + # C6 has not supported WIFI yet. + depends on TEST_I2C_MASTER_MODE && !IDF_TARGET_ESP32C6 menu "WiFi softAP Configuration" depends on TEST_I2C_WIFI_AP_ENABLE