diff --git a/components/driver/i2c.c b/components/driver/i2c.c index 93f050459b..de12e675d8 100644 --- a/components/driver/i2c.c +++ b/components/driver/i2c.c @@ -1,4 +1,4 @@ -// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD +// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -70,6 +70,7 @@ static const char *I2C_TAG = "i2c"; #define I2C_DATA_LEN_ERR_STR "i2c data read length error" #define I2C_PSRAM_BUFFER_WARN_STR "Using buffer allocated from psram" #define I2C_LOCK_ERR_STR "Power lock creation error" +#define I2C_CLK_FLAG_ERR_STR "i2c clock choice is invalid, please check flag and frequency" #define I2C_FIFO_FULL_THRESH_VAL (28) #define I2C_FIFO_EMPTY_THRESH_VAL (5) #define I2C_IO_INIT_LEVEL (1) @@ -92,6 +93,12 @@ static const char *I2C_TAG = "i2c"; .hw_enabled = false,\ } +// Freq limitation when using different clock sources +#define I2C_CLK_LIMIT_REF_TICK (1 * 1000 * 1000 / 20) /*!< Limited by REF_TICK, no more than REF_TICK/20*/ +#define I2C_CLK_LIMIT_APB (80 * 1000 * 1000 / 20) /*!< Limited by APB, no more than APB/20*/ +#define I2C_CLK_LIMIT_RTC (20 * 1000 * 1000 / 20) /*!< Limited by RTC, no more than RTC/20*/ +#define I2C_CLK_LIMIT_XTAL (40 * 1000 * 1000 / 20) /*!< Limited by RTC, no more than XTAL/20*/ + typedef struct { i2c_hw_cmd_t hw_cmd; uint8_t *data; /*!< data address */ @@ -161,11 +168,34 @@ typedef struct { #endif } i2c_context_t; +typedef struct +{ + uint8_t character; /*!< I2C source clock characteristic */ + uint32_t clk_freq; /*!< I2C source clock frequency */ +} i2c_clk_alloc_t; + static i2c_context_t i2c_context[I2C_NUM_MAX] = { I2C_CONTEX_INIT_DEF(I2C_NUM_0), I2C_CONTEX_INIT_DEF(I2C_NUM_1), }; +// i2c clock characteristic, The order is the same as i2c_sclk_t. +static i2c_clk_alloc_t i2c_clk_alloc[I2C_SCLK_MAX] = { + {0, 0}, +#if SOC_I2C_SUPPORT_APB + {0, I2C_CLK_LIMIT_APB}, /*!< I2C APB clock characteristic*/ +#endif +#if SOC_I2C_SUPPORT_XTAL + {0, I2C_CLK_LIMIT_XTAL}, /*!< I2C XTAL characteristic*/ +#endif +#if SOC_I2C_SUPPORT_RTC + {I2C_SCLK_SRC_FLAG_LIGHT_SLEEP, I2C_CLK_LIMIT_RTC}, /*!< I2C 20M RTC characteristic*/ +#endif +#if SOC_I2C_SUPPORT_REF_TICK + {I2C_SCLK_SRC_FLAG_AWARE_DFS | I2C_SCLK_SRC_FLAG_LIGHT_SLEEP, I2C_CLK_LIMIT_REF_TICK}, /*!< I2C REF_TICK characteristic*/ +#endif +}; + static i2c_obj_t *p_i2c_obj[I2C_NUM_MAX] = {0}; static void i2c_isr_handler_default(void *arg); static void IRAM_ATTR i2c_master_cmd_begin_static(i2c_port_t i2c_num); @@ -590,6 +620,21 @@ static esp_err_t i2c_hw_fsm_reset(i2c_port_t i2c_num) return ESP_OK; } +static i2c_sclk_t i2c_get_clk_src(const i2c_config_t *i2c_conf) +{ + for (i2c_sclk_t clk = I2C_SCLK_DEFAULT + 1; clk < I2C_SCLK_MAX; clk++) { +#if CONFIG_IDF_TARGET_ESP32S3 + if (clk == I2C_SCLK_RTC) { // RTC clock for s3 is unaccessable now. + continue; + } +#endif + if (((i2c_conf->clk_flags | i2c_clk_alloc[clk].character) == i2c_clk_alloc[clk].character) && (i2c_conf->master.clk_speed <= i2c_clk_alloc[clk].clk_freq)) { + return clk; + } + } + return I2C_SCLK_MAX; // flag invalid; +} + esp_err_t i2c_param_config(i2c_port_t i2c_num, const i2c_config_t *i2c_conf) { I2C_CHECK(i2c_num < I2C_NUM_MAX, I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG); @@ -614,11 +659,13 @@ esp_err_t i2c_param_config(i2c_port_t i2c_num, const i2c_config_t *i2c_conf) i2c_hal_set_sda_timing(&(i2c_context[i2c_num].hal), I2C_SLAVE_SDA_SAMPLE_DEFAULT, I2C_SLAVE_SDA_HOLD_DEFAULT); i2c_hal_set_tout(&(i2c_context[i2c_num].hal), I2C_SLAVE_TIMEOUT_DEFAULT); i2c_hal_enable_slave_rx_it(&(i2c_context[i2c_num].hal)); + i2c_hal_update_config(&(i2c_context[i2c_num].hal)); } else { i2c_hal_master_init(&(i2c_context[i2c_num].hal), i2c_num); //Default, we enable hardware filter i2c_hal_set_filter(&(i2c_context[i2c_num].hal), I2C_FILTER_CYC_NUM_DEF); - i2c_hal_set_bus_timing(&(i2c_context[i2c_num].hal), i2c_conf->master.clk_speed, I2C_SCLK_APB); + I2C_CHECK(i2c_get_clk_src(i2c_conf) != I2C_SCLK_MAX, I2C_CLK_FLAG_ERR_STR, ESP_ERR_INVALID_ARG); + i2c_hal_set_bus_timing(&(i2c_context[i2c_num].hal), i2c_conf->master.clk_speed, i2c_get_clk_src(i2c_conf)); } I2C_EXIT_CRITICAL(&(i2c_context[i2c_num].spinlock)); return ESP_OK; @@ -882,7 +929,7 @@ esp_err_t i2c_master_start(i2c_cmd_handle_t cmd_handle) cmd.hw_cmd.ack_en = 0; cmd.hw_cmd.ack_exp = 0; cmd.hw_cmd.ack_val = 0; - cmd.hw_cmd.op_code = I2C_CMD_RESTART; + cmd.hw_cmd.op_code = I2C_LL_CMD_RESTART; cmd.hw_cmd.byte_num = 0; cmd.data = NULL; return i2c_cmd_link_append(cmd_handle, &cmd); @@ -895,7 +942,7 @@ esp_err_t i2c_master_stop(i2c_cmd_handle_t cmd_handle) cmd.hw_cmd.ack_en = 0; cmd.hw_cmd.ack_exp = 0; cmd.hw_cmd.ack_val = 0; - cmd.hw_cmd.op_code = I2C_CMD_STOP; + cmd.hw_cmd.op_code = I2C_LL_CMD_STOP; cmd.hw_cmd.byte_num = 0; cmd.data = NULL; return i2c_cmd_link_append(cmd_handle, &cmd); @@ -916,7 +963,7 @@ esp_err_t i2c_master_write(i2c_cmd_handle_t cmd_handle, const uint8_t *data, siz cmd.hw_cmd.ack_en = ack_en; cmd.hw_cmd.ack_exp = 0; cmd.hw_cmd.ack_val = 0; - cmd.hw_cmd.op_code = I2C_CMD_WRITE; + cmd.hw_cmd.op_code = I2C_LL_CMD_WRITE; cmd.hw_cmd.byte_num = len_tmp; cmd.data = (uint8_t*) data + data_offset; ret = i2c_cmd_link_append(cmd_handle, &cmd); @@ -935,7 +982,7 @@ esp_err_t i2c_master_write_byte(i2c_cmd_handle_t cmd_handle, uint8_t data, bool cmd.hw_cmd.ack_en = ack_en; cmd.hw_cmd.ack_exp = 0; cmd.hw_cmd.ack_val = 0; - cmd.hw_cmd.op_code = I2C_CMD_WRITE; + cmd.hw_cmd.op_code = I2C_LL_CMD_WRITE; cmd.hw_cmd.byte_num = 1; cmd.data = NULL; cmd.byte_cmd = data; @@ -955,7 +1002,7 @@ static esp_err_t i2c_master_read_static(i2c_cmd_handle_t cmd_handle, uint8_t *da cmd.hw_cmd.ack_exp = 0; cmd.hw_cmd.ack_val = ack & 0x1; cmd.hw_cmd.byte_num = len_tmp; - cmd.hw_cmd.op_code = I2C_CMD_READ; + cmd.hw_cmd.op_code = I2C_LL_CMD_READ; cmd.data = data + data_offset; ret = i2c_cmd_link_append(cmd_handle, &cmd); data_offset += len_tmp; @@ -977,7 +1024,7 @@ esp_err_t i2c_master_read_byte(i2c_cmd_handle_t cmd_handle, uint8_t *data, i2c_a cmd.hw_cmd.ack_exp = 0; cmd.hw_cmd.ack_val = ((ack == I2C_MASTER_LAST_NACK) ? I2C_MASTER_NACK : (ack & 0x1)); cmd.hw_cmd.byte_num = 1; - cmd.hw_cmd.op_code = I2C_CMD_READ; + cmd.hw_cmd.op_code = I2C_LL_CMD_READ; cmd.data = data; return i2c_cmd_link_append(cmd_handle, &cmd); } @@ -1036,12 +1083,12 @@ static void IRAM_ATTR i2c_master_cmd_begin_static(i2c_port_t i2c_num) return; } const i2c_hw_cmd_t hw_end_cmd = { - .op_code = I2C_CMD_END + .op_code = I2C_LL_CMD_END }; while (p_i2c->cmd_link.head) { i2c_cmd_t *cmd = &p_i2c->cmd_link.head->cmd; i2c_hw_cmd_t hw_cmd = cmd->hw_cmd; - if (cmd->hw_cmd.op_code == I2C_CMD_WRITE) { + if (cmd->hw_cmd.op_code == I2C_LL_CMD_WRITE) { uint8_t wr_filled = 0; uint8_t *write_pr = NULL; //TODO: to reduce interrupt number @@ -1066,7 +1113,7 @@ static void IRAM_ATTR i2c_master_cmd_begin_static(i2c_port_t i2c_num) } p_i2c->status = I2C_STATUS_WRITE; break; - } else if (cmd->hw_cmd.op_code == I2C_CMD_READ) { + } else if (cmd->hw_cmd.op_code == I2C_LL_CMD_READ) { //TODO: to reduce interrupt number p_i2c->rx_cnt = cmd->hw_cmd.byte_num > SOC_I2C_FIFO_LEN ? SOC_I2C_FIFO_LEN : cmd->hw_cmd.byte_num; cmd->hw_cmd.byte_num -= p_i2c->rx_cnt; @@ -1086,6 +1133,7 @@ static void IRAM_ATTR i2c_master_cmd_begin_static(i2c_port_t i2c_num) break; } } + i2c_hal_update_config(&(i2c_context[i2c_num].hal)); i2c_hal_trans_start(&(i2c_context[i2c_num].hal)); return; } @@ -1096,7 +1144,7 @@ static bool is_cmd_link_buffer_internal(i2c_cmd_link_t *link) { i2c_cmd_link_t *cmd_link = link; while (cmd_link != NULL) { - if (cmd_link->cmd.hw_cmd.op_code == I2C_CMD_WRITE || cmd_link->cmd.hw_cmd.op_code == I2C_CMD_READ) { + if (cmd_link->cmd.hw_cmd.op_code == I2C_LL_CMD_WRITE || cmd_link->cmd.hw_cmd.op_code == I2C_LL_CMD_READ) { if (cmd_link->cmd.data != NULL && !esp_ptr_internal(cmd_link->cmd.data)) { return false; } diff --git a/components/driver/include/driver/i2c.h b/components/driver/include/driver/i2c.h index 3cd9f3b74d..9b4107865f 100644 --- a/components/driver/include/driver/i2c.h +++ b/components/driver/include/driver/i2c.h @@ -1,4 +1,4 @@ -// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD +// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/components/driver/test/test_i2c.c b/components/driver/test/test_i2c.c index d1dcc1567d..9a10265b92 100644 --- a/components/driver/test/test_i2c.c +++ b/components/driver/test/test_i2c.c @@ -19,8 +19,6 @@ #include "driver/periph_ctrl.h" #include "esp_rom_gpio.h" -#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S3) - #define DATA_LENGTH 512 /*!fifo_conf.fifo_addr_cfg_en = 0; } +/** + * @brief Update I2C configuration + * + * @param hw Beginning address of the peripheral registers + * + * @return None + */ +static inline void i2c_ll_update(i2c_dev_t *hw) +{ + ;// ESP32 do not support +} + #ifdef __cplusplus } #endif diff --git a/components/hal/esp32s2/include/hal/i2c_ll.h b/components/hal/esp32s2/include/hal/i2c_ll.h index 4ce218bce6..8152557ced 100644 --- a/components/hal/esp32s2/include/hal/i2c_ll.h +++ b/components/hal/esp32s2/include/hal/i2c_ll.h @@ -68,6 +68,13 @@ typedef struct { uint16_t tout; /*!< I2C bus timeout period */ } i2c_clk_cal_t; +// I2C operation mode command +#define I2C_LL_CMD_RESTART 0 /*!ctr.ref_always_on = src_clk; + // src_clk : (1) for APB_CLK, (0) for REF_CLK + hw->ctr.ref_always_on = (src_clk == I2C_SCLK_REF_TICK) ? 0 : 1; } /** @@ -846,8 +854,6 @@ static inline void i2c_ll_master_init(i2c_dev_t *hw) ctrl_reg.ms_mode = 1; ctrl_reg.sda_force_out = 1; ctrl_reg.scl_force_out = 1; - //Disable REF tick; - ctrl_reg.ref_always_on = 1; hw->ctr.val = ctrl_reg.val; } @@ -881,13 +887,23 @@ static inline void i2c_ll_slave_init(i2c_dev_t *hw) //Open-drain output via GPIO ctrl_reg.sda_force_out = 1; ctrl_reg.scl_force_out = 1; - //Disable REF tick; - ctrl_reg.ref_always_on = 1; hw->ctr.val = ctrl_reg.val; hw->fifo_conf.fifo_addr_cfg_en = 0; hw->scl_stretch_conf.slave_scl_stretch_en = 0; } +/** + * @brief Update I2C configuration + * + * @param hw Beginning address of the peripheral registers + * + * @return None + */ +static inline void i2c_ll_update(i2c_dev_t *hw) +{ + ;// ESP32S2 do not support +} + #ifdef __cplusplus } #endif diff --git a/components/hal/esp32s3/include/hal/i2c_ll.h b/components/hal/esp32s3/include/hal/i2c_ll.h index 46ab2ef04b..249840092e 100644 --- a/components/hal/esp32s3/include/hal/i2c_ll.h +++ b/components/hal/esp32s3/include/hal/i2c_ll.h @@ -1,4 +1,4 @@ -// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD +// Copyright 2020 Espressif Systems (Shanghai) PTE LTD // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -23,7 +23,6 @@ extern "C" { #endif #define I2C_LL_INTR_MASK (0x3fff) /*!< I2C all interrupt bitmap */ - /** * @brief I2C hardware cmd register filed. */ @@ -58,8 +57,10 @@ typedef enum { * @brief Data structure for calculating I2C bus timing. */ typedef struct { + uint16_t clkm_div; /*!< I2C core clock devider */ uint16_t scl_low; /*!< I2C scl low period */ uint16_t scl_high; /*!< I2C scl hight period */ + uint16_t scl_wait_high; /*!< I2C scl wait_high period */ uint16_t sda_hold; /*!< I2C scl low period */ uint16_t sda_sample; /*!< I2C sda sample time */ uint16_t setup; /*!< I2C start and stop condition setup period */ @@ -67,24 +68,33 @@ typedef struct { uint16_t tout; /*!< I2C bus timeout period */ } i2c_clk_cal_t; +// I2C operation mode command +#define I2C_LL_CMD_RESTART 6 /*!clkm_div = clkm_div; clk_cal->scl_low = half_cycle; - clk_cal->scl_high = half_cycle; + // default, scl_wait_high < scl_high + clk_cal->scl_high = (bus_freq <= 50000) ? half_cycle : (half_cycle / 5 * 4 + 4); + clk_cal->scl_wait_high = half_cycle - clk_cal->scl_high; clk_cal->sda_hold = half_cycle / 2; - clk_cal->sda_sample = clk_cal->scl_high / 2; + // scl_wait_high < sda_sample <= scl_high + clk_cal->sda_sample = half_cycle / 2; clk_cal->setup = half_cycle; clk_cal->hold = half_cycle; - clk_cal->tout = half_cycle * 20; //default we set the timeout value to 10 bus cycles. + //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 + */ +static inline void i2c_ll_update(i2c_dev_t *hw) +{ + hw->ctr.conf_upgate = 1; } /** @@ -114,8 +145,9 @@ static inline void i2c_ll_cal_bus_clk(uint32_t source_clk, uint32_t bus_freq, i2 */ static inline void i2c_ll_set_bus_timing(i2c_dev_t *hw, i2c_clk_cal_t *bus_cfg) { + hw->clk_conf.sclk_div_num = bus_cfg->clkm_div - 1; //scl period - hw->scl_low_period.period = bus_cfg->scl_low; + hw->scl_low_period.period = bus_cfg->scl_low - 1; hw->scl_high_period.period = bus_cfg->scl_high; //sda sample hw->sda_hold.time = bus_cfg->sda_hold; @@ -124,9 +156,10 @@ static inline void i2c_ll_set_bus_timing(i2c_dev_t *hw, i2c_clk_cal_t *bus_cfg) hw->scl_rstart_setup.time = bus_cfg->setup; hw->scl_stop_setup.time = bus_cfg->setup; //hold - hw->scl_start_hold.time = bus_cfg->hold; + hw->scl_start_hold.time = bus_cfg->hold - 1; hw->scl_stop_hold.time = bus_cfg->hold; - hw->timeout.tout = bus_cfg->tout; + hw->timeout.time_out_value = bus_cfg->tout; + hw->timeout.time_out_en = 1; } /** @@ -159,15 +192,17 @@ static inline void i2c_ll_rxfifo_rst(i2c_dev_t *hw) * @brief Configure I2C SCL timing * * @param hw Beginning address of the peripheral registers - * @param hight_period The I2C SCL hight period (in APB cycle) - * @param low_period The I2C SCL low period (in APB cycle) + * @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) * * @return None. */ -static inline void i2c_ll_set_scl_timing(i2c_dev_t *hw, int hight_period, int low_period) +static inline void i2c_ll_set_scl_timing(i2c_dev_t *hw, int high_period, int low_period) { - hw->scl_low_period.period = low_period; - hw->scl_high_period.period = hight_period; + int high_period_output = high_period - 10; // The rising edge by open-drain output + internal pullup (about 50K) is slow + hw->scl_low_period.period = low_period - 1; + hw->scl_high_period.period = high_period_output; + hw->scl_high_period.scl_wait_high_period = high_period - high_period_output; } /** @@ -238,13 +273,13 @@ static inline void i2c_ll_set_fifo_mode(i2c_dev_t *hw, bool fifo_mode_en) * @brief Configure I2C timeout * * @param hw Beginning address of the peripheral registers - * @param tout_num The I2C timeout value needs to be set (in APB cycle) + * @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->timeout.tout = tout; + hw->timeout.time_out_value = tout; } /** @@ -280,23 +315,23 @@ static inline void i2c_ll_write_cmd_reg(i2c_dev_t *hw, i2c_hw_cmd_t cmd, int cmd * @brief Configure I2C start timing * * @param hw Beginning address of the peripheral registers - * @param start_setup The start condition setup period (in APB cycle) - * @param start_hold The start condition hold period (in APB cycle) + * @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.time = start_setup; - hw->scl_start_hold.time = start_hold; + hw->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 APB cycle) - * @param stop_hold The stop condition hold period (in APB cycle) + * @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 */ @@ -310,8 +345,8 @@ static inline void i2c_ll_set_stop_timing(i2c_dev_t *hw, int stop_setup, int sto * @brief Configure I2C stop timing * * @param hw Beginning address of the peripheral registers - * @param sda_sample The SDA sample time (in APB cycle) - * @param sda_hold The SDA hold time (in APB cycle) + * @param sda_sample The SDA sample time (in core clock cycle) + * @param sda_hold The SDA hold time (in core clock cycle) * * @return None */ @@ -331,7 +366,7 @@ static inline void i2c_ll_set_sda_timing(i2c_dev_t *hw, int sda_sample, int sda_ */ static inline void i2c_ll_set_txfifo_empty_thr(i2c_dev_t *hw, uint8_t empty_thr) { - hw->fifo_conf.tx_fifo_empty_thrhd = empty_thr; + hw->fifo_conf.tx_fifo_wm_thrhd = empty_thr; } /** @@ -344,7 +379,7 @@ static inline void i2c_ll_set_txfifo_empty_thr(i2c_dev_t *hw, uint8_t empty_thr) */ static inline void i2c_ll_set_rxfifo_full_thr(i2c_dev_t *hw, uint8_t full_thr) { - hw->fifo_conf.rx_fifo_full_thrhd = full_thr; + hw->fifo_conf.rx_fifo_wm_thrhd = full_thr; } /** @@ -461,7 +496,7 @@ static inline uint32_t i2c_ll_get_txfifo_len(i2c_dev_t *hw) */ static inline uint32_t i2c_ll_get_tout(i2c_dev_t *hw) { - return hw->timeout.tout; + return hw->timeout.time_out_value; } /** @@ -488,7 +523,7 @@ static inline void i2c_ll_trans_start(i2c_dev_t *hw) static inline void i2c_ll_get_start_timing(i2c_dev_t *hw, int *setup_time, int *hold_time) { *setup_time = hw->scl_rstart_setup.time; - *hold_time = hw->scl_start_hold.time; + *hold_time = hw->scl_start_hold.time + 1; } /** @@ -517,8 +552,8 @@ static inline void i2c_ll_get_stop_timing(i2c_dev_t *hw, int *setup_time, int *h */ static inline void i2c_ll_get_scl_timing(i2c_dev_t *hw, int *high_period, int *low_period) { - *high_period = hw->scl_high_period.period; - *low_period = hw->scl_low_period.period; + *high_period = hw->scl_high_period.period + hw->scl_high_period.scl_wait_high_period; + *low_period = hw->scl_low_period.period + 1; } /** @@ -532,9 +567,8 @@ static inline void i2c_ll_get_scl_timing(i2c_dev_t *hw, int *high_period, int *l */ static inline void i2c_ll_write_txfifo(i2c_dev_t *hw, uint8_t *ptr, uint8_t len) { - uint32_t fifo_addr = (hw == &I2C0) ? 0x6001301c : 0x6002701c; - for(int i = 0; i < len; i++) { - WRITE_PERI_REG(fifo_addr, ptr[i]); + for (int i = 0; i< len; i++) { + hw->fifo_data.data = ptr[i]; } } @@ -565,14 +599,14 @@ static inline void i2c_ll_read_rxfifo(i2c_dev_t *hw, uint8_t *ptr, uint8_t len) */ static inline void i2c_ll_set_filter(i2c_dev_t *hw, uint8_t filter_num) { - if(filter_num > 0) { - hw->scl_filter_cfg.thres = filter_num; - hw->sda_filter_cfg.thres = filter_num; - hw->scl_filter_cfg.en = 1; - hw->sda_filter_cfg.en = 1; + if (filter_num > 0) { + hw->filter_cfg.scl_thres = filter_num; + hw->filter_cfg.sda_thres = filter_num; + hw->filter_cfg.scl_en = 1; + hw->filter_cfg.sda_en = 1; } else { - hw->scl_filter_cfg.en = 0; - hw->sda_filter_cfg.en = 0; + hw->filter_cfg.scl_en = 0; + hw->filter_cfg.sda_en = 0; } } @@ -585,7 +619,7 @@ static inline void i2c_ll_set_filter(i2c_dev_t *hw, uint8_t filter_num) */ static inline uint8_t i2c_ll_get_filter(i2c_dev_t *hw) { - return hw->sda_filter_cfg.thres; + return hw->filter_cfg.scl_thres; } /** @@ -743,7 +777,7 @@ static inline void i2c_ll_slave_clr_rx_it(i2c_dev_t *hw) */ static inline void i2c_ll_master_fsm_rst(i2c_dev_t *hw) { - ;//ESP32 do not support + hw->ctr.fsm_rst = 1; } /** @@ -758,7 +792,10 @@ static inline void i2c_ll_master_fsm_rst(i2c_dev_t *hw) */ static inline void i2c_ll_master_clr_bus(i2c_dev_t *hw) { - ;//ESP32 do not support + hw->scl_sp_conf.scl_rst_slv_num = 9; + hw->scl_sp_conf.scl_rst_slv_en = 0; + hw->ctr.conf_upgate = 1; + hw->scl_sp_conf.scl_rst_slv_en = 1; } /** @@ -771,7 +808,7 @@ static inline void i2c_ll_master_clr_bus(i2c_dev_t *hw) */ static inline void i2c_ll_set_source_clk(i2c_dev_t *hw, i2c_sclk_t src_clk) { - ;//Not support on ESP32 + hw->clk_conf.sclk_sel = (src_clk == I2C_SCLK_RTC) ? 1 : 0; } /** @@ -787,7 +824,7 @@ static inline void i2c_ll_master_get_event(i2c_dev_t *hw, i2c_intr_event_t *even typeof(hw->int_status) int_sts = hw->int_status; if (int_sts.arbitration_lost) { *event = I2C_INTR_EVENT_ARBIT_LOST; - } else if (int_sts.ack_err) { + } else if (int_sts.nack) { *event = I2C_INTR_EVENT_NACK; } else if (int_sts.time_out) { *event = I2C_INTR_EVENT_TOUT; @@ -811,11 +848,11 @@ static inline void i2c_ll_master_get_event(i2c_dev_t *hw, i2c_intr_event_t *even 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.tx_fifo_empty) { + if (int_sts.tx_fifo_wm) { *event = I2C_INTR_EVENT_TXFIFO_EMPTY; } else if (int_sts.trans_complete) { *event = I2C_INTR_EVENT_TRANS_DONE; - } else if (int_sts.rx_fifo_full) { + } else if (int_sts.rx_fifo_wm) { *event = I2C_INTR_EVENT_RXFIFO_FULL; } else { *event = I2C_INTR_EVENT_ERR; @@ -834,6 +871,7 @@ 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.clk_en = 1; ctrl_reg.sda_force_out = 1; ctrl_reg.scl_force_out = 1; hw->ctr.val = ctrl_reg.val; diff --git a/components/hal/i2c_hal.c b/components/hal/i2c_hal.c index 6c8a7770c5..a1f59948f7 100644 --- a/components/hal/i2c_hal.c +++ b/components/hal/i2c_hal.c @@ -176,9 +176,11 @@ void i2c_hal_disable_slave_rx_it(i2c_hal_context_t *hal) void i2c_hal_set_bus_timing(i2c_hal_context_t *hal, uint32_t scl_freq, i2c_sclk_t src_clk) { - uint32_t sclk = (src_clk == I2C_SCLK_REF_TICK) ? 1000000 : 80000000; + i2c_ll_set_source_clk(hal->dev, src_clk); + uint32_t sclk = I2C_LL_CLK_SRC_FREQ(src_clk); i2c_clk_cal_t clk_cal = {0}; - i2c_ll_cal_bus_clk(sclk, scl_freq, &clk_cal); + uint32_t scl_hw_freq = (scl_freq == I2C_CLK_FREQ_MAX) ? (src_clk / 20) : scl_freq; // FREQ_MAX use the highest freq of the chosen clk. + i2c_ll_cal_bus_clk(sclk, scl_hw_freq, &clk_cal); i2c_ll_set_bus_timing(hal->dev, &clk_cal); } @@ -216,3 +218,8 @@ void i2c_hal_master_init(i2c_hal_context_t *hal, int i2c_num) i2c_ll_txfifo_rst(hal->dev); i2c_ll_rxfifo_rst(hal->dev); } + +void i2c_hal_update_config(i2c_hal_context_t *hal) +{ + i2c_ll_update(hal->dev); +} diff --git a/components/hal/include/hal/i2c_hal.h b/components/hal/include/hal/i2c_hal.h index 7df34efcee..829cd92d59 100644 --- a/components/hal/include/hal/i2c_hal.h +++ b/components/hal/include/hal/i2c_hal.h @@ -522,3 +522,13 @@ void i2c_hal_master_handle_rx_event(i2c_hal_context_t *hal, i2c_intr_event_t *ev * @return None */ void i2c_hal_slave_handle_event(i2c_hal_context_t *hal, i2c_intr_event_t *event); + +/** + * @brief Synchronize I2C status + * + * @param hal Context of the HAL layer + * + * @return None + * + */ +void i2c_hal_update_config(i2c_hal_context_t *hal); diff --git a/components/hal/include/hal/i2c_types.h b/components/hal/include/hal/i2c_types.h index cc1c231e5a..3d5864dc10 100644 --- a/components/hal/include/hal/i2c_types.h +++ b/components/hal/include/hal/i2c_types.h @@ -38,14 +38,6 @@ typedef enum { I2C_MASTER_READ, /*!< I2C read data */ } i2c_rw_t; -typedef enum{ - I2C_CMD_RESTART = 0, /*!