From dca7c286d009024d8bacab52425c93a91ffc49c7 Mon Sep 17 00:00:00 2001 From: Song Ruo Jing Date: Wed, 15 May 2024 19:07:58 +0800 Subject: [PATCH] feat(uart): support uart module sleep retention on c6/h2/p4 --- .../esp_driver_uart/include/driver/uart.h | 7 + components/esp_driver_uart/src/uart.c | 114 +++++++++++++- .../test_apps/uart/main/CMakeLists.txt | 14 +- .../uart/main/test_uart_auto_lightsleep.c | 15 +- .../test_apps/uart/main/test_uart_retention.c | 148 ++++++++++++++++++ .../test_apps/uart/pytest_uart.py | 19 ++- .../test_apps/uart/sdkconfig.ci.release | 1 + .../test_apps/uart_vfs/main/test_app_main.c | 2 +- components/esp_hw_support/sleep_modes.c | 4 +- .../esp_hw_support/sleep_system_peripheral.c | 15 +- components/hal/esp32/include/hal/uart_ll.h | 8 +- components/hal/esp32c2/include/hal/uart_ll.h | 8 +- components/hal/esp32c3/include/hal/uart_ll.h | 8 +- components/hal/esp32c5/include/hal/gpio_ll.h | 2 + components/hal/esp32c5/include/hal/uart_ll.h | 6 +- components/hal/esp32c6/include/hal/gpio_ll.h | 2 + components/hal/esp32c6/include/hal/uart_ll.h | 10 +- components/hal/esp32c61/include/hal/gpio_ll.h | 2 + components/hal/esp32c61/include/hal/uart_ll.h | 6 +- components/hal/esp32h2/include/hal/gpio_ll.h | 2 + components/hal/esp32h2/include/hal/uart_ll.h | 10 +- components/hal/esp32p4/include/hal/gpio_ll.h | 2 + components/hal/esp32p4/include/hal/uart_ll.h | 13 +- components/hal/esp32s2/include/hal/uart_ll.h | 10 +- components/hal/esp32s3/include/hal/uart_ll.h | 8 +- components/soc/esp32/uart_periph.c | 21 +-- components/soc/esp32c2/uart_periph.c | 2 - components/soc/esp32c3/uart_periph.c | 20 +-- components/soc/esp32c5/beta3/gdma_periph.c | 6 +- .../beta3/include/soc/Kconfig.soc_caps.in | 4 + .../soc/esp32c5/beta3/include/soc/soc_caps.h | 2 + .../include/soc/system_periph_retention.h | 10 -- .../esp32c5/beta3/system_retention_periph.c | 10 -- components/soc/esp32c5/beta3/uart_periph.c | 43 ++++- components/soc/esp32c5/mp/gdma_periph.c | 6 +- components/soc/esp32c5/mp/uart_periph.c | 3 - components/soc/esp32c6/gdma_periph.c | 2 +- .../esp32c6/include/soc/Kconfig.soc_caps.in | 8 + .../include/soc/retention_periph_defs.h | 9 +- components/soc/esp32c6/include/soc/soc_caps.h | 2 + .../include/soc/system_periph_retention.h | 24 +-- .../soc/esp32c6/system_retention_periph.c | 10 -- components/soc/esp32c6/uart_periph.c | 55 ++++++- components/soc/esp32c61/uart_periph.c | 3 - components/soc/esp32h2/gdma_periph.c | 2 +- .../esp32h2/include/soc/Kconfig.soc_caps.in | 8 + .../include/soc/retention_periph_defs.h | 11 +- components/soc/esp32h2/include/soc/soc_caps.h | 3 + .../include/soc/system_periph_retention.h | 24 +-- .../soc/esp32h2/system_retention_periph.c | 10 -- components/soc/esp32h2/uart_periph.c | 54 ++++++- .../esp32p4/include/soc/Kconfig.soc_caps.in | 4 + .../include/soc/retention_periph_defs.h | 20 ++- components/soc/esp32p4/include/soc/soc_caps.h | 1 + .../include/soc/system_periph_retention.h | 10 -- .../soc/esp32p4/system_retention_periph.c | 10 -- components/soc/esp32p4/uart_periph.c | 73 ++++++++- components/soc/esp32s2/uart_periph.c | 20 +-- components/soc/esp32s3/uart_periph.c | 21 +-- components/soc/include/soc/gdma_periph.h | 3 - components/soc/include/soc/i2c_periph.h | 4 +- components/soc/include/soc/regdma.h | 1 + components/soc/include/soc/uart_periph.h | 17 +- docs/en/api-reference/peripherals/uart.rst | 4 + docs/zh_CN/api-reference/peripherals/uart.rst | 4 + tools/ci/check_copyright_ignore.txt | 4 - 66 files changed, 707 insertions(+), 277 deletions(-) create mode 100644 components/esp_driver_uart/test_apps/uart/main/test_uart_retention.c diff --git a/components/esp_driver_uart/include/driver/uart.h b/components/esp_driver_uart/include/driver/uart.h index 2ade613f599e..903bd670597b 100644 --- a/components/esp_driver_uart/include/driver/uart.h +++ b/components/esp_driver_uart/include/driver/uart.h @@ -46,6 +46,13 @@ typedef struct { lp_uart_sclk_t lp_source_clk; /*!< LP_UART source clock selection */ #endif }; + struct { +#if SOC_UART_SUPPORT_SLEEP_RETENTION + uint32_t backup_before_sleep: 1; /*!< If set, the driver will backup/restore the HP UART registers before entering/after exiting sleep mode. + By this approach, the system can power off HP UART's power domain. + This can save power, but at the expense of more RAM being consumed */ +#endif + } flags; /*!< Configuration flags */ } uart_config_t; /** diff --git a/components/esp_driver_uart/src/uart.c b/components/esp_driver_uart/src/uart.c index 5765800daef8..4be51375b11c 100644 --- a/components/esp_driver_uart/src/uart.c +++ b/components/esp_driver_uart/src/uart.c @@ -5,6 +5,7 @@ */ #include #include +#include #include "esp_types.h" #include "esp_attr.h" #include "esp_intr_alloc.h" @@ -32,6 +33,7 @@ #include "esp_rom_gpio.h" #include "clk_ctrl_os.h" #include "esp_pm.h" +#include "esp_private/sleep_retention.h" #ifdef CONFIG_UART_ISR_IN_IRAM #define UART_ISR_ATTR IRAM_ATTR @@ -95,10 +97,11 @@ static const char *UART_TAG = "uart"; // Check actual UART mode set #define UART_IS_MODE_SET(uart_number, mode) ((p_uart_obj[uart_number]->uart_mode == mode)) -#define UART_CONTEXT_INIT_DEF(uart_num) {\ - .hal.dev = UART_LL_GET_HW(uart_num),\ - INIT_CRIT_SECTION_LOCK_IN_STRUCT(spinlock)\ - .hw_enabled = false,\ +#define UART_CONTEXT_INIT_DEF(uart_num) { \ + .port_id = uart_num, \ + .hal.dev = UART_LL_GET_HW(uart_num), \ + INIT_CRIT_SECTION_LOCK_IN_STRUCT(spinlock) \ + .hw_enabled = false, \ } typedef struct { @@ -155,9 +158,15 @@ typedef struct { } uart_obj_t; typedef struct { + _lock_t mutex; /*!< Protect uart_module_enable, uart_module_disable, retention, etc. */ + uart_port_t port_id; uart_hal_context_t hal; /*!< UART hal context*/ DECLARE_CRIT_SECTION_LOCK_IN_STRUCT(spinlock) bool hw_enabled; +#if SOC_UART_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP + bool retention_link_inited; /*!< Mark whether the retention link is inited */ + bool retention_link_created; /*!< Mark whether the retention link is created */ +#endif } uart_context_t; static uart_obj_t *p_uart_obj[UART_NUM_MAX] = {0}; @@ -181,9 +190,13 @@ static uart_context_t uart_context[UART_NUM_MAX] = { static portMUX_TYPE uart_selectlock = portMUX_INITIALIZER_UNLOCKED; +#if SOC_UART_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP +static esp_err_t uart_create_sleep_retention_link_cb(void *arg); +#endif + static void uart_module_enable(uart_port_t uart_num) { - UART_ENTER_CRITICAL(&(uart_context[uart_num].spinlock)); + _lock_acquire(&(uart_context[uart_num].mutex)); if (uart_context[uart_num].hw_enabled != true) { if (uart_num < SOC_UART_HP_NUM) { HP_UART_BUS_CLK_ATOMIC() { @@ -194,6 +207,28 @@ static void uart_module_enable(uart_port_t uart_num) uart_ll_reset_register(uart_num); } } + +#if SOC_UART_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP + // Initialize sleep retention module for HP UART + if (uart_num != CONFIG_ESP_CONSOLE_UART_NUM) { // Console uart retention has been taken care in sleep_sys_periph_stdout_console_uart_retention_init + assert(!uart_context[uart_num].retention_link_inited); + sleep_retention_module_t module = UART_LL_SLEEP_RETENTION_MODULE_ID(uart_num); + sleep_retention_module_init_param_t init_param = { + .cbs = { + .create = { + .handle = uart_create_sleep_retention_link_cb, + .arg = &uart_context[uart_num], + }, + }, + .depends = BIT(SLEEP_RETENTION_MODULE_CLOCK_SYSTEM), + }; + if (sleep_retention_module_init(module, &init_param) == ESP_OK) { + uart_context[uart_num].retention_link_inited = true; + } else { + ESP_LOGW(UART_TAG, "init sleep retention failed for uart%d, power domain may be turned off during sleep", uart_num); + } + } +#endif } #if (SOC_UART_LP_NUM >= 1) else { @@ -205,14 +240,24 @@ static void uart_module_enable(uart_port_t uart_num) #endif uart_context[uart_num].hw_enabled = true; } - UART_EXIT_CRITICAL(&(uart_context[uart_num].spinlock)); + _lock_release(&(uart_context[uart_num].mutex)); } static void uart_module_disable(uart_port_t uart_num) { - UART_ENTER_CRITICAL(&(uart_context[uart_num].spinlock)); + _lock_acquire(&(uart_context[uart_num].mutex)); if (uart_context[uart_num].hw_enabled != false) { if (uart_num != CONFIG_ESP_CONSOLE_UART_NUM && uart_num < SOC_UART_HP_NUM) { +#if SOC_UART_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP + // Uninitialize sleep retention module for HP UART + sleep_retention_module_t module = UART_LL_SLEEP_RETENTION_MODULE_ID(uart_num); + assert(!uart_context[uart_num].retention_link_created); // HP UART sleep retention should have been freed at this moment + if (uart_context[uart_num].retention_link_inited) { + sleep_retention_module_deinit(module); + uart_context[uart_num].retention_link_inited = false; + } +#endif + HP_UART_BUS_CLK_ATOMIC() { uart_ll_enable_bus_clock(uart_num, false); } @@ -226,7 +271,7 @@ static void uart_module_disable(uart_port_t uart_num) #endif uart_context[uart_num].hw_enabled = false; } - UART_EXIT_CRITICAL(&(uart_context[uart_num].spinlock)); + _lock_release(&(uart_context[uart_num].mutex)); } esp_err_t uart_get_sclk_freq(uart_sclk_t sclk, uint32_t *out_freq_hz) @@ -799,6 +844,31 @@ esp_err_t uart_param_config(uart_port_t uart_num, const uart_config_t *uart_conf uart_module_enable(uart_num); +#if SOC_UART_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP + // Create sleep retention link if desired + if (uart_num != CONFIG_ESP_CONSOLE_UART_NUM && uart_num < SOC_UART_HP_NUM) { + _lock_acquire(&(uart_context[uart_num].mutex)); + sleep_retention_module_t module = UART_LL_SLEEP_RETENTION_MODULE_ID(uart_num); + if (uart_config->flags.backup_before_sleep && !uart_context[uart_num].retention_link_created) { + if (uart_context[uart_num].retention_link_inited) { + if (sleep_retention_module_allocate(module) == ESP_OK) { + uart_context[uart_num].retention_link_created = true; + } else { + // Even though the sleep retention module create failed, UART driver should still work, so just warning here + ESP_LOGW(UART_TAG, "create retention module failed, power domain can't turn off"); + } + } else { + ESP_LOGW(UART_TAG, "retention module not initialized first, unable to create retention module"); + } + } else if (!uart_config->flags.backup_before_sleep && uart_context[uart_num].retention_link_created) { + assert(uart_context[uart_num].retention_link_inited); + sleep_retention_module_free(module); + uart_context[uart_num].retention_link_created = false; + } + _lock_release(&(uart_context[uart_num].mutex)); + } +#endif + soc_module_clk_t uart_sclk_sel = 0; // initialize to an invalid module clock ID if (uart_num < SOC_UART_HP_NUM) { uart_sclk_sel = (soc_module_clk_t)((uart_config->source_clk) ? uart_config->source_clk : UART_SCLK_DEFAULT); // if no specifying the clock source (soc_module_clk_t starts from 1), then just use the default clock @@ -1712,6 +1782,20 @@ esp_err_t uart_driver_delete(uart_port_t uart_num) periph_rtc_dig_clk8m_disable(); } #endif + +#if SOC_UART_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP + // Free sleep retention link for HP UART + if (uart_num != CONFIG_ESP_CONSOLE_UART_NUM && uart_num < SOC_UART_HP_NUM) { + sleep_retention_module_t module = UART_LL_SLEEP_RETENTION_MODULE_ID(uart_num); + _lock_acquire(&(uart_context[uart_num].mutex)); + if (uart_context[uart_num].retention_link_created) { + assert(uart_context[uart_num].retention_link_inited); + sleep_retention_module_free(module); + uart_context[uart_num].retention_link_created = false; + } + _lock_release(&(uart_context[uart_num].mutex)); + } +#endif uart_module_disable(uart_num); return ESP_OK; } @@ -1867,3 +1951,17 @@ void uart_set_always_rx_timeout(uart_port_t uart_num, bool always_rx_timeout) p_uart_obj[uart_num]->rx_always_timeout_flg = false; } } + +#if SOC_UART_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP +static esp_err_t uart_create_sleep_retention_link_cb(void *arg) +{ + uart_context_t *group = (uart_context_t *)arg; + uart_port_t uart_num = group->port_id; + sleep_retention_module_t module = UART_LL_SLEEP_RETENTION_MODULE_ID(uart_num); + esp_err_t err = sleep_retention_entries_create(uart_reg_retention_info[uart_num].regdma_entry_array, + uart_reg_retention_info[uart_num].array_size, + REGDMA_LINK_PRI_UART, module); + ESP_RETURN_ON_ERROR(err, UART_TAG, "create retention link failed"); + return ESP_OK; +} +#endif diff --git a/components/esp_driver_uart/test_apps/uart/main/CMakeLists.txt b/components/esp_driver_uart/test_apps/uart/main/CMakeLists.txt index 22ab1202d2a9..27ff3d84b7d8 100644 --- a/components/esp_driver_uart/test_apps/uart/main/CMakeLists.txt +++ b/components/esp_driver_uart/test_apps/uart/main/CMakeLists.txt @@ -1,7 +1,19 @@ +set(srcs "test_app_main.c" + "test_uart.c") + +if(CONFIG_PM_ENABLE) + list(APPEND srcs "test_uart_auto_lightsleep.c") +endif() + +# Only if the target supports uart retention and the sdkconfig.ci.xxx contains at least PM_ENABLE=y +if(CONFIG_SOC_UART_SUPPORT_SLEEP_RETENTION AND CONFIG_PM_ENABLE) + list(APPEND srcs "test_uart_retention.c") +endif() + # In order for the cases defined by `TEST_CASE` to be linked into the final elf, # the component can be registered as WHOLE_ARCHIVE idf_component_register( - SRCS "test_app_main.c" "test_uart.c" "test_uart_auto_lightsleep.c" + SRCS ${srcs} REQUIRES esp_driver_uart unity esp_psram test_utils esp_driver_gpio esp_pm PRIV_INCLUDE_DIRS . WHOLE_ARCHIVE diff --git a/components/esp_driver_uart/test_apps/uart/main/test_uart_auto_lightsleep.c b/components/esp_driver_uart/test_apps/uart/main/test_uart_auto_lightsleep.c index b409deafd81e..a7df3a10bdcf 100644 --- a/components/esp_driver_uart/test_apps/uart/main/test_uart_auto_lightsleep.c +++ b/components/esp_driver_uart/test_apps/uart/main/test_uart_auto_lightsleep.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -27,15 +27,14 @@ #if CONFIG_XTAL_FREQ_40 #define MIN_FREQ 10 +#elif CONFIG_XTAL_FREQ_48 +#define MIN_FREQ 12 #elif CONFIG_XTAL_FREQ_32 #define MIN_FREQ 8 #elif CONFIG_XTAL_FREQ_26 #define MIN_FREQ 13 #endif -#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32P4) -#if CONFIG_PM_ENABLE - TEST_CASE("uart tx won't be blocked by auto light sleep", "[uart]") { uart_port_param_t port_param = {}; @@ -82,10 +81,8 @@ TEST_CASE("uart tx won't be blocked by auto light sleep", "[uart]") uart_driver_delete(port_num); free(data); -#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP - //When PD_CPU enabled, retention may cause 14K memory leak. Workaround to release the memory - sleep_cpu_configure(false); +#if CONFIG_FREERTOS_USE_TICKLESS_IDLE + pm_config.light_sleep_enable = false; + TEST_ESP_OK(esp_pm_configure(&pm_config)); #endif } -#endif // CONFIG_PM_ENABLE -#endif //!TEMPORARY_DISABLED_FOR_TARGETS(ESP32P4) diff --git a/components/esp_driver_uart/test_apps/uart/main/test_uart_retention.c b/components/esp_driver_uart/test_apps/uart/main/test_uart_retention.c new file mode 100644 index 000000000000..692d24f72f84 --- /dev/null +++ b/components/esp_driver_uart/test_apps/uart/main/test_uart_retention.c @@ -0,0 +1,148 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "sdkconfig.h" +#include "unity.h" +#include "driver/uart.h" +#include "esp_pm.h" +#include "esp_private/sleep_cpu.h" +#include "esp_clk_tree.h" +#include "esp_sleep.h" + +// UART retention test only need to be done on HP UART + +static const uart_port_t uart_num = UART_NUM_1; + +static void uart_init(bool backup_before_sleep) +{ + uart_config_t uart_config = { + .baud_rate = 115200, + .data_bits = UART_DATA_8_BITS, + .parity = UART_PARITY_DISABLE, + .stop_bits = UART_STOP_BITS_1, + .flow_ctrl = UART_HW_FLOWCTRL_DISABLE, + .source_clk = UART_SCLK_DEFAULT, + .flags.backup_before_sleep = backup_before_sleep, + }; + + TEST_ESP_OK(uart_driver_install(uart_num, 256, 0, 20, NULL, 0)); + TEST_ESP_OK(uart_param_config(uart_num, &uart_config)); + TEST_ESP_OK(uart_set_loop_back(uart_num, true)); +} + +TEST_CASE("uart restored correctly after auto light sleep", "[uart][hp-uart-only]") +{ + // Configure dynamic frequency scaling: + // maximum and minimum frequencies are set in sdkconfig, + // automatic light sleep is enabled if tickless idle support is enabled. + uint32_t xtal_hz = 0; + esp_clk_tree_src_get_freq_hz(SOC_MOD_CLK_XTAL, ESP_CLK_TREE_SRC_FREQ_PRECISION_EXACT, &xtal_hz); + esp_pm_config_t pm_config = { + .max_freq_mhz = CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ, + .min_freq_mhz = xtal_hz / 1000000, +#if CONFIG_FREERTOS_USE_TICKLESS_IDLE + .light_sleep_enable = true, +#endif + }; + TEST_ESP_OK(esp_pm_configure(&pm_config)); + + uart_init(true); + + // Ensure UART is fully idle before starting loopback RX/TX test + TEST_ESP_OK(uart_wait_tx_done(uart_num, portMAX_DELAY)); + vTaskDelay(pdMS_TO_TICKS(20)); // make sure last byte has flushed from TX FIFO + TEST_ESP_OK(uart_flush_input(uart_num)); + + for (int i = 0; i < 5; i++) { + char tx_data[20] = {0}; + char rx_data[20] = {0}; + int len = sprintf(tx_data, "Hello World %d!\n", i); + uart_write_bytes(uart_num, tx_data, len); + int size = 0; + // Polling to read the data back to avoid getting into auto light sleep + while (size < len) { + int bytes = uart_read_bytes(uart_num, (void *)((uint32_t)rx_data + size), 1, 0); + size += bytes; + } + rx_data[len] = '\0'; + printf("%s", rx_data); + TEST_ASSERT_TRUE(strcmp(tx_data, rx_data) == 0); + + vTaskDelay(pdMS_TO_TICKS(1000)); // auto light sleep + } + + TEST_ESP_OK(uart_driver_delete(uart_num)); + + pm_config.light_sleep_enable = false; + TEST_ESP_OK(esp_pm_configure(&pm_config)); +} + +TEST_CASE("uart restored correctly after manually enter light sleep", "[uart][hp-uart-only]") +{ + // Prepare a TOP PD sleep + TEST_ESP_OK(esp_sleep_enable_timer_wakeup(1 * 1000 * 1000)); + sleep_cpu_configure(true); + + uart_init(true); + + // Ensure UART is fully idle before starting loopback RX/TX test + TEST_ESP_OK(uart_wait_tx_done(uart_num, portMAX_DELAY)); + vTaskDelay(pdMS_TO_TICKS(20)); // make sure last byte has flushed from TX FIFO + TEST_ESP_OK(uart_flush_input(uart_num)); + + for (int i = 0; i < 5; i++) { + char tx_data[20] = {0}; + char rx_data[20] = {0}; + int len = sprintf(tx_data, "Hello World %d!\n", i); + uart_write_bytes(uart_num, tx_data, len); + int size = uart_read_bytes(uart_num, rx_data, len, pdMS_TO_TICKS(20)); + TEST_ASSERT_EQUAL(len, size); + rx_data[len] = '\0'; + printf("%s", rx_data); + TEST_ASSERT_TRUE(strcmp(tx_data, rx_data) == 0); + + printf("Going into sleep...\n"); + TEST_ESP_OK(esp_light_sleep_start()); + printf("Waked up!\n"); + } + + TEST_ESP_OK(uart_driver_delete(uart_num)); + TEST_ESP_OK(sleep_cpu_configure(false)); +} + +TEST_CASE("uart won't be powered down in light sleep if retention not created", "[uart][hp-uart-only]") +{ + // Prepare a TOP PD sleep + TEST_ESP_OK(esp_sleep_enable_timer_wakeup(1 * 1000 * 1000)); + sleep_cpu_configure(true); + + uart_init(false); // backup_before_sleep set to false, sleep retention module will be inited, but not created + + // Ensure UART is fully idle before starting loopback RX/TX test + TEST_ESP_OK(uart_wait_tx_done(uart_num, portMAX_DELAY)); + vTaskDelay(pdMS_TO_TICKS(20)); // make sure last byte has flushed from TX FIFO + TEST_ESP_OK(uart_flush_input(uart_num)); + + for (int i = 0; i < 3; i++) { + char tx_data[20] = {0}; + char rx_data[20] = {0}; + int len = sprintf(tx_data, "Hello World %d!\n", i); + uart_write_bytes(uart_num, tx_data, len); + int size = uart_read_bytes(uart_num, rx_data, len, pdMS_TO_TICKS(20)); + TEST_ASSERT_EQUAL(len, size); + rx_data[len] = '\0'; + printf("%s", rx_data); + TEST_ASSERT_TRUE(strcmp(tx_data, rx_data) == 0); + + printf("Going into sleep...\n"); + TEST_ESP_OK(esp_light_sleep_start()); // sleep without powering down TOP domain + printf("Waked up!\n"); + } + + TEST_ESP_OK(uart_driver_delete(uart_num)); + TEST_ESP_OK(sleep_cpu_configure(false)); +} diff --git a/components/esp_driver_uart/test_apps/uart/pytest_uart.py b/components/esp_driver_uart/test_apps/uart/pytest_uart.py index 4c94d8565231..e1be06ea5f96 100644 --- a/components/esp_driver_uart/test_apps/uart/pytest_uart.py +++ b/components/esp_driver_uart/test_apps/uart/pytest_uart.py @@ -28,15 +28,18 @@ def test_uart_single_dev(case_tester) -> None: # type: ignore dut = case_tester.first_dut chip_type = dut.app.target - for uart_port in input_argv.get(chip_type, []): - for case in case_tester.test_menu: - dut.serial.hard_reset() - dut._get_ready() - dut.confirm_write(case.index, expect_str=f'Running {case.name}...') + for case in case_tester.test_menu: + if 'hp-uart-only' not in case.groups: + for uart_port in input_argv.get(chip_type, []): + dut.serial.hard_reset() + dut._get_ready() + dut.confirm_write(case.index, expect_str=f'Running {case.name}...') - dut.expect("select to test 'uart' or 'lp_uart' port", timeout=10) - dut.write(f'{uart_port}') - dut.expect_unity_test_output() + dut.expect("select to test 'uart' or 'lp_uart' port", timeout=10) + dut.write(f'{uart_port}') + dut.expect_unity_test_output() + else: + dut._run_normal_case(case, reset=True) @pytest.mark.esp32s3 diff --git a/components/esp_driver_uart/test_apps/uart/sdkconfig.ci.release b/components/esp_driver_uart/test_apps/uart/sdkconfig.ci.release index 673b6f8f748a..a6be7c649bed 100644 --- a/components/esp_driver_uart/test_apps/uart/sdkconfig.ci.release +++ b/components/esp_driver_uart/test_apps/uart/sdkconfig.ci.release @@ -1,5 +1,6 @@ CONFIG_PM_ENABLE=y CONFIG_FREERTOS_USE_TICKLESS_IDLE=y +CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP=y CONFIG_COMPILER_OPTIMIZATION_SIZE=y CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y diff --git a/components/esp_driver_uart/test_apps/uart_vfs/main/test_app_main.c b/components/esp_driver_uart/test_apps/uart_vfs/main/test_app_main.c index 6ee4144067a1..6ab21f1f6736 100644 --- a/components/esp_driver_uart/test_apps/uart_vfs/main/test_app_main.c +++ b/components/esp_driver_uart/test_apps/uart_vfs/main/test_app_main.c @@ -9,7 +9,7 @@ #include "esp_heap_caps.h" // Some resources are lazy allocated, the threadhold is left for that case -#define TEST_MEMORY_LEAK_THRESHOLD (400) +#define TEST_MEMORY_LEAK_THRESHOLD (500) void setUp(void) { diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index f32c3b352ade..7ffe9241dc45 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -980,7 +980,7 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m /* On esp32c6, only the lp_aon pad hold function can only hold the GPIO state in the active mode. In order to avoid the leakage of the SPI cs pin, hold it here */ #if (CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && CONFIG_ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND) -#if !CONFIG_IDF_TARGET_ESP32H2 // ESP32H2 TODO IDF-7359: related rtcio ll func not supported yet +#if !CONFIG_IDF_TARGET_ESP32H2 // ESP32H2 TODO IDF-7359 if(!(pd_flags & RTC_SLEEP_PD_VDDSDIO)) { /* Cache suspend also means SPI bus IDLE, then we can hold SPI CS pin safely */ gpio_ll_hold_en(&GPIO, SPI_CS0_GPIO_NUM); @@ -1031,7 +1031,7 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m /* Unhold the SPI CS pin */ #if (CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && CONFIG_ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND) -#if !CONFIG_IDF_TARGET_ESP32H2 // ESP32H2 TODO IDF-7359: related rtcio ll func not supported yet +#if !CONFIG_IDF_TARGET_ESP32H2 // ESP32H2 TODO IDF-7359 if(!(pd_flags & RTC_SLEEP_PD_VDDSDIO)) { gpio_ll_hold_dis(&GPIO, SPI_CS0_GPIO_NUM); } diff --git a/components/esp_hw_support/sleep_system_peripheral.c b/components/esp_hw_support/sleep_system_peripheral.c index 2f37fb1542c7..97cbafd73b48 100644 --- a/components/esp_hw_support/sleep_system_peripheral.c +++ b/components/esp_hw_support/sleep_system_peripheral.c @@ -10,6 +10,7 @@ #include "sdkconfig.h" #include "soc/soc_caps.h" #include "soc/system_periph_retention.h" +#include "soc/uart_periph.h" #include "esp_sleep.h" #include "esp_log.h" @@ -52,13 +53,17 @@ static __attribute__((unused)) esp_err_t sleep_sys_periph_tee_apm_retention_init } #endif -static __attribute__((unused)) esp_err_t sleep_sys_periph_uart0_retention_init(void *arg) +#if CONFIG_ESP_CONSOLE_UART +static __attribute__((unused)) esp_err_t sleep_sys_periph_stdout_console_uart_retention_init(void *arg) { - esp_err_t err = sleep_retention_entries_create(uart_regs_retention, ARRAY_SIZE(uart_regs_retention), REGDMA_LINK_PRI_SYS_PERIPH_HIGH, SLEEP_RETENTION_MODULE_SYS_PERIPH); + esp_err_t err = sleep_retention_entries_create(uart_reg_retention_info[CONFIG_ESP_CONSOLE_UART_NUM].regdma_entry_array, + uart_reg_retention_info[CONFIG_ESP_CONSOLE_UART_NUM].array_size, + REGDMA_LINK_PRI_SYS_PERIPH_HIGH, SLEEP_RETENTION_MODULE_SYS_PERIPH); ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for digital peripherals (%s) retention", "UART"); - ESP_LOGD(TAG, "UART sleep retention initialization"); + ESP_LOGD(TAG, "stdout console UART sleep retention initialization"); return ESP_OK; } +#endif static __attribute__((unused)) esp_err_t sleep_sys_periph_iomux_retention_init(void *arg) { @@ -119,8 +124,10 @@ static __attribute__((unused)) esp_err_t sleep_sys_periph_retention_init(void *a err = sleep_sys_periph_tee_apm_retention_init(arg); if(err) goto error; #endif - err = sleep_sys_periph_uart0_retention_init(arg); +#if CONFIG_ESP_CONSOLE_UART + err = sleep_sys_periph_stdout_console_uart_retention_init(arg); if(err) goto error; +#endif err = sleep_sys_periph_iomux_retention_init(arg); if(err) goto error; err = sleep_sys_periph_spimem_retention_init(arg); diff --git a/components/hal/esp32/include/hal/uart_ll.h b/components/hal/esp32/include/hal/uart_ll.h index 218fd52ccd99..02134517e7a7 100644 --- a/components/hal/esp32/include/hal/uart_ll.h +++ b/components/hal/esp32/include/hal/uart_ll.h @@ -312,7 +312,7 @@ FORCE_INLINE_ATTR void uart_ll_read_rxfifo(uart_dev_t *hw, uint8_t *buf, uint32_ * * @param hw Beginning address of the peripheral registers. * @param buf The data buffer. - * @param wr_len The data length needs to be writen. + * @param wr_len The data length needs to be written. * * @return None */ @@ -535,7 +535,7 @@ FORCE_INLINE_ATTR void uart_ll_set_tx_idle_num(uart_dev_t *hw, uint32_t idle_num } /** - * @brief Configure the transmiter to send break chars. + * @brief Configure the transmitter to send break chars. * * @param hw Beginning address of the peripheral registers. * @param break_num The number of the break chars need to be send. @@ -600,7 +600,7 @@ FORCE_INLINE_ATTR void uart_ll_get_hw_flow_ctrl(uart_dev_t *hw, uart_hw_flowcont * @brief Configure the software flow control. * * @param hw Beginning address of the peripheral registers. - * @param flow_ctrl The UART sofware flow control settings. + * @param flow_ctrl The UART software flow control settings. * @param sw_flow_ctrl_en Set true to enable software flow control, otherwise set it false. * * @return None. @@ -894,7 +894,7 @@ FORCE_INLINE_ATTR bool uart_ll_is_hw_cts_en(uart_dev_t *hw) * @brief Configure TX signal loop back to RX module, just for the testing purposes * * @param hw Beginning address of the peripheral registers. - * @param loop_back_en Set ture to enable the loop back function, else set it false. + * @param loop_back_en Set true to enable the loop back function, else set it false. * * @return None */ diff --git a/components/hal/esp32c2/include/hal/uart_ll.h b/components/hal/esp32c2/include/hal/uart_ll.h index 67eda746fe25..7c5e3d12ed01 100644 --- a/components/hal/esp32c2/include/hal/uart_ll.h +++ b/components/hal/esp32c2/include/hal/uart_ll.h @@ -339,7 +339,7 @@ FORCE_INLINE_ATTR void uart_ll_read_rxfifo(uart_dev_t *hw, uint8_t *buf, uint32_ * * @param hw Beginning address of the peripheral registers. * @param buf The data buffer. - * @param wr_len The data length needs to be writen. + * @param wr_len The data length needs to be written. * * @return None */ @@ -518,7 +518,7 @@ FORCE_INLINE_ATTR void uart_ll_set_tx_idle_num(uart_dev_t *hw, uint32_t idle_num } /** - * @brief Configure the transmiter to send break chars. + * @brief Configure the transmitter to send break chars. * * @param hw Beginning address of the peripheral registers. * @param break_num The number of the break chars need to be send. @@ -583,7 +583,7 @@ FORCE_INLINE_ATTR void uart_ll_get_hw_flow_ctrl(uart_dev_t *hw, uart_hw_flowcont * @brief Configure the software flow control. * * @param hw Beginning address of the peripheral registers. - * @param flow_ctrl The UART sofware flow control settings. + * @param flow_ctrl The UART software flow control settings. * @param sw_flow_ctrl_en Set true to enable software flow control, otherwise set it false. * * @return None. @@ -881,7 +881,7 @@ FORCE_INLINE_ATTR bool uart_ll_is_hw_cts_en(uart_dev_t *hw) * @brief Configure TX signal loop back to RX module, just for the testing purposes * * @param hw Beginning address of the peripheral registers. - * @param loop_back_en Set ture to enable the loop back function, else set it false. + * @param loop_back_en Set true to enable the loop back function, else set it false. * * @return None */ diff --git a/components/hal/esp32c3/include/hal/uart_ll.h b/components/hal/esp32c3/include/hal/uart_ll.h index 9b83168323ed..f9f00ad85a8c 100644 --- a/components/hal/esp32c3/include/hal/uart_ll.h +++ b/components/hal/esp32c3/include/hal/uart_ll.h @@ -342,7 +342,7 @@ FORCE_INLINE_ATTR void uart_ll_read_rxfifo(uart_dev_t *hw, uint8_t *buf, uint32_ * * @param hw Beginning address of the peripheral registers. * @param buf The data buffer. - * @param wr_len The data length needs to be writen. + * @param wr_len The data length needs to be written. * * @return None */ @@ -521,7 +521,7 @@ FORCE_INLINE_ATTR void uart_ll_set_tx_idle_num(uart_dev_t *hw, uint32_t idle_num } /** - * @brief Configure the transmiter to send break chars. + * @brief Configure the transmitter to send break chars. * * @param hw Beginning address of the peripheral registers. * @param break_num The number of the break chars need to be send. @@ -586,7 +586,7 @@ FORCE_INLINE_ATTR void uart_ll_get_hw_flow_ctrl(uart_dev_t *hw, uart_hw_flowcont * @brief Configure the software flow control. * * @param hw Beginning address of the peripheral registers. - * @param flow_ctrl The UART sofware flow control settings. + * @param flow_ctrl The UART software flow control settings. * @param sw_flow_ctrl_en Set true to enable software flow control, otherwise set it false. * * @return None. @@ -884,7 +884,7 @@ FORCE_INLINE_ATTR bool uart_ll_is_hw_cts_en(uart_dev_t *hw) * @brief Configure TX signal loop back to RX module, just for the testing purposes * * @param hw Beginning address of the peripheral registers. - * @param loop_back_en Set ture to enable the loop back function, else set it false. + * @param loop_back_en Set true to enable the loop back function, else set it false. * * @return None */ diff --git a/components/hal/esp32c5/include/hal/gpio_ll.h b/components/hal/esp32c5/include/hal/gpio_ll.h index dc2268eb9530..fd9bc8d7fb44 100644 --- a/components/hal/esp32c5/include/hal/gpio_ll.h +++ b/components/hal/esp32c5/include/hal/gpio_ll.h @@ -427,6 +427,7 @@ static inline void gpio_ll_get_drive_capability(gpio_dev_t *hw, uint32_t gpio_nu * @param hw Peripheral GPIO hardware instance address. * @param gpio_num GPIO number, only support output GPIOs */ +__attribute__((always_inline)) static inline void gpio_ll_hold_en(gpio_dev_t *hw, uint32_t gpio_num) { LP_AON.gpio_hold0.gpio_hold0 |= GPIO_HOLD_MASK[gpio_num]; @@ -438,6 +439,7 @@ static inline void gpio_ll_hold_en(gpio_dev_t *hw, uint32_t gpio_num) * @param hw Peripheral GPIO hardware instance address. * @param gpio_num GPIO number, only support output GPIOs */ +__attribute__((always_inline)) static inline void gpio_ll_hold_dis(gpio_dev_t *hw, uint32_t gpio_num) { LP_AON.gpio_hold0.gpio_hold0 &= ~GPIO_HOLD_MASK[gpio_num]; diff --git a/components/hal/esp32c5/include/hal/uart_ll.h b/components/hal/esp32c5/include/hal/uart_ll.h index ea56ae3e2e98..a70fd636c61c 100644 --- a/components/hal/esp32c5/include/hal/uart_ll.h +++ b/components/hal/esp32c5/include/hal/uart_ll.h @@ -734,7 +734,7 @@ FORCE_INLINE_ATTR void uart_ll_set_tx_idle_num(uart_dev_t *hw, uint32_t idle_num } /** - * @brief Configure the transmiter to send break chars. + * @brief Configure the transmitter to send break chars. * * @param hw Beginning address of the peripheral registers. * @param break_num The number of the break chars need to be send. @@ -801,7 +801,7 @@ FORCE_INLINE_ATTR void uart_ll_get_hw_flow_ctrl(uart_dev_t *hw, uart_hw_flowcont * @brief Configure the software flow control. * * @param hw Beginning address of the peripheral registers. - * @param flow_ctrl The UART sofware flow control settings. + * @param flow_ctrl The UART software flow control settings. * @param sw_flow_ctrl_en Set true to enable software flow control, otherwise set it false. * * @return None. @@ -1132,7 +1132,7 @@ FORCE_INLINE_ATTR bool uart_ll_is_hw_cts_en(uart_dev_t *hw) * @brief Configure TX signal loop back to RX module, just for the testing purposes * * @param hw Beginning address of the peripheral registers. - * @param loop_back_en Set ture to enable the loop back function, else set it false. + * @param loop_back_en Set true to enable the loop back function, else set it false. * * @return None */ diff --git a/components/hal/esp32c6/include/hal/gpio_ll.h b/components/hal/esp32c6/include/hal/gpio_ll.h index c9310380c461..657043a7124e 100644 --- a/components/hal/esp32c6/include/hal/gpio_ll.h +++ b/components/hal/esp32c6/include/hal/gpio_ll.h @@ -396,6 +396,7 @@ static inline void gpio_ll_get_drive_capability(gpio_dev_t *hw, uint32_t gpio_nu * @param hw Peripheral GPIO hardware instance address. * @param gpio_num GPIO number, only support output GPIOs */ +__attribute__((always_inline)) static inline void gpio_ll_hold_en(gpio_dev_t *hw, uint32_t gpio_num) { LP_AON.gpio_hold0.gpio_hold0 |= GPIO_HOLD_MASK[gpio_num]; @@ -407,6 +408,7 @@ static inline void gpio_ll_hold_en(gpio_dev_t *hw, uint32_t gpio_num) * @param hw Peripheral GPIO hardware instance address. * @param gpio_num GPIO number, only support output GPIOs */ +__attribute__((always_inline)) static inline void gpio_ll_hold_dis(gpio_dev_t *hw, uint32_t gpio_num) { LP_AON.gpio_hold0.gpio_hold0 &= ~GPIO_HOLD_MASK[gpio_num]; diff --git a/components/hal/esp32c6/include/hal/uart_ll.h b/components/hal/esp32c6/include/hal/uart_ll.h index 88759dde2e6d..cbbf308bdc7d 100644 --- a/components/hal/esp32c6/include/hal/uart_ll.h +++ b/components/hal/esp32c6/include/hal/uart_ll.h @@ -61,6 +61,10 @@ extern "C" { #define UART_LL_PCR_REG_GET(hw, reg_suffix, field_suffix) \ (((hw) == &UART0) ? PCR.uart0_##reg_suffix.uart0_##field_suffix : PCR.uart1_##reg_suffix.uart1_##field_suffix) +// UART sleep retention module +#define UART_LL_SLEEP_RETENTION_MODULE_ID(uart_num) ((uart_num == UART_NUM_0) ? SLEEP_RETENTION_MODULE_UART0 : \ + (uart_num == UART_NUM_1) ? SLEEP_RETENTION_MODULE_UART1 : -1) + // Define UART interrupts typedef enum { UART_INTR_RXFIFO_FULL = (0x1 << 0), @@ -704,7 +708,7 @@ FORCE_INLINE_ATTR void uart_ll_set_tx_idle_num(uart_dev_t *hw, uint32_t idle_num } /** - * @brief Configure the transmiter to send break chars. + * @brief Configure the transmitter to send break chars. * * @param hw Beginning address of the peripheral registers. * @param break_num The number of the break chars need to be send. @@ -771,7 +775,7 @@ FORCE_INLINE_ATTR void uart_ll_get_hw_flow_ctrl(uart_dev_t *hw, uart_hw_flowcont * @brief Configure the software flow control. * * @param hw Beginning address of the peripheral registers. - * @param flow_ctrl The UART sofware flow control settings. + * @param flow_ctrl The UART software flow control settings. * @param sw_flow_ctrl_en Set true to enable software flow control, otherwise set it false. * * @return None. @@ -1102,7 +1106,7 @@ FORCE_INLINE_ATTR bool uart_ll_is_hw_cts_en(uart_dev_t *hw) * @brief Configure TX signal loop back to RX module, just for the testing purposes * * @param hw Beginning address of the peripheral registers. - * @param loop_back_en Set ture to enable the loop back function, else set it false. + * @param loop_back_en Set true to enable the loop back function, else set it false. * * @return None */ diff --git a/components/hal/esp32c61/include/hal/gpio_ll.h b/components/hal/esp32c61/include/hal/gpio_ll.h index f872f3648f38..1786ba296a0a 100644 --- a/components/hal/esp32c61/include/hal/gpio_ll.h +++ b/components/hal/esp32c61/include/hal/gpio_ll.h @@ -393,6 +393,7 @@ static inline void gpio_ll_get_drive_capability(gpio_dev_t *hw, uint32_t gpio_nu * @param hw Peripheral GPIO hardware instance address. * @param gpio_num GPIO number, only support output GPIOs */ +__attribute__((always_inline)) static inline void gpio_ll_hold_en(gpio_dev_t *hw, uint32_t gpio_num) { uint32_t mask = LP_AON.gpio_hold0.gpio_hold0; @@ -405,6 +406,7 @@ static inline void gpio_ll_hold_en(gpio_dev_t *hw, uint32_t gpio_num) * @param hw Peripheral GPIO hardware instance address. * @param gpio_num GPIO number, only support output GPIOs */ +__attribute__((always_inline)) static inline void gpio_ll_hold_dis(gpio_dev_t *hw, uint32_t gpio_num) { uint32_t mask = LP_AON.gpio_hold0.gpio_hold0; diff --git a/components/hal/esp32c61/include/hal/uart_ll.h b/components/hal/esp32c61/include/hal/uart_ll.h index bb7873e317f7..fb2dc72b8582 100644 --- a/components/hal/esp32c61/include/hal/uart_ll.h +++ b/components/hal/esp32c61/include/hal/uart_ll.h @@ -556,7 +556,7 @@ FORCE_INLINE_ATTR void uart_ll_set_tx_idle_num(uart_dev_t *hw, uint32_t idle_num } /** - * @brief Configure the transmiter to send break chars. + * @brief Configure the transmitter to send break chars. * * @param hw Beginning address of the peripheral registers. * @param break_num The number of the break chars need to be send. @@ -623,7 +623,7 @@ FORCE_INLINE_ATTR void uart_ll_get_hw_flow_ctrl(uart_dev_t *hw, uart_hw_flowcont * @brief Configure the software flow control. * * @param hw Beginning address of the peripheral registers. - * @param flow_ctrl The UART sofware flow control settings. + * @param flow_ctrl The UART software flow control settings. * @param sw_flow_ctrl_en Set true to enable software flow control, otherwise set it false. * * @return None. @@ -929,7 +929,7 @@ FORCE_INLINE_ATTR bool uart_ll_is_hw_cts_en(uart_dev_t *hw) * @brief Configure TX signal loop back to RX module, just for the testing purposes * * @param hw Beginning address of the peripheral registers. - * @param loop_back_en Set ture to enable the loop back function, else set it false. + * @param loop_back_en Set true to enable the loop back function, else set it false. * * @return None */ diff --git a/components/hal/esp32h2/include/hal/gpio_ll.h b/components/hal/esp32h2/include/hal/gpio_ll.h index 945ec27d2eda..ae7c64508dea 100644 --- a/components/hal/esp32h2/include/hal/gpio_ll.h +++ b/components/hal/esp32h2/include/hal/gpio_ll.h @@ -440,6 +440,7 @@ static inline void gpio_ll_get_drive_capability(gpio_dev_t *hw, gpio_num_t gpio_ * @param hw Peripheral GPIO hardware instance address. * @param gpio_num GPIO number, only support output GPIOs */ +__attribute__((always_inline)) static inline void gpio_ll_hold_en(gpio_dev_t *hw, gpio_num_t gpio_num) { LP_AON.gpio_hold0.gpio_hold0 |= GPIO_HOLD_MASK[gpio_num]; @@ -451,6 +452,7 @@ static inline void gpio_ll_hold_en(gpio_dev_t *hw, gpio_num_t gpio_num) * @param hw Peripheral GPIO hardware instance address. * @param gpio_num GPIO number, only support output GPIOs */ +__attribute__((always_inline)) static inline void gpio_ll_hold_dis(gpio_dev_t *hw, gpio_num_t gpio_num) { LP_AON.gpio_hold0.gpio_hold0 &= ~GPIO_HOLD_MASK[gpio_num]; diff --git a/components/hal/esp32h2/include/hal/uart_ll.h b/components/hal/esp32h2/include/hal/uart_ll.h index 9e018b2bdb9e..14cbbfb14f43 100644 --- a/components/hal/esp32h2/include/hal/uart_ll.h +++ b/components/hal/esp32h2/include/hal/uart_ll.h @@ -57,6 +57,10 @@ extern "C" { #define UART_LL_PCR_REG_GET(hw, reg_suffix, field_suffix) \ (((hw) == &UART0) ? PCR.uart0_##reg_suffix.uart0_##field_suffix : PCR.uart1_##reg_suffix.uart1_##field_suffix) +// UART sleep retention module +#define UART_LL_SLEEP_RETENTION_MODULE_ID(uart_num) ((uart_num == UART_NUM_0) ? SLEEP_RETENTION_MODULE_UART0 : \ + (uart_num == UART_NUM_1) ? SLEEP_RETENTION_MODULE_UART1 : -1) + // Define UART interrupts typedef enum { UART_INTR_RXFIFO_FULL = (0x1 << 0), @@ -554,7 +558,7 @@ FORCE_INLINE_ATTR void uart_ll_set_tx_idle_num(uart_dev_t *hw, uint32_t idle_num } /** - * @brief Configure the transmiter to send break chars. + * @brief Configure the transmitter to send break chars. * * @param hw Beginning address of the peripheral registers. * @param break_num The number of the break chars need to be send. @@ -621,7 +625,7 @@ FORCE_INLINE_ATTR void uart_ll_get_hw_flow_ctrl(uart_dev_t *hw, uart_hw_flowcont * @brief Configure the software flow control. * * @param hw Beginning address of the peripheral registers. - * @param flow_ctrl The UART sofware flow control settings. + * @param flow_ctrl The UART software flow control settings. * @param sw_flow_ctrl_en Set true to enable software flow control, otherwise set it false. * * @return None. @@ -928,7 +932,7 @@ FORCE_INLINE_ATTR bool uart_ll_is_hw_cts_en(uart_dev_t *hw) * @brief Configure TX signal loop back to RX module, just for the testing purposes * * @param hw Beginning address of the peripheral registers. - * @param loop_back_en Set ture to enable the loop back function, else set it false. + * @param loop_back_en Set true to enable the loop back function, else set it false. * * @return None */ diff --git a/components/hal/esp32p4/include/hal/gpio_ll.h b/components/hal/esp32p4/include/hal/gpio_ll.h index 7eea6c7369a4..1e1d6cfc7c1b 100644 --- a/components/hal/esp32p4/include/hal/gpio_ll.h +++ b/components/hal/esp32p4/include/hal/gpio_ll.h @@ -473,6 +473,7 @@ static inline void gpio_ll_get_drive_capability(gpio_dev_t *hw, uint32_t gpio_nu * @param hw Peripheral GPIO hardware instance address. * @param gpio_num GPIO number, only support output GPIOs */ +__attribute__((always_inline)) static inline void gpio_ll_hold_en(gpio_dev_t *hw, uint32_t gpio_num) { uint64_t bit_mask = 1ULL << gpio_num; @@ -498,6 +499,7 @@ static inline void gpio_ll_hold_en(gpio_dev_t *hw, uint32_t gpio_num) * @param hw Peripheral GPIO hardware instance address. * @param gpio_num GPIO number, only support output GPIOs */ +__attribute__((always_inline)) static inline void gpio_ll_hold_dis(gpio_dev_t *hw, uint32_t gpio_num) { uint64_t bit_mask = 1ULL << gpio_num; diff --git a/components/hal/esp32p4/include/hal/uart_ll.h b/components/hal/esp32p4/include/hal/uart_ll.h index e3f5a40d6ee6..70560c235d7b 100644 --- a/components/hal/esp32p4/include/hal/uart_ll.h +++ b/components/hal/esp32p4/include/hal/uart_ll.h @@ -45,6 +45,13 @@ extern "C" { #define UART_LL_FSM_IDLE (0x0) #define UART_LL_FSM_TX_WAIT_SEND (0xf) +// UART sleep retention module +#define UART_LL_SLEEP_RETENTION_MODULE_ID(uart_num) ((uart_num == UART_NUM_0) ? SLEEP_RETENTION_MODULE_UART0 : \ + (uart_num == UART_NUM_1) ? SLEEP_RETENTION_MODULE_UART1 : \ + (uart_num == UART_NUM_2) ? SLEEP_RETENTION_MODULE_UART2 : \ + (uart_num == UART_NUM_3) ? SLEEP_RETENTION_MODULE_UART3 : \ + (uart_num == UART_NUM_4) ? SLEEP_RETENTION_MODULE_UART4 : -1) + // Define UART interrupts typedef enum { UART_INTR_RXFIFO_FULL = (0x1 << 0), @@ -817,7 +824,7 @@ FORCE_INLINE_ATTR void uart_ll_set_tx_idle_num(uart_dev_t *hw, uint32_t idle_num } /** - * @brief Configure the transmiter to send break chars. + * @brief Configure the transmitter to send break chars. * * @param hw Beginning address of the peripheral registers. * @param break_num The number of the break chars need to be send. @@ -884,7 +891,7 @@ FORCE_INLINE_ATTR void uart_ll_get_hw_flow_ctrl(uart_dev_t *hw, uart_hw_flowcont * @brief Configure the software flow control. * * @param hw Beginning address of the peripheral registers. - * @param flow_ctrl The UART sofware flow control settings. + * @param flow_ctrl The UART software flow control settings. * @param sw_flow_ctrl_en Set true to enable software flow control, otherwise set it false. * * @return None. @@ -1215,7 +1222,7 @@ FORCE_INLINE_ATTR bool uart_ll_is_hw_cts_en(uart_dev_t *hw) * @brief Configure TX signal loop back to RX module, just for the testing purposes * * @param hw Beginning address of the peripheral registers. - * @param loop_back_en Set ture to enable the loop back function, else set it false. + * @param loop_back_en Set true to enable the loop back function, else set it false. * * @return None */ diff --git a/components/hal/esp32s2/include/hal/uart_ll.h b/components/hal/esp32s2/include/hal/uart_ll.h index 601cafeeeeda..4dfbeb954327 100644 --- a/components/hal/esp32s2/include/hal/uart_ll.h +++ b/components/hal/esp32s2/include/hal/uart_ll.h @@ -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 */ @@ -298,7 +298,7 @@ FORCE_INLINE_ATTR void uart_ll_read_rxfifo(uart_dev_t *hw, uint8_t *buf, uint32_ * * @param hw Beginning address of the peripheral registers. * @param buf The data buffer. - * @param wr_len The data length needs to be writen. + * @param wr_len The data length needs to be written. * * @return None */ @@ -476,7 +476,7 @@ FORCE_INLINE_ATTR void uart_ll_set_tx_idle_num(uart_dev_t *hw, uint32_t idle_num } /** - * @brief Configure the transmiter to send break chars. + * @brief Configure the transmitter to send break chars. * * @param hw Beginning address of the peripheral registers. * @param break_num The number of the break chars need to be send. @@ -541,7 +541,7 @@ FORCE_INLINE_ATTR void uart_ll_get_hw_flow_ctrl(uart_dev_t *hw, uart_hw_flowcont * @brief Configure the software flow control. * * @param hw Beginning address of the peripheral registers. - * @param flow_ctrl The UART sofware flow control settings. + * @param flow_ctrl The UART software flow control settings. * @param sw_flow_ctrl_en Set true to enable software flow control, otherwise set it false. * * @return None. @@ -832,7 +832,7 @@ FORCE_INLINE_ATTR bool uart_ll_is_hw_cts_en(uart_dev_t *hw) * @brief Configure TX signal loop back to RX module, just for the testing purposes * * @param hw Beginning address of the peripheral registers. - * @param loop_back_en Set ture to enable the loop back function, else set it false. + * @param loop_back_en Set true to enable the loop back function, else set it false. * * @return None */ diff --git a/components/hal/esp32s3/include/hal/uart_ll.h b/components/hal/esp32s3/include/hal/uart_ll.h index 1924c2411119..3dd538ec5057 100644 --- a/components/hal/esp32s3/include/hal/uart_ll.h +++ b/components/hal/esp32s3/include/hal/uart_ll.h @@ -326,7 +326,7 @@ FORCE_INLINE_ATTR void uart_ll_read_rxfifo(uart_dev_t *hw, uint8_t *buf, uint32_ * * @param hw Beginning address of the peripheral registers. * @param buf The data buffer. - * @param wr_len The data length needs to be writen. + * @param wr_len The data length needs to be written. * * @return None */ @@ -505,7 +505,7 @@ FORCE_INLINE_ATTR void uart_ll_set_tx_idle_num(uart_dev_t *hw, uint32_t idle_num } /** - * @brief Configure the transmiter to send break chars. + * @brief Configure the transmitter to send break chars. * * @param hw Beginning address of the peripheral registers. * @param break_num The number of the break chars need to be send. @@ -569,7 +569,7 @@ FORCE_INLINE_ATTR void uart_ll_get_hw_flow_ctrl(uart_dev_t *hw, uart_hw_flowcont * @brief Configure the software flow control. * * @param hw Beginning address of the peripheral registers. - * @param flow_ctrl The UART sofware flow control settings. + * @param flow_ctrl The UART software flow control settings. * @param sw_flow_ctrl_en Set true to enable software flow control, otherwise set it false. * * @return None. @@ -860,7 +860,7 @@ FORCE_INLINE_ATTR bool uart_ll_is_hw_cts_en(uart_dev_t *hw) * @brief Configure TX signal loop back to RX module, just for the testing purposes * * @param hw Beginning address of the peripheral registers. - * @param loop_back_en Set ture to enable the loop back function, else set it false. + * @param loop_back_en Set true to enable the loop back function, else set it false. * * @return None */ diff --git a/components/soc/esp32/uart_periph.c b/components/soc/esp32/uart_periph.c index b9a590fe1858..c9f0a2f4b4eb 100644 --- a/components/soc/esp32/uart_periph.c +++ b/components/soc/esp32/uart_periph.c @@ -1,16 +1,8 @@ -// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// 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. +/* + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include "soc/uart_periph.h" @@ -49,7 +41,6 @@ const uart_signal_conn_t uart_periph_signal[SOC_UART_NUM] = { } }, .irq = ETS_UART0_INTR_SOURCE, - .module = PERIPH_UART0_MODULE, }, { @@ -83,7 +74,6 @@ const uart_signal_conn_t uart_periph_signal[SOC_UART_NUM] = { }, }, .irq = ETS_UART1_INTR_SOURCE, - .module = PERIPH_UART1_MODULE, }, { @@ -117,6 +107,5 @@ const uart_signal_conn_t uart_periph_signal[SOC_UART_NUM] = { } }, .irq = ETS_UART2_INTR_SOURCE, - .module = PERIPH_UART2_MODULE, } }; diff --git a/components/soc/esp32c2/uart_periph.c b/components/soc/esp32c2/uart_periph.c index a23ff14937d6..e43bcd0daf63 100644 --- a/components/soc/esp32c2/uart_periph.c +++ b/components/soc/esp32c2/uart_periph.c @@ -41,7 +41,6 @@ const uart_signal_conn_t uart_periph_signal[SOC_UART_NUM] = { } }, .irq = ETS_UART0_INTR_SOURCE, - .module = PERIPH_UART0_MODULE, }, { @@ -75,6 +74,5 @@ const uart_signal_conn_t uart_periph_signal[SOC_UART_NUM] = { }, }, .irq = ETS_UART1_INTR_SOURCE, - .module = PERIPH_UART1_MODULE, }, }; diff --git a/components/soc/esp32c3/uart_periph.c b/components/soc/esp32c3/uart_periph.c index d4262c6776f5..73eb978cbe7d 100644 --- a/components/soc/esp32c3/uart_periph.c +++ b/components/soc/esp32c3/uart_periph.c @@ -1,16 +1,8 @@ -// Copyright 2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// 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. +/* + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include "soc/uart_periph.h" @@ -49,7 +41,6 @@ const uart_signal_conn_t uart_periph_signal[SOC_UART_NUM] = { } }, .irq = ETS_UART0_INTR_SOURCE, - .module = PERIPH_UART0_MODULE, }, { @@ -83,6 +74,5 @@ const uart_signal_conn_t uart_periph_signal[SOC_UART_NUM] = { }, }, .irq = ETS_UART1_INTR_SOURCE, - .module = PERIPH_UART1_MODULE, }, }; diff --git a/components/soc/esp32c5/beta3/gdma_periph.c b/components/soc/esp32c5/beta3/gdma_periph.c index f17b916be206..490061820104 100644 --- a/components/soc/esp32c5/beta3/gdma_periph.c +++ b/components/soc/esp32c5/beta3/gdma_periph.c @@ -49,7 +49,7 @@ static const regdma_entries_config_t gdma_g0p0_regs_retention[] = { g0p0_regs_map0[0], g0p0_regs_map0[1], \ g0p0_regs_map0[2], g0p0_regs_map0[3]), \ .owner = ENTRY(0) | ENTRY(2) }, - [1] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_GDMA_LINK(0x00), \ + [1] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_GDMA_LINK(0x01), \ G0P0_RETENTION_MAP_BASE_1, G0P0_RETENTION_MAP_BASE_1, \ G0P0_RETENTION_REGS_CNT_1, 0, 0, \ g0p0_regs_map1[0], g0p0_regs_map1[1], \ @@ -76,7 +76,7 @@ static const regdma_entries_config_t gdma_g0p1_regs_retention[] = { g0p1_regs_map0[0], g0p1_regs_map0[1], \ g0p1_regs_map0[2], g0p1_regs_map0[3]), \ .owner = ENTRY(0) | ENTRY(2) }, - [1] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_GDMA_LINK(0x00), \ + [1] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_GDMA_LINK(0x01), \ G0P1_RETENTION_MAP_BASE_1, G0P1_RETENTION_MAP_BASE_1, \ G0P1_RETENTION_REGS_CNT_1, 0, 0, \ g0p1_regs_map1[0], g0p1_regs_map1[1], \ @@ -103,7 +103,7 @@ static const regdma_entries_config_t gdma_g0p2_regs_retention[] = { g0p2_regs_map0[0], g0p2_regs_map0[1], \ g0p2_regs_map0[2], g0p2_regs_map0[3]), \ .owner = ENTRY(0) | ENTRY(2) }, - [1] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_GDMA_LINK(0x00), \ + [1] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_GDMA_LINK(0x01), \ G0P2_RETENTION_MAP_BASE_1, G0P2_RETENTION_MAP_BASE_1, \ G0P2_RETENTION_REGS_CNT_1, 0, 0, \ g0p2_regs_map1[0], g0p2_regs_map1[1], \ diff --git a/components/soc/esp32c5/beta3/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c5/beta3/include/soc/Kconfig.soc_caps.in index 0d15944cbf49..fe573d27c061 100644 --- a/components/soc/esp32c5/beta3/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c5/beta3/include/soc/Kconfig.soc_caps.in @@ -691,6 +691,10 @@ config SOC_UART_SUPPORT_FSM_TX_WAIT_SEND bool default y +config SOC_UART_SUPPORT_SLEEP_RETENTION + bool + default y + config SOC_COEX_HW_PTI bool default y diff --git a/components/soc/esp32c5/beta3/include/soc/soc_caps.h b/components/soc/esp32c5/beta3/include/soc/soc_caps.h index 3ca1bd23eb7e..a4eaf8deb196 100644 --- a/components/soc/esp32c5/beta3/include/soc/soc_caps.h +++ b/components/soc/esp32c5/beta3/include/soc/soc_caps.h @@ -498,6 +498,8 @@ // UART has an extra TX_WAIT_SEND state when the FIFO is not empty and XOFF is enabled #define SOC_UART_SUPPORT_FSM_TX_WAIT_SEND (1) +#define SOC_UART_SUPPORT_SLEEP_RETENTION (1) /*!< Support back up registers before sleep */ + /*-------------------------- COEXISTENCE HARDWARE PTI CAPS -------------------------------*/ #define SOC_COEX_HW_PTI (1) diff --git a/components/soc/esp32c5/beta3/include/soc/system_periph_retention.h b/components/soc/esp32c5/beta3/include/soc/system_periph_retention.h index b0cafd51bfda..23c82b295388 100644 --- a/components/soc/esp32c5/beta3/include/soc/system_periph_retention.h +++ b/components/soc/esp32c5/beta3/include/soc/system_periph_retention.h @@ -48,16 +48,6 @@ extern const regdma_entries_config_t tee_apm_regs_retention[TEE_APM_RETENTION_LI #define TEE_APM_HIGH_PRI_RETENTION_LINK_LEN 1 extern const regdma_entries_config_t tee_apm_highpri_regs_retention[TEE_APM_HIGH_PRI_RETENTION_LINK_LEN]; -/** - * @brief Provide access to uart configuration registers retention - * context definition. - * - * This is an internal function of the sleep retention driver, and is not - * useful for external use. - */ -#define UART_RETENTION_LINK_LEN 3 -extern const regdma_entries_config_t uart_regs_retention[UART_RETENTION_LINK_LEN]; - /** * @brief Provide access to timer group configuration registers retention * context definition. diff --git a/components/soc/esp32c5/beta3/system_retention_periph.c b/components/soc/esp32c5/beta3/system_retention_periph.c index d2a9863ca6cf..52822f92720e 100644 --- a/components/soc/esp32c5/beta3/system_retention_periph.c +++ b/components/soc/esp32c5/beta3/system_retention_periph.c @@ -44,16 +44,6 @@ const regdma_entries_config_t tee_apm_highpri_regs_retention[] = { }; _Static_assert((ARRAY_SIZE(tee_apm_regs_retention) == TEE_APM_RETENTION_LINK_LEN) && (ARRAY_SIZE(tee_apm_highpri_regs_retention) == TEE_APM_HIGH_PRI_RETENTION_LINK_LEN), "Inconsistent TEE_APM retention link length definitions"); -/* UART0 Registers Context */ -#define N_REGS_UART() (((UART_ID_REG(0) - UART_INT_RAW_REG(0)) / 4) + 1) -const regdma_entries_config_t uart_regs_retention[] = { - [0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_UART_LINK(0x00), UART_INT_RAW_REG(0), UART_INT_RAW_REG(0), N_REGS_UART(), 0, 0), .owner = ENTRY(0) | ENTRY(2) }, /* uart */ - /* Note: uart register should set update reg to make the configuration take effect */ - [1] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_UART_LINK(0x01), UART_REG_UPDATE_REG(0), UART_REG_UPDATE, UART_REG_UPDATE_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, - [2] = { .config = REGDMA_LINK_WAIT_INIT (REGDMA_UART_LINK(0x02), UART_REG_UPDATE_REG(0), 0x0, UART_REG_UPDATE_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) } -}; -_Static_assert(ARRAY_SIZE(uart_regs_retention) == UART_RETENTION_LINK_LEN, "Inconsistent UART retention link length definitions"); - /* IO MUX Registers Context */ #define N_REGS_IOMUX_0() (((IO_MUX_GPIO26_REG - REG_IO_MUX_BASE) / 4) + 1) #define N_REGS_IOMUX_1() (((GPIO_FUNC30_OUT_SEL_CFG_REG - GPIO_FUNC0_OUT_SEL_CFG_REG) / 4) + 1) diff --git a/components/soc/esp32c5/beta3/uart_periph.c b/components/soc/esp32c5/beta3/uart_periph.c index 154038a7b655..49af724e2697 100644 --- a/components/soc/esp32c5/beta3/uart_periph.c +++ b/components/soc/esp32c5/beta3/uart_periph.c @@ -5,6 +5,7 @@ */ #include "soc/uart_periph.h" +#include "soc/uart_reg.h" /* Bunch of constants for every UART peripheral: GPIO signals, irqs, hw addr of registers etc @@ -41,7 +42,6 @@ const uart_signal_conn_t uart_periph_signal[SOC_UART_NUM] = { } }, .irq = ETS_UART0_INTR_SOURCE, - .module = PERIPH_UART0_MODULE, }, { // HP UART1 @@ -75,7 +75,6 @@ const uart_signal_conn_t uart_periph_signal[SOC_UART_NUM] = { }, }, .irq = ETS_UART1_INTR_SOURCE, - .module = PERIPH_UART1_MODULE, }, { // LP UART0 @@ -109,6 +108,44 @@ const uart_signal_conn_t uart_periph_signal[SOC_UART_NUM] = { }, }, .irq = ETS_LP_UART_INTR_SOURCE, - .module = PERIPH_LP_UART0_MODULE, + }, +}; + +/** + * UART registers to be saved during sleep retention + * + * Reset TXFIFO and RXFIFO + * UART registers require set the reg_update bit to make the configuration take effect + */ +#define N_REGS_UART(uart_num) (((UART_ID_REG(uart_num) - UART_INT_RAW_REG(uart_num)) / 4) + 1) +#define UART_SLEEP_RETENTION_ENTRIES(uart_num) { \ + [0] = {.config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_UART_LINK(0x00), \ + UART_INT_RAW_REG(uart_num), UART_INT_RAW_REG(uart_num), \ + N_REGS_UART(uart_num), 0, 0 \ + ), \ + .owner = ENTRY(0) | ENTRY(2) }, \ + [1] = {.config = REGDMA_LINK_WRITE_INIT(REGDMA_UART_LINK(0x01), \ + UART_REG_UPDATE_REG(uart_num), UART_REG_UPDATE, \ + UART_REG_UPDATE_M, 1, 0 \ + ), \ + .owner = ENTRY(0) | ENTRY(2) }, \ + [2] = {.config = REGDMA_LINK_WAIT_INIT(REGDMA_UART_LINK(0x02), \ + UART_REG_UPDATE_REG(uart_num), 0x0, \ + UART_REG_UPDATE_M, 1, 0 \ + ), \ + .owner = ENTRY(0) | ENTRY(2) }, \ +} + +static const regdma_entries_config_t uart0_regdma_entries[] = UART_SLEEP_RETENTION_ENTRIES(0); +static const regdma_entries_config_t uart1_regdma_entries[] = UART_SLEEP_RETENTION_ENTRIES(1); + +const uart_reg_retention_info_t uart_reg_retention_info[SOC_UART_HP_NUM] = { + [0] = { + .regdma_entry_array = uart0_regdma_entries, + .array_size = ARRAY_SIZE(uart0_regdma_entries), + }, + [1] = { + .regdma_entry_array = uart1_regdma_entries, + .array_size = ARRAY_SIZE(uart1_regdma_entries), }, }; diff --git a/components/soc/esp32c5/mp/gdma_periph.c b/components/soc/esp32c5/mp/gdma_periph.c index 3217ef607cf4..9385a76ed59f 100644 --- a/components/soc/esp32c5/mp/gdma_periph.c +++ b/components/soc/esp32c5/mp/gdma_periph.c @@ -56,7 +56,7 @@ static const regdma_entries_config_t gdma_g0p0_regs_retention[] = { g0p0_regs_map0[0], g0p0_regs_map0[1], \ g0p0_regs_map0[2], g0p0_regs_map0[3]), \ .owner = ENTRY(0) | ENTRY(2) }, \ - [1] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_AHB_DMA_LINK(0x00), \ + [1] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_AHB_DMA_LINK(0x01), \ G0P0_RETENTION_MAP_BASE_1, G0P0_RETENTION_MAP_BASE_1, \ G0P0_RETENTION_REGS_CNT_1, 0, 0, \ g0p0_regs_map1[0], g0p0_regs_map1[1], \ @@ -90,7 +90,7 @@ static const regdma_entries_config_t gdma_g0p1_regs_retention[] = { g0p1_regs_map0[0], g0p1_regs_map0[1], \ g0p1_regs_map0[2], g0p1_regs_map0[3]), \ .owner = ENTRY(0) | ENTRY(2) }, - [1] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_AHB_DMA_LINK(0x00), \ + [1] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_AHB_DMA_LINK(0x01), \ G0P1_RETENTION_MAP_BASE_1, G0P1_RETENTION_MAP_BASE_1, \ G0P1_RETENTION_REGS_CNT_1, 0, 0, \ g0p1_regs_map1[0], g0p1_regs_map1[1], \ @@ -125,7 +125,7 @@ static const regdma_entries_config_t gdma_g0p2_regs_retention[] = { g0p2_regs_map0[0], g0p2_regs_map0[1], \ g0p2_regs_map0[2], g0p2_regs_map0[3]), \ .owner = ENTRY(0) | ENTRY(2) }, - [1] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_AHB_DMA_LINK(0x00), \ + [1] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_AHB_DMA_LINK(0x01), \ G0P2_RETENTION_MAP_BASE_1, G0P2_RETENTION_MAP_BASE_1, \ G0P2_RETENTION_REGS_CNT_1, 0, 0, \ g0p2_regs_map1[0], g0p2_regs_map1[1], \ diff --git a/components/soc/esp32c5/mp/uart_periph.c b/components/soc/esp32c5/mp/uart_periph.c index e641d11f7479..13a83fce13b7 100644 --- a/components/soc/esp32c5/mp/uart_periph.c +++ b/components/soc/esp32c5/mp/uart_periph.c @@ -41,7 +41,6 @@ const uart_signal_conn_t uart_periph_signal[SOC_UART_NUM] = { } }, .irq = ETS_UART0_INTR_SOURCE, - .module = PERIPH_UART0_MODULE, }, { // HP UART1 @@ -75,7 +74,6 @@ const uart_signal_conn_t uart_periph_signal[SOC_UART_NUM] = { }, }, .irq = ETS_UART1_INTR_SOURCE, - .module = PERIPH_UART1_MODULE, }, { // LP UART0 @@ -109,6 +107,5 @@ const uart_signal_conn_t uart_periph_signal[SOC_UART_NUM] = { }, }, .irq = ETS_LP_UART_INTR_SOURCE, - .module = PERIPH_LP_UART0_MODULE, }, }; diff --git a/components/soc/esp32c6/gdma_periph.c b/components/soc/esp32c6/gdma_periph.c index c5795713ea18..fd24fad766c5 100644 --- a/components/soc/esp32c6/gdma_periph.c +++ b/components/soc/esp32c6/gdma_periph.c @@ -84,7 +84,7 @@ static const regdma_entries_config_t gdma_g0p2_regs_retention[] = { g0p2_regs_map0[0], g0p2_regs_map0[1], \ g0p2_regs_map0[2], g0p2_regs_map0[3]), \ .owner = ENTRY(0) | ENTRY(2) }, - [1] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_GDMA_LINK(0x00), \ + [1] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_GDMA_LINK(0x01), \ G0P2_RETENTION_MAP_BASE_1, G0P2_RETENTION_MAP_BASE_1, \ G0P2_RETENTION_REGS_CNT_1, 0, 0, \ g0p2_regs_map1[0], g0p2_regs_map1[1], \ diff --git a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in index 1451df15906b..092fb261eb40 100644 --- a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in @@ -615,6 +615,10 @@ config SOC_I2C_SLAVE_SUPPORT_SLAVE_UNMATCH bool default y +config SOC_I2C_SUPPORT_SLEEP_RETENTION + bool + default y + config SOC_LP_I2C_NUM int default 1 @@ -1255,6 +1259,10 @@ config SOC_UART_HAS_LP_UART bool default y +config SOC_UART_SUPPORT_SLEEP_RETENTION + bool + default y + config SOC_UART_SUPPORT_FSM_TX_WAIT_SEND bool default y diff --git a/components/soc/esp32c6/include/soc/retention_periph_defs.h b/components/soc/esp32c6/include/soc/retention_periph_defs.h index 47b33960179a..e0d6c4da4ccb 100644 --- a/components/soc/esp32c6/include/soc/retention_periph_defs.h +++ b/components/soc/esp32c6/include/soc/retention_periph_defs.h @@ -34,6 +34,8 @@ typedef enum periph_retention_module { SLEEP_RETENTION_MODULE_ADC = 11, SLEEP_RETENTION_MODULE_I2C0 = 12, SLEEP_RETENTION_MODULE_RMT0 = 13, + SLEEP_RETENTION_MODULE_UART0 = 14, + SLEEP_RETENTION_MODULE_UART1 = 15, /* Modem module, which includes WiFi, BLE and 802.15.4 */ SLEEP_RETENTION_MODULE_WIFI_MAC = 26, @@ -64,6 +66,8 @@ typedef enum periph_retention_module_bitmap { SLEEP_RETENTION_MODULE_BM_ADC = BIT(SLEEP_RETENTION_MODULE_ADC), SLEEP_RETENTION_MODULE_BM_I2C0 = BIT(SLEEP_RETENTION_MODULE_I2C0), SLEEP_RETENTION_MODULE_BM_RMT0 = BIT(SLEEP_RETENTION_MODULE_RMT0), + SLEEP_RETENTION_MODULE_BM_UART0 = BIT(SLEEP_RETENTION_MODULE_UART0), + SLEEP_RETENTION_MODULE_BM_UART1 = BIT(SLEEP_RETENTION_MODULE_UART1), /* modem module, which includes WiFi, BLE and 802.15.4 */ SLEEP_RETENTION_MODULE_BM_WIFI_MAC = BIT(SLEEP_RETENTION_MODULE_WIFI_MAC), SLEEP_RETENTION_MODULE_BM_WIFI_BB = BIT(SLEEP_RETENTION_MODULE_WIFI_BB), @@ -85,7 +89,10 @@ typedef enum periph_retention_module_bitmap { | SLEEP_RETENTION_MODULE_BM_GDMA_CH2 \ | SLEEP_RETENTION_MODULE_BM_ADC \ | SLEEP_RETENTION_MODULE_BM_I2C0 \ - | SLEEP_RETENTION_MODULE_BM_RMT0) + | SLEEP_RETENTION_MODULE_BM_RMT0 \ + | SLEEP_RETENTION_MODULE_BM_UART0 \ + | SLEEP_RETENTION_MODULE_BM_UART1 \ + ) #ifdef __cplusplus } diff --git a/components/soc/esp32c6/include/soc/soc_caps.h b/components/soc/esp32c6/include/soc/soc_caps.h index a25bb048fcd4..31bc9530ec35 100644 --- a/components/soc/esp32c6/include/soc/soc_caps.h +++ b/components/soc/esp32c6/include/soc/soc_caps.h @@ -252,6 +252,7 @@ #define SOC_I2C_SLAVE_CAN_GET_STRETCH_CAUSE (1) #define SOC_I2C_SLAVE_SUPPORT_I2CRAM_ACCESS (1) #define SOC_I2C_SLAVE_SUPPORT_SLAVE_UNMATCH (1) +#define SOC_I2C_SUPPORT_SLEEP_RETENTION (1) /*-------------------------- LP_I2C CAPS -------------------------------------*/ // ESP32-C6 has 1 LP_I2C @@ -491,6 +492,7 @@ #define SOC_UART_SUPPORT_XTAL_CLK (1) /*!< Support XTAL clock as the clock source */ #define SOC_UART_SUPPORT_WAKEUP_INT (1) /*!< Support UART wakeup interrupt */ #define SOC_UART_HAS_LP_UART (1) /*!< Support LP UART */ +#define SOC_UART_SUPPORT_SLEEP_RETENTION (1) /*!< Support back up registers before sleep */ // UART has an extra TX_WAIT_SEND state when the FIFO is not empty and XOFF is enabled #define SOC_UART_SUPPORT_FSM_TX_WAIT_SEND (1) diff --git a/components/soc/esp32c6/include/soc/system_periph_retention.h b/components/soc/esp32c6/include/soc/system_periph_retention.h index 6c84932742de..539b3500d35c 100644 --- a/components/soc/esp32c6/include/soc/system_periph_retention.h +++ b/components/soc/esp32c6/include/soc/system_periph_retention.h @@ -17,7 +17,7 @@ extern "C" /** * @brief Provide access to interrupt matrix configuration registers retention - * context defination. + * context definition. * * This is an internal function of the sleep retention driver, and is not * useful for external use. @@ -27,7 +27,7 @@ extern const regdma_entries_config_t intr_matrix_regs_retention[INT_MTX_RETENTIO /** * @brief Provide access to hp_system configuration registers retention - * context defination. + * context definition. * * This is an internal function of the sleep retention driver, and is not * useful for external use. @@ -37,7 +37,7 @@ extern const regdma_entries_config_t hp_system_regs_retention[HP_SYSTEM_RETENTIO /** * @brief Provide access to TEE_APM configuration registers retention - * context defination. + * context definition. * * This is an internal function of the sleep retention driver, and is not * useful for external use. @@ -47,19 +47,9 @@ extern const regdma_entries_config_t tee_apm_regs_retention[TEE_APM_RETENTION_LI #define TEE_APM_HIGH_PRI_RETENTION_LINK_LEN 1 extern const regdma_entries_config_t tee_apm_highpri_regs_retention[TEE_APM_HIGH_PRI_RETENTION_LINK_LEN]; -/** - * @brief Provide access to uart configuration registers retention - * context defination. - * - * This is an internal function of the sleep retention driver, and is not - * useful for external use. - */ -#define UART_RETENTION_LINK_LEN 3 -extern const regdma_entries_config_t uart_regs_retention[UART_RETENTION_LINK_LEN]; - /** * @brief Provide access to timer group configuration registers retention - * context defination. + * context definition. * * This is an internal function of the sleep retention driver, and is not * useful for external use. @@ -69,7 +59,7 @@ extern const regdma_entries_config_t tg_regs_retention[TIMG_RETENTION_LINK_LEN]; /** * @brief Provide access to IOMUX configuration registers retention - * context defination. + * context definition. * * This is an internal function of the sleep retention driver, and is not * useful for external use. @@ -79,7 +69,7 @@ extern const regdma_entries_config_t iomux_regs_retention[IOMUX_RETENTION_LINK_L /** * @brief Provide access to spimem configuration registers retention - * context defination. + * context definition. * * This is an internal function of the sleep retention driver, and is not * useful for external use. @@ -89,7 +79,7 @@ extern const regdma_entries_config_t spimem_regs_retention[SPIMEM_RETENTION_LINK /** * @brief Provide access to systimer configuration registers retention - * context defination. + * context definition. * * This is an internal function of the sleep retention driver, and is not * useful for external use. diff --git a/components/soc/esp32c6/system_retention_periph.c b/components/soc/esp32c6/system_retention_periph.c index b9645c39a439..4ff06bdbcbfb 100644 --- a/components/soc/esp32c6/system_retention_periph.c +++ b/components/soc/esp32c6/system_retention_periph.c @@ -44,16 +44,6 @@ const regdma_entries_config_t tee_apm_highpri_regs_retention[] = { }; _Static_assert((ARRAY_SIZE(tee_apm_regs_retention) == TEE_APM_RETENTION_LINK_LEN) && (ARRAY_SIZE(tee_apm_highpri_regs_retention) == TEE_APM_HIGH_PRI_RETENTION_LINK_LEN), "Inconsistent TEE_APM retention link length definitions"); -/* UART0 Registers Context */ -#define N_REGS_UART() (((UART_ID_REG(0) - UART_INT_RAW_REG(0)) / 4) + 1) -const regdma_entries_config_t uart_regs_retention[] = { - [0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_UART_LINK(0x00), UART_INT_RAW_REG(0), UART_INT_RAW_REG(0), N_REGS_UART(), 0, 0), .owner = ENTRY(0) | ENTRY(2) }, /* uart */ - /* Note: uart register should set update reg to make the configuration take effect */ - [1] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_UART_LINK(0x01), UART_REG_UPDATE_REG(0), UART_REG_UPDATE, UART_REG_UPDATE_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, - [2] = { .config = REGDMA_LINK_WAIT_INIT (REGDMA_UART_LINK(0x02), UART_REG_UPDATE_REG(0), 0x0, UART_REG_UPDATE_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) } -}; -_Static_assert(ARRAY_SIZE(uart_regs_retention) == UART_RETENTION_LINK_LEN, "Inconsistent UART retention link length definitions"); - /* IO MUX Registers Context */ #define N_REGS_IOMUX_0() (((IO_MUX_GPIO30_REG - REG_IO_MUX_BASE) / 4) + 1) #define N_REGS_IOMUX_1() (((GPIO_FUNC34_OUT_SEL_CFG_REG - GPIO_FUNC0_OUT_SEL_CFG_REG) / 4) + 1) diff --git a/components/soc/esp32c6/uart_periph.c b/components/soc/esp32c6/uart_periph.c index c353d5e3b3cb..22c7f99d1197 100644 --- a/components/soc/esp32c6/uart_periph.c +++ b/components/soc/esp32c6/uart_periph.c @@ -1,10 +1,11 @@ /* - * 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/uart_periph.h" +#include "soc/uart_reg.h" /* Bunch of constants for every UART peripheral: GPIO signals, irqs, hw addr of registers etc @@ -41,7 +42,6 @@ const uart_signal_conn_t uart_periph_signal[SOC_UART_NUM] = { } }, .irq = ETS_UART0_INTR_SOURCE, - .module = PERIPH_UART0_MODULE, }, { // HP UART1 @@ -75,7 +75,6 @@ const uart_signal_conn_t uart_periph_signal[SOC_UART_NUM] = { }, }, .irq = ETS_UART1_INTR_SOURCE, - .module = PERIPH_UART1_MODULE, }, { // LP UART0 @@ -109,6 +108,54 @@ const uart_signal_conn_t uart_periph_signal[SOC_UART_NUM] = { }, }, .irq = ETS_LP_UART_INTR_SOURCE, - .module = PERIPH_LP_UART0_MODULE, + }, +}; + +/** + * UART registers to be saved during sleep retention + * + * Reset TXFIFO and RXFIFO + * UART registers require set the reg_update bit to make the configuration take effect + * + * UART_INT_ENA_REG, UART_CLKDIV_SYNC_REG, UART_RX_FILT_REG, UART_CONF0_SYNC_REG, UART_CONF1_REG, + * UART_HWFC_CONF_SYNC_REG, UART_SLEEP_CONF0_REG, UART_SLEEP_CONF1_REG, UART_SLEEP_CONF2_REG, + * UART_SWFC_CONF0_SYNC_REG, UART_SWFC_CONF1_REG, UART_TXBRK_CONF_SYNC_REG, UART_IDLE_CONF_SYNC_REG, + * UART_RS485_CONF_SYNC_REG, UART_AT_CMD_PRECNT_SYNC_REG, UART_AT_CMD_POSTCNT_SYNC_REG, UART_AT_CMD_GAPTOUT_SYNC_REG, + * UART_AT_CMD_CHAR_SYNC_REG, UART_MEM_CONF_REG, UART_TOUT_CONF_SYNC_REG, UART_ID_REG + */ +#define UART_RETENTION_ADDR_MAP_REGS_CNT 21 +#define UART_RETENTION_REGS_BASE(i) UART_INT_ENA_REG(i) +static const uint32_t uart_regs_map[4] = {0x7fff6d, 0x10, 0x0, 0x0}; +#define UART_SLEEP_RETENTION_ENTRIES(uart_num) { \ + [0] = {.config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_UART_LINK(0x00), \ + UART_RETENTION_REGS_BASE(uart_num), UART_RETENTION_REGS_BASE(uart_num), \ + UART_RETENTION_ADDR_MAP_REGS_CNT, 0, 0, \ + uart_regs_map[0], uart_regs_map[1], \ + uart_regs_map[2], uart_regs_map[3] \ + ), \ + .owner = ENTRY(0) | ENTRY(2) }, \ + [1] = {.config = REGDMA_LINK_WRITE_INIT(REGDMA_UART_LINK(0x01), \ + UART_REG_UPDATE_REG(uart_num), UART_REG_UPDATE, \ + UART_REG_UPDATE_M, 1, 0 \ + ), \ + .owner = ENTRY(0) | ENTRY(2) }, \ + [2] = {.config = REGDMA_LINK_WAIT_INIT(REGDMA_UART_LINK(0x02), \ + UART_REG_UPDATE_REG(uart_num), 0x0, \ + UART_REG_UPDATE_M, 1, 0 \ + ), \ + .owner = ENTRY(0) | ENTRY(2) }, \ +} + +static const regdma_entries_config_t uart0_regdma_entries[] = UART_SLEEP_RETENTION_ENTRIES(0); +static const regdma_entries_config_t uart1_regdma_entries[] = UART_SLEEP_RETENTION_ENTRIES(1); + +const uart_reg_retention_info_t uart_reg_retention_info[SOC_UART_HP_NUM] = { + [0] = { + .regdma_entry_array = uart0_regdma_entries, + .array_size = ARRAY_SIZE(uart0_regdma_entries), + }, + [1] = { + .regdma_entry_array = uart1_regdma_entries, + .array_size = ARRAY_SIZE(uart1_regdma_entries), }, }; diff --git a/components/soc/esp32c61/uart_periph.c b/components/soc/esp32c61/uart_periph.c index 4058abaecf5d..5e3c90c8cce3 100644 --- a/components/soc/esp32c61/uart_periph.c +++ b/components/soc/esp32c61/uart_periph.c @@ -41,7 +41,6 @@ const uart_signal_conn_t uart_periph_signal[SOC_UART_NUM] = { } }, .irq = ETS_UART0_INTR_SOURCE, - .module = PERIPH_UART0_MODULE, }, { // HP UART1 @@ -75,7 +74,6 @@ const uart_signal_conn_t uart_periph_signal[SOC_UART_NUM] = { }, }, .irq = ETS_UART1_INTR_SOURCE, - .module = PERIPH_UART1_MODULE, }, #if 0 //TODO: [ESP32C61] IDF-9329, IDF-9341 { // LP UART0 @@ -109,7 +107,6 @@ const uart_signal_conn_t uart_periph_signal[SOC_UART_NUM] = { }, }, .irq = ETS_LP_UART_INTR_SOURCE, - .module = PERIPH_LP_UART0_MODULE, }, #endif }; diff --git a/components/soc/esp32h2/gdma_periph.c b/components/soc/esp32h2/gdma_periph.c index c5795713ea18..fd24fad766c5 100644 --- a/components/soc/esp32h2/gdma_periph.c +++ b/components/soc/esp32h2/gdma_periph.c @@ -84,7 +84,7 @@ static const regdma_entries_config_t gdma_g0p2_regs_retention[] = { g0p2_regs_map0[0], g0p2_regs_map0[1], \ g0p2_regs_map0[2], g0p2_regs_map0[3]), \ .owner = ENTRY(0) | ENTRY(2) }, - [1] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_GDMA_LINK(0x00), \ + [1] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_GDMA_LINK(0x01), \ G0P2_RETENTION_MAP_BASE_1, G0P2_RETENTION_MAP_BASE_1, \ G0P2_RETENTION_REGS_CNT_1, 0, 0, \ g0p2_regs_map1[0], g0p2_regs_map1[1], \ diff --git a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in index a770f6f263b3..b9e4d36f1cdb 100644 --- a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in @@ -615,6 +615,10 @@ config SOC_I2C_SLAVE_SUPPORT_SLAVE_UNMATCH bool default y +config SOC_I2C_SUPPORT_SLEEP_RETENTION + bool + default y + config SOC_I2S_NUM int default 1 @@ -1251,6 +1255,10 @@ config SOC_UART_SUPPORT_FSM_TX_WAIT_SEND bool default y +config SOC_UART_SUPPORT_SLEEP_RETENTION + bool + default y + config SOC_COEX_HW_PTI bool default y diff --git a/components/soc/esp32h2/include/soc/retention_periph_defs.h b/components/soc/esp32h2/include/soc/retention_periph_defs.h index 353bc1c2bc9d..bcc1b969311b 100644 --- a/components/soc/esp32h2/include/soc/retention_periph_defs.h +++ b/components/soc/esp32h2/include/soc/retention_periph_defs.h @@ -22,7 +22,7 @@ typedef enum periph_retention_module { * TEE, APM, UART, IOMUX, SPIMEM, SysTimer, etc.. */ SLEEP_RETENTION_MODULE_SYS_PERIPH = 3, /* Timer Group by target*/ - SLEEP_RETENTION_MODULE_TG0_WDT = 4, + SLEEP_RETENTION_MODULE_TG0_WDT = 4, SLEEP_RETENTION_MODULE_TG1_WDT = 5, SLEEP_RETENTION_MODULE_TG0_TIMER = 6, SLEEP_RETENTION_MODULE_TG1_TIMER = 7, @@ -35,6 +35,8 @@ typedef enum periph_retention_module { SLEEP_RETENTION_MODULE_I2C0 = 12, SLEEP_RETENTION_MODULE_I2C1 = 13, SLEEP_RETENTION_MODULE_RMT0 = 14, + SLEEP_RETENTION_MODULE_UART0 = 15, + SLEEP_RETENTION_MODULE_UART1 = 16, /* Modem module, which includes BLE and 802.15.4 */ SLEEP_RETENTION_MODULE_BLE_MAC = 28, @@ -64,6 +66,8 @@ typedef enum periph_retention_module_bitmap { SLEEP_RETENTION_MODULE_BM_I2C0 = BIT(SLEEP_RETENTION_MODULE_I2C0), SLEEP_RETENTION_MODULE_BM_I2C1 = BIT(SLEEP_RETENTION_MODULE_I2C1), SLEEP_RETENTION_MODULE_BM_RMT0 = BIT(SLEEP_RETENTION_MODULE_RMT0), + SLEEP_RETENTION_MODULE_BM_UART0 = BIT(SLEEP_RETENTION_MODULE_UART0), + SLEEP_RETENTION_MODULE_BM_UART1 = BIT(SLEEP_RETENTION_MODULE_UART1), /* modem module, which includes BLE and 802.15.4 */ SLEEP_RETENTION_MODULE_BM_BLE_MAC = BIT(SLEEP_RETENTION_MODULE_BLE_MAC), SLEEP_RETENTION_MODULE_BM_BT_BB = BIT(SLEEP_RETENTION_MODULE_BT_BB), @@ -84,7 +88,10 @@ typedef enum periph_retention_module_bitmap { | SLEEP_RETENTION_MODULE_BM_ADC \ | SLEEP_RETENTION_MODULE_BM_I2C0 \ | SLEEP_RETENTION_MODULE_BM_I2C1 \ - | SLEEP_RETENTION_MODULE_BM_RMT0) + | SLEEP_RETENTION_MODULE_BM_RMT0 \ + | SLEEP_RETENTION_MODULE_BM_UART0 \ + | SLEEP_RETENTION_MODULE_BM_UART1 \ + ) #ifdef __cplusplus } diff --git a/components/soc/esp32h2/include/soc/soc_caps.h b/components/soc/esp32h2/include/soc/soc_caps.h index e47f77cc80e8..258d105e41f0 100644 --- a/components/soc/esp32h2/include/soc/soc_caps.h +++ b/components/soc/esp32h2/include/soc/soc_caps.h @@ -254,6 +254,7 @@ #define SOC_I2C_SLAVE_CAN_GET_STRETCH_CAUSE (1) #define SOC_I2C_SLAVE_SUPPORT_I2CRAM_ACCESS (1) #define SOC_I2C_SLAVE_SUPPORT_SLAVE_UNMATCH (1) +#define SOC_I2C_SUPPORT_SLEEP_RETENTION (1) /*-------------------------- I2S CAPS ----------------------------------------*/ #define SOC_I2S_NUM (1U) @@ -491,6 +492,8 @@ // UART has an extra TX_WAIT_SEND state when the FIFO is not empty and XOFF is enabled #define SOC_UART_SUPPORT_FSM_TX_WAIT_SEND (1) +#define SOC_UART_SUPPORT_SLEEP_RETENTION (1) /*!< Support back up registers before sleep */ + // TODO: IDF-5679 (Copy from esp32c6, need check) /*-------------------------- COEXISTENCE HARDWARE PTI CAPS -------------------------------*/ #define SOC_COEX_HW_PTI (1) diff --git a/components/soc/esp32h2/include/soc/system_periph_retention.h b/components/soc/esp32h2/include/soc/system_periph_retention.h index 6c84932742de..539b3500d35c 100644 --- a/components/soc/esp32h2/include/soc/system_periph_retention.h +++ b/components/soc/esp32h2/include/soc/system_periph_retention.h @@ -17,7 +17,7 @@ extern "C" /** * @brief Provide access to interrupt matrix configuration registers retention - * context defination. + * context definition. * * This is an internal function of the sleep retention driver, and is not * useful for external use. @@ -27,7 +27,7 @@ extern const regdma_entries_config_t intr_matrix_regs_retention[INT_MTX_RETENTIO /** * @brief Provide access to hp_system configuration registers retention - * context defination. + * context definition. * * This is an internal function of the sleep retention driver, and is not * useful for external use. @@ -37,7 +37,7 @@ extern const regdma_entries_config_t hp_system_regs_retention[HP_SYSTEM_RETENTIO /** * @brief Provide access to TEE_APM configuration registers retention - * context defination. + * context definition. * * This is an internal function of the sleep retention driver, and is not * useful for external use. @@ -47,19 +47,9 @@ extern const regdma_entries_config_t tee_apm_regs_retention[TEE_APM_RETENTION_LI #define TEE_APM_HIGH_PRI_RETENTION_LINK_LEN 1 extern const regdma_entries_config_t tee_apm_highpri_regs_retention[TEE_APM_HIGH_PRI_RETENTION_LINK_LEN]; -/** - * @brief Provide access to uart configuration registers retention - * context defination. - * - * This is an internal function of the sleep retention driver, and is not - * useful for external use. - */ -#define UART_RETENTION_LINK_LEN 3 -extern const regdma_entries_config_t uart_regs_retention[UART_RETENTION_LINK_LEN]; - /** * @brief Provide access to timer group configuration registers retention - * context defination. + * context definition. * * This is an internal function of the sleep retention driver, and is not * useful for external use. @@ -69,7 +59,7 @@ extern const regdma_entries_config_t tg_regs_retention[TIMG_RETENTION_LINK_LEN]; /** * @brief Provide access to IOMUX configuration registers retention - * context defination. + * context definition. * * This is an internal function of the sleep retention driver, and is not * useful for external use. @@ -79,7 +69,7 @@ extern const regdma_entries_config_t iomux_regs_retention[IOMUX_RETENTION_LINK_L /** * @brief Provide access to spimem configuration registers retention - * context defination. + * context definition. * * This is an internal function of the sleep retention driver, and is not * useful for external use. @@ -89,7 +79,7 @@ extern const regdma_entries_config_t spimem_regs_retention[SPIMEM_RETENTION_LINK /** * @brief Provide access to systimer configuration registers retention - * context defination. + * context definition. * * This is an internal function of the sleep retention driver, and is not * useful for external use. diff --git a/components/soc/esp32h2/system_retention_periph.c b/components/soc/esp32h2/system_retention_periph.c index da52fbe53fc8..d9f3c5b469f8 100644 --- a/components/soc/esp32h2/system_retention_periph.c +++ b/components/soc/esp32h2/system_retention_periph.c @@ -44,16 +44,6 @@ const regdma_entries_config_t tee_apm_highpri_regs_retention[] = { }; _Static_assert((ARRAY_SIZE(tee_apm_regs_retention) == TEE_APM_RETENTION_LINK_LEN) && (ARRAY_SIZE(tee_apm_highpri_regs_retention) == TEE_APM_HIGH_PRI_RETENTION_LINK_LEN), "Inconsistent TEE_APM retention link length definitions"); -/* UART0 Registers Context */ -#define N_REGS_UART() (((UART_ID_REG(0) - UART_INT_RAW_REG(0)) / 4) + 1) -const regdma_entries_config_t uart_regs_retention[] = { - [0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_UART_LINK(0x00), UART_INT_RAW_REG(0), UART_INT_RAW_REG(0), N_REGS_UART(), 0, 0), .owner = ENTRY(0) | ENTRY(2) }, /* uart */ - /* Note: uart register should set update reg to make the configuration take effect */ - [1] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_UART_LINK(0x01), UART_REG_UPDATE_REG(0), UART_REG_UPDATE, UART_REG_UPDATE_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, - [2] = { .config = REGDMA_LINK_WAIT_INIT (REGDMA_UART_LINK(0x02), UART_REG_UPDATE_REG(0), 0x0, UART_REG_UPDATE_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) } -}; -_Static_assert(ARRAY_SIZE(uart_regs_retention) == UART_RETENTION_LINK_LEN, "Inconsistent UART retention link length definitions"); - /* IO MUX Registers Context */ #define N_REGS_IOMUX_0() (((IO_MUX_GPIO27_REG - REG_IO_MUX_BASE) / 4) + 1) #define N_REGS_IOMUX_1() (((GPIO_FUNC31_OUT_SEL_CFG_REG - GPIO_FUNC0_OUT_SEL_CFG_REG) / 4) + 1) diff --git a/components/soc/esp32h2/uart_periph.c b/components/soc/esp32h2/uart_periph.c index a23ff14937d6..7e44499e1e63 100644 --- a/components/soc/esp32h2/uart_periph.c +++ b/components/soc/esp32h2/uart_periph.c @@ -1,10 +1,11 @@ /* - * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #include "soc/uart_periph.h" +#include "soc/uart_reg.h" /* Bunch of constants for every UART peripheral: GPIO signals, irqs, hw addr of registers etc @@ -41,7 +42,6 @@ const uart_signal_conn_t uart_periph_signal[SOC_UART_NUM] = { } }, .irq = ETS_UART0_INTR_SOURCE, - .module = PERIPH_UART0_MODULE, }, { @@ -75,6 +75,54 @@ const uart_signal_conn_t uart_periph_signal[SOC_UART_NUM] = { }, }, .irq = ETS_UART1_INTR_SOURCE, - .module = PERIPH_UART1_MODULE, + }, +}; + +/** + * UART registers to be saved during sleep retention + * + * Reset TXFIFO and RXFIFO + * UART registers require set the reg_update bit to make the configuration take effect + * + * UART_INT_ENA_REG, UART_CLKDIV_SYNC_REG, UART_RX_FILT_REG, UART_CONF0_SYNC_REG, UART_CONF1_REG, + * UART_HWFC_CONF_SYNC_REG, UART_SLEEP_CONF0_REG, UART_SLEEP_CONF1_REG, UART_SLEEP_CONF2_REG, + * UART_SWFC_CONF0_SYNC_REG, UART_SWFC_CONF1_REG, UART_TXBRK_CONF_SYNC_REG, UART_IDLE_CONF_SYNC_REG, + * UART_RS485_CONF_SYNC_REG, UART_AT_CMD_PRECNT_SYNC_REG, UART_AT_CMD_POSTCNT_SYNC_REG, UART_AT_CMD_GAPTOUT_SYNC_REG, + * UART_AT_CMD_CHAR_SYNC_REG, UART_MEM_CONF_REG, UART_TOUT_CONF_SYNC_REG, UART_ID_REG + */ +#define UART_RETENTION_ADDR_MAP_REGS_CNT 21 +#define UART_RETENTION_REGS_BASE(i) UART_INT_ENA_REG(i) +static const uint32_t uart_regs_map[4] = {0x7fff6d, 0x10, 0x0, 0x0}; +#define UART_SLEEP_RETENTION_ENTRIES(uart_num) { \ + [0] = {.config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_UART_LINK(0x00), \ + UART_RETENTION_REGS_BASE(uart_num), UART_RETENTION_REGS_BASE(uart_num), \ + UART_RETENTION_ADDR_MAP_REGS_CNT, 0, 0, \ + uart_regs_map[0], uart_regs_map[1], \ + uart_regs_map[2], uart_regs_map[3] \ + ), \ + .owner = ENTRY(0) | ENTRY(2) }, \ + [1] = {.config = REGDMA_LINK_WRITE_INIT(REGDMA_UART_LINK(0x01), \ + UART_REG_UPDATE_REG(uart_num), UART_REG_UPDATE, \ + UART_REG_UPDATE_M, 1, 0 \ + ), \ + .owner = ENTRY(0) | ENTRY(2) }, \ + [2] = {.config = REGDMA_LINK_WAIT_INIT(REGDMA_UART_LINK(0x02), \ + UART_REG_UPDATE_REG(uart_num), 0x0, \ + UART_REG_UPDATE_M, 1, 0 \ + ), \ + .owner = ENTRY(0) | ENTRY(2) }, \ +} + +static const regdma_entries_config_t uart0_regdma_entries[] = UART_SLEEP_RETENTION_ENTRIES(0); +static const regdma_entries_config_t uart1_regdma_entries[] = UART_SLEEP_RETENTION_ENTRIES(1); + +const uart_reg_retention_info_t uart_reg_retention_info[SOC_UART_HP_NUM] = { + [0] = { + .regdma_entry_array = uart0_regdma_entries, + .array_size = ARRAY_SIZE(uart0_regdma_entries), + }, + [1] = { + .regdma_entry_array = uart1_regdma_entries, + .array_size = ARRAY_SIZE(uart1_regdma_entries), }, }; diff --git a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in index 90e655d3c5fe..f105ddf41052 100644 --- a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in @@ -1503,6 +1503,10 @@ config SOC_UART_HAS_LP_UART bool default y +config SOC_UART_SUPPORT_SLEEP_RETENTION + bool + default y + config SOC_UART_SUPPORT_FSM_TX_WAIT_SEND bool default y diff --git a/components/soc/esp32p4/include/soc/retention_periph_defs.h b/components/soc/esp32p4/include/soc/retention_periph_defs.h index 34219a85e0bc..1460d3d5bf7a 100644 --- a/components/soc/esp32p4/include/soc/retention_periph_defs.h +++ b/components/soc/esp32p4/include/soc/retention_periph_defs.h @@ -25,6 +25,12 @@ typedef enum periph_retention_module { SLEEP_RETENTION_MODULE_TG1_WDT = 4, SLEEP_RETENTION_MODULE_TG0_TIMER = 5, SLEEP_RETENTION_MODULE_TG1_TIMER = 6, + /* MISC Peripherals */ + SLEEP_RETENTION_MODULE_UART0 = 7, + SLEEP_RETENTION_MODULE_UART1 = 8, + SLEEP_RETENTION_MODULE_UART2 = 9, + SLEEP_RETENTION_MODULE_UART3 = 10, + SLEEP_RETENTION_MODULE_UART4 = 11, SLEEP_RETENTION_MODULE_MAX = 31 } periph_retention_module_t; @@ -40,6 +46,12 @@ typedef enum periph_retention_module_bitmap { SLEEP_RETENTION_MODULE_BM_TG1_WDT = BIT(SLEEP_RETENTION_MODULE_TG1_WDT), SLEEP_RETENTION_MODULE_BM_TG0_TIMER = BIT(SLEEP_RETENTION_MODULE_TG0_TIMER), SLEEP_RETENTION_MODULE_BM_TG1_TIMER = BIT(SLEEP_RETENTION_MODULE_TG1_TIMER), + /* MISC Peripherals */ + SLEEP_RETENTION_MODULE_BM_UART0 = BIT(SLEEP_RETENTION_MODULE_UART0), + SLEEP_RETENTION_MODULE_BM_UART1 = BIT(SLEEP_RETENTION_MODULE_UART1), + SLEEP_RETENTION_MODULE_BM_UART2 = BIT(SLEEP_RETENTION_MODULE_UART2), + SLEEP_RETENTION_MODULE_BM_UART3 = BIT(SLEEP_RETENTION_MODULE_UART3), + SLEEP_RETENTION_MODULE_BM_UART4 = BIT(SLEEP_RETENTION_MODULE_UART4), SLEEP_RETENTION_MODULE_BM_ALL = (uint32_t)-1 } periph_retention_module_bitmap_t; @@ -49,7 +61,13 @@ typedef enum periph_retention_module_bitmap { | SLEEP_RETENTION_MODULE_BM_TG0_WDT \ | SLEEP_RETENTION_MODULE_BM_TG1_WDT \ | SLEEP_RETENTION_MODULE_BM_TG0_TIMER \ - | SLEEP_RETENTION_MODULE_BM_TG1_TIMER) + | SLEEP_RETENTION_MODULE_BM_TG1_TIMER \ + | SLEEP_RETENTION_MODULE_BM_UART0 \ + | SLEEP_RETENTION_MODULE_BM_UART1 \ + | SLEEP_RETENTION_MODULE_BM_UART2 \ + | SLEEP_RETENTION_MODULE_BM_UART3 \ + | SLEEP_RETENTION_MODULE_BM_UART4 \ + ) #ifdef __cplusplus } diff --git a/components/soc/esp32p4/include/soc/soc_caps.h b/components/soc/esp32p4/include/soc/soc_caps.h index 5c869f7b99f8..10c18c1cd2b0 100644 --- a/components/soc/esp32p4/include/soc/soc_caps.h +++ b/components/soc/esp32p4/include/soc/soc_caps.h @@ -591,6 +591,7 @@ #define SOC_UART_SUPPORT_XTAL_CLK (1) /*!< Support XTAL clock as the clock source */ #define SOC_UART_SUPPORT_WAKEUP_INT (1) /*!< Support UART wakeup interrupt */ #define SOC_UART_HAS_LP_UART (1) /*!< Support LP UART */ +#define SOC_UART_SUPPORT_SLEEP_RETENTION (1) /*!< Support back up registers before sleep */ // UART has an extra TX_WAIT_SEND state when the FIFO is not empty and XOFF is enabled #define SOC_UART_SUPPORT_FSM_TX_WAIT_SEND (1) diff --git a/components/soc/esp32p4/include/soc/system_periph_retention.h b/components/soc/esp32p4/include/soc/system_periph_retention.h index 136832f33499..d7fd022775fa 100644 --- a/components/soc/esp32p4/include/soc/system_periph_retention.h +++ b/components/soc/esp32p4/include/soc/system_periph_retention.h @@ -45,16 +45,6 @@ extern const regdma_entries_config_t l2_cache_regs_retention[L2_CACHE_RETENTION_ #define HP_SYSTEM_RETENTION_LINK_LEN 1 extern const regdma_entries_config_t hp_system_regs_retention[HP_SYSTEM_RETENTION_LINK_LEN]; -/** - * @brief Provide access to uart configuration registers retention - * context definition. - * - * This is an internal function of the sleep retention driver, and is not - * useful for external use. - */ -#define UART_RETENTION_LINK_LEN 3 -extern const regdma_entries_config_t uart_regs_retention[UART_RETENTION_LINK_LEN]; - /** * @brief Provide access to timer group configuration registers retention * context definition. diff --git a/components/soc/esp32p4/system_retention_periph.c b/components/soc/esp32p4/system_retention_periph.c index 381b20641a73..1cc4a49da4a5 100644 --- a/components/soc/esp32p4/system_retention_periph.c +++ b/components/soc/esp32p4/system_retention_periph.c @@ -42,16 +42,6 @@ const regdma_entries_config_t hp_system_regs_retention[] = { }; _Static_assert(ARRAY_SIZE(hp_system_regs_retention) == HP_SYSTEM_RETENTION_LINK_LEN, "Inconsistent HP_SYSTEM retention link length definitions"); -/* UART0 Registers Context */ -#define N_REGS_UART() (((UART_CLK_CONF_REG(0) - REG_UART_BASE(0)) / 4) + 1) -const regdma_entries_config_t uart_regs_retention[] = { - [0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_UART_LINK(0x00), REG_UART_BASE(0), REG_UART_BASE(0), N_REGS_UART(), 0, 0), .owner = ENTRY(0) }, /* uart */ - /* Note: uart register should set update reg to make the configuration take effect */ - [1] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_UART_LINK(0x01), UART_REG_UPDATE_REG(0), UART_REG_UPDATE, UART_REG_UPDATE_M, 1, 0), .owner = ENTRY(0) }, - [2] = { .config = REGDMA_LINK_WAIT_INIT (REGDMA_UART_LINK(0x02), UART_REG_UPDATE_REG(0), 0x0, UART_REG_UPDATE_M, 1, 0), .owner = ENTRY(0) } -}; -_Static_assert(ARRAY_SIZE(uart_regs_retention) == UART_RETENTION_LINK_LEN, "Inconsistent UART retention link length definitions"); - /* IO MUX Registers Context */ #define N_REGS_IOMUX_0() (((IO_MUX_GPIO54_REG - REG_IO_MUX_BASE) / 4) + 1) #define N_REGS_IOMUX_1() (((GPIO_ZERO_DET1_FILTER_CNT_REG - DR_REG_GPIO_BASE) / 4) + 1) diff --git a/components/soc/esp32p4/uart_periph.c b/components/soc/esp32p4/uart_periph.c index 76e12d5c9c03..98d00fd4a224 100644 --- a/components/soc/esp32p4/uart_periph.c +++ b/components/soc/esp32p4/uart_periph.c @@ -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/uart_periph.h" #include "soc/lp_gpio_sig_map.h" +#include "soc/uart_reg.h" /* Bunch of constants for every UART peripheral: GPIO signals, irqs, hw addr of registers etc @@ -42,7 +43,6 @@ const uart_signal_conn_t uart_periph_signal[SOC_UART_NUM] = { } }, .irq = ETS_UART0_INTR_SOURCE, - .module = PERIPH_UART0_MODULE, }, { // HP UART1 @@ -76,7 +76,6 @@ const uart_signal_conn_t uart_periph_signal[SOC_UART_NUM] = { }, }, .irq = ETS_UART1_INTR_SOURCE, - .module = PERIPH_UART1_MODULE, }, { // HP UART2 @@ -110,7 +109,6 @@ const uart_signal_conn_t uart_periph_signal[SOC_UART_NUM] = { }, }, .irq = ETS_UART2_INTR_SOURCE, - .module = PERIPH_UART2_MODULE, }, { // HP UART3 @@ -144,7 +142,6 @@ const uart_signal_conn_t uart_periph_signal[SOC_UART_NUM] = { }, }, .irq = ETS_UART3_INTR_SOURCE, - .module = PERIPH_UART3_MODULE, }, { // HP UART4 @@ -178,7 +175,6 @@ const uart_signal_conn_t uart_periph_signal[SOC_UART_NUM] = { }, }, .irq = ETS_UART4_INTR_SOURCE, - .module = PERIPH_UART4_MODULE, }, { // LP UART0 .pins = { @@ -211,6 +207,69 @@ const uart_signal_conn_t uart_periph_signal[SOC_UART_NUM] = { }, }, .irq = ETS_LP_UART_INTR_SOURCE, - .module = PERIPH_LP_UART0_MODULE, + }, +}; + +/** + * UART registers to be saved during sleep retention + * + * Reset TXFIFO and RXFIFO + * UART registers require set the reg_update bit to make the configuration take effect + * + * UART_INT_ENA_REG, UART_CLKDIV_SYNC_REG, UART_RX_FILT_REG, UART_CONF0_SYNC_REG, UART_CONF1_REG, + * UART_HWFC_CONF_SYNC_REG, UART_SLEEP_CONF0_REG, UART_SLEEP_CONF1_REG, UART_SLEEP_CONF2_REG, + * UART_SWFC_CONF0_SYNC_REG, UART_SWFC_CONF1_REG, UART_TXBRK_CONF_SYNC_REG, UART_IDLE_CONF_SYNC_REG, + * UART_RS485_CONF_SYNC_REG, UART_AT_CMD_PRECNT_SYNC_REG, UART_AT_CMD_POSTCNT_SYNC_REG, UART_AT_CMD_GAPTOUT_SYNC_REG, + * UART_AT_CMD_CHAR_SYNC_REG, UART_MEM_CONF_REG, UART_TOUT_CONF_SYNC_REG, UART_ID_REG + */ +#define UART_RETENTION_ADDR_MAP_REGS_CNT 21 +#define UART_RETENTION_REGS_BASE(i) UART_INT_ENA_REG(i) +static const uint32_t uart_regs_map[4] = {0x7fff6d, 0x10, 0x0, 0x0}; +#define UART_SLEEP_RETENTION_ENTRIES(uart_num) { \ + [0] = {.config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_UART_LINK(0x00), \ + UART_RETENTION_REGS_BASE(uart_num), UART_RETENTION_REGS_BASE(uart_num), \ + UART_RETENTION_ADDR_MAP_REGS_CNT, 0, 0, \ + uart_regs_map[0], uart_regs_map[1], \ + uart_regs_map[2], uart_regs_map[3] \ + ), \ + .owner = ENTRY(0) }, \ + [1] = {.config = REGDMA_LINK_WRITE_INIT(REGDMA_UART_LINK(0x01), \ + UART_REG_UPDATE_REG(uart_num), UART_REG_UPDATE, \ + UART_REG_UPDATE_M, 1, 0 \ + ), \ + .owner = ENTRY(0) }, \ + [2] = {.config = REGDMA_LINK_WAIT_INIT(REGDMA_UART_LINK(0x02), \ + UART_REG_UPDATE_REG(uart_num), 0x0, \ + UART_REG_UPDATE_M, 1, 0 \ + ), \ + .owner = ENTRY(0) }, \ +} + +static const regdma_entries_config_t uart0_regdma_entries[] = UART_SLEEP_RETENTION_ENTRIES(0); +static const regdma_entries_config_t uart1_regdma_entries[] = UART_SLEEP_RETENTION_ENTRIES(1); +static const regdma_entries_config_t uart2_regdma_entries[] = UART_SLEEP_RETENTION_ENTRIES(2); +static const regdma_entries_config_t uart3_regdma_entries[] = UART_SLEEP_RETENTION_ENTRIES(3); +static const regdma_entries_config_t uart4_regdma_entries[] = UART_SLEEP_RETENTION_ENTRIES(4); + +const uart_reg_retention_info_t uart_reg_retention_info[SOC_UART_HP_NUM] = { + [0] = { + .regdma_entry_array = uart0_regdma_entries, + .array_size = ARRAY_SIZE(uart0_regdma_entries), + }, + [1] = { + .regdma_entry_array = uart1_regdma_entries, + .array_size = ARRAY_SIZE(uart1_regdma_entries), + }, + [2] = { + .regdma_entry_array = uart2_regdma_entries, + .array_size = ARRAY_SIZE(uart2_regdma_entries), + }, + [3] = { + .regdma_entry_array = uart3_regdma_entries, + .array_size = ARRAY_SIZE(uart3_regdma_entries), + }, + [4] = { + .regdma_entry_array = uart4_regdma_entries, + .array_size = ARRAY_SIZE(uart4_regdma_entries), }, }; diff --git a/components/soc/esp32s2/uart_periph.c b/components/soc/esp32s2/uart_periph.c index 8360cae08292..3d3da8ad7a46 100644 --- a/components/soc/esp32s2/uart_periph.c +++ b/components/soc/esp32s2/uart_periph.c @@ -1,16 +1,8 @@ -// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// 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. +/* + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include "soc/uart_periph.h" @@ -49,7 +41,6 @@ const uart_signal_conn_t uart_periph_signal[SOC_UART_NUM] = { } }, .irq = ETS_UART0_INTR_SOURCE, - .module = PERIPH_UART0_MODULE, }, { @@ -83,6 +74,5 @@ const uart_signal_conn_t uart_periph_signal[SOC_UART_NUM] = { }, }, .irq = ETS_UART1_INTR_SOURCE, - .module = PERIPH_UART1_MODULE, }, }; diff --git a/components/soc/esp32s3/uart_periph.c b/components/soc/esp32s3/uart_periph.c index 450787854f6b..c9f0a2f4b4eb 100644 --- a/components/soc/esp32s3/uart_periph.c +++ b/components/soc/esp32s3/uart_periph.c @@ -1,16 +1,8 @@ -// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// 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. +/* + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include "soc/uart_periph.h" @@ -49,7 +41,6 @@ const uart_signal_conn_t uart_periph_signal[SOC_UART_NUM] = { } }, .irq = ETS_UART0_INTR_SOURCE, - .module = PERIPH_UART0_MODULE, }, { @@ -83,7 +74,6 @@ const uart_signal_conn_t uart_periph_signal[SOC_UART_NUM] = { }, }, .irq = ETS_UART1_INTR_SOURCE, - .module = PERIPH_UART1_MODULE, }, { @@ -117,6 +107,5 @@ const uart_signal_conn_t uart_periph_signal[SOC_UART_NUM] = { } }, .irq = ETS_UART2_INTR_SOURCE, - .module = PERIPH_UART2_MODULE, } }; diff --git a/components/soc/include/soc/gdma_periph.h b/components/soc/include/soc/gdma_periph.h index 3376e4d88175..233c366ebb5f 100644 --- a/components/soc/include/soc/gdma_periph.h +++ b/components/soc/include/soc/gdma_periph.h @@ -8,10 +8,7 @@ #include "soc/soc_caps.h" #include "soc/periph_defs.h" - -#if SOC_PM_SUPPORT_TOP_PD #include "soc/regdma.h" -#endif #ifdef __cplusplus extern "C" { diff --git a/components/soc/include/soc/i2c_periph.h b/components/soc/include/soc/i2c_periph.h index 47471d9e22bb..c72e7720f16e 100644 --- a/components/soc/include/soc/i2c_periph.h +++ b/components/soc/include/soc/i2c_periph.h @@ -10,9 +10,7 @@ #include "soc/soc_caps.h" #if SOC_I2C_SUPPORTED // TODO: [ESP32C5] IDF-8694 #include "soc/periph_defs.h" -#if SOC_PM_SUPPORT_TOP_PD #include "soc/regdma.h" -#endif #endif // SOC_I2C_SUPPORTED #ifdef __cplusplus @@ -32,7 +30,7 @@ typedef struct { extern const i2c_signal_conn_t i2c_periph_signal[SOC_I2C_NUM]; -#if SOC_PM_SUPPORT_TOP_PD +#if SOC_I2C_SUPPORT_SLEEP_RETENTION typedef struct { const regdma_entries_config_t *link_list; uint32_t link_num; diff --git a/components/soc/include/soc/regdma.h b/components/soc/include/soc/regdma.h index b6fd9ff00e84..59897b1ebf37 100644 --- a/components/soc/include/soc/regdma.h +++ b/components/soc/include/soc/regdma.h @@ -66,6 +66,7 @@ extern "C" { #define REGDMA_LINK_PRI_RMT REGDMA_LINK_PRI_GENERAL_PERIPH #define REGDMA_LINK_PRI_GPTIMER REGDMA_LINK_PRI_GENERAL_PERIPH #define REGDMA_LINK_PRI_I2C REGDMA_LINK_PRI_GENERAL_PERIPH +#define REGDMA_LINK_PRI_UART REGDMA_LINK_PRI_GENERAL_PERIPH typedef enum { REGDMA_LINK_PRI_0 = 0, diff --git a/components/soc/include/soc/uart_periph.h b/components/soc/include/soc/uart_periph.h index 45781b208aae..2c0681e8dad6 100644 --- a/components/soc/include/soc/uart_periph.h +++ b/components/soc/include/soc/uart_periph.h @@ -1,17 +1,18 @@ /* - * SPDX-FileCopyrightText: 2019-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #pragma once #include "soc/soc_caps.h" -#include "soc/periph_defs.h" +#include "soc/interrupts.h" #include "soc/gpio_sig_map.h" #include "soc/io_mux_reg.h" #include "soc/uart_pins.h" #include "soc/uart_struct.h" #include "soc/uart_reg.h" +#include "soc/regdma.h" #ifdef __cplusplus extern "C" { @@ -45,13 +46,19 @@ typedef struct { typedef struct { const uart_periph_sig_t pins[SOC_UART_PINS_COUNT]; const uint8_t irq; - union { - const periph_module_t module; - }; } uart_signal_conn_t; extern const uart_signal_conn_t uart_periph_signal[SOC_UART_NUM]; +#if SOC_UART_SUPPORT_SLEEP_RETENTION +typedef struct { + const regdma_entries_config_t *regdma_entry_array; + uint32_t array_size; +} uart_reg_retention_info_t; + +extern const uart_reg_retention_info_t uart_reg_retention_info[SOC_UART_HP_NUM]; +#endif + #ifdef __cplusplus } #endif diff --git a/docs/en/api-reference/peripherals/uart.rst b/docs/en/api-reference/peripherals/uart.rst index eba495f20eeb..b28bdf929ea5 100644 --- a/docs/en/api-reference/peripherals/uart.rst +++ b/docs/en/api-reference/peripherals/uart.rst @@ -68,6 +68,10 @@ Call the function :cpp:func:`uart_param_config` and pass to it a :cpp:type:`uart For more information on how to configure the hardware flow control options, please refer to :example:`peripherals/uart/uart_echo`. +.. only:: SOC_UART_SUPPORT_SLEEP_RETENTION + + Additionally, :cpp:member:`uart_config_t::backup_before_sleep` can be set to enable the backup of the UART configuration registers before entering sleep and restore these registers after exiting sleep. This allows the UART to continue working properly after waking up even when the UART module power domain is entirely off during sleep. This option implies an balance between power consumption and memory usage. If the power consumption is not a concern, you can disable this option to save memory. + Multiple Steps """""""""""""" diff --git a/docs/zh_CN/api-reference/peripherals/uart.rst b/docs/zh_CN/api-reference/peripherals/uart.rst index d93f7e239585..e2cf8b6ca895 100644 --- a/docs/zh_CN/api-reference/peripherals/uart.rst +++ b/docs/zh_CN/api-reference/peripherals/uart.rst @@ -68,6 +68,10 @@ UART 通信参数可以在一个步骤中完成全部配置,也可以在多个 了解配置硬件流控模式的更多信息,请参考 :example:`peripherals/uart/uart_echo`。 +.. only:: SOC_UART_SUPPORT_SLEEP_RETENTION + + 此外,置位 :cpp:member:`uart_config_t::backup_before_sleep` 会使能在进入睡眠模式前备份 UART 配置寄存器并在退出睡眠后恢复这些寄存器。这个功能使 UART 能够在系统唤醒后继续正常工作,即使其电源域在睡眠过程中被完全关闭。此选项需要用户在功耗和内存使用之间取得平衡。如果功耗不是一个问题,可以禁用这个选项来节省内存。 + 分步依次配置每个参数 """"""""""""""""""""""""""""""" diff --git a/tools/ci/check_copyright_ignore.txt b/tools/ci/check_copyright_ignore.txt index cd94a1d3488c..9016a55af8d1 100644 --- a/tools/ci/check_copyright_ignore.txt +++ b/tools/ci/check_copyright_ignore.txt @@ -586,7 +586,6 @@ components/soc/esp32/include/soc/uhci_struct.h components/soc/esp32/include/soc/wdev_reg.h components/soc/esp32/ledc_periph.c components/soc/esp32/spi_periph.c -components/soc/esp32/uart_periph.c components/soc/esp32c3/i2c_periph.c components/soc/esp32c3/include/soc/apb_saradc_reg.h components/soc/esp32c3/include/soc/assist_debug_reg.h @@ -617,7 +616,6 @@ components/soc/esp32c3/include/soc/usb_serial_jtag_struct.h components/soc/esp32c3/include/soc/wdev_reg.h components/soc/esp32c3/interrupts.c components/soc/esp32c3/ledc_periph.c -components/soc/esp32c3/uart_periph.c components/soc/esp32s2/adc_periph.c components/soc/esp32s2/dedic_gpio_periph.c components/soc/esp32s2/i2c_periph.c @@ -655,7 +653,6 @@ components/soc/esp32s2/include/soc/usb_wrap_reg.h components/soc/esp32s2/include/soc/usb_wrap_struct.h components/soc/esp32s2/include/soc/wdev_reg.h components/soc/esp32s2/ledc_periph.c -components/soc/esp32s2/uart_periph.c components/soc/esp32s3/dedic_gpio_periph.c components/soc/esp32s3/i2c_periph.c components/soc/esp32s3/include/soc/apb_saradc_reg.h @@ -715,7 +712,6 @@ components/soc/esp32s3/include/soc/usb_wrap_reg.h components/soc/esp32s3/include/soc/usb_wrap_struct.h components/soc/esp32s3/include/soc/wdev_reg.h components/soc/esp32s3/ledc_periph.c -components/soc/esp32s3/uart_periph.c components/soc/include/soc/dedic_gpio_periph.h components/soc/include/soc/gpio_periph.h components/soc/include/soc/ledc_periph.h