From bae0d8a3134e51e67524340f408c31f6d3d4c8ca Mon Sep 17 00:00:00 2001 From: kooho <2229179028@qq.com> Date: Thu, 15 Nov 2018 20:21:49 +0800 Subject: [PATCH] driver(i2c): enable I2C master hardware filter by default for release/v3.2 --- components/driver/i2c.c | 27 +++++++++++++++++++++++- components/driver/include/driver/i2c.h | 29 ++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 1 deletion(-) diff --git a/components/driver/i2c.c b/components/driver/i2c.c index e21c137c4..1fec11589 100644 --- a/components/driver/i2c.c +++ b/components/driver/i2c.c @@ -79,6 +79,7 @@ static DRAM_ATTR i2c_dev_t* const I2C[I2C_NUM_MAX] = { &I2C0, &I2C1 }; #define I2C_SLAVE_SDA_HOLD_DEFAULT (10) /* I2C slave hold time after scl negative edge default value */ #define I2C_MASTER_TOUT_CNUM_DEFAULT (8) /* I2C master timeout cycle number of I2C clock, after which the timeout interrupt will be triggered */ #define I2C_ACKERR_CNT_MAX (10) +#define I2C_FILTER_CYC_NUM_DEF (7) /* The number of apb cycles filtered by default*/ typedef struct { uint8_t byte_num; /*!< cmd byte number */ @@ -660,6 +661,8 @@ esp_err_t i2c_param_config(i2c_port_t i2c_num, const i2c_config_t* i2c_conf) //set timing for stop signal I2C[i2c_num]->scl_stop_hold.time = half_cycle; I2C[i2c_num]->scl_stop_setup.time = half_cycle; + //Default, we enable hardware filter + i2c_filter_enable(i2c_num, I2C_FILTER_CYC_NUM_DEF); } I2C_EXIT_CRITICAL(&i2c_spinlock[i2c_num]); @@ -693,6 +696,28 @@ esp_err_t i2c_get_period(i2c_port_t i2c_num, int* high_period, int* low_period) return ESP_OK; } +esp_err_t i2c_filter_enable(i2c_port_t i2c_num, uint8_t cyc_num) +{ + I2C_CHECK(i2c_num < I2C_NUM_MAX, I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG); + I2C_ENTER_CRITICAL(&i2c_spinlock[i2c_num]); + I2C[i2c_num]->scl_filter_cfg.thres = cyc_num; + I2C[i2c_num]->sda_filter_cfg.thres = cyc_num; + I2C[i2c_num]->scl_filter_cfg.en = 1; + I2C[i2c_num]->sda_filter_cfg.en = 1; + I2C_EXIT_CRITICAL(&i2c_spinlock[i2c_num]); + return ESP_OK; +} + +esp_err_t i2c_filter_disable(i2c_port_t i2c_num) +{ + I2C_CHECK(i2c_num < I2C_NUM_MAX, I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG); + I2C_ENTER_CRITICAL(&i2c_spinlock[i2c_num]); + I2C[i2c_num]->scl_filter_cfg.en = 0; + I2C[i2c_num]->sda_filter_cfg.en = 0; + I2C_EXIT_CRITICAL(&i2c_spinlock[i2c_num]); + return ESP_OK; +} + esp_err_t i2c_set_start_timing(i2c_port_t i2c_num, int setup_time, int hold_time) { I2C_CHECK(i2c_num < I2C_NUM_MAX, I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG); @@ -1375,4 +1400,4 @@ int i2c_slave_read_buffer(i2c_port_t i2c_num, uint8_t* data, size_t max_size, Ti } xSemaphoreGive(p_i2c->slv_rx_mux); return cnt; -} +} \ No newline at end of file diff --git a/components/driver/include/driver/i2c.h b/components/driver/include/driver/i2c.h index 8f8cb9a14..feb1d78bd 100644 --- a/components/driver/include/driver/i2c.h +++ b/components/driver/include/driver/i2c.h @@ -420,6 +420,35 @@ esp_err_t i2c_set_period(i2c_port_t i2c_num, int high_period, int low_period); */ esp_err_t i2c_get_period(i2c_port_t i2c_num, int* high_period, int* low_period); +/** + * @brief enable hardware filter on I2C bus + * Sometimes the I2C bus is disturbed by high frequency noise(about 20ns), or the rising edge of + * the SCL clock is very slow, these may cause the master state machine broken. enable hardware + * filter can filter out high frequency interference and make the master more stable. + * @note + * Enable filter will slow the SCL clock. + * + * @param i2c_num I2C port number + * @param cyc_num the APB cycles need to be filtered(0<= cyc_num <=7). + * When the period of a pulse is less than cyc_num * APB_cycle, the I2C controller will ignore this pulse. + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t i2c_filter_enable(i2c_port_t i2c_num, uint8_t cyc_num); + +/** + * @brief disable filter on I2C bus + * + * @param i2c_num I2C port number + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t i2c_filter_disable(i2c_port_t i2c_num); + /** * @brief set I2C master start signal timing *