kopia lustrzana https://github.com/espressif/esp-idf
Merge branch 'feature/i2c_sleep' into 'master'
feat(i2c): Support i2c sleep retention on esp32c6/h2 Closes IDF-8458 See merge request espressif/esp-idf!28885pull/13294/head
commit
2302dd5a91
|
@ -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
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
@ -28,6 +28,10 @@
|
||||||
#include "esp_rom_sys.h"
|
#include "esp_rom_sys.h"
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include "soc/clk_tree_defs.h"
|
#include "soc/clk_tree_defs.h"
|
||||||
|
#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
|
||||||
|
#include "esp_private/sleep_retention.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#if SOC_I2C_SUPPORT_APB || SOC_I2C_SUPPORT_XTAL
|
#if SOC_I2C_SUPPORT_APB || SOC_I2C_SUPPORT_XTAL
|
||||||
#include "esp_private/esp_clk.h"
|
#include "esp_private/esp_clk.h"
|
||||||
|
@ -316,6 +320,7 @@ esp_err_t i2c_driver_install(i2c_port_t i2c_num, i2c_mode_t mode, size_t slv_rx_
|
||||||
#if CONFIG_SPIRAM_USE_MALLOC
|
#if CONFIG_SPIRAM_USE_MALLOC
|
||||||
p_i2c->intr_alloc_flags = intr_alloc_flags;
|
p_i2c->intr_alloc_flags = intr_alloc_flags;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if SOC_I2C_SUPPORT_SLAVE
|
#if SOC_I2C_SUPPORT_SLAVE
|
||||||
if (mode == I2C_MODE_SLAVE) {
|
if (mode == I2C_MODE_SLAVE) {
|
||||||
|
|
||||||
|
@ -409,6 +414,11 @@ esp_err_t i2c_driver_install(i2c_port_t i2c_num, i2c_mode_t mode, size_t slv_rx_
|
||||||
i2c_ll_slave_enable_rx_it(i2c_context[i2c_num].hal.dev);
|
i2c_ll_slave_enable_rx_it(i2c_context[i2c_num].hal.dev);
|
||||||
}
|
}
|
||||||
#endif // SOC_I2C_SUPPORT_SLAVE
|
#endif // SOC_I2C_SUPPORT_SLAVE
|
||||||
|
|
||||||
|
#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
|
||||||
|
ret = sleep_retention_entries_create(i2c_regs_retention[i2c_num].link_list, i2c_regs_retention[i2c_num].link_num, REGDMA_LINK_PRI_7, I2C_SLEEP_RETENTION_MODULE(i2c_num));
|
||||||
|
ESP_GOTO_ON_ERROR(ret, err, I2C_TAG, "failed to allocate mem for sleep retention");
|
||||||
|
#endif
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
|
@ -461,6 +471,10 @@ esp_err_t i2c_driver_delete(i2c_port_t i2c_num)
|
||||||
esp_intr_free(p_i2c->intr_handle);
|
esp_intr_free(p_i2c->intr_handle);
|
||||||
p_i2c->intr_handle = NULL;
|
p_i2c->intr_handle = NULL;
|
||||||
|
|
||||||
|
#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
|
||||||
|
sleep_retention_entries_destroy(I2C_SLEEP_RETENTION_MODULE(i2c_num));
|
||||||
|
#endif
|
||||||
|
|
||||||
if (p_i2c->cmd_mux) {
|
if (p_i2c->cmd_mux) {
|
||||||
// Let any command in progress finish.
|
// Let any command in progress finish.
|
||||||
xSemaphoreTake(p_i2c->cmd_mux, portMAX_DELAY);
|
xSemaphoreTake(p_i2c->cmd_mux, portMAX_DELAY);
|
||||||
|
|
|
@ -2,6 +2,13 @@ set(srcs "test_app_main.c"
|
||||||
"test_i2c.c"
|
"test_i2c.c"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# 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.
|
||||||
|
if(CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP AND CONFIG_IEEE802154_ENABLED)
|
||||||
|
list(APPEND srcs "test_legacy_i2c_sleep_retention.c")
|
||||||
|
endif()
|
||||||
|
|
||||||
idf_component_register(SRCS ${srcs}
|
idf_component_register(SRCS ${srcs}
|
||||||
PRIV_REQUIRES unity test_utils driver
|
PRIV_REQUIRES unity test_utils driver ieee802154
|
||||||
WHOLE_ARCHIVE)
|
WHOLE_ARCHIVE)
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
// Some resources are lazy allocated in I2C driver, so we reserved this threshold when checking memory leak
|
// Some resources are lazy allocated in I2C driver, so we reserved this threshold when checking memory leak
|
||||||
// A better way to check a potential memory leak is running a same case by twice, for the second time, the memory usage delta should be zero
|
// A better way to check a potential memory leak is running a same case by twice, for the second time, the memory usage delta should be zero
|
||||||
#define LEAKS (400)
|
#define LEAKS (900)
|
||||||
|
|
||||||
void setUp(void)
|
void setUp(void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,194 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "unity.h"
|
||||||
|
#include "unity_config.h"
|
||||||
|
#include "driver/i2c.h"
|
||||||
|
#include "esp_attr.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "esp_system.h"
|
||||||
|
#include "hal/i2c_types.h"
|
||||||
|
#include "test_utils.h"
|
||||||
|
#include "esp_sleep.h"
|
||||||
|
#include "esp_private/sleep_cpu.h"
|
||||||
|
#include "esp_ieee802154.h"
|
||||||
|
#include "esp_pm.h"
|
||||||
|
|
||||||
|
#define DATA_LENGTH 100 /*!<Data buffer length for test buffer*/
|
||||||
|
|
||||||
|
#define I2C_SLAVE_SCL_IO 4 /*!<gpio number for i2c slave clock */
|
||||||
|
#define I2C_SLAVE_SDA_IO 5 /*!<gpio number for i2c slave data */
|
||||||
|
|
||||||
|
#define I2C_SLAVE_NUM I2C_NUM_0 /*!<I2C port number for slave dev */
|
||||||
|
#define I2C_SLAVE_TX_BUF_LEN (2*DATA_LENGTH) /*!<I2C slave tx buffer size */
|
||||||
|
#define I2C_SLAVE_RX_BUF_LEN (2*DATA_LENGTH) /*!<I2C slave rx buffer size */
|
||||||
|
|
||||||
|
#define I2C_MASTER_SCL_IO 4 /*!<gpio number for i2c master clock */
|
||||||
|
#define I2C_MASTER_SDA_IO 5 /*!<gpio number for i2c master data */
|
||||||
|
|
||||||
|
#define I2C_MASTER_NUM I2C_NUM_0 /*!< I2C port number for master dev */
|
||||||
|
#define I2C_MASTER_TX_BUF_DISABLE 0 /*!< I2C master do not need buffer */
|
||||||
|
#define I2C_MASTER_RX_BUF_DISABLE 0 /*!< I2C master do not need buffer */
|
||||||
|
#define I2C_MASTER_FREQ_HZ 100000 /*!< I2C master clock frequency */
|
||||||
|
|
||||||
|
#define ESP_SLAVE_ADDR 0x28 /*!< ESP32 slave address, you can set any 7bit value */
|
||||||
|
#define WRITE_BIT I2C_MASTER_WRITE /*!< I2C master write */
|
||||||
|
#define ACK_CHECK_EN 0x1 /*!< I2C master will check ack from slave*/
|
||||||
|
|
||||||
|
|
||||||
|
static esp_err_t i2c_master_write_slave(i2c_port_t i2c_num, uint8_t *data_wr, size_t size)
|
||||||
|
{
|
||||||
|
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
||||||
|
i2c_master_start(cmd);
|
||||||
|
TEST_ESP_OK(i2c_master_write_byte(cmd, ( ESP_SLAVE_ADDR << 1 ) | WRITE_BIT, ACK_CHECK_EN));
|
||||||
|
TEST_ESP_OK(i2c_master_write(cmd, data_wr, size, ACK_CHECK_EN));
|
||||||
|
TEST_ESP_OK(i2c_master_stop(cmd));
|
||||||
|
esp_err_t ret = i2c_master_cmd_begin(i2c_num, cmd, 5000 / portTICK_PERIOD_MS);
|
||||||
|
i2c_cmd_link_delete(cmd);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static i2c_config_t i2c_master_init(void)
|
||||||
|
{
|
||||||
|
i2c_config_t conf_master = {
|
||||||
|
.mode = I2C_MODE_MASTER,
|
||||||
|
.sda_pullup_en = GPIO_PULLUP_ENABLE,
|
||||||
|
.scl_pullup_en = GPIO_PULLUP_ENABLE,
|
||||||
|
.master.clk_speed = I2C_MASTER_FREQ_HZ,
|
||||||
|
.sda_io_num = I2C_MASTER_SDA_IO,
|
||||||
|
.scl_io_num = I2C_MASTER_SCL_IO,
|
||||||
|
.clk_flags = 0,
|
||||||
|
};
|
||||||
|
return conf_master;
|
||||||
|
}
|
||||||
|
|
||||||
|
static i2c_config_t i2c_slave_init(void)
|
||||||
|
{
|
||||||
|
i2c_config_t conf_slave = {
|
||||||
|
.mode = I2C_MODE_SLAVE,
|
||||||
|
.sda_io_num = I2C_SLAVE_SDA_IO,
|
||||||
|
.scl_io_num = I2C_SLAVE_SCL_IO,
|
||||||
|
.sda_pullup_en = GPIO_PULLUP_ENABLE,
|
||||||
|
.scl_pullup_en = GPIO_PULLUP_ENABLE,
|
||||||
|
.slave.addr_10bit_en = 0,
|
||||||
|
.slave.slave_addr = ESP_SLAVE_ADDR,
|
||||||
|
};
|
||||||
|
return conf_slave;
|
||||||
|
}
|
||||||
|
|
||||||
|
// print the reading buffer
|
||||||
|
static void disp_buf(uint8_t *buf, int len)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
printf("%02x ", buf[i]);
|
||||||
|
if (( i + 1 ) % 16 == 0) {
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void i2c_master_write_sleep_test(void)
|
||||||
|
{
|
||||||
|
uint8_t *data_wr = (uint8_t *) malloc(DATA_LENGTH);
|
||||||
|
int i;
|
||||||
|
|
||||||
|
i2c_config_t conf_master = i2c_master_init();
|
||||||
|
TEST_ESP_OK(i2c_param_config(I2C_MASTER_NUM, &conf_master));
|
||||||
|
|
||||||
|
TEST_ESP_OK(i2c_driver_install(I2C_MASTER_NUM, I2C_MODE_MASTER,
|
||||||
|
I2C_MASTER_RX_BUF_DISABLE,
|
||||||
|
I2C_MASTER_TX_BUF_DISABLE, 0));
|
||||||
|
unity_wait_for_signal("i2c slave init finish");
|
||||||
|
|
||||||
|
unity_send_signal("master write and sleep");
|
||||||
|
for (i = 0; i < DATA_LENGTH; i++) {
|
||||||
|
data_wr[i] = i;
|
||||||
|
}
|
||||||
|
i2c_master_write_slave(I2C_MASTER_NUM, data_wr, DATA_LENGTH);
|
||||||
|
disp_buf(data_wr, i + 1);
|
||||||
|
|
||||||
|
TEST_ESP_OK(esp_ieee802154_enable());
|
||||||
|
TEST_ESP_OK(sleep_cpu_configure(true));
|
||||||
|
TEST_ESP_OK(esp_sleep_enable_timer_wakeup(3 * 1000 * 1000));
|
||||||
|
TEST_ESP_OK(esp_light_sleep_start());
|
||||||
|
|
||||||
|
printf("Waked up!!\n");
|
||||||
|
unity_wait_for_signal("i2c slave receive once");
|
||||||
|
|
||||||
|
for (i = 0; i < DATA_LENGTH; i++) {
|
||||||
|
data_wr[i] = i;
|
||||||
|
}
|
||||||
|
i2c_master_write_slave(I2C_MASTER_NUM, data_wr, DATA_LENGTH);
|
||||||
|
disp_buf(data_wr, i + 1);
|
||||||
|
unity_send_signal("master write again");
|
||||||
|
|
||||||
|
free(data_wr);
|
||||||
|
unity_wait_for_signal("ready to delete");
|
||||||
|
TEST_ESP_OK(sleep_cpu_configure(false));
|
||||||
|
TEST_ESP_OK(esp_ieee802154_disable());
|
||||||
|
TEST_ESP_OK(i2c_driver_delete(I2C_MASTER_NUM));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void i2c_slave_read_sleep_test(void)
|
||||||
|
{
|
||||||
|
uint8_t *data_rd = (uint8_t *) malloc(DATA_LENGTH);
|
||||||
|
int size_rd = 0;
|
||||||
|
int len = 0;
|
||||||
|
|
||||||
|
i2c_config_t conf_slave = i2c_slave_init();
|
||||||
|
TEST_ESP_OK(i2c_param_config( I2C_SLAVE_NUM, &conf_slave));
|
||||||
|
TEST_ESP_OK(i2c_driver_install(I2C_SLAVE_NUM, I2C_MODE_SLAVE,
|
||||||
|
I2C_SLAVE_RX_BUF_LEN,
|
||||||
|
I2C_SLAVE_TX_BUF_LEN, 0));
|
||||||
|
unity_send_signal("i2c slave init finish");
|
||||||
|
|
||||||
|
unity_wait_for_signal("master write and sleep");
|
||||||
|
while (1) {
|
||||||
|
len = i2c_slave_read_buffer( I2C_SLAVE_NUM, data_rd + size_rd, DATA_LENGTH, 10000 / portTICK_PERIOD_MS);
|
||||||
|
if (len == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
size_rd += len;
|
||||||
|
}
|
||||||
|
disp_buf(data_rd, size_rd);
|
||||||
|
for (int i = 0; i < size_rd; i++) {
|
||||||
|
TEST_ASSERT(data_rd[i] == i);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_ESP_OK(esp_ieee802154_enable());
|
||||||
|
TEST_ESP_OK(sleep_cpu_configure(true));
|
||||||
|
TEST_ESP_OK(esp_sleep_enable_timer_wakeup(1 * 1000 * 1000));
|
||||||
|
TEST_ESP_OK(esp_light_sleep_start());
|
||||||
|
|
||||||
|
unity_send_signal("i2c slave receive once");
|
||||||
|
unity_wait_for_signal("master write again");
|
||||||
|
|
||||||
|
memset(data_rd, 0, DATA_LENGTH);
|
||||||
|
size_rd = 0;
|
||||||
|
while (1) {
|
||||||
|
len = i2c_slave_read_buffer( I2C_SLAVE_NUM, data_rd + size_rd, DATA_LENGTH, 10000 / portTICK_PERIOD_MS);
|
||||||
|
if (len == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
size_rd += len;
|
||||||
|
}
|
||||||
|
disp_buf(data_rd, size_rd);
|
||||||
|
for (int i = 0; i < size_rd; i++) {
|
||||||
|
TEST_ASSERT(data_rd[i] == i);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(data_rd);
|
||||||
|
unity_send_signal("ready to delete");
|
||||||
|
TEST_ESP_OK(sleep_cpu_configure(false));
|
||||||
|
TEST_ESP_OK(esp_ieee802154_disable());
|
||||||
|
TEST_ESP_OK(i2c_driver_delete(I2C_SLAVE_NUM));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE_MULTIPLE_DEVICES("I2C legacy sleep retention test", "[i2c][test_env=generic_multi_device][timeout=250]", i2c_master_write_sleep_test, i2c_slave_read_sleep_test);
|
|
@ -1,6 +1,5 @@
|
||||||
# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
# SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||||
# SPDX-License-Identifier: CC0-1.0
|
# SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from pytest_embedded import Dut
|
from pytest_embedded import Dut
|
||||||
|
|
||||||
|
@ -38,3 +37,19 @@ def test_i2c_multi_dev_legacy(case_tester) -> None: # type: ignore
|
||||||
for case in case_tester.test_menu:
|
for case in case_tester.test_menu:
|
||||||
if case.attributes.get('test_env', 'generic_multi_device') == 'generic_multi_device':
|
if case.attributes.get('test_env', 'generic_multi_device') == 'generic_multi_device':
|
||||||
case_tester.run_multi_dev_case(case=case, reset=True, timeout=120)
|
case_tester.run_multi_dev_case(case=case, reset=True, timeout=120)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.esp32c6
|
||||||
|
@pytest.mark.esp32h2
|
||||||
|
@pytest.mark.generic_multi_device
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
'count, config',
|
||||||
|
[
|
||||||
|
(2, 'sleep_retention',),
|
||||||
|
],
|
||||||
|
indirect=True
|
||||||
|
)
|
||||||
|
def test_i2c_sleep_retention_legacy(case_tester) -> None: # type: ignore
|
||||||
|
for case in case_tester.test_menu:
|
||||||
|
if case.attributes.get('test_env', 'generic_multi_device') == 'generic_multi_device':
|
||||||
|
case_tester.run_multi_dev_case(case=case, reset=True, timeout=250)
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
CONFIG_PM_ENABLE=y
|
||||||
|
CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP=y
|
||||||
|
CONFIG_FREERTOS_USE_TICKLESS_IDLE=y
|
||||||
|
CONFIG_IEEE802154_ENABLED=y
|
||||||
|
CONFIG_IEEE802154_SLEEP_ENABLE=y
|
|
@ -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
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
@ -26,6 +26,9 @@
|
||||||
#include "soc/i2c_periph.h"
|
#include "soc/i2c_periph.h"
|
||||||
#include "esp_clk_tree.h"
|
#include "esp_clk_tree.h"
|
||||||
#include "clk_ctrl_os.h"
|
#include "clk_ctrl_os.h"
|
||||||
|
#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
|
||||||
|
#include "esp_private/sleep_retention.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
static const char *TAG = "i2c.common";
|
static const char *TAG = "i2c.common";
|
||||||
|
|
||||||
|
@ -55,6 +58,11 @@ static esp_err_t s_i2c_bus_handle_aquire(i2c_port_num_t port_num, i2c_bus_handle
|
||||||
bus->spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED;
|
bus->spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED;
|
||||||
bus->bus_mode = mode;
|
bus->bus_mode = mode;
|
||||||
|
|
||||||
|
#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
|
||||||
|
ret = sleep_retention_entries_create(i2c_regs_retention[port_num].link_list, i2c_regs_retention[port_num].link_num, REGDMA_LINK_PRI_7, I2C_SLEEP_RETENTION_MODULE(port_num));
|
||||||
|
ESP_RETURN_ON_ERROR(ret, TAG, "failed to allocate mem for sleep retention");
|
||||||
|
#endif
|
||||||
|
|
||||||
// Enable the I2C module
|
// Enable the I2C module
|
||||||
I2C_RCC_ATOMIC() {
|
I2C_RCC_ATOMIC() {
|
||||||
i2c_ll_enable_bus_clock(bus->port_num, true);
|
i2c_ll_enable_bus_clock(bus->port_num, true);
|
||||||
|
@ -128,6 +136,9 @@ esp_err_t i2c_release_bus_handle(i2c_bus_handle_t i2c_bus)
|
||||||
if (s_i2c_platform.count[port_num] == 0) {
|
if (s_i2c_platform.count[port_num] == 0) {
|
||||||
do_deinitialize = true;
|
do_deinitialize = true;
|
||||||
s_i2c_platform.buses[port_num] = NULL;
|
s_i2c_platform.buses[port_num] = NULL;
|
||||||
|
#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
|
||||||
|
sleep_retention_entries_destroy(I2C_SLEEP_RETENTION_MODULE(port_num));
|
||||||
|
#endif
|
||||||
if (i2c_bus->intr_handle) {
|
if (i2c_bus->intr_handle) {
|
||||||
ESP_RETURN_ON_ERROR(esp_intr_free(i2c_bus->intr_handle), TAG, "delete interrupt service failed");
|
ESP_RETURN_ON_ERROR(esp_intr_free(i2c_bus->intr_handle), TAG, "delete interrupt service failed");
|
||||||
}
|
}
|
||||||
|
|
|
@ -189,7 +189,7 @@ esp_err_t i2c_new_slave_device(const i2c_slave_config_t *slave_config, i2c_slave
|
||||||
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");
|
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");
|
||||||
ESP_RETURN_ON_FALSE((slave_config->send_buf_depth > 0), ESP_ERR_INVALID_ARG, TAG, "invalid SCL speed");
|
ESP_RETURN_ON_FALSE((slave_config->send_buf_depth > 0), ESP_ERR_INVALID_ARG, TAG, "invalid SCL speed");
|
||||||
#if SOC_I2C_SLAVE_SUPPORT_BROADCAST
|
#if SOC_I2C_SLAVE_SUPPORT_BROADCAST
|
||||||
ESP_GOTO_ON_FALSE(((slave_config->addr_bit_len != I2C_ADDR_BIT_LEN_10) || (!slave_config->flags.broadcast_en)), ESP_ERR_INVALID_STATE, err, TAG, "10bits address cannot used together with 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");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int i2c_port_num = slave_config->i2c_port;
|
int i2c_port_num = slave_config->i2c_port;
|
||||||
|
|
|
@ -21,6 +21,13 @@ if(CONFIG_SOC_I2C_SUPPORT_10BIT_ADDR AND CONFIG_SOC_I2C_SUPPORT_SLAVE)
|
||||||
list(APPEND srcs "test_i2c_10bit.c")
|
list(APPEND srcs "test_i2c_10bit.c")
|
||||||
endif()
|
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.
|
||||||
|
if(CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP AND CONFIG_IEEE802154_ENABLED)
|
||||||
|
list(APPEND srcs "test_i2c_sleep_retention.c")
|
||||||
|
endif()
|
||||||
|
|
||||||
idf_component_register(SRCS ${srcs}
|
idf_component_register(SRCS ${srcs}
|
||||||
PRIV_REQUIRES unity driver test_utils
|
PRIV_REQUIRES unity driver test_utils ieee802154
|
||||||
WHOLE_ARCHIVE)
|
WHOLE_ARCHIVE)
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
// Some resources are lazy allocated in I2C driver, so we reserved this threshold when checking memory leak
|
// Some resources are lazy allocated in I2C driver, so we reserved this threshold when checking memory leak
|
||||||
// A better way to check a potential memory leak is running a same case by twice, for the second time, the memory usage delta should be zero
|
// A better way to check a potential memory leak is running a same case by twice, for the second time, the memory usage delta should be zero
|
||||||
#define LEAKS (400)
|
#define LEAKS (1000)
|
||||||
|
|
||||||
void setUp(void)
|
void setUp(void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,159 @@
|
||||||
|
/*
|
||||||
|
* 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/queue.h"
|
||||||
|
#include "esp_err.h"
|
||||||
|
#include "driver/i2c_master.h"
|
||||||
|
#include "driver/i2c_slave.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "test_utils.h"
|
||||||
|
#include "test_board.h"
|
||||||
|
#include "esp_sleep.h"
|
||||||
|
#include "esp_private/sleep_cpu.h"
|
||||||
|
#include "esp_ieee802154.h"
|
||||||
|
#include "esp_pm.h"
|
||||||
|
|
||||||
|
#define DATA_LENGTH 100
|
||||||
|
|
||||||
|
static QueueHandle_t s_receive_queue;
|
||||||
|
|
||||||
|
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 i2c_master_write_sleep_retention_test(void)
|
||||||
|
{
|
||||||
|
uint8_t data_wr[DATA_LENGTH] = { 0 };
|
||||||
|
int i;
|
||||||
|
|
||||||
|
i2c_master_bus_config_t i2c_mst_config = {
|
||||||
|
.clk_source = I2C_CLK_SRC_DEFAULT,
|
||||||
|
.i2c_port = TEST_I2C_PORT,
|
||||||
|
.scl_io_num = I2C_MASTER_SCL_IO,
|
||||||
|
.sda_io_num = I2C_MASTER_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("i2c slave receive once, master to sleep");
|
||||||
|
|
||||||
|
TEST_ESP_OK(esp_ieee802154_enable());
|
||||||
|
TEST_ESP_OK(sleep_cpu_configure(true));
|
||||||
|
TEST_ESP_OK(esp_sleep_enable_timer_wakeup(3 * 1000 * 1000));
|
||||||
|
TEST_ESP_OK(esp_light_sleep_start());
|
||||||
|
|
||||||
|
printf("Waked up!!\n");
|
||||||
|
unity_send_signal("master sleep-wakeup");
|
||||||
|
unity_wait_for_signal("i2c slave receive again");
|
||||||
|
|
||||||
|
for (i = 0; i < DATA_LENGTH; i++) {
|
||||||
|
data_wr[i] = i;
|
||||||
|
}
|
||||||
|
TEST_ESP_OK(i2c_master_transmit(dev_handle, data_wr, DATA_LENGTH, -1));
|
||||||
|
disp_buf(data_wr, i);
|
||||||
|
unity_send_signal("master write again");
|
||||||
|
|
||||||
|
unity_wait_for_signal("ready to delete");
|
||||||
|
TEST_ESP_OK(sleep_cpu_configure(false));
|
||||||
|
TEST_ESP_OK(esp_ieee802154_disable());
|
||||||
|
TEST_ESP_OK(i2c_master_bus_rm_device(dev_handle));
|
||||||
|
|
||||||
|
TEST_ESP_OK(i2c_del_master_bus(bus_handle));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void i2c_slave_read_sleep_retention_test(void)
|
||||||
|
{
|
||||||
|
uint8_t data_rd[DATA_LENGTH] = {0};
|
||||||
|
uint8_t data_rd2[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 = I2C_SLAVE_SCL_IO,
|
||||||
|
.sda_io_num = I2C_SLAVE_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);
|
||||||
|
}
|
||||||
|
|
||||||
|
unity_send_signal("i2c slave receive once, master to sleep");
|
||||||
|
// Slave sleep as well..
|
||||||
|
TEST_ESP_OK(esp_ieee802154_enable());
|
||||||
|
TEST_ESP_OK(sleep_cpu_configure(true));
|
||||||
|
TEST_ESP_OK(esp_sleep_enable_timer_wakeup(1 * 1000 * 1000));
|
||||||
|
TEST_ESP_OK(esp_light_sleep_start());
|
||||||
|
|
||||||
|
unity_wait_for_signal("master sleep-wakeup");
|
||||||
|
|
||||||
|
TEST_ESP_OK(i2c_slave_receive(slave_handle, data_rd2, DATA_LENGTH));
|
||||||
|
unity_send_signal("i2c slave receive again");
|
||||||
|
|
||||||
|
unity_wait_for_signal("master write again");
|
||||||
|
|
||||||
|
xQueueReceive(s_receive_queue, &rx_data, pdMS_TO_TICKS(10000));
|
||||||
|
disp_buf(data_rd2, DATA_LENGTH);
|
||||||
|
for (int i = 0; i < DATA_LENGTH; i++) {
|
||||||
|
TEST_ASSERT(data_rd2[i] == i);
|
||||||
|
}
|
||||||
|
|
||||||
|
vQueueDelete(s_receive_queue);
|
||||||
|
unity_send_signal("ready to delete");
|
||||||
|
TEST_ESP_OK(sleep_cpu_configure(false));
|
||||||
|
TEST_ESP_OK(esp_ieee802154_disable());
|
||||||
|
TEST_ESP_OK(i2c_del_slave_device(slave_handle));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE_MULTIPLE_DEVICES("I2C sleep retention test", "[i2c][test_env=generic_multi_device][timeout=150]", i2c_master_write_sleep_retention_test, i2c_slave_read_sleep_retention_test);
|
|
@ -1,6 +1,5 @@
|
||||||
# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
# SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||||
# SPDX-License-Identifier: CC0-1.0
|
# SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from pytest_embedded import Dut
|
from pytest_embedded import Dut
|
||||||
|
|
||||||
|
@ -38,3 +37,19 @@ def test_i2c_multi_device(case_tester) -> None: # type: ignore
|
||||||
for case in case_tester.test_menu:
|
for case in case_tester.test_menu:
|
||||||
if case.attributes.get('test_env', 'generic_multi_device') == 'generic_multi_device':
|
if case.attributes.get('test_env', 'generic_multi_device') == 'generic_multi_device':
|
||||||
case_tester.run_multi_dev_case(case=case, reset=True)
|
case_tester.run_multi_dev_case(case=case, reset=True)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.esp32c6
|
||||||
|
@pytest.mark.esp32h2
|
||||||
|
@pytest.mark.generic_multi_device
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
'count, config',
|
||||||
|
[
|
||||||
|
(2, 'sleep_retention',),
|
||||||
|
],
|
||||||
|
indirect=True
|
||||||
|
)
|
||||||
|
def test_i2c_sleep_retention(case_tester) -> None: # type: ignore
|
||||||
|
for case in case_tester.test_menu:
|
||||||
|
if case.attributes.get('test_env', 'generic_multi_device') == 'generic_multi_device':
|
||||||
|
case_tester.run_multi_dev_case(case=case, reset=True, timeout=250)
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
CONFIG_PM_ENABLE=y
|
||||||
|
CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP=y
|
||||||
|
CONFIG_FREERTOS_USE_TICKLESS_IDLE=y
|
||||||
|
CONFIG_IEEE802154_ENABLED=y
|
||||||
|
CONFIG_IEEE802154_SLEEP_ENABLE=y
|
|
@ -76,6 +76,9 @@ typedef enum {
|
||||||
#define I2C_LL_SLAVE_TX_EVENT_INTR (I2C_TXFIFO_WM_INT_ENA_M)
|
#define I2C_LL_SLAVE_TX_EVENT_INTR (I2C_TXFIFO_WM_INT_ENA_M)
|
||||||
#define I2C_LL_RESET_SLV_SCL_PULSE_NUM_DEFAULT (9)
|
#define I2C_LL_RESET_SLV_SCL_PULSE_NUM_DEFAULT (9)
|
||||||
|
|
||||||
|
// I2C sleep retention module
|
||||||
|
#define I2C_SLEEP_RETENTION_MODULE(i2c_num) (SLEEP_RETENTION_MODULE_I2C0)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Calculate I2C bus frequency
|
* @brief Calculate I2C bus frequency
|
||||||
* Note that the clock accuracy is affected by the external pull-up resistor,
|
* Note that the clock accuracy is affected by the external pull-up resistor,
|
||||||
|
|
|
@ -75,6 +75,9 @@ typedef enum {
|
||||||
#define I2C_LL_SLAVE_TX_EVENT_INTR (I2C_TXFIFO_WM_INT_ENA_M)
|
#define I2C_LL_SLAVE_TX_EVENT_INTR (I2C_TXFIFO_WM_INT_ENA_M)
|
||||||
#define I2C_LL_RESET_SLV_SCL_PULSE_NUM_DEFAULT (9)
|
#define I2C_LL_RESET_SLV_SCL_PULSE_NUM_DEFAULT (9)
|
||||||
|
|
||||||
|
// I2C sleep retention module
|
||||||
|
#define I2C_SLEEP_RETENTION_MODULE(i2c_num) ((i2c_num == 0) ? SLEEP_RETENTION_MODULE_I2C0 : SLEEP_RETENTION_MODULE_I2C1)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Calculate I2C bus frequency
|
* @brief Calculate I2C bus frequency
|
||||||
* Note that the clock accuracy is affected by the external pull-up resistor,
|
* Note that the clock accuracy is affected by the external pull-up resistor,
|
||||||
|
|
|
@ -335,10 +335,6 @@ config SOC_PM_SUPPORT_VDDSDIO_PD
|
||||||
bool
|
bool
|
||||||
default y
|
default y
|
||||||
|
|
||||||
config SOC_PM_SUPPORT_TOP_PD
|
|
||||||
bool
|
|
||||||
default y
|
|
||||||
|
|
||||||
config SOC_PM_SUPPORT_HP_AON_PD
|
config SOC_PM_SUPPORT_HP_AON_PD
|
||||||
bool
|
bool
|
||||||
default y
|
default y
|
||||||
|
|
|
@ -508,7 +508,7 @@
|
||||||
#define SOC_PM_SUPPORT_RC32K_PD (1)
|
#define SOC_PM_SUPPORT_RC32K_PD (1)
|
||||||
#define SOC_PM_SUPPORT_RC_FAST_PD (1)
|
#define SOC_PM_SUPPORT_RC_FAST_PD (1)
|
||||||
#define SOC_PM_SUPPORT_VDDSDIO_PD (1)
|
#define SOC_PM_SUPPORT_VDDSDIO_PD (1)
|
||||||
#define SOC_PM_SUPPORT_TOP_PD (1)
|
// #define SOC_PM_SUPPORT_TOP_PD (1) // TODO: IDF-8643
|
||||||
#define SOC_PM_SUPPORT_HP_AON_PD (1)
|
#define SOC_PM_SUPPORT_HP_AON_PD (1)
|
||||||
// #define SOC_PM_SUPPORT_MAC_BB_PD (1)
|
// #define SOC_PM_SUPPORT_MAC_BB_PD (1)
|
||||||
#define SOC_PM_SUPPORT_RTC_PERIPH_PD (1)
|
#define SOC_PM_SUPPORT_RTC_PERIPH_PD (1)
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "soc/i2c_periph.h"
|
#include "soc/i2c_periph.h"
|
||||||
#include "soc/gpio_sig_map.h"
|
#include "soc/gpio_sig_map.h"
|
||||||
|
#include "soc/regdma.h"
|
||||||
|
#include "soc/i2c_reg.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Bunch of constants for every I2C peripheral: GPIO signals, irqs, hw addr of registers etc
|
Bunch of constants for every I2C peripheral: GPIO signals, irqs, hw addr of registers etc
|
||||||
|
@ -20,3 +22,32 @@ const i2c_signal_conn_t i2c_periph_signal[SOC_I2C_NUM] = {
|
||||||
.module = PERIPH_I2C0_MODULE,
|
.module = PERIPH_I2C0_MODULE,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// I2C sleep retention entries
|
||||||
|
// I2C registers require set the reg_update bit to make the configuration take effect
|
||||||
|
|
||||||
|
/* I2C Registers Context
|
||||||
|
Include: I2C_SCL_LOW_PERIOD_REG /
|
||||||
|
I2C_CTR_REG / I2C_TO_REG / I2C_SLAVE_ADDR_REG / I2C_FIFO_CONF_REG
|
||||||
|
I2C_INT_ENA_REG / I2C_SDA_HOLD_REG / I2C_SDA_SAMPLE_REG / I2C_SCL_START_HOLD_REG
|
||||||
|
I2C_SCL_RSTART_SETUP_REG / I2C_SCL_STOP_HOLD_REG / I2C_SCL_STOP_SETUP_REG /I2C_FILTER_CFG_REG / I2C_CLK_CONF_REG / I2C_SCL_ST_TIME_OUT_REG / I2C_SCL_MAIN_ST_TIME_OUT_REG / I2C_SCL_SP_CONF_REG / I2C_SCL_STRETCH_CONF_REG
|
||||||
|
*/
|
||||||
|
#define I2C0_RETENTION_REGS_CNT 18
|
||||||
|
#define I2C0_RETENTION_MAP_BASE I2C_SCL_LOW_PERIOD_REG(0)
|
||||||
|
static const uint32_t i2c0_regs_map[4] = {0xc03f345b, 0x3, 0, 0};
|
||||||
|
static const regdma_entries_config_t i2c0_regs_retention[] = {
|
||||||
|
[0] = {.config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_I2C_LINK(0x00), I2C0_RETENTION_MAP_BASE, I2C0_RETENTION_MAP_BASE, I2C0_RETENTION_REGS_CNT, 0, 0, i2c0_regs_map[0], i2c0_regs_map[1], i2c0_regs_map[2], i2c0_regs_map[3]), \
|
||||||
|
.owner = ENTRY(0) | ENTRY(2) }, \
|
||||||
|
[1] = {.config = REGDMA_LINK_WRITE_INIT(REGDMA_I2C_LINK(0x01), I2C_CTR_REG(0), I2C_FSM_RST, I2C_FSM_RST_M, 1, 0), \
|
||||||
|
.owner = ENTRY(0) | ENTRY(2) }, \
|
||||||
|
[2] = {.config = REGDMA_LINK_WRITE_INIT(REGDMA_I2C_LINK(0x02), I2C_CTR_REG(0), 0x0, I2C_FSM_RST_M, 1, 0), \
|
||||||
|
.owner = ENTRY(0) | ENTRY(2) }, \
|
||||||
|
[3] = {.config = REGDMA_LINK_WRITE_INIT(REGDMA_I2C_LINK(0x03), I2C_CTR_REG(0), I2C_CONF_UPGATE, I2C_CONF_UPGATE_M, 1, 0), \
|
||||||
|
.owner = ENTRY(0) | ENTRY(2) }, \
|
||||||
|
[4] = {.config = REGDMA_LINK_WAIT_INIT(REGDMA_I2C_LINK(0x04), I2C_CTR_REG(0), 0x0, I2C_CONF_UPGATE_M, 1, 0), \
|
||||||
|
.owner = ENTRY(0) | ENTRY(2) }, \
|
||||||
|
};
|
||||||
|
|
||||||
|
const i2c_reg_ctx_link_t i2c_regs_retention[SOC_I2C_NUM] = {
|
||||||
|
{i2c0_regs_retention, ARRAY_SIZE(i2c0_regs_retention)},
|
||||||
|
};
|
||||||
|
|
|
@ -38,6 +38,7 @@ typedef enum periph_retention_module_bitmap {
|
||||||
SLEEP_RETENTION_MODULE_GDMA_CH0 = BIT(24),
|
SLEEP_RETENTION_MODULE_GDMA_CH0 = BIT(24),
|
||||||
SLEEP_RETENTION_MODULE_GDMA_CH1 = BIT(25),
|
SLEEP_RETENTION_MODULE_GDMA_CH1 = BIT(25),
|
||||||
SLEEP_RETENTION_MODULE_GDMA_CH2 = BIT(26),
|
SLEEP_RETENTION_MODULE_GDMA_CH2 = BIT(26),
|
||||||
|
SLEEP_RETENTION_MODULE_I2C0 = BIT(27),
|
||||||
SLEEP_RETENTION_MODULE_ALL = (uint32_t)-1
|
SLEEP_RETENTION_MODULE_ALL = (uint32_t)-1
|
||||||
} periph_retention_module_bitmap_t;
|
} periph_retention_module_bitmap_t;
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "soc/i2c_periph.h"
|
#include "soc/i2c_periph.h"
|
||||||
#include "soc/gpio_sig_map.h"
|
#include "soc/gpio_sig_map.h"
|
||||||
|
#include "soc/regdma.h"
|
||||||
|
#include "soc/i2c_reg.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Bunch of constants for every I2C peripheral: GPIO signals, irqs, hw addr of registers etc
|
Bunch of constants for every I2C peripheral: GPIO signals, irqs, hw addr of registers etc
|
||||||
|
@ -28,3 +30,49 @@ const i2c_signal_conn_t i2c_periph_signal[SOC_I2C_NUM] = {
|
||||||
.module = PERIPH_I2C1_MODULE,
|
.module = PERIPH_I2C1_MODULE,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// I2C sleep retention entries
|
||||||
|
// I2C registers require set the reg_update bit to make the configuration take effect
|
||||||
|
|
||||||
|
/* I2C Registers Context
|
||||||
|
Include: I2C_SCL_LOW_PERIOD_REG /
|
||||||
|
I2C_CTR_REG / I2C_TO_REG / I2C_SLAVE_ADDR_REG / I2C_FIFO_CONF_REG
|
||||||
|
I2C_INT_ENA_REG / I2C_SDA_HOLD_REG / I2C_SDA_SAMPLE_REG / I2C_SCL_START_HOLD_REG
|
||||||
|
I2C_SCL_RSTART_SETUP_REG / I2C_SCL_STOP_HOLD_REG / I2C_SCL_STOP_SETUP_REG /I2C_FILTER_CFG_REG / I2C_CLK_CONF_REG / I2C_SCL_ST_TIME_OUT_REG / I2C_SCL_MAIN_ST_TIME_OUT_REG / I2C_SCL_SP_CONF_REG / I2C_SCL_STRETCH_CONF_REG
|
||||||
|
*/
|
||||||
|
#define I2C0_RETENTION_REGS_CNT 18
|
||||||
|
#define I2C0_RETENTION_MAP_BASE I2C_SCL_LOW_PERIOD_REG(0)
|
||||||
|
static const uint32_t i2c0_regs_map[4] = {0xc03f345b, 0x3, 0, 0};
|
||||||
|
static const regdma_entries_config_t i2c0_regs_retention[] = {
|
||||||
|
[0] = {.config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_I2C_LINK(0x00), I2C0_RETENTION_MAP_BASE, I2C0_RETENTION_MAP_BASE, I2C0_RETENTION_REGS_CNT, 0, 0, i2c0_regs_map[0], i2c0_regs_map[1], i2c0_regs_map[2], i2c0_regs_map[3]), \
|
||||||
|
.owner = ENTRY(0) | ENTRY(2) }, \
|
||||||
|
[1] = {.config = REGDMA_LINK_WRITE_INIT(REGDMA_I2C_LINK(0x01), I2C_CTR_REG(0), I2C_FSM_RST, I2C_FSM_RST_M, 1, 0), \
|
||||||
|
.owner = ENTRY(0) | ENTRY(2) }, \
|
||||||
|
[2] = {.config = REGDMA_LINK_WRITE_INIT(REGDMA_I2C_LINK(0x02), I2C_CTR_REG(0), 0x0, I2C_FSM_RST_M, 1, 0), \
|
||||||
|
.owner = ENTRY(0) | ENTRY(2) }, \
|
||||||
|
[3] = {.config = REGDMA_LINK_WRITE_INIT(REGDMA_I2C_LINK(0x03), I2C_CTR_REG(0), I2C_CONF_UPGATE, I2C_CONF_UPGATE_M, 1, 0), \
|
||||||
|
.owner = ENTRY(0) | ENTRY(2) }, \
|
||||||
|
[4] = {.config = REGDMA_LINK_WAIT_INIT(REGDMA_I2C_LINK(0x04), I2C_CTR_REG(0), 0x0, I2C_CONF_UPGATE_M, 1, 0), \
|
||||||
|
.owner = ENTRY(0) | ENTRY(2) }, \
|
||||||
|
};
|
||||||
|
|
||||||
|
#define I2C1_RETENTION_REGS_CNT 18
|
||||||
|
#define I2C1_RETENTION_MAP_BASE I2C_SCL_LOW_PERIOD_REG(1)
|
||||||
|
static const uint32_t i2c1_regs_map[4] = {0xc03f345b, 0x3, 0, 0};
|
||||||
|
static const regdma_entries_config_t i2c1_regs_retention[] = {
|
||||||
|
[0] = {.config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_I2C_LINK(0x00), I2C1_RETENTION_MAP_BASE, I2C1_RETENTION_MAP_BASE, I2C1_RETENTION_REGS_CNT, 0, 0, i2c1_regs_map[0], i2c1_regs_map[1], i2c1_regs_map[2], i2c1_regs_map[3]), \
|
||||||
|
.owner = ENTRY(0) | ENTRY(2) }, \
|
||||||
|
[1] = {.config = REGDMA_LINK_WRITE_INIT(REGDMA_I2C_LINK(0x01), I2C_CTR_REG(1), I2C_FSM_RST, I2C_FSM_RST_M, 1, 0), \
|
||||||
|
.owner = ENTRY(0) | ENTRY(2) }, \
|
||||||
|
[2] = {.config = REGDMA_LINK_WRITE_INIT(REGDMA_I2C_LINK(0x02), I2C_CTR_REG(1), 0x0, I2C_FSM_RST_M, 1, 0), \
|
||||||
|
.owner = ENTRY(0) | ENTRY(2) }, \
|
||||||
|
[3] = {.config = REGDMA_LINK_WRITE_INIT(REGDMA_I2C_LINK(0x03), I2C_CTR_REG(1), I2C_CONF_UPGATE, I2C_CONF_UPGATE_M, 1, 0), \
|
||||||
|
.owner = ENTRY(0) | ENTRY(2) }, \
|
||||||
|
[4] = {.config = REGDMA_LINK_WAIT_INIT(REGDMA_I2C_LINK(0x04), I2C_CTR_REG(1), 0x0, I2C_CONF_UPGATE_M, 1, 0), \
|
||||||
|
.owner = ENTRY(0) | ENTRY(2) }, \
|
||||||
|
};
|
||||||
|
|
||||||
|
const i2c_reg_ctx_link_t i2c_regs_retention[SOC_I2C_NUM] = {
|
||||||
|
{i2c0_regs_retention, ARRAY_SIZE(i2c0_regs_retention)},
|
||||||
|
{i2c1_regs_retention, ARRAY_SIZE(i2c1_regs_retention)},
|
||||||
|
};
|
||||||
|
|
|
@ -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
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
@ -15,7 +15,7 @@ extern "C" {
|
||||||
* Configures the low level width of the SCL
|
* Configures the low level width of the SCL
|
||||||
* Clock
|
* Clock
|
||||||
*/
|
*/
|
||||||
#define I2C_SCL_LOW_PERIOD_REG (DR_REG_I2C_BASE + 0x0)
|
#define I2C_SCL_LOW_PERIOD_REG(i) (REG_I2C_BASE(i) + 0x0)
|
||||||
/** I2C_SCL_LOW_PERIOD : R/W; bitpos: [8:0]; default: 0;
|
/** I2C_SCL_LOW_PERIOD : R/W; bitpos: [8:0]; default: 0;
|
||||||
* This register is used to configure for how long SCL remains low in master mode, in
|
* This register is used to configure for how long SCL remains low in master mode, in
|
||||||
* I2C module clock cycles.
|
* I2C module clock cycles.
|
||||||
|
@ -28,7 +28,7 @@ extern "C" {
|
||||||
/** I2C_CTR_REG register
|
/** I2C_CTR_REG register
|
||||||
* Transmission setting
|
* Transmission setting
|
||||||
*/
|
*/
|
||||||
#define I2C_CTR_REG (DR_REG_I2C_BASE + 0x4)
|
#define I2C_CTR_REG(i) (REG_I2C_BASE(i) + 0x4)
|
||||||
/** I2C_SDA_FORCE_OUT : R/W; bitpos: [0]; default: 0;
|
/** I2C_SDA_FORCE_OUT : R/W; bitpos: [0]; default: 0;
|
||||||
* 1: direct output, 0: open drain output.
|
* 1: direct output, 0: open drain output.
|
||||||
*/
|
*/
|
||||||
|
@ -148,7 +148,7 @@ extern "C" {
|
||||||
/** I2C_SR_REG register
|
/** I2C_SR_REG register
|
||||||
* Describe I2C work status.
|
* Describe I2C work status.
|
||||||
*/
|
*/
|
||||||
#define I2C_SR_REG (DR_REG_I2C_BASE + 0x8)
|
#define I2C_SR_REG(i) (REG_I2C_BASE(i) + 0x8)
|
||||||
/** I2C_RESP_REC : RO; bitpos: [0]; default: 0;
|
/** I2C_RESP_REC : RO; bitpos: [0]; default: 0;
|
||||||
* The received ACK value in master mode or slave mode. 0: ACK, 1: NACK.
|
* The received ACK value in master mode or slave mode. 0: ACK, 1: NACK.
|
||||||
*/
|
*/
|
||||||
|
@ -229,7 +229,7 @@ extern "C" {
|
||||||
/** I2C_TO_REG register
|
/** I2C_TO_REG register
|
||||||
* Setting time out control for receiving data.
|
* Setting time out control for receiving data.
|
||||||
*/
|
*/
|
||||||
#define I2C_TO_REG (DR_REG_I2C_BASE + 0xc)
|
#define I2C_TO_REG(i) (REG_I2C_BASE(i) + 0xc)
|
||||||
/** I2C_TIME_OUT_VALUE : R/W; bitpos: [4:0]; default: 16;
|
/** I2C_TIME_OUT_VALUE : R/W; bitpos: [4:0]; default: 16;
|
||||||
* This register is used to configure the timeout for receiving a data bit in APB
|
* This register is used to configure the timeout for receiving a data bit in APB
|
||||||
* clock cycles.
|
* clock cycles.
|
||||||
|
@ -249,7 +249,7 @@ extern "C" {
|
||||||
/** I2C_SLAVE_ADDR_REG register
|
/** I2C_SLAVE_ADDR_REG register
|
||||||
* Local slave address setting
|
* Local slave address setting
|
||||||
*/
|
*/
|
||||||
#define I2C_SLAVE_ADDR_REG (DR_REG_I2C_BASE + 0x10)
|
#define I2C_SLAVE_ADDR_REG(i) (REG_I2C_BASE(i) + 0x10)
|
||||||
/** I2C_SLAVE_ADDR : R/W; bitpos: [14:0]; default: 0;
|
/** I2C_SLAVE_ADDR : R/W; bitpos: [14:0]; default: 0;
|
||||||
* When configured as an I2C Slave, this field is used to configure the slave address.
|
* When configured as an I2C Slave, this field is used to configure the slave address.
|
||||||
*/
|
*/
|
||||||
|
@ -268,7 +268,7 @@ extern "C" {
|
||||||
/** I2C_FIFO_ST_REG register
|
/** I2C_FIFO_ST_REG register
|
||||||
* FIFO status register.
|
* FIFO status register.
|
||||||
*/
|
*/
|
||||||
#define I2C_FIFO_ST_REG (DR_REG_I2C_BASE + 0x14)
|
#define I2C_FIFO_ST_REG(i) (REG_I2C_BASE(i) + 0x14)
|
||||||
/** I2C_RXFIFO_RADDR : RO; bitpos: [4:0]; default: 0;
|
/** I2C_RXFIFO_RADDR : RO; bitpos: [4:0]; default: 0;
|
||||||
* This is the offset address of the APB reading from rxfifo
|
* This is the offset address of the APB reading from rxfifo
|
||||||
*/
|
*/
|
||||||
|
@ -308,7 +308,7 @@ extern "C" {
|
||||||
/** I2C_FIFO_CONF_REG register
|
/** I2C_FIFO_CONF_REG register
|
||||||
* FIFO configuration register.
|
* FIFO configuration register.
|
||||||
*/
|
*/
|
||||||
#define I2C_FIFO_CONF_REG (DR_REG_I2C_BASE + 0x18)
|
#define I2C_FIFO_CONF_REG(i) (REG_I2C_BASE(i) + 0x18)
|
||||||
/** I2C_RXFIFO_WM_THRHD : R/W; bitpos: [4:0]; default: 11;
|
/** I2C_RXFIFO_WM_THRHD : R/W; bitpos: [4:0]; default: 11;
|
||||||
* The water mark threshold of rx FIFO in nonfifo access mode. When
|
* The water mark threshold of rx FIFO in nonfifo access mode. When
|
||||||
* reg_reg_fifo_prt_en is 1 and rx FIFO counter is bigger than
|
* reg_reg_fifo_prt_en is 1 and rx FIFO counter is bigger than
|
||||||
|
@ -368,7 +368,7 @@ extern "C" {
|
||||||
/** I2C_DATA_REG register
|
/** I2C_DATA_REG register
|
||||||
* Rx FIFO read data.
|
* Rx FIFO read data.
|
||||||
*/
|
*/
|
||||||
#define I2C_DATA_REG (DR_REG_I2C_BASE + 0x1c)
|
#define I2C_DATA_REG(i) (REG_I2C_BASE(i) + 0x1c)
|
||||||
/** I2C_FIFO_RDATA : HRO; bitpos: [7:0]; default: 0;
|
/** I2C_FIFO_RDATA : HRO; bitpos: [7:0]; default: 0;
|
||||||
* The value of rx FIFO read data.
|
* The value of rx FIFO read data.
|
||||||
*/
|
*/
|
||||||
|
@ -380,7 +380,7 @@ extern "C" {
|
||||||
/** I2C_INT_RAW_REG register
|
/** I2C_INT_RAW_REG register
|
||||||
* Raw interrupt status
|
* Raw interrupt status
|
||||||
*/
|
*/
|
||||||
#define I2C_INT_RAW_REG (DR_REG_I2C_BASE + 0x20)
|
#define I2C_INT_RAW_REG(i) (REG_I2C_BASE(i) + 0x20)
|
||||||
/** I2C_RXFIFO_WM_INT_RAW : R/SS/WTC; bitpos: [0]; default: 0;
|
/** I2C_RXFIFO_WM_INT_RAW : R/SS/WTC; bitpos: [0]; default: 0;
|
||||||
* The raw interrupt bit for I2C_RXFIFO_WM_INT interrupt.
|
* The raw interrupt bit for I2C_RXFIFO_WM_INT interrupt.
|
||||||
*/
|
*/
|
||||||
|
@ -518,7 +518,7 @@ extern "C" {
|
||||||
/** I2C_INT_CLR_REG register
|
/** I2C_INT_CLR_REG register
|
||||||
* Interrupt clear bits
|
* Interrupt clear bits
|
||||||
*/
|
*/
|
||||||
#define I2C_INT_CLR_REG (DR_REG_I2C_BASE + 0x24)
|
#define I2C_INT_CLR_REG(i) (REG_I2C_BASE(i) + 0x24)
|
||||||
/** I2C_RXFIFO_WM_INT_CLR : WT; bitpos: [0]; default: 0;
|
/** I2C_RXFIFO_WM_INT_CLR : WT; bitpos: [0]; default: 0;
|
||||||
* Set this bit to clear I2C_RXFIFO_WM_INT interrupt.
|
* Set this bit to clear I2C_RXFIFO_WM_INT interrupt.
|
||||||
*/
|
*/
|
||||||
|
@ -656,7 +656,7 @@ extern "C" {
|
||||||
/** I2C_INT_ENA_REG register
|
/** I2C_INT_ENA_REG register
|
||||||
* Interrupt enable bits
|
* Interrupt enable bits
|
||||||
*/
|
*/
|
||||||
#define I2C_INT_ENA_REG (DR_REG_I2C_BASE + 0x28)
|
#define I2C_INT_ENA_REG(i) (REG_I2C_BASE(i) + 0x28)
|
||||||
/** I2C_RXFIFO_WM_INT_ENA : R/W; bitpos: [0]; default: 0;
|
/** I2C_RXFIFO_WM_INT_ENA : R/W; bitpos: [0]; default: 0;
|
||||||
* The interrupt enable bit for I2C_RXFIFO_WM_INT interrupt.
|
* The interrupt enable bit for I2C_RXFIFO_WM_INT interrupt.
|
||||||
*/
|
*/
|
||||||
|
@ -794,7 +794,7 @@ extern "C" {
|
||||||
/** I2C_INT_STATUS_REG register
|
/** I2C_INT_STATUS_REG register
|
||||||
* Status of captured I2C communication events
|
* Status of captured I2C communication events
|
||||||
*/
|
*/
|
||||||
#define I2C_INT_STATUS_REG (DR_REG_I2C_BASE + 0x2c)
|
#define I2C_INT_STATUS_REG(i) (REG_I2C_BASE(i) + 0x2c)
|
||||||
/** I2C_RXFIFO_WM_INT_ST : RO; bitpos: [0]; default: 0;
|
/** I2C_RXFIFO_WM_INT_ST : RO; bitpos: [0]; default: 0;
|
||||||
* The masked interrupt status bit for I2C_RXFIFO_WM_INT interrupt.
|
* The masked interrupt status bit for I2C_RXFIFO_WM_INT interrupt.
|
||||||
*/
|
*/
|
||||||
|
@ -932,7 +932,7 @@ extern "C" {
|
||||||
/** I2C_SDA_HOLD_REG register
|
/** I2C_SDA_HOLD_REG register
|
||||||
* Configures the hold time after a negative SCL edge.
|
* Configures the hold time after a negative SCL edge.
|
||||||
*/
|
*/
|
||||||
#define I2C_SDA_HOLD_REG (DR_REG_I2C_BASE + 0x30)
|
#define I2C_SDA_HOLD_REG(i) (REG_I2C_BASE(i) + 0x30)
|
||||||
/** I2C_SDA_HOLD_TIME : R/W; bitpos: [8:0]; default: 0;
|
/** I2C_SDA_HOLD_TIME : R/W; bitpos: [8:0]; default: 0;
|
||||||
* This register is used to configure the time to hold the data after the negative
|
* This register is used to configure the time to hold the data after the negative
|
||||||
* edge of SCL, in I2C module clock cycles.
|
* edge of SCL, in I2C module clock cycles.
|
||||||
|
@ -945,7 +945,7 @@ extern "C" {
|
||||||
/** I2C_SDA_SAMPLE_REG register
|
/** I2C_SDA_SAMPLE_REG register
|
||||||
* Configures the sample time after a positive SCL edge.
|
* Configures the sample time after a positive SCL edge.
|
||||||
*/
|
*/
|
||||||
#define I2C_SDA_SAMPLE_REG (DR_REG_I2C_BASE + 0x34)
|
#define I2C_SDA_SAMPLE_REG(i) (REG_I2C_BASE(i) + 0x34)
|
||||||
/** I2C_SDA_SAMPLE_TIME : R/W; bitpos: [8:0]; default: 0;
|
/** I2C_SDA_SAMPLE_TIME : R/W; bitpos: [8:0]; default: 0;
|
||||||
* This register is used to configure for how long SDA is sampled, in I2C module clock
|
* This register is used to configure for how long SDA is sampled, in I2C module clock
|
||||||
* cycles.
|
* cycles.
|
||||||
|
@ -958,7 +958,7 @@ extern "C" {
|
||||||
/** I2C_SCL_HIGH_PERIOD_REG register
|
/** I2C_SCL_HIGH_PERIOD_REG register
|
||||||
* Configures the high level width of SCL
|
* Configures the high level width of SCL
|
||||||
*/
|
*/
|
||||||
#define I2C_SCL_HIGH_PERIOD_REG (DR_REG_I2C_BASE + 0x38)
|
#define I2C_SCL_HIGH_PERIOD_REG(i) (REG_I2C_BASE(i) + 0x38)
|
||||||
/** I2C_SCL_HIGH_PERIOD : R/W; bitpos: [8:0]; default: 0;
|
/** I2C_SCL_HIGH_PERIOD : R/W; bitpos: [8:0]; default: 0;
|
||||||
* This register is used to configure for how long SCL remains high in master mode, in
|
* This register is used to configure for how long SCL remains high in master mode, in
|
||||||
* I2C module clock cycles.
|
* I2C module clock cycles.
|
||||||
|
@ -979,7 +979,7 @@ extern "C" {
|
||||||
/** I2C_SCL_START_HOLD_REG register
|
/** I2C_SCL_START_HOLD_REG register
|
||||||
* Configures the delay between the SDA and SCL negative edge for a start condition
|
* Configures the delay between the SDA and SCL negative edge for a start condition
|
||||||
*/
|
*/
|
||||||
#define I2C_SCL_START_HOLD_REG (DR_REG_I2C_BASE + 0x40)
|
#define I2C_SCL_START_HOLD_REG(i) (REG_I2C_BASE(i) + 0x40)
|
||||||
/** I2C_SCL_START_HOLD_TIME : R/W; bitpos: [8:0]; default: 8;
|
/** I2C_SCL_START_HOLD_TIME : R/W; bitpos: [8:0]; default: 8;
|
||||||
* This register is used to configure the time between the negative edge
|
* This register is used to configure the time between the negative edge
|
||||||
* of SDA and the negative edge of SCL for a START condition, in I2C module clock
|
* of SDA and the negative edge of SCL for a START condition, in I2C module clock
|
||||||
|
@ -994,7 +994,7 @@ extern "C" {
|
||||||
* Configures the delay between the positive
|
* Configures the delay between the positive
|
||||||
* edge of SCL and the negative edge of SDA
|
* edge of SCL and the negative edge of SDA
|
||||||
*/
|
*/
|
||||||
#define I2C_SCL_RSTART_SETUP_REG (DR_REG_I2C_BASE + 0x44)
|
#define I2C_SCL_RSTART_SETUP_REG(i) (REG_I2C_BASE(i) + 0x44)
|
||||||
/** I2C_SCL_RSTART_SETUP_TIME : R/W; bitpos: [8:0]; default: 8;
|
/** I2C_SCL_RSTART_SETUP_TIME : R/W; bitpos: [8:0]; default: 8;
|
||||||
* This register is used to configure the time between the positive
|
* This register is used to configure the time between the positive
|
||||||
* edge of SCL and the negative edge of SDA for a RESTART condition, in I2C module
|
* edge of SCL and the negative edge of SDA for a RESTART condition, in I2C module
|
||||||
|
@ -1009,7 +1009,7 @@ extern "C" {
|
||||||
* Configures the delay after the SCL clock
|
* Configures the delay after the SCL clock
|
||||||
* edge for a stop condition
|
* edge for a stop condition
|
||||||
*/
|
*/
|
||||||
#define I2C_SCL_STOP_HOLD_REG (DR_REG_I2C_BASE + 0x48)
|
#define I2C_SCL_STOP_HOLD_REG(i) (REG_I2C_BASE(i) + 0x48)
|
||||||
/** I2C_SCL_STOP_HOLD_TIME : R/W; bitpos: [8:0]; default: 8;
|
/** I2C_SCL_STOP_HOLD_TIME : R/W; bitpos: [8:0]; default: 8;
|
||||||
* This register is used to configure the delay after the STOP condition,
|
* This register is used to configure the delay after the STOP condition,
|
||||||
* in I2C module clock cycles.
|
* in I2C module clock cycles.
|
||||||
|
@ -1023,7 +1023,7 @@ extern "C" {
|
||||||
* Configures the delay between the SDA and
|
* Configures the delay between the SDA and
|
||||||
* SCL positive edge for a stop condition
|
* SCL positive edge for a stop condition
|
||||||
*/
|
*/
|
||||||
#define I2C_SCL_STOP_SETUP_REG (DR_REG_I2C_BASE + 0x4c)
|
#define I2C_SCL_STOP_SETUP_REG(i) (REG_I2C_BASE(i) + 0x4c)
|
||||||
/** I2C_SCL_STOP_SETUP_TIME : R/W; bitpos: [8:0]; default: 8;
|
/** I2C_SCL_STOP_SETUP_TIME : R/W; bitpos: [8:0]; default: 8;
|
||||||
* This register is used to configure the time between the positive edge
|
* This register is used to configure the time between the positive edge
|
||||||
* of SCL and the positive edge of SDA, in I2C module clock cycles.
|
* of SCL and the positive edge of SDA, in I2C module clock cycles.
|
||||||
|
@ -1036,7 +1036,7 @@ extern "C" {
|
||||||
/** I2C_FILTER_CFG_REG register
|
/** I2C_FILTER_CFG_REG register
|
||||||
* SCL and SDA filter configuration register
|
* SCL and SDA filter configuration register
|
||||||
*/
|
*/
|
||||||
#define I2C_FILTER_CFG_REG (DR_REG_I2C_BASE + 0x50)
|
#define I2C_FILTER_CFG_REG(i) (REG_I2C_BASE(i) + 0x50)
|
||||||
/** I2C_SCL_FILTER_THRES : R/W; bitpos: [3:0]; default: 0;
|
/** I2C_SCL_FILTER_THRES : R/W; bitpos: [3:0]; default: 0;
|
||||||
* When a pulse on the SCL input has smaller width than this register value
|
* When a pulse on the SCL input has smaller width than this register value
|
||||||
* in I2C module clock cycles, the I2C controller will ignore that pulse.
|
* in I2C module clock cycles, the I2C controller will ignore that pulse.
|
||||||
|
@ -1071,7 +1071,7 @@ extern "C" {
|
||||||
/** I2C_CLK_CONF_REG register
|
/** I2C_CLK_CONF_REG register
|
||||||
* I2C CLK configuration register
|
* I2C CLK configuration register
|
||||||
*/
|
*/
|
||||||
#define I2C_CLK_CONF_REG (DR_REG_I2C_BASE + 0x54)
|
#define I2C_CLK_CONF_REG(i) (REG_I2C_BASE(i) + 0x54)
|
||||||
/** I2C_SCLK_DIV_NUM : R/W; bitpos: [7:0]; default: 0;
|
/** I2C_SCLK_DIV_NUM : R/W; bitpos: [7:0]; default: 0;
|
||||||
* the integral part of the fractional divisor for i2c module
|
* the integral part of the fractional divisor for i2c module
|
||||||
*/
|
*/
|
||||||
|
@ -1111,7 +1111,7 @@ extern "C" {
|
||||||
/** I2C_COMD0_REG register
|
/** I2C_COMD0_REG register
|
||||||
* I2C command register 0
|
* I2C command register 0
|
||||||
*/
|
*/
|
||||||
#define I2C_COMD0_REG (DR_REG_I2C_BASE + 0x58)
|
#define I2C_COMD0_REG(i) (REG_I2C_BASE(i) + 0x58)
|
||||||
/** I2C_COMMAND0 : R/W; bitpos: [13:0]; default: 0;
|
/** I2C_COMMAND0 : R/W; bitpos: [13:0]; default: 0;
|
||||||
* This is the content of command 0. It consists of three parts:
|
* This is the content of command 0. It consists of three parts:
|
||||||
* op_code is the command, 0: RSTART, 1: WRITE, 2: READ, 3: STOP, 4: END.
|
* op_code is the command, 0: RSTART, 1: WRITE, 2: READ, 3: STOP, 4: END.
|
||||||
|
@ -1136,7 +1136,7 @@ extern "C" {
|
||||||
/** I2C_COMD1_REG register
|
/** I2C_COMD1_REG register
|
||||||
* I2C command register 1
|
* I2C command register 1
|
||||||
*/
|
*/
|
||||||
#define I2C_COMD1_REG (DR_REG_I2C_BASE + 0x5c)
|
#define I2C_COMD1_REG(i) (REG_I2C_BASE(i) + 0x5c)
|
||||||
/** I2C_COMMAND1 : R/W; bitpos: [13:0]; default: 0;
|
/** I2C_COMMAND1 : R/W; bitpos: [13:0]; default: 0;
|
||||||
* This is the content of command 1. It consists of three parts:
|
* This is the content of command 1. It consists of three parts:
|
||||||
* op_code is the command, 0: RSTART, 1: WRITE, 2: READ, 3: STOP, 4: END.
|
* op_code is the command, 0: RSTART, 1: WRITE, 2: READ, 3: STOP, 4: END.
|
||||||
|
@ -1161,7 +1161,7 @@ extern "C" {
|
||||||
/** I2C_COMD2_REG register
|
/** I2C_COMD2_REG register
|
||||||
* I2C command register 2
|
* I2C command register 2
|
||||||
*/
|
*/
|
||||||
#define I2C_COMD2_REG (DR_REG_I2C_BASE + 0x60)
|
#define I2C_COMD2_REG(i) (REG_I2C_BASE(i) + 0x60)
|
||||||
/** I2C_COMMAND2 : R/W; bitpos: [13:0]; default: 0;
|
/** I2C_COMMAND2 : R/W; bitpos: [13:0]; default: 0;
|
||||||
* This is the content of command 2. It consists of three parts:
|
* This is the content of command 2. It consists of three parts:
|
||||||
* op_code is the command, 0: RSTART, 1: WRITE, 2: READ, 3: STOP, 4: END.
|
* op_code is the command, 0: RSTART, 1: WRITE, 2: READ, 3: STOP, 4: END.
|
||||||
|
@ -1186,7 +1186,7 @@ extern "C" {
|
||||||
/** I2C_COMD3_REG register
|
/** I2C_COMD3_REG register
|
||||||
* I2C command register 3
|
* I2C command register 3
|
||||||
*/
|
*/
|
||||||
#define I2C_COMD3_REG (DR_REG_I2C_BASE + 0x64)
|
#define I2C_COMD3_REG(i) (REG_I2C_BASE(i) + 0x64)
|
||||||
/** I2C_COMMAND3 : R/W; bitpos: [13:0]; default: 0;
|
/** I2C_COMMAND3 : R/W; bitpos: [13:0]; default: 0;
|
||||||
* This is the content of command 3. It consists of three parts:
|
* This is the content of command 3. It consists of three parts:
|
||||||
* op_code is the command, 0: RSTART, 1: WRITE, 2: READ, 3: STOP, 4: END.
|
* op_code is the command, 0: RSTART, 1: WRITE, 2: READ, 3: STOP, 4: END.
|
||||||
|
@ -1211,7 +1211,7 @@ extern "C" {
|
||||||
/** I2C_COMD4_REG register
|
/** I2C_COMD4_REG register
|
||||||
* I2C command register 4
|
* I2C command register 4
|
||||||
*/
|
*/
|
||||||
#define I2C_COMD4_REG (DR_REG_I2C_BASE + 0x68)
|
#define I2C_COMD4_REG(i) (REG_I2C_BASE(i) + 0x68)
|
||||||
/** I2C_COMMAND4 : R/W; bitpos: [13:0]; default: 0;
|
/** I2C_COMMAND4 : R/W; bitpos: [13:0]; default: 0;
|
||||||
* This is the content of command 4. It consists of three parts:
|
* This is the content of command 4. It consists of three parts:
|
||||||
* op_code is the command, 0: RSTART, 1: WRITE, 2: READ, 3: STOP, 4: END.
|
* op_code is the command, 0: RSTART, 1: WRITE, 2: READ, 3: STOP, 4: END.
|
||||||
|
@ -1236,7 +1236,7 @@ extern "C" {
|
||||||
/** I2C_COMD5_REG register
|
/** I2C_COMD5_REG register
|
||||||
* I2C command register 5
|
* I2C command register 5
|
||||||
*/
|
*/
|
||||||
#define I2C_COMD5_REG (DR_REG_I2C_BASE + 0x6c)
|
#define I2C_COMD5_REG(i) (REG_I2C_BASE(i) + 0x6c)
|
||||||
/** I2C_COMMAND5 : R/W; bitpos: [13:0]; default: 0;
|
/** I2C_COMMAND5 : R/W; bitpos: [13:0]; default: 0;
|
||||||
* This is the content of command 5. It consists of three parts:
|
* This is the content of command 5. It consists of three parts:
|
||||||
* op_code is the command, 0: RSTART, 1: WRITE, 2: READ, 3: STOP, 4: END.
|
* op_code is the command, 0: RSTART, 1: WRITE, 2: READ, 3: STOP, 4: END.
|
||||||
|
@ -1260,7 +1260,7 @@ extern "C" {
|
||||||
/** I2C_COMD6_REG register
|
/** I2C_COMD6_REG register
|
||||||
* I2C command register 6
|
* I2C command register 6
|
||||||
*/
|
*/
|
||||||
#define I2C_COMD6_REG (DR_REG_I2C_BASE + 0x70)
|
#define I2C_COMD6_REG(i) (REG_I2C_BASE(i) + 0x70)
|
||||||
/** I2C_COMMAND6 : R/W; bitpos: [13:0]; default: 0;
|
/** I2C_COMMAND6 : R/W; bitpos: [13:0]; default: 0;
|
||||||
* This is the content of command 6. It consists of three parts:
|
* This is the content of command 6. It consists of three parts:
|
||||||
* op_code is the command, 0: RSTART, 1: WRITE, 2: READ, 3: STOP, 4: END.
|
* op_code is the command, 0: RSTART, 1: WRITE, 2: READ, 3: STOP, 4: END.
|
||||||
|
@ -1284,7 +1284,7 @@ extern "C" {
|
||||||
/** I2C_COMD7_REG register
|
/** I2C_COMD7_REG register
|
||||||
* I2C command register 7
|
* I2C command register 7
|
||||||
*/
|
*/
|
||||||
#define I2C_COMD7_REG (DR_REG_I2C_BASE + 0x74)
|
#define I2C_COMD7_REG(i) (REG_I2C_BASE(i) + 0x74)
|
||||||
/** I2C_COMMAND7 : R/W; bitpos: [13:0]; default: 0;
|
/** I2C_COMMAND7 : R/W; bitpos: [13:0]; default: 0;
|
||||||
* This is the content of command 7. It consists of three parts:
|
* This is the content of command 7. It consists of three parts:
|
||||||
* op_code is the command, 0: RSTART, 1: WRITE, 2: READ, 3: STOP, 4: END.
|
* op_code is the command, 0: RSTART, 1: WRITE, 2: READ, 3: STOP, 4: END.
|
||||||
|
@ -1308,7 +1308,7 @@ extern "C" {
|
||||||
/** I2C_SCL_ST_TIME_OUT_REG register
|
/** I2C_SCL_ST_TIME_OUT_REG register
|
||||||
* SCL status time out register
|
* SCL status time out register
|
||||||
*/
|
*/
|
||||||
#define I2C_SCL_ST_TIME_OUT_REG (DR_REG_I2C_BASE + 0x78)
|
#define I2C_SCL_ST_TIME_OUT_REG(i) (REG_I2C_BASE(i) + 0x78)
|
||||||
/** I2C_SCL_ST_TO_I2C : R/W; bitpos: [4:0]; default: 16;
|
/** I2C_SCL_ST_TO_I2C : R/W; bitpos: [4:0]; default: 16;
|
||||||
* The threshold value of SCL_FSM state unchanged period. It should be o more than 23
|
* The threshold value of SCL_FSM state unchanged period. It should be o more than 23
|
||||||
*/
|
*/
|
||||||
|
@ -1320,7 +1320,7 @@ extern "C" {
|
||||||
/** I2C_SCL_MAIN_ST_TIME_OUT_REG register
|
/** I2C_SCL_MAIN_ST_TIME_OUT_REG register
|
||||||
* SCL main status time out register
|
* SCL main status time out register
|
||||||
*/
|
*/
|
||||||
#define I2C_SCL_MAIN_ST_TIME_OUT_REG (DR_REG_I2C_BASE + 0x7c)
|
#define I2C_SCL_MAIN_ST_TIME_OUT_REG(i) (REG_I2C_BASE(i) + 0x7c)
|
||||||
/** I2C_SCL_MAIN_ST_TO_I2C : R/W; bitpos: [4:0]; default: 16;
|
/** I2C_SCL_MAIN_ST_TO_I2C : R/W; bitpos: [4:0]; default: 16;
|
||||||
* The threshold value of SCL_MAIN_FSM state unchanged period.nIt should be o more
|
* The threshold value of SCL_MAIN_FSM state unchanged period.nIt should be o more
|
||||||
* than 23
|
* than 23
|
||||||
|
@ -1333,7 +1333,7 @@ extern "C" {
|
||||||
/** I2C_SCL_SP_CONF_REG register
|
/** I2C_SCL_SP_CONF_REG register
|
||||||
* Power configuration register
|
* Power configuration register
|
||||||
*/
|
*/
|
||||||
#define I2C_SCL_SP_CONF_REG (DR_REG_I2C_BASE + 0x80)
|
#define I2C_SCL_SP_CONF_REG(i) (REG_I2C_BASE(i) + 0x80)
|
||||||
/** I2C_SCL_RST_SLV_EN : R/W/SC; bitpos: [0]; default: 0;
|
/** I2C_SCL_RST_SLV_EN : R/W/SC; bitpos: [0]; default: 0;
|
||||||
* When I2C master is IDLE, set this bit to send out SCL pulses. The number of pulses
|
* When I2C master is IDLE, set this bit to send out SCL pulses. The number of pulses
|
||||||
* equals to reg_scl_rst_slv_num[4:0].
|
* equals to reg_scl_rst_slv_num[4:0].
|
||||||
|
@ -1370,7 +1370,7 @@ extern "C" {
|
||||||
/** I2C_SCL_STRETCH_CONF_REG register
|
/** I2C_SCL_STRETCH_CONF_REG register
|
||||||
* Set SCL stretch of I2C slave
|
* Set SCL stretch of I2C slave
|
||||||
*/
|
*/
|
||||||
#define I2C_SCL_STRETCH_CONF_REG (DR_REG_I2C_BASE + 0x84)
|
#define I2C_SCL_STRETCH_CONF_REG(i) (REG_I2C_BASE(i) + 0x84)
|
||||||
/** I2C_STRETCH_PROTECT_NUM : R/W; bitpos: [9:0]; default: 0;
|
/** I2C_STRETCH_PROTECT_NUM : R/W; bitpos: [9:0]; default: 0;
|
||||||
* Configure the period of I2C slave stretching SCL line.
|
* Configure the period of I2C slave stretching SCL line.
|
||||||
*/
|
*/
|
||||||
|
@ -1412,7 +1412,7 @@ extern "C" {
|
||||||
/** I2C_DATE_REG register
|
/** I2C_DATE_REG register
|
||||||
* Version register
|
* Version register
|
||||||
*/
|
*/
|
||||||
#define I2C_DATE_REG (DR_REG_I2C_BASE + 0xf8)
|
#define I2C_DATE_REG(i) (REG_I2C_BASE(i) + 0xf8)
|
||||||
/** I2C_DATE : R/W; bitpos: [31:0]; default: 35656050;
|
/** I2C_DATE : R/W; bitpos: [31:0]; default: 35656050;
|
||||||
* This is the the version register.
|
* This is the the version register.
|
||||||
*/
|
*/
|
||||||
|
@ -1424,7 +1424,7 @@ extern "C" {
|
||||||
/** I2C_TXFIFO_START_ADDR_REG register
|
/** I2C_TXFIFO_START_ADDR_REG register
|
||||||
* I2C TXFIFO base address register
|
* I2C TXFIFO base address register
|
||||||
*/
|
*/
|
||||||
#define I2C_TXFIFO_START_ADDR_REG (DR_REG_I2C_BASE + 0x100)
|
#define I2C_TXFIFO_START_ADDR_REG(i) (REG_I2C_BASE(i) + 0x100)
|
||||||
/** I2C_TXFIFO_START_ADDR : HRO; bitpos: [31:0]; default: 0;
|
/** I2C_TXFIFO_START_ADDR : HRO; bitpos: [31:0]; default: 0;
|
||||||
* This is the I2C txfifo first address.
|
* This is the I2C txfifo first address.
|
||||||
*/
|
*/
|
||||||
|
@ -1436,7 +1436,7 @@ extern "C" {
|
||||||
/** I2C_RXFIFO_START_ADDR_REG register
|
/** I2C_RXFIFO_START_ADDR_REG register
|
||||||
* I2C RXFIFO base address register
|
* I2C RXFIFO base address register
|
||||||
*/
|
*/
|
||||||
#define I2C_RXFIFO_START_ADDR_REG (DR_REG_I2C_BASE + 0x180)
|
#define I2C_RXFIFO_START_ADDR_REG(i) (REG_I2C_BASE(i) + 0x180)
|
||||||
/** I2C_RXFIFO_START_ADDR : HRO; bitpos: [31:0]; default: 0;
|
/** I2C_RXFIFO_START_ADDR : HRO; bitpos: [31:0]; default: 0;
|
||||||
* This is the I2C rxfifo first address.
|
* This is the I2C rxfifo first address.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -36,6 +36,8 @@ typedef enum periph_retention_module_bitmap {
|
||||||
SLEEP_RETENTION_MODULE_GDMA_CH0 = BIT(24),
|
SLEEP_RETENTION_MODULE_GDMA_CH0 = BIT(24),
|
||||||
SLEEP_RETENTION_MODULE_GDMA_CH1 = BIT(25),
|
SLEEP_RETENTION_MODULE_GDMA_CH1 = BIT(25),
|
||||||
SLEEP_RETENTION_MODULE_GDMA_CH2 = BIT(26),
|
SLEEP_RETENTION_MODULE_GDMA_CH2 = BIT(26),
|
||||||
|
SLEEP_RETENTION_MODULE_I2C0 = BIT(27),
|
||||||
|
SLEEP_RETENTION_MODULE_I2C1 = BIT(28),
|
||||||
SLEEP_RETENTION_MODULE_ALL = (uint32_t)-1
|
SLEEP_RETENTION_MODULE_ALL = (uint32_t)-1
|
||||||
} periph_retention_module_bitmap_t;
|
} periph_retention_module_bitmap_t;
|
||||||
|
|
||||||
|
|
|
@ -1,22 +1,17 @@
|
||||||
// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
|
/*
|
||||||
//
|
* SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
*
|
||||||
// you may not use this file except in compliance with the License.
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
// You may obtain a copy of the License at
|
*/
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "soc/i2c_reg.h"
|
#include "soc/i2c_reg.h"
|
||||||
#include "soc/i2c_struct.h"
|
#include "soc/i2c_struct.h"
|
||||||
#include "soc/soc_caps.h"
|
#include "soc/soc_caps.h"
|
||||||
#include "soc/periph_defs.h"
|
#include "soc/periph_defs.h"
|
||||||
|
#if SOC_PM_SUPPORT_TOP_PD
|
||||||
|
#include "soc/regdma.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -33,6 +28,15 @@ typedef struct {
|
||||||
|
|
||||||
extern const i2c_signal_conn_t i2c_periph_signal[SOC_I2C_NUM];
|
extern const i2c_signal_conn_t i2c_periph_signal[SOC_I2C_NUM];
|
||||||
|
|
||||||
|
#if SOC_PM_SUPPORT_TOP_PD
|
||||||
|
typedef struct {
|
||||||
|
const regdma_entries_config_t *link_list;
|
||||||
|
uint32_t link_num;
|
||||||
|
} i2c_reg_ctx_link_t;
|
||||||
|
|
||||||
|
extern const i2c_reg_ctx_link_t i2c_regs_retention[SOC_I2C_NUM];
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -44,6 +44,7 @@ extern "C" {
|
||||||
#define REGDMA_MODEM_BT_BB_LINK(_pri) ((0x16 << 8) | _pri)
|
#define REGDMA_MODEM_BT_BB_LINK(_pri) ((0x16 << 8) | _pri)
|
||||||
#define REGDMA_MODEM_IEEE802154_LINK(_pri) ((0x17 << 8) | _pri)
|
#define REGDMA_MODEM_IEEE802154_LINK(_pri) ((0x17 << 8) | _pri)
|
||||||
#define REGDMA_GDMA_LINK(_pri) ((0x18 << 8) | _pri)
|
#define REGDMA_GDMA_LINK(_pri) ((0x18 << 8) | _pri)
|
||||||
|
#define REGDMA_I2C_LINK(_pri) ((0x19 << 8) | _pri)
|
||||||
#define REGDMA_MODEM_FE_LINK(_pri) ((0xFF << 8) | _pri)
|
#define REGDMA_MODEM_FE_LINK(_pri) ((0xFF << 8) | _pri)
|
||||||
|
|
||||||
#define REGDMA_LINK_PRI_SYS_CLK REGDMA_LINK_PRI_0
|
#define REGDMA_LINK_PRI_SYS_CLK REGDMA_LINK_PRI_0
|
||||||
|
|
|
@ -154,7 +154,6 @@ Light-sleep Peripheral Power Down
|
||||||
- Trace
|
- Trace
|
||||||
- Crypto: AES/ECC/HMAC/RSA/SHA/DS/XTA_AES/ECDSA
|
- Crypto: AES/ECC/HMAC/RSA/SHA/DS/XTA_AES/ECDSA
|
||||||
- SPI2
|
- SPI2
|
||||||
- I2C
|
|
||||||
- I2S
|
- I2S
|
||||||
- PCNT
|
- PCNT
|
||||||
- USB-Serial-JTAG
|
- USB-Serial-JTAG
|
||||||
|
|
|
@ -154,7 +154,6 @@ Light-sleep 外设下电
|
||||||
- Trace
|
- Trace
|
||||||
- Crypto: AES/ECC/HMAC/RSA/SHA/DS/XTA_AES/ECDSA
|
- Crypto: AES/ECC/HMAC/RSA/SHA/DS/XTA_AES/ECDSA
|
||||||
- SPI2
|
- SPI2
|
||||||
- I2C
|
|
||||||
- I2S
|
- I2S
|
||||||
- PCNT
|
- PCNT
|
||||||
- USB-Serial-JTAG
|
- USB-Serial-JTAG
|
||||||
|
|
|
@ -755,7 +755,6 @@ components/soc/esp32s3/uart_periph.c
|
||||||
components/soc/include/soc/dedic_gpio_periph.h
|
components/soc/include/soc/dedic_gpio_periph.h
|
||||||
components/soc/include/soc/emac_periph.h
|
components/soc/include/soc/emac_periph.h
|
||||||
components/soc/include/soc/gpio_periph.h
|
components/soc/include/soc/gpio_periph.h
|
||||||
components/soc/include/soc/i2c_periph.h
|
|
||||||
components/soc/include/soc/ledc_periph.h
|
components/soc/include/soc/ledc_periph.h
|
||||||
components/soc/lldesc.c
|
components/soc/lldesc.c
|
||||||
components/spi_flash/include/spi_flash_chip_boya.h
|
components/spi_flash/include/spi_flash_chip_boya.h
|
||||||
|
|
Ładowanie…
Reference in New Issue