mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-06 06:04:33 +02:00
Merge branch 'fix/i2c_clk_26M' into 'master'
I2C: Add the I2C clock tree, and support 26M XTAL on ESP32-C2 Closes IDF-5005, IDF-5415, and IDF-4535 See merge request espressif/esp-idf!19057
This commit is contained in:
@@ -26,6 +26,15 @@
|
||||
#include "esp_rom_gpio.h"
|
||||
#include "esp_rom_sys.h"
|
||||
#include <sys/param.h>
|
||||
#include "soc/clk_tree_defs.h"
|
||||
#if SOC_I2C_SUPPORT_APB || SOC_I2C_SUPPORT_XTAL
|
||||
#include "esp_private/esp_clk.h"
|
||||
#endif
|
||||
#if SOC_I2C_SUPPORT_RTC
|
||||
#include "clk_ctrl_os.h"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
static const char *I2C_TAG = "i2c";
|
||||
|
||||
@@ -94,11 +103,7 @@ 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*/
|
||||
#define I2C_CLOCK_INVALID (-1)
|
||||
|
||||
typedef struct {
|
||||
i2c_hw_cmd_t hw_cmd;
|
||||
@@ -184,7 +189,6 @@ typedef struct {
|
||||
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] = {
|
||||
@@ -194,20 +198,19 @@ static i2c_context_t i2c_context[I2C_NUM_MAX] = {
|
||||
#endif
|
||||
};
|
||||
|
||||
// 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},
|
||||
// i2c clock characteristic, the entry order and numbers MUST be the same as SOC_I2C_CLKS
|
||||
static i2c_clk_alloc_t i2c_clk_alloc[] = {
|
||||
#if SOC_I2C_SUPPORT_APB
|
||||
{0, I2C_CLK_LIMIT_APB}, /*!< I2C APB clock characteristic*/
|
||||
{0}, /*!< I2C APB clock characteristic*/
|
||||
#endif
|
||||
#if SOC_I2C_SUPPORT_XTAL
|
||||
{0, I2C_CLK_LIMIT_XTAL}, /*!< I2C XTAL characteristic*/
|
||||
{0}, /*!< I2C XTAL characteristic*/
|
||||
#endif
|
||||
#if SOC_I2C_SUPPORT_RTC
|
||||
{I2C_SCLK_SRC_FLAG_LIGHT_SLEEP | I2C_SCLK_SRC_FLAG_AWARE_DFS, I2C_CLK_LIMIT_RTC}, /*!< I2C 20M RTC characteristic*/
|
||||
{I2C_SCLK_SRC_FLAG_LIGHT_SLEEP | I2C_SCLK_SRC_FLAG_AWARE_DFS}, /*!< I2C 20M RTC characteristic*/
|
||||
#endif
|
||||
#if SOC_I2C_SUPPORT_REF_TICK
|
||||
{I2C_SCLK_SRC_FLAG_AWARE_DFS, I2C_CLK_LIMIT_REF_TICK}, /*!< I2C REF_TICK characteristic*/
|
||||
{I2C_SCLK_SRC_FLAG_AWARE_DFS}, /*!< I2C REF_TICK characteristic*/
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -678,48 +681,76 @@ 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 uint32_t clk_flags, const uint32_t clk_speed)
|
||||
static uint32_t s_get_src_clk_freq(i2c_clock_source_t clk_src)
|
||||
{
|
||||
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;
|
||||
}
|
||||
// TODO: replace the following switch table by clk_tree API
|
||||
uint32_t periph_src_clk_hz = 0;
|
||||
switch (clk_src) {
|
||||
#if SOC_I2C_SUPPORT_APB
|
||||
case I2C_CLK_SRC_APB:
|
||||
periph_src_clk_hz = esp_clk_apb_freq();
|
||||
break;
|
||||
#endif
|
||||
if ( ((clk_flags & i2c_clk_alloc[clk].character) == clk_flags) &&
|
||||
(clk_speed <= i2c_clk_alloc[clk].clk_freq) ) {
|
||||
return clk;
|
||||
#if SOC_I2C_SUPPORT_XTAL
|
||||
case I2C_CLK_SRC_XTAL:
|
||||
periph_src_clk_hz = esp_clk_xtal_freq();
|
||||
break;
|
||||
#endif
|
||||
#if SOC_I2C_SUPPORT_RTC
|
||||
case I2C_CLK_SRC_RC_FAST:
|
||||
periph_rtc_dig_clk8m_enable();
|
||||
periph_src_clk_hz = periph_rtc_dig_clk8m_get_freq();
|
||||
break;
|
||||
#endif
|
||||
#if SOC_I2C_SUPPORT_REF_TICK
|
||||
case RMT_CLK_SRC_REF_TICK:
|
||||
periph_src_clk_hz = REF_CLK_FREQ;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
ESP_RETURN_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, I2C_TAG, "clock source %d is not supported", clk_src);
|
||||
break;
|
||||
}
|
||||
|
||||
return periph_src_clk_hz;
|
||||
}
|
||||
|
||||
static i2c_clock_source_t s_get_clk_src(const uint32_t clk_flags, const uint32_t clk_speed)
|
||||
{
|
||||
i2c_clock_source_t clk_srcs[] = SOC_I2C_CLKS;
|
||||
for (size_t i = 0; i < sizeof(clk_srcs)/ sizeof(clk_srcs[0]); i++) {
|
||||
if ( ((clk_flags & i2c_clk_alloc[i].character) == clk_flags) &&
|
||||
(clk_speed <= (s_get_src_clk_freq(clk_srcs[i]) / 20))) { // I2C SCL clock frequency should not larger than clock source frequency/20
|
||||
return clk_srcs[i];
|
||||
}
|
||||
}
|
||||
return I2C_SCLK_MAX; // flag invalid;
|
||||
return I2C_CLOCK_INVALID; // flag invalid;
|
||||
}
|
||||
|
||||
esp_err_t i2c_param_config(i2c_port_t i2c_num, const i2c_config_t *i2c_conf)
|
||||
{
|
||||
i2c_sclk_t src_clk = I2C_SCLK_DEFAULT;
|
||||
i2c_clock_source_t src_clk = I2C_CLK_SRC_DEFAULT;
|
||||
esp_err_t ret = ESP_OK;
|
||||
|
||||
ESP_RETURN_ON_FALSE(i2c_num < I2C_NUM_MAX, ESP_ERR_INVALID_ARG, I2C_TAG, I2C_NUM_ERROR_STR);
|
||||
ESP_RETURN_ON_FALSE(i2c_conf != NULL, ESP_ERR_INVALID_ARG, I2C_TAG, I2C_ADDR_ERROR_STR);
|
||||
ESP_RETURN_ON_FALSE(i2c_conf->mode < I2C_MODE_MAX, ESP_ERR_INVALID_ARG, I2C_TAG, I2C_MODE_ERR_STR);
|
||||
|
||||
if (i2c_conf->mode == I2C_MODE_MASTER) {
|
||||
src_clk = i2c_get_clk_src(i2c_conf->clk_flags, i2c_conf->master.clk_speed);
|
||||
ESP_RETURN_ON_FALSE(src_clk != I2C_SCLK_MAX, ESP_ERR_INVALID_ARG, I2C_TAG, I2C_CLK_FLAG_ERR_STR);
|
||||
src_clk = s_get_clk_src(i2c_conf->clk_flags, i2c_conf->master.clk_speed);
|
||||
}
|
||||
#if SOC_I2C_SUPPORT_SLAVE
|
||||
else {
|
||||
#if SOC_I2C_SUPPORT_REF_TICK
|
||||
/* On ESP32-S2, APB clock shall always be used in slave mode as the
|
||||
* other one, I2C_SCLK_REF_TICK, is too slow, even for sampling a
|
||||
* other one, I2C_CLK_SRC_REF_TICK, is too slow, even for sampling a
|
||||
* 100KHz SCL. */
|
||||
src_clk = I2C_SCLK_APB;
|
||||
src_clk = I2C_CLK_SRC_APB;
|
||||
#else
|
||||
src_clk = i2c_get_clk_src(i2c_conf->clk_flags, i2c_conf->slave.maximum_speed);
|
||||
ESP_RETURN_ON_FALSE(src_clk != I2C_SCLK_MAX, ESP_ERR_INVALID_ARG, I2C_TAG, I2C_CLK_FLAG_ERR_STR);
|
||||
src_clk = s_get_clk_src(i2c_conf->clk_flags, i2c_conf->slave.maximum_speed);
|
||||
#endif // CONFIG_IDF_TARGET_ESP32S2
|
||||
}
|
||||
#endif // SOC_I2C_SUPPORT_SLAVE
|
||||
ESP_RETURN_ON_FALSE(src_clk != I2C_CLOCK_INVALID, ESP_ERR_INVALID_ARG, I2C_TAG, I2C_CLK_FLAG_ERR_STR);
|
||||
|
||||
ret = i2c_set_pin(i2c_num, i2c_conf->sda_io_num, i2c_conf->scl_io_num,
|
||||
i2c_conf->sda_pullup_en, i2c_conf->scl_pullup_en, i2c_conf->mode);
|
||||
@@ -747,7 +778,7 @@ esp_err_t i2c_param_config(i2c_port_t i2c_num, const i2c_config_t *i2c_conf)
|
||||
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, src_clk);
|
||||
i2c_hal_set_bus_timing(&(i2c_context[i2c_num].hal), i2c_conf->master.clk_speed, src_clk, s_get_src_clk_freq(src_clk));
|
||||
}
|
||||
i2c_hal_update_config(&(i2c_context[i2c_num].hal));
|
||||
I2C_EXIT_CRITICAL(&(i2c_context[i2c_num].spinlock));
|
||||
|
@@ -11,6 +11,7 @@
|
||||
#include "hal/misc.h"
|
||||
#include "soc/i2c_periph.h"
|
||||
#include "soc/i2c_struct.h"
|
||||
#include "soc/clk_tree_defs.h"
|
||||
#include "hal/i2c_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -81,8 +82,6 @@ typedef struct {
|
||||
#define I2C_LL_SLAVE_TX_INT (I2C_TXFIFO_EMPTY_INT_ENA_M)
|
||||
// I2C slave RX interrupt bitmap
|
||||
#define I2C_LL_SLAVE_RX_INT (I2C_RXFIFO_FULL_INT_ENA_M | I2C_TRANS_COMPLETE_INT_ENA_M)
|
||||
// I2C source clock frequency
|
||||
#define I2C_LL_CLK_SRC_FREQ(src_clk) (80*1000*1000)
|
||||
// I2C max timeout value
|
||||
#define I2C_LL_MAX_TIMEOUT I2C_TIME_OUT_REG_V
|
||||
|
||||
@@ -791,7 +790,7 @@ static inline void i2c_ll_master_clr_bus(i2c_dev_t *hw)
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void i2c_ll_set_source_clk(i2c_dev_t *hw, i2c_sclk_t src_clk)
|
||||
static inline void i2c_ll_set_source_clk(i2c_dev_t *hw, i2c_clock_source_t src_clk)
|
||||
{
|
||||
;//Not support on ESP32
|
||||
}
|
||||
|
@@ -14,6 +14,7 @@
|
||||
#include "soc/i2c_struct.h"
|
||||
#include "hal/i2c_types.h"
|
||||
#include "soc/rtc_cntl_reg.h"
|
||||
#include "soc/clk_tree_defs.h"
|
||||
#include "esp_rom_sys.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -82,8 +83,6 @@ typedef struct {
|
||||
#define I2C_LL_MASTER_TX_INT (I2C_NACK_INT_ENA_M|I2C_TIME_OUT_INT_ENA_M|I2C_TRANS_COMPLETE_INT_ENA_M|I2C_ARBITRATION_LOST_INT_ENA_M|I2C_END_DETECT_INT_ENA_M)
|
||||
// I2C master RX interrupt bitmap
|
||||
#define I2C_LL_MASTER_RX_INT (I2C_TIME_OUT_INT_ENA_M|I2C_TRANS_COMPLETE_INT_ENA_M|I2C_ARBITRATION_LOST_INT_ENA_M|I2C_END_DETECT_INT_ENA_M)
|
||||
// I2C source clock
|
||||
#define I2C_LL_CLK_SRC_FREQ(src_clk) (((src_clk) == I2C_SCLK_RTC) ? 20*1000*1000 : 40*1000*1000); // Another clock is XTAL clock
|
||||
// delay time after rtc_clk swiching on
|
||||
#define DELAY_RTC_CLK_SWITCH (5)
|
||||
// I2C max timeout value
|
||||
@@ -726,15 +725,10 @@ static inline void i2c_ll_master_clr_bus(i2c_dev_t *hw)
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void i2c_ll_set_source_clk(i2c_dev_t *hw, i2c_sclk_t src_clk)
|
||||
static inline void i2c_ll_set_source_clk(i2c_dev_t *hw, i2c_clock_source_t src_clk)
|
||||
{
|
||||
// rtc_clk needs to switch on.
|
||||
if (src_clk == I2C_SCLK_RTC) {
|
||||
SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M);
|
||||
esp_rom_delay_us(DELAY_RTC_CLK_SWITCH); // TODO: IDF-4535
|
||||
}
|
||||
// src_clk : (1) for RTC_CLK, (0) for XTAL
|
||||
hw->clk_conf.sclk_sel = (src_clk == I2C_SCLK_RTC) ? 1 : 0;
|
||||
hw->clk_conf.sclk_sel = (src_clk == I2C_CLK_SRC_RC_FAST) ? 1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -14,6 +14,7 @@
|
||||
#include "soc/i2c_struct.h"
|
||||
#include "hal/i2c_types.h"
|
||||
#include "soc/rtc_cntl_reg.h"
|
||||
#include "soc/clk_tree_defs.h"
|
||||
#include "esp_rom_sys.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -86,8 +87,6 @@ typedef struct {
|
||||
#define I2C_LL_SLAVE_TX_INT (I2C_TXFIFO_WM_INT_ENA_M)
|
||||
// I2C slave RX interrupt bitmap
|
||||
#define I2C_LL_SLAVE_RX_INT (I2C_RXFIFO_WM_INT_ENA_M | I2C_TRANS_COMPLETE_INT_ENA_M)
|
||||
// I2C source clock
|
||||
#define I2C_LL_CLK_SRC_FREQ(src_clk) (((src_clk) == I2C_SCLK_RTC) ? 20*1000*1000 : 40*1000*1000); // Another clock is XTAL clock
|
||||
// delay time after rtc_clk swiching on
|
||||
#define DELAY_RTC_CLK_SWITCH (5)
|
||||
// I2C max timeout value
|
||||
@@ -817,15 +816,10 @@ static inline void i2c_ll_master_clr_bus(i2c_dev_t *hw)
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void i2c_ll_set_source_clk(i2c_dev_t *hw, i2c_sclk_t src_clk)
|
||||
static inline void i2c_ll_set_source_clk(i2c_dev_t *hw, i2c_clock_source_t src_clk)
|
||||
{
|
||||
// rtc_clk needs to switch on.
|
||||
if (src_clk == I2C_SCLK_RTC) {
|
||||
SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M);
|
||||
esp_rom_delay_us(DELAY_RTC_CLK_SWITCH);
|
||||
}
|
||||
// src_clk : (1) for RTC_CLK, (0) for XTAL
|
||||
hw->clk_conf.sclk_sel = (src_clk == I2C_SCLK_RTC) ? 1 : 0;
|
||||
hw->clk_conf.sclk_sel = (src_clk == I2C_CLK_SRC_RC_FAST) ? 1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -14,6 +14,7 @@
|
||||
#include "soc/i2c_struct.h"
|
||||
#include "hal/i2c_types.h"
|
||||
#include "soc/rtc_cntl_reg.h"
|
||||
#include "soc/clk_tree_defs.h"
|
||||
#include "esp_rom_sys.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -86,8 +87,6 @@ typedef struct {
|
||||
#define I2C_LL_SLAVE_TX_INT (I2C_TXFIFO_WM_INT_ENA_M)
|
||||
// I2C slave RX interrupt bitmap
|
||||
#define I2C_LL_SLAVE_RX_INT (I2C_RXFIFO_WM_INT_ENA_M | I2C_TRANS_COMPLETE_INT_ENA_M)
|
||||
// I2C source clock
|
||||
#define I2C_LL_CLK_SRC_FREQ(src_clk) (((src_clk) == I2C_SCLK_RTC) ? 8*1000*1000 : 32*1000*1000); // Another clock is XTAL clock
|
||||
// delay time after rtc_clk swiching on
|
||||
#define DELAY_RTC_CLK_SWITCH (5)
|
||||
// I2C max timeout value
|
||||
@@ -814,15 +813,10 @@ static inline void i2c_ll_master_clr_bus(i2c_dev_t *hw)
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void i2c_ll_set_source_clk(i2c_dev_t *hw, i2c_sclk_t src_clk)
|
||||
static inline void i2c_ll_set_source_clk(i2c_dev_t *hw, i2c_clock_source_t src_clk)
|
||||
{
|
||||
// rtc_clk needs to switch on.
|
||||
if (src_clk == I2C_SCLK_RTC) {
|
||||
SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M);
|
||||
esp_rom_delay_us(DELAY_RTC_CLK_SWITCH);
|
||||
}
|
||||
// src_clk : (1) for RTC_CLK, (0) for XTAL
|
||||
hw->clk_conf.sclk_sel = (src_clk == I2C_SCLK_RTC) ? 1 : 0;
|
||||
hw->clk_conf.sclk_sel = (src_clk == I2C_CLK_SRC_RC_FAST) ? 1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -9,6 +9,7 @@
|
||||
#pragma once
|
||||
#include "soc/i2c_periph.h"
|
||||
#include "soc/i2c_struct.h"
|
||||
#include "soc/clk_tree_defs.h"
|
||||
#include "hal/i2c_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -80,8 +81,6 @@ typedef struct {
|
||||
#define I2C_LL_SLAVE_TX_INT (I2C_TXFIFO_WM_INT_ENA_M)
|
||||
// I2C slave RX interrupt bitmap
|
||||
#define I2C_LL_SLAVE_RX_INT (I2C_RXFIFO_WM_INT_ENA_M | I2C_TRANS_COMPLETE_INT_ENA_M)
|
||||
// I2C source clock
|
||||
#define I2C_LL_CLK_SRC_FREQ(src_clk) (((src_clk) == I2C_SCLK_REF_TICK) ? 1000*1000 : 80*1000*1000); // Another clock is APB clock
|
||||
// I2C max timeout value
|
||||
#define I2C_LL_MAX_TIMEOUT I2C_TIME_OUT_REG_V
|
||||
/**
|
||||
@@ -781,10 +780,10 @@ static inline void i2c_ll_master_clr_bus(i2c_dev_t *hw)
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void i2c_ll_set_source_clk(i2c_dev_t *hw, i2c_sclk_t src_clk)
|
||||
static inline void i2c_ll_set_source_clk(i2c_dev_t *hw, i2c_clock_source_t 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;
|
||||
hw->ctr.ref_always_on = (src_clk == I2C_CLK_SRC_REF_TICK) ? 0 : 1;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -12,6 +12,7 @@
|
||||
#include "soc/i2c_periph.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#include "soc/i2c_struct.h"
|
||||
#include "soc/clk_tree_defs.h"
|
||||
#include "hal/i2c_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -83,8 +84,6 @@ typedef struct {
|
||||
#define I2C_LL_SLAVE_TX_INT (I2C_TXFIFO_WM_INT_ENA_M)
|
||||
// I2C slave RX interrupt bitmap
|
||||
#define I2C_LL_SLAVE_RX_INT (I2C_RXFIFO_WM_INT_ENA_M | I2C_TRANS_COMPLETE_INT_ENA_M)
|
||||
// I2C source clock
|
||||
#define I2C_LL_CLK_SRC_FREQ(src_clk) (((src_clk) == I2C_SCLK_RTC) ? 8*1000*1000 : 40*1000*1000); // Another clock is XTAL clock
|
||||
// I2C max timeout value
|
||||
#define I2C_LL_MAX_TIMEOUT I2C_TIME_OUT_VALUE_V
|
||||
|
||||
@@ -846,9 +845,9 @@ static inline void i2c_ll_master_clr_bus(i2c_dev_t *hw)
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void i2c_ll_set_source_clk(i2c_dev_t *hw, i2c_sclk_t src_clk)
|
||||
static inline void i2c_ll_set_source_clk(i2c_dev_t *hw, i2c_clock_source_t src_clk)
|
||||
{
|
||||
hw->clk_conf.sclk_sel = (src_clk == I2C_SCLK_RTC) ? 1 : 0;
|
||||
hw->clk_conf.sclk_sel = (src_clk == I2C_CLK_SRC_RC_FAST) ? 1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -165,13 +165,11 @@ void i2c_hal_slave_init(i2c_hal_context_t *hal, int i2c_num)
|
||||
}
|
||||
#endif
|
||||
|
||||
void i2c_hal_set_bus_timing(i2c_hal_context_t *hal, int scl_freq, i2c_sclk_t src_clk)
|
||||
void i2c_hal_set_bus_timing(i2c_hal_context_t *hal, int scl_freq, i2c_clock_source_t src_clk, int source_freq)
|
||||
{
|
||||
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};
|
||||
uint32_t scl_hw_freq = (scl_freq == I2C_CLK_FREQ_MAX) ? (sclk / 20) : (uint32_t)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_cal_bus_clk(source_freq, scl_freq, &clk_cal);
|
||||
i2c_ll_set_bus_timing(hal->dev, &clk_cal);
|
||||
}
|
||||
|
||||
|
@@ -178,7 +178,7 @@ void i2c_hal_slave_handle_event(i2c_hal_context_t *hal, i2c_intr_event_t *event)
|
||||
* the expected SCL frequency.
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
* @param src_clk Source clock to use choosen from `i2c_sclk_t` type
|
||||
* @param src_clk Source clock to use choosen from `i2c_clock_source_t` type
|
||||
*/
|
||||
#define i2c_hal_set_source_clk(hal, src_clk) i2c_ll_set_source_clk((hal)->dev, src_clk)
|
||||
|
||||
@@ -486,11 +486,12 @@ void i2c_hal_get_rxfifo_cnt(i2c_hal_context_t *hal, uint32_t *len);
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
* @param scl_freq The scl frequency to be set
|
||||
* @param src_clk Source clock of I2C
|
||||
* @param src_clk The source clock of I2C
|
||||
* @param source_freq Source clock frequency of I2C
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
void i2c_hal_set_bus_timing(i2c_hal_context_t *hal, int scl_freq, i2c_sclk_t src_clk);
|
||||
void i2c_hal_set_bus_timing(i2c_hal_context_t *hal, int scl_freq, i2c_clock_source_t src_clk, int source_freq);
|
||||
|
||||
/**
|
||||
* @brief Get I2C txFIFO writeable length
|
||||
|
@@ -13,6 +13,7 @@ extern "C" {
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "soc/soc_caps.h"
|
||||
#include "soc/clk_tree_defs.h"
|
||||
|
||||
/**
|
||||
* @brief I2C port number, can be I2C_NUM_0 ~ (I2C_NUM_MAX-1).
|
||||
@@ -52,29 +53,10 @@ typedef enum {
|
||||
} i2c_ack_type_t;
|
||||
|
||||
/**
|
||||
* @brief I2C clock source, sorting from smallest to largest,
|
||||
* place them in order.
|
||||
* This can be expanded in the future use.
|
||||
* @brief I2C group clock source
|
||||
*/
|
||||
typedef enum {
|
||||
I2C_SCLK_DEFAULT = 0, /*!< I2C source clock not selected*/
|
||||
#if SOC_I2C_SUPPORT_APB
|
||||
I2C_SCLK_APB, /*!< I2C source clock from APB, 80M*/
|
||||
#endif
|
||||
#if SOC_I2C_SUPPORT_XTAL
|
||||
I2C_SCLK_XTAL, /*!< I2C source clock from XTAL, 40M */
|
||||
#endif
|
||||
#if SOC_I2C_SUPPORT_RTC
|
||||
I2C_SCLK_RTC, /*!< I2C source clock from 8M RTC, 8M */
|
||||
#endif
|
||||
#if SOC_I2C_SUPPORT_REF_TICK
|
||||
I2C_SCLK_REF_TICK, /*!< I2C source clock from REF_TICK, 1M */
|
||||
#endif
|
||||
I2C_SCLK_MAX,
|
||||
} i2c_sclk_t;
|
||||
typedef soc_periph_i2c_clk_src_t i2c_clock_source_t;
|
||||
|
||||
/// Use the highest speed that is available for the clock source picked by clk_flags
|
||||
#define I2C_CLK_FREQ_MAX (-1)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@@ -257,6 +257,21 @@ typedef enum {
|
||||
I2S_CLK_SRC_APLL = SOC_MOD_CLK_APLL, /*!< Select APLL as the source clock */
|
||||
} soc_periph_i2s_clk_src_t;
|
||||
|
||||
/////////////////////////////////////////////////I2C////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* @brief Array initializer for all supported clock sources of I2C
|
||||
*/
|
||||
#define SOC_I2C_CLKS {SOC_MOD_CLK_APB}
|
||||
|
||||
/**
|
||||
* @brief Type of I2C clock source.
|
||||
*/
|
||||
typedef enum {
|
||||
I2C_CLK_SRC_APB = SOC_MOD_CLK_APB,
|
||||
I2C_CLK_SRC_DEFAULT = SOC_MOD_CLK_APB,
|
||||
} soc_periph_i2c_clk_src_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@@ -174,6 +174,22 @@ typedef enum {
|
||||
UART_SCLK_DEFAULT = SOC_MOD_CLK_PLL_F40M, /*!< UART source clock default choice is PLL_F40M */
|
||||
} soc_periph_uart_clk_src_legacy_t;
|
||||
|
||||
/////////////////////////////////////////////////I2C////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* @brief Array initializer for all supported clock sources of I2C
|
||||
*/
|
||||
#define SOC_I2C_CLKS {SOC_MOD_CLK_XTAL, SOC_MOD_CLK_RC_FAST}
|
||||
|
||||
/**
|
||||
* @brief Type of I2C clock source.
|
||||
*/
|
||||
typedef enum {
|
||||
I2C_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL,
|
||||
I2C_CLK_SRC_RC_FAST = SOC_MOD_CLK_RC_FAST,
|
||||
I2C_CLK_SRC_DEFAULT = SOC_MOD_CLK_XTAL,
|
||||
} soc_periph_i2c_clk_src_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@@ -217,6 +217,22 @@ typedef enum {
|
||||
I2S_CLK_SRC_PLL_160M = SOC_MOD_CLK_PLL_F160M, /*!< Select PLL_F160M as the source clock */
|
||||
} soc_periph_i2s_clk_src_t;
|
||||
|
||||
/////////////////////////////////////////////////I2C////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* @brief Array initializer for all supported clock sources of I2C
|
||||
*/
|
||||
#define SOC_I2C_CLKS {SOC_MOD_CLK_XTAL, SOC_MOD_CLK_RC_FAST}
|
||||
|
||||
/**
|
||||
* @brief Type of I2C clock source.
|
||||
*/
|
||||
typedef enum {
|
||||
I2C_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL,
|
||||
I2C_CLK_SRC_RC_FAST = SOC_MOD_CLK_RC_FAST,
|
||||
I2C_CLK_SRC_DEFAULT = SOC_MOD_CLK_XTAL,
|
||||
} soc_periph_i2c_clk_src_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@@ -222,6 +222,22 @@ typedef enum {
|
||||
I2S_CLK_SRC_PLL_96M = SOC_MOD_CLK_PLL, /*!< Select PLL as the source clock */
|
||||
} soc_periph_i2s_clk_src_t;
|
||||
|
||||
/////////////////////////////////////////////////I2C////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* @brief Array initializer for all supported clock sources of I2C
|
||||
*/
|
||||
#define SOC_I2C_CLKS {SOC_MOD_CLK_XTAL, SOC_MOD_CLK_RC_FAST}
|
||||
|
||||
/**
|
||||
* @brief Type of I2C clock source.
|
||||
*/
|
||||
typedef enum {
|
||||
I2C_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL,
|
||||
I2C_CLK_SRC_RC_FAST = SOC_MOD_CLK_RC_FAST,
|
||||
I2C_CLK_SRC_DEFAULT = SOC_MOD_CLK_XTAL,
|
||||
} soc_periph_i2c_clk_src_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@@ -235,6 +235,22 @@ typedef enum {
|
||||
I2S_CLK_SRC_APLL = SOC_MOD_CLK_APLL, /*!< Select APLL as the source clock */
|
||||
} soc_periph_i2s_clk_src_t;
|
||||
|
||||
/////////////////////////////////////////////////I2C////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* @brief Array initializer for all supported clock sources of I2C
|
||||
*/
|
||||
#define SOC_I2C_CLKS {SOC_MOD_CLK_APB, SOC_MOD_CLK_REF_TICK}
|
||||
|
||||
/**
|
||||
* @brief Type of I2C clock source.
|
||||
*/
|
||||
typedef enum {
|
||||
I2C_CLK_SRC_APB = SOC_MOD_CLK_APB,
|
||||
I2C_CLK_SRC_REF_TICK = SOC_MOD_CLK_REF_TICK,
|
||||
I2C_CLK_SRC_DEFAULT = SOC_MOD_CLK_APB,
|
||||
} soc_periph_i2c_clk_src_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@@ -263,6 +263,22 @@ typedef enum {
|
||||
I2S_CLK_SRC_PLL_160M = SOC_MOD_CLK_PLL_F160M, /*!< Select PLL_F160M as the source clock */
|
||||
} soc_periph_i2s_clk_src_t;
|
||||
|
||||
/////////////////////////////////////////////////I2C////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* @brief Array initializer for all supported clock sources of I2C
|
||||
*/
|
||||
#define SOC_I2C_CLKS {SOC_MOD_CLK_XTAL, SOC_MOD_CLK_RC_FAST}
|
||||
|
||||
/**
|
||||
* @brief Type of I2C clock source.
|
||||
*/
|
||||
typedef enum {
|
||||
I2C_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL,
|
||||
I2C_CLK_SRC_RC_FAST = SOC_MOD_CLK_RC_FAST,
|
||||
I2C_CLK_SRC_DEFAULT = SOC_MOD_CLK_XTAL,
|
||||
} soc_periph_i2c_clk_src_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user