fix(i2c_master): Fix issue that i2c clock got wrong after reset,

Closes https://github.com/espressif/esp-idf/issues/13397
This commit is contained in:
Cao Sen Miao
2024-03-21 13:13:53 +08:00
parent 1f3160cd78
commit c0e5f2b73a
10 changed files with 333 additions and 3 deletions
+38
View File
@@ -148,6 +148,44 @@ static inline void i2c_ll_master_set_fractional_divider(i2c_dev_t *hw, uint8_t d
// Not supported on ESP32
}
/**
* @brief Set fractional divider
*
* @param hw Beginning address of the peripheral registers
* @param div_a The denominator of the frequency divider factor of the i2c function clock
* @param div_b The numerator of the frequency divider factor of the i2c function clock.
*/
static inline void i2c_ll_master_get_fractional_divider(i2c_dev_t *hw, uint32_t *div_a, uint32_t *div_b)
{
// Not supported on ESP32
}
/**
* @brief Get clock configurations from registers
*
* @param hw Beginning address of the peripheral registers
* @param div_num div_num
* @param clk_sel clk_sel
* @param clk_active clk_active
*/
static inline void i2c_ll_master_save_clock_configurations(i2c_dev_t *hw, uint32_t *div_num, uint8_t *clk_sel, uint8_t *clk_active)
{
// Not supported on ESP32
}
/**
* @brief Get clock configurations from registers
*
* @param hw Beginning address of the peripheral registers
* @param div_num div_num
* @param clk_sel clk_sel
* @param clk_active clk_active
*/
static inline void i2c_ll_master_restore_clock_configurations(i2c_dev_t *hw, uint32_t div_num, uint8_t clk_sel, uint8_t clk_active)
{
// Not supported on ESP32
}
/**
* @brief Reset I2C txFIFO
*
@@ -190,6 +190,50 @@ static inline void i2c_ll_master_set_fractional_divider(i2c_dev_t *hw, uint8_t d
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clk_conf, sclk_div_b, div_b);
}
/**
* @brief Set fractional divider
*
* @param hw Beginning address of the peripheral registers
* @param div_a The denominator of the frequency divider factor of the i2c function clock
* @param div_b The numerator of the frequency divider factor of the i2c function clock.
*/
static inline void i2c_ll_master_get_fractional_divider(i2c_dev_t *hw, uint32_t *div_a, uint32_t *div_b)
{
/* Set div_a and div_b to 0, as it's not necessary to use them */
*div_a = hw->clk_conf.sclk_div_a;
*div_b = hw->clk_conf.sclk_div_b;
}
/**
* @brief Get clock configurations from registers
*
* @param hw Beginning address of the peripheral registers
* @param div_num div_num
* @param clk_sel clk_sel
* @param clk_active clk_active
*/
static inline void i2c_ll_master_save_clock_configurations(i2c_dev_t *hw, uint32_t *div_num, uint8_t *clk_sel, uint8_t *clk_active)
{
*div_num = HAL_FORCE_READ_U32_REG_FIELD(hw->clk_conf, sclk_div_num);
*clk_sel = hw->clk_conf.sclk_sel;
*clk_active = hw->clk_conf.sclk_active;
}
/**
* @brief Get clock configurations from registers
*
* @param hw Beginning address of the peripheral registers
* @param div_num div_num
* @param clk_sel clk_sel
* @param clk_active clk_active
*/
static inline void i2c_ll_master_restore_clock_configurations(i2c_dev_t *hw, uint32_t div_num, uint8_t clk_sel, uint8_t clk_active)
{
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clk_conf, sclk_div_num, div_num);
hw->clk_conf.sclk_sel = clk_sel;
hw->clk_conf.sclk_active = clk_active;
}
/**
* @brief Reset I2C txFIFO
*
@@ -204,6 +204,50 @@ static inline void i2c_ll_master_set_fractional_divider(i2c_dev_t *hw, uint8_t d
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clk_conf, sclk_div_b, div_b);
}
/**
* @brief Set fractional divider
*
* @param hw Beginning address of the peripheral registers
* @param div_a The denominator of the frequency divider factor of the i2c function clock
* @param div_b The numerator of the frequency divider factor of the i2c function clock.
*/
static inline void i2c_ll_master_get_fractional_divider(i2c_dev_t *hw, uint32_t *div_a, uint32_t *div_b)
{
/* Set div_a and div_b to 0, as it's not necessary to use them */
*div_a = hw->clk_conf.sclk_div_a;
*div_b = hw->clk_conf.sclk_div_b;
}
/**
* @brief Get clock configurations from registers
*
* @param hw Beginning address of the peripheral registers
* @param div_num div_num
* @param clk_sel clk_sel
* @param clk_active clk_active
*/
static inline void i2c_ll_master_save_clock_configurations(i2c_dev_t *hw, uint32_t *div_num, uint8_t *clk_sel, uint8_t *clk_active)
{
*div_num = HAL_FORCE_READ_U32_REG_FIELD(hw->clk_conf, sclk_div_num);
*clk_sel = hw->clk_conf.sclk_sel;
*clk_active = hw->clk_conf.sclk_active;
}
/**
* @brief Get clock configurations from registers
*
* @param hw Beginning address of the peripheral registers
* @param div_num div_num
* @param clk_sel clk_sel
* @param clk_active clk_active
*/
static inline void i2c_ll_master_restore_clock_configurations(i2c_dev_t *hw, uint32_t div_num, uint8_t clk_sel, uint8_t clk_active)
{
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clk_conf, sclk_div_num, div_num);
hw->clk_conf.sclk_sel = clk_sel;
hw->clk_conf.sclk_active = clk_active;
}
/**
* @brief Reset I2C txFIFO
*
@@ -135,6 +135,45 @@ static inline void i2c_ll_master_set_fractional_divider(i2c_dev_t *hw, uint8_t d
// Not supported on ESP32S2
}
/**
* @brief Set fractional divider
*
* @param hw Beginning address of the peripheral registers
* @param div_a The denominator of the frequency divider factor of the i2c function clock
* @param div_b The numerator of the frequency divider factor of the i2c function clock.
*/
static inline void i2c_ll_master_get_fractional_divider(i2c_dev_t *hw, uint32_t *div_a, uint32_t *div_b)
{
// Not supported on ESP32S2
}
/**
* @brief Get clock configurations from registers
*
* @param hw Beginning address of the peripheral registers
* @param div_num div_num
* @param clk_sel clk_sel
* @param clk_active clk_active
*/
static inline void i2c_ll_master_save_clock_configurations(i2c_dev_t *hw, uint32_t *div_num, uint8_t *clk_sel, uint8_t *clk_active)
{
// Not supported on ESP32S2
}
/**
* @brief Get clock configurations from registers
*
* @param hw Beginning address of the peripheral registers
* @param div_num div_num
* @param clk_sel clk_sel
* @param clk_active clk_active
*/
static inline void i2c_ll_master_restore_clock_configurations(i2c_dev_t *hw, uint32_t div_num, uint8_t clk_sel, uint8_t clk_active)
{
// Not supported on ESP32S2
}
/**
* @brief Reset I2C txFIFO
*
@@ -212,6 +212,50 @@ static inline void i2c_ll_master_set_fractional_divider(i2c_dev_t *hw, uint8_t d
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clk_conf, sclk_div_b, div_b);
}
/**
* @brief Set fractional divider
*
* @param hw Beginning address of the peripheral registers
* @param div_a The denominator of the frequency divider factor of the i2c function clock
* @param div_b The numerator of the frequency divider factor of the i2c function clock.
*/
static inline void i2c_ll_master_get_fractional_divider(i2c_dev_t *hw, uint32_t *div_a, uint32_t *div_b)
{
/* Set div_a and div_b to 0, as it's not necessary to use them */
*div_a = hw->clk_conf.sclk_div_a;
*div_b = hw->clk_conf.sclk_div_b;
}
/**
* @brief Get clock configurations from registers
*
* @param hw Beginning address of the peripheral registers
* @param div_num div_num
* @param clk_sel clk_sel
* @param clk_active clk_active
*/
static inline void i2c_ll_master_save_clock_configurations(i2c_dev_t *hw, uint32_t *div_num, uint8_t *clk_sel, uint8_t *clk_active)
{
*div_num = HAL_FORCE_READ_U32_REG_FIELD(hw->clk_conf, sclk_div_num);
*clk_sel = hw->clk_conf.sclk_sel;
*clk_active = hw->clk_conf.sclk_active;
}
/**
* @brief Get clock configurations from registers
*
* @param hw Beginning address of the peripheral registers
* @param div_num div_num
* @param clk_sel clk_sel
* @param clk_active clk_active
*/
static inline void i2c_ll_master_restore_clock_configurations(i2c_dev_t *hw, uint32_t div_num, uint8_t clk_sel, uint8_t clk_active)
{
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clk_conf, sclk_div_num, div_num);
hw->clk_conf.sclk_sel = clk_sel;
hw->clk_conf.sclk_active = clk_active;
}
/**
* @brief Reset I2C txFIFO
*
+9 -1
View File
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -58,6 +58,8 @@ void _i2c_hal_deinit(i2c_hal_context_t *hal)
hal->dev = NULL;
}
#if !SOC_I2C_SUPPORT_HW_FSM_RST
void i2c_hal_get_timing_config(i2c_hal_context_t *hal, i2c_hal_timing_config_t *timing_config)
{
i2c_ll_get_scl_clk_timing(hal->dev, &timing_config->high_period, &timing_config->low_period, &timing_config->wait_high_period);
@@ -65,6 +67,8 @@ void i2c_hal_get_timing_config(i2c_hal_context_t *hal, i2c_hal_timing_config_t *
i2c_ll_get_stop_timing(hal->dev, &timing_config->stop_setup, &timing_config->stop_hold);
i2c_ll_get_sda_timing(hal->dev, &timing_config->sda_sample, &timing_config->sda_hold);
i2c_ll_get_tout(hal->dev, &timing_config->timeout);
i2c_ll_master_save_clock_configurations(hal->dev, &timing_config->clk_cfg.clk_div.integer, &timing_config->clk_cfg.clk_sel, &timing_config->clk_cfg.clk_active);
i2c_ll_master_get_fractional_divider(hal->dev, &timing_config->clk_cfg.clk_div.numerator, &timing_config->clk_cfg.clk_div.denominator);
}
void i2c_hal_set_timing_config(i2c_hal_context_t *hal, i2c_hal_timing_config_t *timing_config)
@@ -74,8 +78,12 @@ void i2c_hal_set_timing_config(i2c_hal_context_t *hal, i2c_hal_timing_config_t *
i2c_ll_master_set_stop_timing(hal->dev, timing_config->stop_setup, timing_config->stop_hold);
i2c_ll_set_sda_timing(hal->dev, timing_config->sda_sample, timing_config->sda_hold);
i2c_ll_set_tout(hal->dev, timing_config->timeout);
i2c_ll_master_restore_clock_configurations(hal->dev, timing_config->clk_cfg.clk_div.integer, timing_config->clk_cfg.clk_sel, timing_config->clk_cfg.clk_active);
i2c_ll_master_set_fractional_divider(hal->dev, timing_config->clk_cfg.clk_div.numerator, timing_config->clk_cfg.clk_div.denominator);
}
#endif // !SOC_I2C_SUPPORT_HW_FSM_RST
void i2c_hal_master_trans_start(i2c_hal_context_t *hal)
{
i2c_ll_update(hal->dev);
+15 -1
View File
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -33,6 +33,15 @@ typedef struct {
i2c_dev_t *dev;
} i2c_hal_context_t;
/**
* @brief I2C hal clock configurations
*/
typedef struct {
uint8_t clk_sel; // clock select
uint8_t clk_active; // clock active
hal_utils_clk_div_t clk_div; // clock dividers
} i2c_hal_sclk_info_t;
/**
* @brief Timing configuration structure. Used for I2C reset internally.
*/
@@ -47,6 +56,7 @@ typedef struct {
int sda_sample; /*!< high_period time */
int sda_hold; /*!< sda hold time */
int timeout; /*!< timeout value */
i2c_hal_sclk_info_t clk_cfg; /*!< clock configuration */
} i2c_hal_timing_config_t;
#if SOC_I2C_SUPPORT_SLAVE
@@ -160,6 +170,8 @@ void _i2c_hal_deinit(i2c_hal_context_t *hal);
*/
void i2c_hal_master_trans_start(i2c_hal_context_t *hal);
#if !SOC_I2C_SUPPORT_HW_FSM_RST
/**
* @brief Get timing configuration
*
@@ -176,6 +188,8 @@ void i2c_hal_get_timing_config(i2c_hal_context_t *hal, i2c_hal_timing_config_t *
*/
void i2c_hal_set_timing_config(i2c_hal_context_t *hal, i2c_hal_timing_config_t *timing_config);
#endif // !SOC_I2C_SUPPORT_HW_FSM_RST
#endif // #if SOC_I2C_SUPPORTED
#ifdef __cplusplus
+2 -1
View File
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -14,6 +14,7 @@ extern "C" {
#include <stdbool.h>
#include "soc/soc_caps.h"
#include "soc/clk_tree_defs.h"
#include "hal/hal_utils.h"
/**
* @brief I2C port number, can be I2C_NUM_0 ~ (I2C_NUM_MAX-1).