Merge branch 'feature/support_lp_i2c_in_drv' into 'master'

feat(i2c_master): Add feature for support using lp_i2c in i2c_master driver

See merge request espressif/esp-idf!29907
pull/13660/head
C.S.M 2024-04-07 19:27:04 +08:00
commit 6224fca8a0
42 zmienionych plików z 501 dodań i 73 usunięć

Wyświetl plik

@ -129,13 +129,13 @@ static const char *I2C_TAG = "i2c";
/**
* I2C bus are defined in the header files, let's check that the values are correct
*/
#if SOC_I2C_NUM >= 2
#if SOC_HP_I2C_NUM >= 2
_Static_assert(I2C_NUM_1 == 1, "I2C_NUM_1 must be equal to 1");
#endif // SOC_I2C_NUM >= 2
#endif // SOC_HP_I2C_NUM >= 2
#if SOC_LP_I2C_SUPPORTED
_Static_assert(I2C_NUM_MAX == (SOC_I2C_NUM + SOC_LP_I2C_NUM), "I2C_NUM_MAX must be equal to SOC_I2C_NUM + SOC_LP_I2C_NUM");
_Static_assert(I2C_NUM_MAX == (SOC_HP_I2C_NUM + SOC_LP_I2C_NUM), "I2C_NUM_MAX must be equal to SOC_HP_I2C_NUM + SOC_LP_I2C_NUM");
#else
_Static_assert(I2C_NUM_MAX == SOC_I2C_NUM, "I2C_NUM_MAX must be equal to SOC_I2C_NUM");
_Static_assert(I2C_NUM_MAX == SOC_HP_I2C_NUM, "I2C_NUM_MAX must be equal to SOC_HP_I2C_NUM");
#endif /* SOC_LP_I2C_SUPPORTED */
typedef struct {
@ -225,7 +225,7 @@ static i2c_context_t i2c_context[I2C_NUM_MAX] = {
I2C_CONTEX_INIT_DEF(I2C_NUM_0),
/* Now that I2C_NUM_MAX is part of an enum (i2c_port_t), we cannot use
* it anomore in the preprocessor! */
#if SOC_I2C_NUM > 1
#if SOC_HP_I2C_NUM > 1
I2C_CONTEX_INIT_DEF(I2C_NUM_1),
#endif
};

Wyświetl plik

@ -47,11 +47,11 @@
#define READ_BIT I2C_MASTER_READ /*!< I2C master read */
#define ACK_CHECK_EN 0x1 /*!< I2C master will check ack from slave*/
static DRAM_ATTR i2c_dev_t *const I2C[SOC_I2C_NUM] = { &I2C0,
#if SOC_I2C_NUM > 1
&I2C1,
static DRAM_ATTR i2c_dev_t *const I2C[SOC_HP_I2C_NUM] = { &I2C0,
#if SOC_HP_I2C_NUM > 1
&I2C1,
#endif
};
};
#define ACK_VAL 0
#define NACK_VAL 1
@ -503,7 +503,7 @@ static void i2c_slave_repeat_read(void)
TEST_CASE_MULTIPLE_DEVICES("I2C repeat write test", "[i2c][test_env=generic_multi_device][timeout=150]", i2c_master_repeat_write, i2c_slave_repeat_read);
#if SOC_I2C_NUM > 1
#if SOC_HP_I2C_NUM > 1
static void i2c_master_write_test_more_ports(void)
{

Wyświetl plik

@ -27,6 +27,12 @@
#include "esp_clk_tree.h"
#include "clk_ctrl_os.h"
#include "esp_private/gpio.h"
#if SOC_LP_I2C_SUPPORTED
#include "hal/rtc_io_ll.h"
#include "driver/rtc_io.h"
#include "soc/rtc_io_channel.h"
#include "driver/lp_io.h"
#endif
#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
#include "esp_private/sleep_retention.h"
#endif
@ -69,22 +75,38 @@ static esp_err_t s_i2c_bus_handle_acquire(i2c_port_num_t port_num, i2c_bus_handl
bus->port_num = port_num;
bus->spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED;
bus->bus_mode = mode;
bus->is_lp_i2c = (bus->port_num < SOC_HP_I2C_NUM) ? false : true;
#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && !CONFIG_IDF_TARGET_ESP32P4 // TODO: IDF-9353
sleep_retention_module_init_param_t init_param = {
.cbs = { .create = { .handle = s_i2c_sleep_retention_init, .arg = (void *)bus } }
};
ret = sleep_retention_module_init(I2C_SLEEP_RETENTION_MODULE(port_num), &init_param);
if (ret == ESP_OK) {
sleep_retention_module_allocate(I2C_SLEEP_RETENTION_MODULE(port_num));
if (bus->is_lp_i2c == false) {
sleep_retention_module_init_param_t init_param = {
.cbs = { .create = { .handle = s_i2c_sleep_retention_init, .arg = (void *)bus } }
};
ret = sleep_retention_module_init(I2C_SLEEP_RETENTION_MODULE(port_num), &init_param);
if (ret == ESP_OK) {
sleep_retention_module_allocate(I2C_SLEEP_RETENTION_MODULE(port_num));
}
} else {
ESP_LOGW(TAG, "Detected PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP is enabled while LP_I2C is used. Sleep retention is not supported on LP I2C. Please use it properly");
}
#endif
// Enable the I2C module
I2C_RCC_ATOMIC() {
i2c_ll_enable_bus_clock(bus->port_num, true);
i2c_ll_reset_register(bus->port_num);
if (!bus->is_lp_i2c) {
I2C_RCC_ATOMIC() {
i2c_ll_enable_bus_clock(bus->port_num, true);
i2c_ll_reset_register(bus->port_num);
}
}
#if SOC_LP_I2C_SUPPORTED
else {
LP_I2C_BUS_CLK_ATOMIC() {
lp_i2c_ll_enable_bus_clock(bus->port_num - SOC_HP_I2C_NUM, true);
lp_i2c_ll_reset_register(bus->port_num - SOC_HP_I2C_NUM);
}
}
#endif
I2C_CLOCK_SRC_ATOMIC() {
i2c_hal_init(&bus->hal, port_num);
}
@ -117,7 +139,7 @@ esp_err_t i2c_acquire_bus_handle(i2c_port_num_t port_num, i2c_bus_handle_t *i2c_
esp_err_t ret = ESP_OK;
_lock_acquire(&s_i2c_platform.mutex);
if (port_num == -1) {
for (int i = 0; i < SOC_I2C_NUM; i++) {
for (int i = 0; i < SOC_HP_I2C_NUM; i++) {
bus_occupied = i2c_bus_occupied(i);
if (bus_occupied == false) {
ret = s_i2c_bus_handle_acquire(i, i2c_new_bus, mode);
@ -154,9 +176,11 @@ esp_err_t i2c_release_bus_handle(i2c_bus_handle_t i2c_bus)
do_deinitialize = true;
s_i2c_platform.buses[port_num] = NULL;
#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && !CONFIG_IDF_TARGET_ESP32P4 // TODO: IDF-9353
esp_err_t err = sleep_retention_module_free(I2C_SLEEP_RETENTION_MODULE(port_num));
if (err == ESP_OK) {
err = sleep_retention_module_deinit(I2C_SLEEP_RETENTION_MODULE(port_num));
if (i2c_bus->is_lp_i2c == false) {
esp_err_t err = sleep_retention_module_free(I2C_SLEEP_RETENTION_MODULE(port_num));
if (err == ESP_OK) {
err = sleep_retention_module_deinit(I2C_SLEEP_RETENTION_MODULE(port_num));
}
}
#endif
if (i2c_bus->intr_handle) {
@ -166,9 +190,18 @@ esp_err_t i2c_release_bus_handle(i2c_bus_handle_t i2c_bus)
ESP_RETURN_ON_ERROR(esp_pm_lock_delete(i2c_bus->pm_lock), TAG, "delete pm_lock failed");
}
// Disable I2C module
I2C_RCC_ATOMIC() {
i2c_ll_enable_bus_clock(port_num, false);
if (!i2c_bus->is_lp_i2c) {
I2C_RCC_ATOMIC() {
i2c_ll_enable_bus_clock(port_num, false);
}
}
#if SOC_LP_I2C_SUPPORTED
else {
LP_I2C_BUS_CLK_ATOMIC() {
lp_i2c_ll_enable_bus_clock(port_num - SOC_HP_I2C_NUM, false);
}
}
#endif
free(i2c_bus);
}
}
@ -192,7 +225,7 @@ esp_err_t i2c_release_bus_handle(i2c_bus_handle_t i2c_bus)
return ESP_OK;
}
esp_err_t i2c_select_periph_clock(i2c_bus_handle_t handle, i2c_clock_source_t clk_src)
esp_err_t i2c_select_periph_clock(i2c_bus_handle_t handle, soc_module_clk_t clk_src)
{
esp_err_t ret = ESP_OK;
ESP_RETURN_ON_FALSE(handle, ESP_ERR_INVALID_ARG, TAG, "I2C empty controller handle");
@ -211,7 +244,7 @@ esp_err_t i2c_select_periph_clock(i2c_bus_handle_t handle, i2c_clock_source_t cl
// TODO: [clk_tree] to use a generic clock enable/disable or acquire/release function for all clock source
#if SOC_I2C_SUPPORT_RTC
if (clk_src == I2C_CLK_SRC_RC_FAST) {
if (clk_src == (soc_module_clk_t)I2C_CLK_SRC_RC_FAST) {
// RC_FAST clock is not enabled automatically on start up, we enable it here manually.
// Note there's a ref count in the enable/disable function, we must call them in pair in the driver.
periph_rtc_dig_clk8m_enable();
@ -229,19 +262,24 @@ esp_err_t i2c_select_periph_clock(i2c_bus_handle_t handle, i2c_clock_source_t cl
esp_pm_lock_type_t pm_lock_type = ESP_PM_NO_LIGHT_SLEEP;
#if SOC_I2C_SUPPORT_RTC
if (clk_src == I2C_CLK_SRC_RC_FAST) {
if (clk_src == (soc_module_clk_t)I2C_CLK_SRC_RC_FAST) {
// I2C use fifo, which connected to APB, so we cannot use I2C either when in light sleep.
need_pm_lock = ESP_PM_NO_LIGHT_SLEEP;
pm_lock_type = ESP_PM_NO_LIGHT_SLEEP;
}
#endif // SOC_I2C_SUPPORT_RTC
#if SOC_I2C_SUPPORT_APB
if (clk_src == I2C_CLK_SRC_APB) {
if (clk_src == (soc_module_clk_t)I2C_CLK_SRC_APB) {
// APB clock frequency can be changed during DFS
pm_lock_type = ESP_PM_APB_FREQ_MAX;
}
#endif // SOC_I2C_SUPPORT_APB
if (handle->is_lp_i2c) {
// Even for LP I2C, the clock will also be powered down when going into light sleep.
pm_lock_type = ESP_PM_NO_LIGHT_SLEEP;
}
if (need_pm_lock) {
sprintf(handle->pm_lock_name, "I2C_%d", handle->port_num); // e.g. PORT_0
ret = esp_pm_lock_create(pm_lock_type, 0, handle->pm_lock_name, &handle->pm_lock);
@ -253,10 +291,8 @@ esp_err_t i2c_select_periph_clock(i2c_bus_handle_t handle, i2c_clock_source_t cl
return ret;
}
esp_err_t i2c_common_set_pins(i2c_bus_handle_t handle)
static esp_err_t s_hp_i2c_pins_config(i2c_bus_handle_t handle)
{
esp_err_t ret = ESP_OK;
ESP_RETURN_ON_FALSE(handle, ESP_ERR_INVALID_ARG, TAG, "I2C empty controller handle");
int port_id = handle->port_num;
// SDA pin configurations
@ -286,5 +322,71 @@ esp_err_t i2c_common_set_pins(i2c_bus_handle_t handle)
gpio_func_sel(handle->scl_num, PIN_FUNC_GPIO);
esp_rom_gpio_connect_out_signal(handle->scl_num, i2c_periph_signal[port_id].scl_out_sig, 0, 0);
esp_rom_gpio_connect_in_signal(handle->scl_num, i2c_periph_signal[port_id].scl_in_sig, 0);
return ESP_OK;
}
#if SOC_LP_I2C_SUPPORTED
static esp_err_t s_lp_i2c_pins_config(i2c_bus_handle_t handle)
{
ESP_RETURN_ON_ERROR(!rtc_gpio_is_valid_gpio(handle->sda_num), TAG, "LP I2C SDA GPIO invalid");
ESP_RETURN_ON_ERROR(!rtc_gpio_is_valid_gpio(handle->scl_num), TAG, "LP I2C SCL GPIO invalid");
#if !SOC_LP_GPIO_MATRIX_SUPPORTED
/* Verify that the SDA and SCL line belong to the LP IO Mux I2C function group */
ESP_RETURN_ON_FALSE((handle->sda_num == LP_I2C_SDA_IOMUX_PAD), ESP_ERR_INVALID_ARG, TAG, LP_I2C_SDA_PIN_ERR_LOG);
ESP_RETURN_ON_FALSE((handle->scl_num == LP_I2C_SCL_IOMUX_PAD), ESP_ERR_INVALID_ARG, TAG, LP_I2C_SCL_PIN_ERR_LOG);
#endif /* !SOC_LP_GPIO_MATRIX_SUPPORTED */
int port_id = handle->port_num;
rtc_gpio_init(handle->sda_num);
rtc_gpio_set_direction(handle->sda_num, RTC_GPIO_MODE_INPUT_OUTPUT_OD);
rtc_gpio_pulldown_dis(handle->sda_num);
if (handle->pull_up_enable) {
rtc_gpio_pullup_en(handle->sda_num);
} else {
rtc_gpio_pullup_dis(handle->sda_num);
}
#if !SOC_LP_GPIO_MATRIX_SUPPORTED
rtc_gpio_iomux_func_sel(handle->sda_num, i2c_periph_signal[port_id].iomux_func);
#else
lp_gpio_connect_out_signal(handle->sda_num, i2c_periph_signal[port_id].scl_out_sig, 0, 0);
lp_gpio_connect_in_signal(handle->sda_num, i2c_periph_signal[port_id].scl_in_sig, 0);
#endif
rtc_gpio_init(handle->scl_num);
rtc_gpio_set_direction(handle->scl_num, RTC_GPIO_MODE_INPUT_OUTPUT_OD);
rtc_gpio_pulldown_dis(handle->scl_num);
if (handle->pull_up_enable) {
rtc_gpio_pullup_en(handle->scl_num);
} else {
rtc_gpio_pullup_dis(handle->scl_num);
}
#if !SOC_LP_GPIO_MATRIX_SUPPORTED
rtc_gpio_iomux_func_sel(handle->scl_num, i2c_periph_signal[port_id].iomux_func);
#else
lp_gpio_connect_out_signal(handle->scl_num, i2c_periph_signal[port_id].sda_out_sig, 0, 0);
lp_gpio_connect_in_signal(handle->scl_num, i2c_periph_signal[port_id].sda_in_sig, 0);
#endif
return ESP_OK;
}
#endif // SOC_LP_I2C_SUPPORTED
esp_err_t i2c_common_set_pins(i2c_bus_handle_t handle)
{
esp_err_t ret = ESP_OK;
if (handle->is_lp_i2c == false) {
ESP_RETURN_ON_ERROR(s_hp_i2c_pins_config(handle), TAG, "config i2c pins failed");
}
#if SOC_LP_I2C_SUPPORTED
else {
ESP_RETURN_ON_ERROR(s_lp_i2c_pins_config(handle), TAG, "config i2c lp pins failed");
}
#endif
return ret;
}

Wyświetl plik

@ -40,6 +40,12 @@ static const char *TAG = "i2c.master";
#define I2C_ADDRESS_TRANS_WRITE(device_address) (((device_address) << 1) | 0)
#define I2C_ADDRESS_TRANS_READ(device_address) (((device_address) << 1) | 1)
#if SOC_LP_I2C_SUPPORTED
#define I2C_FIFO_LEN(port_num) (((port_num) < SOC_HP_I2C_NUM) ? SOC_I2C_FIFO_LEN : SOC_LP_I2C_FIFO_LEN)
#else
#define I2C_FIFO_LEN(port_num) (SOC_I2C_FIFO_LEN)
#endif
static esp_err_t s_i2c_master_clear_bus(i2c_bus_handle_t handle)
{
#if !SOC_I2C_SUPPORT_HW_CLR_BUS
@ -136,7 +142,7 @@ static bool s_i2c_write_command(i2c_master_bus_handle_t i2c_master, i2c_operatio
uint8_t data_fill = 0;
// data_fill refers to the length to fill the data
data_fill = MIN(remaining_bytes, SOC_I2C_FIFO_LEN - *address_fill);
data_fill = MIN(remaining_bytes, I2C_FIFO_LEN(i2c_master->base->port_num) - *address_fill);
write_pr = i2c_operation->data + i2c_operation->bytes_used;
i2c_operation->bytes_used += data_fill;
hw_cmd.byte_num = data_fill + *address_fill;
@ -216,13 +222,13 @@ static bool s_i2c_read_command(i2c_master_bus_handle_t i2c_master, i2c_operation
i2c_bus_handle_t handle = i2c_master->base;
i2c_ll_hw_cmd_t hw_cmd = i2c_operation->hw_cmd;
*fifo_fill = MIN(remaining_bytes, SOC_I2C_FIFO_LEN - i2c_master->read_len_static);
*fifo_fill = MIN(remaining_bytes, I2C_FIFO_LEN(i2c_master->base->port_num) - i2c_master->read_len_static);
i2c_master->rx_cnt = *fifo_fill;
hw_cmd.byte_num = *fifo_fill;
i2c_master->contains_read = true;
#if !SOC_I2C_STOP_INDEPENDENT
if (remaining_bytes < SOC_I2C_FIFO_LEN - 1) {
if (remaining_bytes < I2C_FIFO_LEN(i2c_master->base->port_num) - 1) {
if (i2c_operation->hw_cmd.ack_val == ACK_VAL) {
if (remaining_bytes != 0) {
i2c_ll_master_write_cmd_reg(hal->dev, hw_cmd, i2c_master->cmd_idx);
@ -531,8 +537,20 @@ static esp_err_t s_i2c_transaction_start(i2c_master_dev_handle_t i2c_dev, int xf
i2c_master->read_len_static = 0;
i2c_hal_master_set_scl_timeout_val(hal, i2c_dev->scl_wait_us, i2c_master->base->clk_src_freq_hz);
if (!i2c_master->base->is_lp_i2c) {
I2C_CLOCK_SRC_ATOMIC() {
i2c_ll_set_source_clk(hal->dev, i2c_master->base->clk_src);
}
}
#if SOC_LP_I2C_SUPPORTED
else {
LP_I2C_SRC_CLK_ATOMIC() {
lp_i2c_ll_set_source_clk(hal->dev, i2c_master->base->clk_src);
}
}
#endif
I2C_CLOCK_SRC_ATOMIC() {
i2c_ll_set_source_clk(hal->dev, i2c_master->base->clk_src);
i2c_hal_set_bus_timing(hal, i2c_dev->scl_speed_hz, i2c_master->base->clk_src, i2c_master->base->clk_src_freq_hz);
}
i2c_ll_master_set_fractional_divider(hal->dev, 0, 0);
@ -692,7 +710,8 @@ static esp_err_t i2c_param_master_config(i2c_bus_handle_t handle, const i2c_mast
i2c_hal_context_t *hal = &handle->hal;
ESP_RETURN_ON_ERROR(i2c_common_set_pins(handle), TAG, "i2c master set pin failed");
ESP_RETURN_ON_ERROR(i2c_select_periph_clock(handle, i2c_conf->clk_source), TAG, "i2c select clock failed");
soc_module_clk_t clk_source = i2c_conf->clk_source;
ESP_RETURN_ON_ERROR(i2c_select_periph_clock(handle, clk_source), TAG, "i2c select clock failed");
handle->clk_src = i2c_conf->clk_source;
portENTER_CRITICAL(&handle->spinlock);
i2c_hal_master_init(hal);

Wyświetl plik

@ -36,6 +36,11 @@ extern "C" {
#define I2C_RCC_ATOMIC()
#endif
#if SOC_LP_I2C_SUPPORTED
#define LP_I2C_SRC_CLK_ATOMIC() PERIPH_RCC_ATOMIC()
#define LP_I2C_BUS_CLK_ATOMIC() PERIPH_RCC_ATOMIC()
#endif
#if CONFIG_I2C_ISR_IRAM_SAFE
#define I2C_MEM_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT)
#else
@ -100,9 +105,10 @@ typedef struct {
struct i2c_bus_t {
i2c_port_num_t port_num; // Port(Bus) ID, index from 0
bool is_lp_i2c; // true if current port is lp_i2c. false is hp_i2c
portMUX_TYPE spinlock; // To protect pre-group register level concurrency access
i2c_hal_context_t hal; // Hal layer for each port(bus)
i2c_clock_source_t clk_src; // Record the port clock source
soc_module_clk_t clk_src; // Record the port clock source
uint32_t clk_src_freq_hz; // Record the clock source frequency
int sda_num; // SDA pin number
int scl_num; // SCL pin number
@ -232,7 +238,7 @@ esp_err_t i2c_release_bus_handle(i2c_bus_handle_t i2c_bus);
* - ESP_ERR_INVALID_STATE: Set clock source failed because the clk_src is different from other I2C controller
* - ESP_FAIL: Set clock source failed because of other error
*/
esp_err_t i2c_select_periph_clock(i2c_bus_handle_t handle, i2c_clock_source_t clk_src);
esp_err_t i2c_select_periph_clock(i2c_bus_handle_t handle, soc_module_clk_t clk_src);
/**
* @brief Set I2C SCL/SDA pins

Wyświetl plik

@ -188,7 +188,10 @@ esp_err_t i2c_new_slave_device(const i2c_slave_config_t *slave_config, i2c_slave
i2c_slave_dev_t *i2c_slave = NULL;
ESP_RETURN_ON_FALSE(slave_config && ret_handle, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
ESP_RETURN_ON_FALSE(GPIO_IS_VALID_GPIO(slave_config->sda_io_num) && GPIO_IS_VALID_GPIO(slave_config->scl_io_num), ESP_ERR_INVALID_ARG, TAG, "invalid SDA/SCL pin number");
ESP_RETURN_ON_FALSE(slave_config->i2c_port < SOC_I2C_NUM || slave_config->i2c_port == -1, ESP_ERR_INVALID_ARG, TAG, "invalid i2c port number");
#if SOC_LP_I2C_SUPPORTED
ESP_RETURN_ON_FALSE(slave_config->i2c_port != (SOC_I2C_NUM - 1), ESP_ERR_NOT_SUPPORTED, TAG, "LP i2c is not supported in I2C slave");
#endif
ESP_RETURN_ON_FALSE(slave_config->i2c_port < SOC_HP_I2C_NUM || slave_config->i2c_port == -1, ESP_ERR_INVALID_ARG, TAG, "invalid i2c port number");
ESP_RETURN_ON_FALSE((slave_config->send_buf_depth > 0), ESP_ERR_INVALID_ARG, TAG, "invalid SCL speed");
#if SOC_I2C_SLAVE_SUPPORT_BROADCAST
ESP_RETURN_ON_FALSE(((slave_config->addr_bit_len != I2C_ADDR_BIT_LEN_10) || (!slave_config->flags.broadcast_en)), ESP_ERR_INVALID_STATE, TAG, "10bits address cannot used together with broadcast");

Wyświetl plik

@ -19,10 +19,15 @@ extern "C" {
* @brief I2C master bus specific configurations
*/
typedef struct {
i2c_port_num_t i2c_port; /*!< I2C port number, `-1` for auto selecting */
i2c_port_num_t i2c_port; /*!< I2C port number, `-1` for auto selecting, (not include LP I2C instance) */
gpio_num_t sda_io_num; /*!< GPIO number of I2C SDA signal, pulled-up internally */
gpio_num_t scl_io_num; /*!< GPIO number of I2C SCL signal, pulled-up internally */
i2c_clock_source_t clk_source; /*!< Clock source of I2C master bus, channels in the same group must use the same clock source */
union {
i2c_clock_source_t clk_source; /*!< Clock source of I2C master bus */
#if SOC_LP_I2C_SUPPORTED
lp_i2c_clock_source_t lp_source_clk; /*!< LP_UART source clock selection */
#endif
};
uint8_t glitch_ignore_cnt; /*!< If the glitch period on the line is less than this value, it can be filtered out, typically value is 7 (unit: I2C module clock cycle)*/
int intr_priority; /*!< I2C interrupt priority, if set to 0, driver will select the default priority (1,2,3). */
size_t trans_queue_depth; /*!< Depth of internal transfer queue, increase this value can support more transfers pending in the background, only valid in asynchronous transaction. (Typically max_device_num * per_transaction)*/

Wyświetl plik

@ -21,6 +21,10 @@ if(CONFIG_SOC_I2C_SUPPORT_10BIT_ADDR AND CONFIG_SOC_I2C_SUPPORT_SLAVE)
list(APPEND srcs "test_i2c_10bit.c")
endif()
if(CONFIG_SOC_LP_I2C_SUPPORTED)
list(APPEND srcs "test_lp_i2c.c")
endif()
# Only build this file with `CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP` and `CONFIG_IEEE802154_ENABLED` enabled
# Enable `CONFIG_IEEE802154_ENABLED` is for modem domain really power down.
# This reliable can be removed if the sleep retention got finished.

Wyświetl plik

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -25,6 +25,11 @@ extern "C" {
#define I2C_MASTER_SDA_IO 2 /*!< gpio number for I2C master data */
#endif
#if SOC_LP_I2C_SUPPORTED
#define LP_I2C_SCL_IO 7
#define LP_I2C_SDA_IO 6
#endif
#define ESP_SLAVE_ADDR 0x28 /*!< ESP_I2C slave address, you can set any 7bit value */
#define TEST_I2C_PORT 0
#define DATA_LENGTH 100

Wyświetl plik

@ -55,7 +55,7 @@ TEST_CASE("I2C bus install-uninstall test", "[i2c]")
};
i2c_master_bus_handle_t i2c_mst_handle1;
#if SOC_I2C_NUM > 1
#if SOC_HP_I2C_NUM > 1
i2c_master_bus_config_t i2c_mst_config_2 = {
.clk_source = I2C_CLK_SRC_DEFAULT,
.i2c_port = 1,
@ -68,7 +68,7 @@ TEST_CASE("I2C bus install-uninstall test", "[i2c]")
// Install master bus 0
ESP_LOGI(TAG, "Initialize bus0");
TEST_ESP_OK(i2c_new_master_bus(&i2c_mst_config_1, &i2c_mst_handle1));
#if SOC_I2C_NUM > 1
#if SOC_HP_I2C_NUM > 1
// Install master bus 1
ESP_LOGI(TAG, "Initialize bus1");
TEST_ESP_OK(i2c_new_master_bus(&i2c_mst_config_2, &i2c_mst_handle2));
@ -78,7 +78,7 @@ TEST_CASE("I2C bus install-uninstall test", "[i2c]")
TEST_ESP_ERR(ESP_ERR_INVALID_STATE, i2c_new_master_bus(&i2c_mst_config_1, &i2c_mst_handle1));
ESP_LOGI(TAG, "Delete bus0");
TEST_ESP_OK(i2c_del_master_bus(i2c_mst_handle1));
#if SOC_I2C_NUM > 1
#if SOC_HP_I2C_NUM > 1
ESP_LOGI(TAG, "Delete bus1");
TEST_ESP_OK(i2c_del_master_bus(i2c_mst_handle2));
#endif

Wyświetl plik

@ -613,7 +613,7 @@ static void slave_init_for_probe(void)
TEST_CASE_MULTIPLE_DEVICES("I2C master probe slave test", "[i2c][test_env=generic_multi_device][timeout=150]", master_probe_slave, slave_init_for_probe);
#if SOC_I2C_NUM > 1
#if SOC_HP_I2C_NUM > 1
// Now chips with multiple I2C controllers are up to 2, can test more ports when we have more I2C controllers.
static void i2c_master_write_test_more_port(void)
{

Wyświetl plik

@ -0,0 +1,154 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
#include <stdio.h>
#include <string.h>
#include "sdkconfig.h"
#include "unity.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "esp_err.h"
#include "soc/gpio_periph.h"
#include "soc/clk_tree_defs.h"
#include "soc/soc_caps.h"
#include "hal/gpio_hal.h"
#include "hal/uart_ll.h"
#include "esp_private/periph_ctrl.h"
#include "driver/gpio.h"
#include "driver/i2c_master.h"
#include "driver/i2c_slave.h"
#include "esp_rom_gpio.h"
#include "esp_log.h"
#include "test_utils.h"
#include "test_board.h"
#define DATA_LENGTH 100
static QueueHandle_t s_receive_queue;
TEST_CASE("LP I2C initialize on i2c slave", "[i2c]")
{
i2c_slave_config_t i2c_slv_config = {
.addr_bit_len = I2C_ADDR_BIT_LEN_7,
.clk_source = LP_I2C_SCLK_DEFAULT,
.i2c_port = LP_I2C_NUM_0,
.send_buf_depth = 256,
.scl_io_num = LP_I2C_SCL_IO,
.sda_io_num = LP_I2C_SDA_IO,
.slave_addr = 0x58,
};
i2c_slave_dev_handle_t slave_handle;
TEST_ESP_ERR(ESP_ERR_NOT_SUPPORTED, i2c_new_slave_device(&i2c_slv_config, &slave_handle));
}
#if CONFIG_IDF_TARGET_ESP32C6
TEST_CASE("LP I2C initialize with wrong IO", "[i2c]")
{
i2c_master_bus_config_t i2c_mst_config = {
.lp_source_clk = LP_I2C_SCLK_DEFAULT,
.i2c_port = LP_I2C_NUM_0,
.scl_io_num = 5,
.sda_io_num = 6,
.flags.enable_internal_pullup = true,
};
i2c_master_bus_handle_t bus_handle;
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, i2c_new_master_bus(&i2c_mst_config, &bus_handle));
}
#endif
static IRAM_ATTR bool test_i2c_rx_done_callback(i2c_slave_dev_handle_t channel, const i2c_slave_rx_done_event_data_t *edata, void *user_data)
{
BaseType_t high_task_wakeup = pdFALSE;
QueueHandle_t receive_queue = (QueueHandle_t)user_data;
xQueueSendFromISR(receive_queue, edata, &high_task_wakeup);
return high_task_wakeup == pdTRUE;
}
static void lp_i2c_master_write_test(void)
{
uint8_t data_wr[DATA_LENGTH] = { 0 };
int i;
i2c_master_bus_config_t i2c_mst_config = {
.lp_source_clk = LP_I2C_SCLK_DEFAULT,
.i2c_port = LP_I2C_NUM_0,
.scl_io_num = LP_I2C_SCL_IO,
.sda_io_num = LP_I2C_SDA_IO,
.flags.enable_internal_pullup = true,
};
i2c_master_bus_handle_t bus_handle;
TEST_ESP_OK(i2c_new_master_bus(&i2c_mst_config, &bus_handle));
i2c_device_config_t dev_cfg = {
.dev_addr_length = I2C_ADDR_BIT_LEN_7,
.device_address = 0x58,
.scl_speed_hz = 100000,
};
i2c_master_dev_handle_t dev_handle;
TEST_ESP_OK(i2c_master_bus_add_device(bus_handle, &dev_cfg, &dev_handle));
unity_wait_for_signal("i2c slave init finish");
unity_send_signal("master write");
for (i = 0; i < DATA_LENGTH; i++) {
data_wr[i] = i;
}
disp_buf(data_wr, i);
TEST_ESP_OK(i2c_master_transmit(dev_handle, data_wr, DATA_LENGTH, -1));
unity_wait_for_signal("ready to delete");
TEST_ESP_OK(i2c_master_bus_rm_device(dev_handle));
TEST_ESP_OK(i2c_del_master_bus(bus_handle));
}
static void hp_i2c_slave_read_test(void)
{
uint8_t data_rd[DATA_LENGTH] = {0};
i2c_slave_config_t i2c_slv_config = {
.addr_bit_len = I2C_ADDR_BIT_LEN_7,
.clk_source = I2C_CLK_SRC_DEFAULT,
.i2c_port = TEST_I2C_PORT,
.send_buf_depth = 256,
.scl_io_num = LP_I2C_SCL_IO,
.sda_io_num = LP_I2C_SDA_IO,
.slave_addr = 0x58,
};
i2c_slave_dev_handle_t slave_handle;
TEST_ESP_OK(i2c_new_slave_device(&i2c_slv_config, &slave_handle));
s_receive_queue = xQueueCreate(1, sizeof(i2c_slave_rx_done_event_data_t));
i2c_slave_event_callbacks_t cbs = {
.on_recv_done = test_i2c_rx_done_callback,
};
ESP_ERROR_CHECK(i2c_slave_register_event_callbacks(slave_handle, &cbs, s_receive_queue));
i2c_slave_rx_done_event_data_t rx_data;
TEST_ESP_OK(i2c_slave_receive(slave_handle, data_rd, DATA_LENGTH));
unity_send_signal("i2c slave init finish");
unity_wait_for_signal("master write");
xQueueReceive(s_receive_queue, &rx_data, pdMS_TO_TICKS(10000));
disp_buf(data_rd, DATA_LENGTH);
for (int i = 0; i < DATA_LENGTH; i++) {
TEST_ASSERT(data_rd[i] == i);
}
vQueueDelete(s_receive_queue);
unity_send_signal("ready to delete");
TEST_ESP_OK(i2c_del_slave_device(slave_handle));
}
TEST_CASE_MULTIPLE_DEVICES("LP_I2C master write slave test", "[i2c][test_env=generic_multi_device][timeout=150]", lp_i2c_master_write_test, hp_i2c_slave_read_test);

Wyświetl plik

@ -77,6 +77,14 @@ typedef enum {
#define I2C_LL_RESET_SLV_SCL_PULSE_NUM_DEFAULT (9)
#define I2C_LL_SCL_WAIT_US_VAL_DEFAULT (2000) // Approximate value for SCL timeout regs (in us).
// Record for Pins usage logs
#define LP_I2C_SCL_PIN_ERR_LOG "SCL pin can only be configured as GPIO#7"
#define LP_I2C_SDA_PIN_ERR_LOG "SDA pin can only be configured as GPIO#6"
#define LP_I2C_SDA_IOMUX_PAD 6
#define LP_I2C_SCL_IOMUX_PAD 7
// I2C sleep retention module
#define I2C_SLEEP_RETENTION_MODULE(i2c_num) (SLEEP_RETENTION_MODULE_I2C0)
@ -619,7 +627,7 @@ static inline void i2c_ll_get_stop_timing(i2c_dev_t *hw, int *setup_time, int *h
*
* @param hw Beginning address of the peripheral registers
* @param ptr Pointer to data buffer
* @param len Amount of data needs to be writen
* @param len Amount of data needs to be written
*
* @return None.
*/
@ -654,7 +662,7 @@ static inline void i2c_ll_read_rxfifo(i2c_dev_t *hw, uint8_t *ptr, uint8_t len)
* @param hw Beginning address of the peripheral registers
* @param ram_offset Offset value of I2C RAM.
* @param ptr Pointer to data buffer
* @param len Amount of data needs to be writen
* @param len Amount of data needs to be written
*/
static inline void i2c_ll_write_by_nonfifo(i2c_dev_t *hw, uint8_t ram_offset, const uint8_t *ptr, uint8_t len)
{
@ -754,7 +762,7 @@ static inline void i2c_ll_master_clr_bus(i2c_dev_t *hw, uint32_t slave_pulses)
hw->scl_sp_conf.scl_rst_slv_num = slave_pulses;
hw->scl_sp_conf.scl_rst_slv_en = 1;
hw->ctr.conf_upgate = 1;
// hardward will clear scl_rst_slv_en after sending SCL pulses,
// hardware will clear scl_rst_slv_en after sending SCL pulses,
// and we should set conf_upgate bit to synchronize register value.
while (hw->scl_sp_conf.scl_rst_slv_en);
hw->ctr.conf_upgate = 1;
@ -1003,7 +1011,7 @@ typedef enum {
* @brief Configure I2C SCL timing
*
* @param hw Beginning address of the peripheral registers
* @param high_period The I2C SCL hight period (in core clock cycle, hight_period > 2)
* @param high_period The I2C SCL height period (in core clock cycle, hight_period > 2)
* @param low_period The I2C SCL low period (in core clock cycle, low_period > 1)
* @param wait_high_period The I2C SCL wait rising edge period.
*
@ -1191,7 +1199,7 @@ static inline void i2c_ll_slave_disable_rx_it(i2c_dev_t *hw)
* @brief Configure I2C SCL timing
*
* @param hw Beginning address of the peripheral registers
* @param hight_period The I2C SCL hight period (in core clock cycle, hight_period > 2)
* @param hight_period The I2C SCL height period (in core clock cycle, hight_period > 2)
* @param low_period The I2C SCL low period (in core clock cycle, low_period > 1)
*
* @return None.

Wyświetl plik

@ -21,9 +21,9 @@ extern "C" {
*/
typedef enum {
I2C_NUM_0 = 0, /*!< I2C port 0 */
#if SOC_I2C_NUM >= 2
#if SOC_HP_I2C_NUM >= 2
I2C_NUM_1, /*!< I2C port 1 */
#endif /* SOC_I2C_NUM >= 2 */
#endif /* SOC_HP_I2C_NUM >= 2 */
#if SOC_LP_I2C_NUM >= 1
LP_I2C_NUM_0, /*< LP_I2C port 0 */
#endif /* SOC_LP_I2C_NUM >= 1 */
@ -44,9 +44,9 @@ typedef enum {
* @brief Data structure for calculating I2C bus timing.
*/
typedef struct {
uint16_t clkm_div; /*!< I2C core clock devider */
uint16_t clkm_div; /*!< I2C core clock divider */
uint16_t scl_low; /*!< I2C scl low period */
uint16_t scl_high; /*!< I2C scl hight period */
uint16_t scl_high; /*!< I2C scl high period */
uint16_t scl_wait_high; /*!< I2C scl wait_high period */
uint16_t sda_hold; /*!< I2C scl low period */
uint16_t sda_sample; /*!< I2C sda sample time */
@ -103,6 +103,14 @@ typedef enum {
* @brief I2C group clock source
*/
typedef soc_periph_i2c_clk_src_t i2c_clock_source_t;
#if SOC_LP_I2C_SUPPORTED
/**
* @brief LP_UART source clock
*/
typedef soc_periph_lp_i2c_clk_src_t lp_i2c_clock_source_t;
#endif
#else
/**
* @brief Default type

Wyświetl plik

@ -355,6 +355,10 @@ config SOC_I2C_NUM
int
default 2
config SOC_HP_I2C_NUM
int
default 2
config SOC_I2C_FIFO_LEN
int
default 32

Wyświetl plik

@ -193,7 +193,8 @@
/*-------------------------- I2C CAPS ----------------------------------------*/
// ESP32 has 2 I2C
#define SOC_I2C_NUM (2)
#define SOC_I2C_NUM (2U)
#define SOC_HP_I2C_NUM (2)
#define SOC_I2C_FIFO_LEN (32) /*!< I2C hardware FIFO depth */
#define SOC_I2C_CMD_REG_NUM (16) /*!< Number of I2C command registers */

Wyświetl plik

@ -327,6 +327,10 @@ config SOC_I2C_NUM
int
default 1
config SOC_HP_I2C_NUM
int
default 1
config SOC_I2C_FIFO_LEN
int
default 16

Wyświetl plik

@ -148,6 +148,7 @@
/*-------------------------- I2C CAPS ----------------------------------------*/
// ESP32-C2 has 1 I2C
#define SOC_I2C_NUM (1U)
#define SOC_HP_I2C_NUM (1U)
#define SOC_I2C_FIFO_LEN (16) /*!< I2C hardware FIFO depth */
#define SOC_I2C_CMD_REG_NUM (8) /*!< Number of I2C command registers */

Wyświetl plik

@ -419,6 +419,10 @@ config SOC_I2C_NUM
int
default 1
config SOC_HP_I2C_NUM
int
default 1
config SOC_I2C_FIFO_LEN
int
default 32

Wyświetl plik

@ -186,6 +186,7 @@
/*-------------------------- I2C CAPS ----------------------------------------*/
// ESP32-C3 has 1 I2C
#define SOC_I2C_NUM (1U)
#define SOC_HP_I2C_NUM (1U)
#define SOC_I2C_FIFO_LEN (32) /*!< I2C hardware FIFO depth */
#define SOC_I2C_CMD_REG_NUM (8) /*!< Number of I2C command registers */

Wyświetl plik

@ -263,6 +263,10 @@ config SOC_I2C_NUM
int
default 1
config SOC_HP_I2C_NUM
int
default 1
config SOC_I2C_FIFO_LEN
int
default 32

Wyświetl plik

@ -234,7 +234,8 @@
/*-------------------------- I2C CAPS ----------------------------------------*/
// ESP32-C5 has 1 I2C
#define SOC_I2C_NUM (1UL)
#define SOC_I2C_NUM (1U)
#define SOC_HP_I2C_NUM (1U)
#define SOC_I2C_FIFO_LEN (32) /*!< I2C hardware FIFO depth */
#define SOC_I2C_CMD_REG_NUM (8) /*!< Number of I2C command registers */

Wyświetl plik

@ -131,6 +131,10 @@ config SOC_I2C_NUM
int
default 1
config SOC_HP_I2C_NUM
int
default 1
config SOC_LEDC_SUPPORT_PLL_DIV_CLOCK
bool
default y

Wyświetl plik

@ -208,7 +208,7 @@
// Support to hold a single digital I/O when the digital domain is powered off
#define SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP (1)
// The Clock Out singnal is route to the pin by GPIO matrix
// The Clock Out signal is route to the pin by GPIO matrix
// #define SOC_GPIO_CLOCKOUT_BY_GPIO_MATRIX (1)
/*-------------------------- RTCIO CAPS --------------------------------------*/
@ -227,7 +227,8 @@
/*-------------------------- I2C CAPS ----------------------------------------*/
// ESP32-C5 has 1 I2C
#define SOC_I2C_NUM (1UL)
#define SOC_I2C_NUM (1U)
#define SOC_HP_I2C_NUM (1U)
// #define SOC_I2C_FIFO_LEN (32) /*!< I2C hardware FIFO depth */
// #define SOC_I2C_CMD_REG_NUM (8) /*!< Number of I2C command registers */
@ -501,7 +502,7 @@
// #define SOC_PM_SUPPORT_BEACON_WAKEUP (1)
// #define SOC_PM_SUPPORT_BT_WAKEUP (1)
// #define SOC_PM_SUPPORT_EXT1_WAKEUP (1)
// #define SOC_PM_SUPPORT_EXT1_WAKEUP_MODE_PER_PIN (1) /*!<Supports one bit per pin to configue the EXT1 trigger level */
// #define SOC_PM_SUPPORT_EXT1_WAKEUP_MODE_PER_PIN (1) /*!<Supports one bit per pin to configure the EXT1 trigger level */
#define SOC_PM_SUPPORT_CPU_PD (1)
#define SOC_PM_SUPPORT_MODEM_PD (1)
#define SOC_PM_SUPPORT_XTAL32K_PD (1)

Wyświetl plik

@ -9,6 +9,8 @@
#include "soc/regdma.h"
#include "soc/i2c_reg.h"
#define LP_I2C_MUX_FUNC (1)
/*
Bunch of constants for every I2C peripheral: GPIO signals, irqs, hw addr of registers etc
*/
@ -21,6 +23,15 @@ const i2c_signal_conn_t i2c_periph_signal[SOC_I2C_NUM] = {
.irq = ETS_I2C_EXT0_INTR_SOURCE,
.module = PERIPH_I2C0_MODULE,
},
{
.sda_out_sig = 0,
.sda_in_sig = 0,
.scl_out_sig = 0,
.scl_in_sig = 0,
.iomux_func = LP_I2C_MUX_FUNC,
.irq = ETS_LP_I2C_INTR_SOURCE,
.module = PERIPH_LP_I2C0_MODULE,
},
};
// I2C sleep retention entries
@ -48,6 +59,6 @@ static const regdma_entries_config_t i2c0_regs_retention[] = {
.owner = ENTRY(0) | ENTRY(2) }, \
};
const i2c_reg_ctx_link_t i2c_regs_retention[SOC_I2C_NUM] = {
const i2c_reg_ctx_link_t i2c_regs_retention[SOC_HP_I2C_NUM] = {
{i2c0_regs_retention, ARRAY_SIZE(i2c0_regs_retention)},
};

Wyświetl plik

@ -552,6 +552,10 @@ config SOC_DEDIC_PERIPH_ALWAYS_ENABLE
default y
config SOC_I2C_NUM
int
default 2
config SOC_HP_I2C_NUM
int
default 1

Wyświetl plik

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/

Wyświetl plik

@ -233,7 +233,8 @@
/*-------------------------- I2C CAPS ----------------------------------------*/
// ESP32-C6 has 1 I2C
#define SOC_I2C_NUM (1U)
#define SOC_I2C_NUM (2U) // I2C_NUM = HP_I2C + LP_I2C
#define SOC_HP_I2C_NUM (1U)
#define SOC_I2C_FIFO_LEN (32) /*!< I2C hardware FIFO depth */
#define SOC_I2C_CMD_REG_NUM (8) /*!< Number of I2C command registers */

Wyświetl plik

@ -219,6 +219,10 @@ config SOC_I2C_NUM
int
default 1
config SOC_HP_I2C_NUM
int
default 1
config SOC_I2C_FIFO_LEN
int
default 32

Wyświetl plik

@ -233,6 +233,7 @@
/*-------------------------- I2C CAPS ----------------------------------------*/
// ESP32-C61 has 1 I2C
#define SOC_I2C_NUM (1U)
#define SOC_HP_I2C_NUM (1U)
#define SOC_I2C_FIFO_LEN (32) /*!< I2C hardware FIFO depth */
#define SOC_I2C_CMD_REG_NUM (8) /*!< Number of I2C command registers */

Wyświetl plik

@ -72,7 +72,7 @@ static const regdma_entries_config_t i2c1_regs_retention[] = {
.owner = ENTRY(0) | ENTRY(2) }, \
};
const i2c_reg_ctx_link_t i2c_regs_retention[SOC_I2C_NUM] = {
const i2c_reg_ctx_link_t i2c_regs_retention[SOC_HP_I2C_NUM] = {
{i2c0_regs_retention, ARRAY_SIZE(i2c0_regs_retention)},
{i2c1_regs_retention, ARRAY_SIZE(i2c1_regs_retention)},
};

Wyświetl plik

@ -555,6 +555,10 @@ config SOC_I2C_NUM
int
default 2
config SOC_HP_I2C_NUM
int
default 2
config SOC_I2C_FIFO_LEN
int
default 32

Wyświetl plik

@ -236,6 +236,7 @@
/*-------------------------- I2C CAPS ----------------------------------------*/
// ESP32-H2 has 2 I2C
#define SOC_I2C_NUM (2U)
#define SOC_HP_I2C_NUM (2U)
#define SOC_I2C_FIFO_LEN (32) /*!< I2C hardware FIFO depth */
#define SOC_I2C_CMD_REG_NUM (8) /*!< Number of I2C command registers */

Wyświetl plik

@ -1,11 +1,12 @@
/*
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "soc/i2c_periph.h"
#include "soc/gpio_sig_map.h"
#include "soc/lp_gpio_sig_map.h"
/*
Bunch of constants for every I2C peripheral: GPIO signals, irqs, hw addr of registers etc
@ -27,4 +28,12 @@ const i2c_signal_conn_t i2c_periph_signal[SOC_I2C_NUM] = {
.irq = ETS_I2C1_INTR_SOURCE,
.module = PERIPH_I2C1_MODULE,
},
{
.sda_out_sig = LP_I2C_SDA_PAD_OUT_IDX,
.sda_in_sig = LP_I2C_SDA_PAD_IN_IDX,
.scl_out_sig = LP_I2C_SCL_PAD_OUT_IDX,
.scl_in_sig = LP_I2C_SCL_PAD_IN_IDX,
.irq = ETS_LP_I2C_INTR_SOURCE,
.module = PERIPH_LP_I2C0_MODULE,
},
};

Wyświetl plik

@ -600,6 +600,10 @@ config SOC_ANA_CMPR_SUPPORT_ETM
default y
config SOC_I2C_NUM
int
default 3
config SOC_HP_I2C_NUM
int
default 2

Wyświetl plik

@ -256,7 +256,8 @@
/*-------------------------- I2C CAPS ----------------------------------------*/
// ESP32-P4 has 2 I2Cs
#define SOC_I2C_NUM (2U)
#define SOC_I2C_NUM (3U) // I2C_NUM = HP_I2C + LP_I2C
#define SOC_HP_I2C_NUM (2U)
#define SOC_I2C_FIFO_LEN (32) /*!< I2C hardware FIFO depth */
#define SOC_I2C_CMD_REG_NUM (8) /*!< Number of I2C command registers */

Wyświetl plik

@ -423,6 +423,10 @@ config SOC_I2C_NUM
int
default 2
config SOC_HP_I2C_NUM
int
default 2
config SOC_I2C_FIFO_LEN
int
default 32

Wyświetl plik

@ -189,7 +189,8 @@
/*-------------------------- I2C CAPS ----------------------------------------*/
// ESP32-S2 has 2 I2C
#define SOC_I2C_NUM (2)
#define SOC_I2C_NUM (2U)
#define SOC_HP_I2C_NUM (2U)
#define SOC_I2C_FIFO_LEN (32) /*!< I2C hardware FIFO depth */
#define SOC_I2C_CMD_REG_NUM (16) /*!< Number of I2C command registers */

Wyświetl plik

@ -491,6 +491,10 @@ config SOC_I2C_NUM
int
default 2
config SOC_HP_I2C_NUM
int
default 2
config SOC_I2C_FIFO_LEN
int
default 32

Wyświetl plik

@ -195,7 +195,8 @@
/*-------------------------- I2C CAPS ----------------------------------------*/
// ESP32-S3 has 2 I2C
#define SOC_I2C_NUM (2)
#define SOC_I2C_NUM (2U)
#define SOC_HP_I2C_NUM (2U)
#define SOC_I2C_FIFO_LEN (32) /*!< I2C hardware FIFO depth */
#define SOC_I2C_CMD_REG_NUM (8) /*!< Number of I2C command registers */

Wyświetl plik

@ -25,6 +25,7 @@ typedef struct {
const uint8_t sda_in_sig;
const uint8_t scl_out_sig;
const uint8_t scl_in_sig;
const uint8_t iomux_func;
const uint8_t irq;
const periph_module_t module;
} i2c_signal_conn_t;
@ -37,7 +38,7 @@ typedef struct {
uint32_t link_num;
} i2c_reg_ctx_link_t;
extern const i2c_reg_ctx_link_t i2c_regs_retention[SOC_I2C_NUM];
extern const i2c_reg_ctx_link_t i2c_regs_retention[SOC_HP_I2C_NUM];
#endif
#endif // SOC_I2C_SUPPORTED

Wyświetl plik

@ -6,7 +6,13 @@ Introduction
I2C is a serial, synchronous, multi-device, half-duplex communication protocol that allows co-existence of multiple masters and slaves on the same bus. I2C uses two bidirectional open-drain lines: serial data line (SDA) and serial clock line (SCL), pulled up by resistors.
{IDF_TARGET_NAME} has {IDF_TARGET_SOC_I2C_NUM} I2C controller (also called port), responsible for handling communication on the I2C bus. A single I2C controller can be a master or a slave.
{IDF_TARGET_NAME} has {IDF_TARGET_SOC_HP_I2C_NUM} I2C controller (also called port), responsible for handling communication on the I2C bus. A single I2C controller can be a master or a slave.
.. only:: SOC_LP_I2C_SUPPORTED
Additionally, the {IDF_TARGET_NAME} chip has 1 low-power (LP) I2C controller. It is the cut-down version of regular I2C. Usually, the LP I2C controller only support basic I2C functionality with a much smaller RAM size, and does not support slave mode. For a full list of difference between HP I2C and LP I2C, please refer to the *{IDF_TARGET_NAME} Technical Reference Manual* > *I2C Controller (I2C)* > *Features* [`PDF <{IDF_TARGET_TRM_EN_URL}#i2c>`__].
You can use LP I2C peripheral when HP I2C is not sufficient for users' usage. But please note again the LP I2C does not support all HP I2C functions. Please read docs before you use it.
Typically, an I2C slave device has a 7-bit address or 10-bit address. {IDF_TARGET_NAME} supports both I2C Standard-mode (Sm) and Fast-mode (Fm) which can go up to 100KHz and 400KHz respectively.
@ -134,6 +140,38 @@ Once the :cpp:type:`i2c_device_config_t` structure is populated with mandatory p
i2c_master_dev_handle_t dev_handle;
ESP_ERROR_CHECK(i2c_master_bus_add_device(bus_handle, &dev_cfg, &dev_handle));
.. only:: SOC_LP_I2C_SUPPORTED
Install I2C master bus with LP I2C Peripheral
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Install I2C master bus with LP I2C peripheral is almost as same as how HP I2C peripheral is installed. However, there are still some difference user should take focus on including IOs, clock sources, i2c port number, etc. Following code will show you how to install I2C master bus with LP_I2C.
.. code:: c
#include "driver/i2c_master.h"
i2c_master_bus_config_t i2c_mst_config = {
.clk_source = LP_I2C_SCLK_DEFAULT, // clock source for LP i2c, might different from HP I2C
.i2c_port = LP_I2C_NUM_0, // Assign to LP I2C port
.scl_io_num = 7, // SCL IO number. Please refer to technical reference manual
.sda_io_num = 6, // SDA IO number. Please refer to technical reference manual
.glitch_ignore_cnt = 7,
.flags.enable_internal_pullup = true,
};
i2c_master_bus_handle_t bus_handle;
ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_mst_config, &bus_handle));
i2c_device_config_t dev_cfg = {
.dev_addr_length = I2C_ADDR_BIT_LEN_7,
.device_address = 0x58,
.scl_speed_hz = 100000,
};
i2c_master_dev_handle_t dev_handle;
ESP_ERROR_CHECK(i2c_master_bus_add_device(bus_handle, &dev_cfg, &dev_handle));
Uninstall I2C master bus and device
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -292,7 +330,7 @@ Simple example for writing and reading from slave:
ESP_ERROR_CHECK(i2c_master_bus_add_device(I2C_PORT_NUM_0, &dev_cfg, &dev_handle));
uint8_t buf[20] = {0x20};
uint8_t buffer[2];
ESP_ERROR_CHECK(i2c_master_transmit_receive(i2c_bus_handle, buf, sizeof(buf), buffer, 2, -1));
ESP_ERROR_CHECK(i2c_master_transmit_receive(dev_handle, buf, sizeof(buf), buffer, 2, -1));
I2C Master Probe
~~~~~~~~~~~~~~~~