mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-02 11:10:54 +03:00
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:
@@ -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
|
||||
*
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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).
|
||||
|
||||
Reference in New Issue
Block a user