diff --git a/components/esp_driver_rmt/test_apps/rmt/main/test_rmt_sleep.c b/components/esp_driver_rmt/test_apps/rmt/main/test_rmt_sleep.c index 21c6db4a58aa..ebcedd358a2b 100644 --- a/components/esp_driver_rmt/test_apps/rmt/main/test_rmt_sleep.c +++ b/components/esp_driver_rmt/test_apps/rmt/main/test_rmt_sleep.c @@ -15,6 +15,8 @@ #include "esp_timer.h" #include "esp_sleep.h" #include "esp_private/sleep_cpu.h" +#include "esp_private/esp_sleep_internal.h" +#include "esp_private/esp_pmu.h" #include "test_util_rmt_encoders.h" #include "test_board.h" @@ -91,18 +93,29 @@ static void test_rmt_tx_rx_sleep_retention(bool back_up_before_sleep) // Note: don't enable the RMT channel before going to sleep, ensure no power management lock is acquired by RMT + esp_sleep_context_t sleep_ctx; + esp_sleep_set_sleep_context(&sleep_ctx); printf("go to light sleep for 2 seconds\r\n"); -#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP +#if ESP_SLEEP_POWER_DOWN_CPU TEST_ESP_OK(sleep_cpu_configure(true)); #endif TEST_ESP_OK(esp_sleep_enable_timer_wakeup(2 * 1000 * 1000)); TEST_ESP_OK(esp_light_sleep_start()); printf("Waked up! Let's see if RMT driver can still work...\r\n"); -#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP +#if ESP_SLEEP_POWER_DOWN_CPU TEST_ESP_OK(sleep_cpu_configure(false)); #endif + printf("check if the sleep happened as expected\r\n"); + TEST_ASSERT_EQUAL(0, sleep_ctx.sleep_request_result); +#if SOC_RMT_SUPPORT_SLEEP_RETENTION + if (back_up_before_sleep) { + printf("sleep_ctx.sleep_flags=%lx\r\n", sleep_ctx.sleep_flags); + TEST_ASSERT_EQUAL(PMU_SLEEP_PD_TOP, sleep_ctx.sleep_flags & PMU_SLEEP_PD_TOP); + } +#endif + TEST_ESP_OK(rmt_enable(tx_channel)); TEST_ESP_OK(rmt_enable(rx_channel)); diff --git a/components/esp_driver_rmt/test_apps/rmt/sdkconfig.defaults b/components/esp_driver_rmt/test_apps/rmt/sdkconfig.defaults index f67db9e921e2..c00e05913fd0 100644 --- a/components/esp_driver_rmt/test_apps/rmt/sdkconfig.defaults +++ b/components/esp_driver_rmt/test_apps/rmt/sdkconfig.defaults @@ -5,3 +5,6 @@ CONFIG_FREERTOS_HZ=1000 CONFIG_UNITY_ENABLE_64BIT=y CONFIG_ESP_MAIN_TASK_STACK_SIZE=4096 + +# primitives for checking sleep internal state +CONFIG_ESP_SLEEP_DEBUG=y diff --git a/components/hal/esp32p4/include/hal/rmt_ll.h b/components/hal/esp32p4/include/hal/rmt_ll.h index 620597cbb6dd..d7830865b806 100644 --- a/components/hal/esp32p4/include/hal/rmt_ll.h +++ b/components/hal/esp32p4/include/hal/rmt_ll.h @@ -33,6 +33,8 @@ extern "C" { #define RMT_LL_EVENT_TX_MASK(channel) (RMT_LL_EVENT_TX_DONE(channel) | RMT_LL_EVENT_TX_THRES(channel) | RMT_LL_EVENT_TX_LOOP_END(channel)) #define RMT_LL_EVENT_RX_MASK(channel) (RMT_LL_EVENT_RX_DONE(channel) | RMT_LL_EVENT_RX_THRES(channel)) +#define RMT_LL_SLEEP_RETENTION_MODULE_ID(group_id) (SLEEP_RETENTION_MODULE_RMT0) + #define RMT_LL_MAX_LOOP_COUNT_PER_BATCH 1023 #define RMT_LL_MAX_FILTER_VALUE 255 #define RMT_LL_MAX_IDLE_VALUE 32767 diff --git a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in index b7a549816d0f..4771972a6cfd 100644 --- a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in @@ -979,10 +979,18 @@ config SOC_RMT_SUPPORT_XTAL bool default y +config SOC_RMT_SUPPORT_RC_FAST + bool + default y + config SOC_RMT_SUPPORT_DMA bool default y +config SOC_RMT_SUPPORT_SLEEP_RETENTION + bool + default y + config SOC_LCD_I80_BUSES int default 1 diff --git a/components/soc/esp32p4/include/soc/retention_periph_defs.h b/components/soc/esp32p4/include/soc/retention_periph_defs.h index 1460d3d5bf7a..3103933edb71 100644 --- a/components/soc/esp32p4/include/soc/retention_periph_defs.h +++ b/components/soc/esp32p4/include/soc/retention_periph_defs.h @@ -31,6 +31,7 @@ typedef enum periph_retention_module { SLEEP_RETENTION_MODULE_UART2 = 9, SLEEP_RETENTION_MODULE_UART3 = 10, SLEEP_RETENTION_MODULE_UART4 = 11, + SLEEP_RETENTION_MODULE_RMT0 = 12, SLEEP_RETENTION_MODULE_MAX = 31 } periph_retention_module_t; @@ -52,6 +53,7 @@ typedef enum periph_retention_module_bitmap { 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_RMT0 = BIT(SLEEP_RETENTION_MODULE_RMT0), SLEEP_RETENTION_MODULE_BM_ALL = (uint32_t)-1 } periph_retention_module_bitmap_t; @@ -67,6 +69,7 @@ typedef enum periph_retention_module_bitmap { | SLEEP_RETENTION_MODULE_BM_UART2 \ | SLEEP_RETENTION_MODULE_BM_UART3 \ | SLEEP_RETENTION_MODULE_BM_UART4 \ + | SLEEP_RETENTION_MODULE_BM_RMT0 \ ) #ifdef __cplusplus diff --git a/components/soc/esp32p4/include/soc/soc_caps.h b/components/soc/esp32p4/include/soc/soc_caps.h index 17afee4f518f..996527ad6572 100644 --- a/components/soc/esp32p4/include/soc/soc_caps.h +++ b/components/soc/esp32p4/include/soc/soc_caps.h @@ -377,8 +377,9 @@ #define SOC_RMT_SUPPORT_TX_SYNCHRO 1 /*!< Support coordinate a group of TX channels to start simultaneously */ #define SOC_RMT_SUPPORT_TX_CARRIER_DATA_ONLY 1 /*!< TX carrier can be modulated to data phase only */ #define SOC_RMT_SUPPORT_XTAL 1 /*!< Support set XTAL clock as the RMT clock source */ -// #define SOC_RMT_SUPPORT_RC_FAST 1 /*!< Support set RC_FAST clock as the RMT clock source */ +#define SOC_RMT_SUPPORT_RC_FAST 1 /*!< Support set RC_FAST clock as the RMT clock source */ #define SOC_RMT_SUPPORT_DMA 1 /*!< RMT peripheral can connect to DMA channel */ +#define SOC_RMT_SUPPORT_SLEEP_RETENTION 1 /*!< The sleep retention feature can help back up RMT registers before sleep */ /*-------------------------- LCD CAPS ----------------------------------------*/ /* I80 bus and RGB timing generator can't work at the same time */ diff --git a/components/soc/esp32p4/rmt_periph.c b/components/soc/esp32p4/rmt_periph.c index fa18256d27ff..e17779a4490d 100644 --- a/components/soc/esp32p4/rmt_periph.c +++ b/components/soc/esp32p4/rmt_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/rmt_periph.h" +#include "soc/rmt_reg.h" #include "soc/gpio_sig_map.h" const rmt_signal_conn_t rmt_periph_signals = { @@ -48,3 +49,32 @@ const rmt_signal_conn_t rmt_periph_signals = { } } }; + +/** + * RMT Registers to be saved during sleep retention + * - Channel configuration registers, e.g.: RMT_CH0CONF0_REG, RMT_CH3CONF0_REG, RMT_CH3CONF1_REG, RMT_CH0_TX_LIM_REG, RMT_CH3_RX_LIM_REG + * - TX synchronization registers, e.g.: RMT_TX_SIM_REG + * - Interrupt enable registers, e.g.: RMT_INT_ENA_REG + * - Carrier duty registers, e.g.: RMT_CH0CARRIER_DUTY_REG, RMT_CH3_RX_CARRIER_RM_REG + * - Global configuration registers, e.g.: RMT_SYS_CONF_REG +*/ +#define RMT_RETENTION_REGS_CNT 31 +#define RMT_RETENTION_REGS_BASE (DR_REG_RMT_BASE + 0x20) +static const uint32_t rmt_regs_map[4] = {0xff400fff, 0x3ff, 0x0, 0x0}; +static const regdma_entries_config_t rmt_regdma_entries[] = { + [0] = { + .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_RMT_LINK(0x00), + RMT_RETENTION_REGS_BASE, RMT_RETENTION_REGS_BASE, + RMT_RETENTION_REGS_CNT, 0, 0, + rmt_regs_map[0], rmt_regs_map[1], + rmt_regs_map[2], rmt_regs_map[3]), + .owner = ENTRY(0), + }, +}; + +const rmt_reg_retention_info_t rmt_reg_retention_info[SOC_RMT_GROUPS] = { + [0] = { + .regdma_entry_array = rmt_regdma_entries, + .array_size = ARRAY_SIZE(rmt_regdma_entries) + }, +};