]> granicus.if.org Git - esp-idf/commitdiff
driver(i2c): enable I2C master hardware filter by default.
authorkooho <2229179028@qq.com>
Thu, 15 Nov 2018 12:21:49 +0000 (20:21 +0800)
committerkooho <2229179028@qq.com>
Fri, 23 Nov 2018 02:27:59 +0000 (10:27 +0800)
components/driver/i2c.c
components/driver/include/driver/i2c.h

index e21c137c4a0d46dfcc22b964d6d23f1b16c5624b..1fec11589613701253253b2711ac0684363171d0 100644 (file)
@@ -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
index 8f8cb9a148613a859d31fa52857e747c68940b22..feb1d78bd63132a003437511fc0b8a36df4a3fd6 100644 (file)
@@ -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
  *