From ea142bb6d1b5eaf4e2ed15e137470cb09f6a0af2 Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Thu, 23 May 2024 10:42:52 +0800 Subject: [PATCH 1/9] change(esp_hw_support): do timergroup watchdogs retention by needs --- components/esp_hw_support/sleep_modes.c | 15 +++- .../esp_hw_support/sleep_system_peripheral.c | 14 +--- components/esp_pm/Kconfig | 2 +- components/esp_system/int_wdt.c | 41 +++++++++ .../task_wdt/task_wdt_impl_timergroup.c | 57 ++++++++++++- .../beta3/include/soc/retention_periph_defs.h | 78 +++++++++++------ .../soc/esp32c5/beta3/include/soc/soc_caps.h | 1 + .../esp32c5/beta3/system_retention_periph.c | 15 ---- components/soc/esp32c5/beta3/timer_periph.c | 31 ++++++- .../soc/esp32c5/mp/include/soc/soc_caps.h | 1 + components/soc/esp32c5/mp/timer_periph.c | 31 ++++++- .../esp32c6/include/soc/Kconfig.soc_caps.in | 4 + .../include/soc/retention_periph_defs.h | 80 +++++++++++------- components/soc/esp32c6/include/soc/soc_caps.h | 1 + .../soc/esp32c6/system_retention_periph.c | 15 ---- components/soc/esp32c6/timer_periph.c | 29 ++++++- .../esp32h2/include/soc/Kconfig.soc_caps.in | 4 + .../include/soc/retention_periph_defs.h | 84 ++++++++++++------- components/soc/esp32h2/include/soc/soc_caps.h | 1 + .../soc/esp32h2/system_retention_periph.c | 15 ---- components/soc/esp32h2/timer_periph.c | 29 ++++++- .../esp32p4/include/soc/Kconfig.soc_caps.in | 4 + .../include/soc/retention_periph_defs.h | 23 ++++- components/soc/esp32p4/include/soc/soc_caps.h | 1 + .../soc/esp32p4/system_retention_periph.c | 15 ---- components/soc/esp32p4/timer_periph.c | 29 ++++++- components/soc/include/soc/regdma.h | 23 +++-- components/soc/include/soc/timer_periph.h | 12 ++- 28 files changed, 472 insertions(+), 183 deletions(-) diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index 39e7af3708..481095366a 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -674,8 +674,19 @@ FORCE_INLINE_ATTR void misc_modules_sleep_prepare(bool deep_sleep) /** * These save-restore workaround should be moved to lower layer */ -FORCE_INLINE_ATTR void misc_modules_wake_prepare(void) +FORCE_INLINE_ATTR void misc_modules_wake_prepare(uint32_t pd_flags) { +#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP + if (pd_flags & PMU_SLEEP_PD_TOP) { + // There is no driver to manage the flashboot watchdog, and it is definitely be in off state when + // the system is running, after waking up from pd_top sleep, shut it down by software here. + wdt_hal_context_t mwdt_ctx = {.inst = WDT_MWDT0, .mwdt_dev = &TIMERG0}; + wdt_hal_write_protect_disable(&mwdt_ctx); + wdt_hal_set_flashboot_en(&mwdt_ctx, false); + wdt_hal_write_protect_enable(&mwdt_ctx); + } +#endif + #if SOC_USB_SERIAL_JTAG_SUPPORTED && !SOC_USB_SERIAL_JTAG_SUPPORT_LIGHT_SLEEP sleep_console_usj_pad_restore(); #endif @@ -1043,7 +1054,7 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m sleep_retention_do_system_retention(false); } #endif - misc_modules_wake_prepare(); + misc_modules_wake_prepare(pd_flags); } #if SOC_SPI_MEM_SUPPORT_TIMING_TUNING diff --git a/components/esp_hw_support/sleep_system_peripheral.c b/components/esp_hw_support/sleep_system_peripheral.c index 3ba63ffaff..531f3dd670 100644 --- a/components/esp_hw_support/sleep_system_peripheral.c +++ b/components/esp_hw_support/sleep_system_peripheral.c @@ -57,14 +57,6 @@ static __attribute__((unused)) esp_err_t sleep_sys_periph_uart0_retention_init(v return ESP_OK; } -static __attribute__((unused)) esp_err_t sleep_sys_periph_tg0_retention_init(void *arg) -{ - esp_err_t err = sleep_retention_entries_create(tg_regs_retention, ARRAY_SIZE(tg_regs_retention), REGDMA_LINK_PRI_SYS_PERIPH_LOW, SLEEP_RETENTION_MODULE_SYS_PERIPH); - ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for digital peripherals (%s) retention", "Timer Group"); - ESP_LOGD(TAG, "Timer Group sleep retention initialization"); - return ESP_OK; -} - static __attribute__((unused)) esp_err_t sleep_sys_periph_iomux_retention_init(void *arg) { esp_err_t err = sleep_retention_entries_create(iomux_regs_retention, ARRAY_SIZE(iomux_regs_retention), REGDMA_LINK_PRI_SYS_PERIPH_LOW, SLEEP_RETENTION_MODULE_SYS_PERIPH); @@ -126,8 +118,6 @@ static __attribute__((unused)) esp_err_t sleep_sys_periph_retention_init(void *a #endif err = sleep_sys_periph_uart0_retention_init(arg); if(err) goto error; - err = sleep_sys_periph_tg0_retention_init(arg); - if(err) goto error; err = sleep_sys_periph_iomux_retention_init(arg); if(err) goto error; err = sleep_sys_periph_spimem_retention_init(arg); @@ -147,9 +137,7 @@ bool peripheral_domain_pd_allowed(void) #if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP const uint32_t inited_modules = sleep_retention_get_inited_modules(); const uint32_t created_modules = sleep_retention_get_created_modules(); - const uint32_t mask = (const uint32_t) (BIT(SLEEP_RETENTION_MODULE_SYS_PERIPH)); - - return ((inited_modules & mask) == (created_modules & mask)); + return (((inited_modules ^ created_modules) & TOP_DOMAIN_PERIPHERALS_BM) == 0); #else return false; #endif diff --git a/components/esp_pm/Kconfig b/components/esp_pm/Kconfig index 8e5cc13158..d7f0ee7d3b 100644 --- a/components/esp_pm/Kconfig +++ b/components/esp_pm/Kconfig @@ -142,7 +142,7 @@ menu "Power Management" config PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP bool "Power down Digital Peripheral in light sleep (EXPERIMENTAL)" - depends on SOC_PM_SUPPORT_TOP_PD + depends on SOC_PM_SUPPORT_TOP_PD && SOC_PAU_SUPPORTED select PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP if !SOC_CPU_IN_TOP_DOMAIN default n #TODO: enable by default if periph init/deinit management supported (WIFI-5252) help diff --git a/components/esp_system/int_wdt.c b/components/esp_system/int_wdt.c index e4936f0a66..68d031d533 100644 --- a/components/esp_system/int_wdt.c +++ b/components/esp_system/int_wdt.c @@ -14,6 +14,7 @@ #include "hal/timer_ll.h" #include "freertos/FreeRTOS.h" #include "esp_cpu.h" +#include "esp_check.h" #include "esp_err.h" #include "esp_attr.h" #include "esp_log.h" @@ -23,6 +24,10 @@ #include "esp_private/periph_ctrl.h" #include "esp_private/esp_int_wdt.h" +#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && SOC_TIMER_SUPPORT_SLEEP_RETENTION +#include "esp_private/sleep_retention.h" +#endif + #if SOC_TIMER_GROUPS > 1 /* If we have two hardware timer groups, use the second one for interrupt watchdog. */ @@ -47,6 +52,38 @@ #endif // SOC_TIMER_GROUPS > 1 #if CONFIG_ESP_INT_WDT +#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && SOC_TIMER_SUPPORT_SLEEP_RETENTION +static const char* TAG = "int_wdt"; +static esp_err_t sleep_int_wdt_retention_init(void *arg) +{ + uint32_t group_id = *(uint32_t *)arg; + esp_err_t err = sleep_retention_entries_create(tg_wdt_regs_retention[group_id].link_list, + tg_wdt_regs_retention[group_id].link_num, + REGDMA_LINK_PRI_6, + (group_id == 0) ? SLEEP_RETENTION_MODULE_TG0_WDT : SLEEP_RETENTION_MODULE_TG1_WDT); + if (err == ESP_OK) { + ESP_LOGD(TAG, "Interrupt watchdog timer retention initialization"); + } + ESP_RETURN_ON_ERROR(err, TAG, "Failed to create sleep retention linked list for interrupt watchdog timer"); + return err; +} + +static esp_err_t esp_int_wdt_retention_enable(uint32_t group_id) +{ + sleep_retention_module_init_param_t init_param = { + .cbs = { .create = { .handle = sleep_int_wdt_retention_init, .arg = &group_id } }, + .depends = BIT(SLEEP_RETENTION_MODULE_CLOCK_SYSTEM) + }; + esp_err_t err = sleep_retention_module_init((group_id == 0) ? SLEEP_RETENTION_MODULE_TG0_WDT : SLEEP_RETENTION_MODULE_TG1_WDT, &init_param); + if (err == ESP_OK) { + err = sleep_retention_module_allocate((group_id == 0) ? SLEEP_RETENTION_MODULE_TG0_WDT : SLEEP_RETENTION_MODULE_TG1_WDT); + if (err != ESP_OK) { + ESP_LOGW(TAG, "Failed to allocate sleep retention linked list for interrupt watchdog timer retention"); + } + } + return err; +} +#endif static wdt_hal_context_t iwdt_context; @@ -122,6 +159,10 @@ void esp_int_wdt_init(void) wdt_hal_enable(&iwdt_context); wdt_hal_write_protect_enable(&iwdt_context); +#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && SOC_TIMER_SUPPORT_SLEEP_RETENTION + esp_int_wdt_retention_enable(IWDT_TIMER_GROUP); +#endif + #if (CONFIG_ESP32_ECO3_CACHE_LOCK_FIX && CONFIG_BTDM_CTRL_HLI) #define APB_DCRSET (0x200c) #define APB_ITCTRL (0x3f00) diff --git a/components/esp_system/task_wdt/task_wdt_impl_timergroup.c b/components/esp_system/task_wdt/task_wdt_impl_timergroup.c index 5d0fef7234..533a4f2461 100644 --- a/components/esp_system/task_wdt/task_wdt_impl_timergroup.c +++ b/components/esp_system/task_wdt/task_wdt_impl_timergroup.c @@ -11,13 +11,19 @@ #include "hal/wdt_hal.h" #include "hal/mwdt_ll.h" #include "hal/timer_ll.h" +#include "esp_check.h" #include "esp_err.h" #include "esp_attr.h" #include "esp_intr_alloc.h" +#include "esp_log.h" #include "esp_private/system_internal.h" #include "esp_private/periph_ctrl.h" #include "esp_private/esp_task_wdt_impl.h" +#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && SOC_TIMER_SUPPORT_SLEEP_RETENTION +#include "esp_private/sleep_retention.h" +#endif + #define TWDT_INSTANCE WDT_MWDT0 #define TWDT_TICKS_PER_US 500 #define TWDT_PRESCALER MWDT_LL_DEFAULT_CLK_PRESCALER // Tick period of 500us if WDT source clock is 80MHz @@ -39,6 +45,48 @@ typedef struct { * init function. */ static twdt_ctx_hard_t init_context; +#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && SOC_TIMER_SUPPORT_SLEEP_RETENTION +static const char* TAG = "task_wdt"; +static esp_err_t sleep_task_wdt_retention_init(void *arg) +{ + uint32_t group_id = *(uint32_t *)arg; + esp_err_t err = sleep_retention_entries_create(tg_wdt_regs_retention[group_id].link_list, + tg_wdt_regs_retention[group_id].link_num, + REGDMA_LINK_PRI_6, + (group_id == 0) ? SLEEP_RETENTION_MODULE_TG0_WDT : SLEEP_RETENTION_MODULE_TG1_WDT); + if (err == ESP_OK) { + ESP_LOGD(TAG, "Task watchdog timer retention initialization"); + } + ESP_RETURN_ON_ERROR(err, TAG, "Failed to create sleep retention linked list for task watchdog timer"); + return err; +} + +static esp_err_t esp_task_wdt_retention_enable(uint32_t group_id) +{ + sleep_retention_module_init_param_t init_param = { + .cbs = { .create = { .handle = sleep_task_wdt_retention_init, .arg = &group_id } }, + .depends = BIT(SLEEP_RETENTION_MODULE_CLOCK_SYSTEM) + }; + esp_err_t err = sleep_retention_module_init((group_id == 0) ? SLEEP_RETENTION_MODULE_TG0_WDT : SLEEP_RETENTION_MODULE_TG1_WDT, &init_param); + if (err == ESP_OK) { + err = sleep_retention_module_allocate((group_id == 0) ? SLEEP_RETENTION_MODULE_TG0_WDT : SLEEP_RETENTION_MODULE_TG1_WDT); + if (err != ESP_OK) { + ESP_LOGW(TAG, "Failed to allocate sleep retention linked list for task watchdog timer retention"); + } + } + return err; +} + +static esp_err_t esp_task_wdt_retention_disable(uint32_t group_id) +{ + esp_err_t err = sleep_retention_module_free((group_id == 0) ? SLEEP_RETENTION_MODULE_TG0_WDT : SLEEP_RETENTION_MODULE_TG1_WDT); + if (err == ESP_OK) { + err = sleep_retention_module_deinit((group_id == 0) ? SLEEP_RETENTION_MODULE_TG0_WDT : SLEEP_RETENTION_MODULE_TG1_WDT); + } + return err; +} +#endif + esp_err_t esp_task_wdt_impl_timer_allocate(const esp_task_wdt_config_t *config, twdt_isr_callback callback, twdt_ctx_t *obj) @@ -74,8 +122,11 @@ esp_err_t esp_task_wdt_impl_timer_allocate(const esp_task_wdt_config_t *config, /* Return the implementation context to the caller */ *obj = (twdt_ctx_t) ctx; - } +#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && SOC_TIMER_SUPPORT_SLEEP_RETENTION + esp_task_wdt_retention_enable(TWDT_TIMER_GROUP); +#endif + } return ret; } @@ -118,6 +169,10 @@ void esp_task_wdt_impl_timer_free(twdt_ctx_t obj) /* Deregister interrupt */ ESP_ERROR_CHECK(esp_intr_free(ctx->intr_handle)); + +#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && SOC_TIMER_SUPPORT_SLEEP_RETENTION + ESP_ERROR_CHECK(esp_task_wdt_retention_disable(TWDT_TIMER_GROUP)); +#endif } } diff --git a/components/soc/esp32c5/beta3/include/soc/retention_periph_defs.h b/components/soc/esp32c5/beta3/include/soc/retention_periph_defs.h index 2ef044eb40..47b3396017 100644 --- a/components/soc/esp32c5/beta3/include/soc/retention_periph_defs.h +++ b/components/soc/esp32c5/beta3/include/soc/retention_periph_defs.h @@ -18,24 +18,29 @@ typedef enum periph_retention_module { /* clock module, which includes system and modem */ SLEEP_RETENTION_MODULE_CLOCK_SYSTEM = 1, SLEEP_RETENTION_MODULE_CLOCK_MODEM = 2, - - /* modem module, which includes WiFi, BLE and 802.15.4 */ - SLEEP_RETENTION_MODULE_WIFI_MAC = 10, - SLEEP_RETENTION_MODULE_WIFI_BB = 11, - SLEEP_RETENTION_MODULE_BLE_MAC = 12, - SLEEP_RETENTION_MODULE_BT_BB = 13, - SLEEP_RETENTION_MODULE_802154_MAC = 14, - /* digital peripheral module, which includes Interrupt Matrix, HP_SYSTEM, - * TEE, APM, UART, Timer Group, IOMUX, SPIMEM, SysTimer, etc.. */ - SLEEP_RETENTION_MODULE_SYS_PERIPH = 16, - - SLEEP_RETENTION_MODULE_ADC = 17, - - SLEEP_RETENTION_MODULE_GDMA_CH0 = 24, - SLEEP_RETENTION_MODULE_GDMA_CH1 = 25, - SLEEP_RETENTION_MODULE_GDMA_CH2 = 26, + * 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_TG1_WDT = 5, + SLEEP_RETENTION_MODULE_TG0_TIMER = 6, + SLEEP_RETENTION_MODULE_TG1_TIMER = 7, + /* GDMA by channel */ + SLEEP_RETENTION_MODULE_GDMA_CH0 = 8, + SLEEP_RETENTION_MODULE_GDMA_CH1 = 9, + SLEEP_RETENTION_MODULE_GDMA_CH2 = 10, + /* MISC Peripherals */ + SLEEP_RETENTION_MODULE_ADC = 11, + SLEEP_RETENTION_MODULE_I2C0 = 12, + SLEEP_RETENTION_MODULE_RMT0 = 13, + /* Modem module, which includes WiFi, BLE and 802.15.4 */ + SLEEP_RETENTION_MODULE_WIFI_MAC = 26, + SLEEP_RETENTION_MODULE_WIFI_BB = 27, + SLEEP_RETENTION_MODULE_BLE_MAC = 28, + SLEEP_RETENTION_MODULE_BT_BB = 29, + SLEEP_RETENTION_MODULE_802154_MAC = 30, SLEEP_RETENTION_MODULE_MAX = 31 } periph_retention_module_t; @@ -43,26 +48,45 @@ typedef enum periph_retention_module_bitmap { /* clock module, which includes system and modem */ SLEEP_RETENTION_MODULE_BM_CLOCK_SYSTEM = BIT(SLEEP_RETENTION_MODULE_CLOCK_SYSTEM), SLEEP_RETENTION_MODULE_BM_CLOCK_MODEM = BIT(SLEEP_RETENTION_MODULE_CLOCK_MODEM), - + /* digital peripheral module, which includes Interrupt Matrix, HP_SYSTEM, + * TEE, APM, UART, IOMUX, SPIMEM, SysTimer, etc.. */ + SLEEP_RETENTION_MODULE_BM_SYS_PERIPH = BIT(SLEEP_RETENTION_MODULE_SYS_PERIPH), + /* Timer Group by target*/ + SLEEP_RETENTION_MODULE_BM_TASK_WDT = BIT(SLEEP_RETENTION_MODULE_TG0_WDT), + SLEEP_RETENTION_MODULE_BM_INT_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), + /* GDMA by channel */ + SLEEP_RETENTION_MODULE_BM_GDMA_CH0 = BIT(SLEEP_RETENTION_MODULE_GDMA_CH0), + SLEEP_RETENTION_MODULE_BM_GDMA_CH1 = BIT(SLEEP_RETENTION_MODULE_GDMA_CH1), + SLEEP_RETENTION_MODULE_BM_GDMA_CH2 = BIT(SLEEP_RETENTION_MODULE_GDMA_CH2), + /* MISC Peripherals */ + 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), /* 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), SLEEP_RETENTION_MODULE_BM_BLE_MAC = BIT(SLEEP_RETENTION_MODULE_BLE_MAC), SLEEP_RETENTION_MODULE_BM_BT_BB = BIT(SLEEP_RETENTION_MODULE_BT_BB), SLEEP_RETENTION_MODULE_BM_802154_MAC = BIT(SLEEP_RETENTION_MODULE_802154_MAC), - - /* digital peripheral module, which includes Interrupt Matrix, HP_SYSTEM, - * TEE, APM, UART, Timer Group, IOMUX, SPIMEM, SysTimer, etc.. */ - SLEEP_RETENTION_MODULE_BM_SYS_PERIPH = BIT(SLEEP_RETENTION_MODULE_SYS_PERIPH), - - SLEEP_RETENTION_MODULE_BM_ADC = BIT(SLEEP_RETENTION_MODULE_ADC), - - SLEEP_RETENTION_MODULE_BM_GDMA_CH0 = BIT(SLEEP_RETENTION_MODULE_GDMA_CH0), - SLEEP_RETENTION_MODULE_BM_GDMA_CH1 = BIT(SLEEP_RETENTION_MODULE_GDMA_CH1), - SLEEP_RETENTION_MODULE_BM_GDMA_CH2 = BIT(SLEEP_RETENTION_MODULE_GDMA_CH2), SLEEP_RETENTION_MODULE_BM_ALL = (uint32_t)-1 } periph_retention_module_bitmap_t; +#define TOP_DOMAIN_PERIPHERALS_BM (SLEEP_RETENTION_MODULE_BM_CLOCK_SYSTEM \ + | SLEEP_RETENTION_MODULE_BM_CLOCK_MODEM \ + | SLEEP_RETENTION_MODULE_BM_SYS_PERIPH \ + | SLEEP_RETENTION_MODULE_BM_TASK_WDT \ + | SLEEP_RETENTION_MODULE_BM_INT_WDT \ + | SLEEP_RETENTION_MODULE_BM_TG0_TIMER \ + | SLEEP_RETENTION_MODULE_BM_TG1_TIMER \ + | SLEEP_RETENTION_MODULE_BM_GDMA_CH0 \ + | SLEEP_RETENTION_MODULE_BM_GDMA_CH1 \ + | SLEEP_RETENTION_MODULE_BM_GDMA_CH2 \ + | SLEEP_RETENTION_MODULE_BM_ADC \ + | SLEEP_RETENTION_MODULE_BM_I2C0 \ + | SLEEP_RETENTION_MODULE_BM_RMT0) + #ifdef __cplusplus } #endif diff --git a/components/soc/esp32c5/beta3/include/soc/soc_caps.h b/components/soc/esp32c5/beta3/include/soc/soc_caps.h index fa64ffd022..de65604530 100644 --- a/components/soc/esp32c5/beta3/include/soc/soc_caps.h +++ b/components/soc/esp32c5/beta3/include/soc/soc_caps.h @@ -444,6 +444,7 @@ // #define SOC_TIMER_GROUP_SUPPORT_RC_FAST (1) #define SOC_TIMER_GROUP_TOTAL_TIMERS (2) // #define SOC_TIMER_SUPPORT_ETM (1) +// #define SOC_TIMER_SUPPORT_SLEEP_RETENTION (1) /*--------------------------- WATCHDOG CAPS ---------------------------------------*/ // #define SOC_MWDT_SUPPORT_XTAL (1) diff --git a/components/soc/esp32c5/beta3/system_retention_periph.c b/components/soc/esp32c5/beta3/system_retention_periph.c index 08848b4c75..d2a9863ca6 100644 --- a/components/soc/esp32c5/beta3/system_retention_periph.c +++ b/components/soc/esp32c5/beta3/system_retention_periph.c @@ -54,21 +54,6 @@ const regdma_entries_config_t uart_regs_retention[] = { }; _Static_assert(ARRAY_SIZE(uart_regs_retention) == UART_RETENTION_LINK_LEN, "Inconsistent UART retention link length definitions"); -/* Timergroup Registers Context */ -#define N_REGS_TG() (((TIMG_REGCLK_REG(0) - REG_TIMG_BASE(0)) / 4) + 1) -const regdma_entries_config_t tg_regs_retention[] = { - /*Timer group0 backup. T0_wdt should get of write project firstly. wdt used by RTOS.*/ - [0] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TIMG_LINK(0x00), TIMG_WDTWPROTECT_REG(0), TIMG_WDT_WKEY_VALUE, TIMG_WDT_WKEY_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, /* TG0 */ - [1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TIMG_LINK(0x01), REG_TIMG_BASE(0), REG_TIMG_BASE(0), N_REGS_TG(), 0, 0), .owner = ENTRY(0) | ENTRY(2) }, - [2] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TIMG_LINK(0x02), TIMG_WDTWPROTECT_REG(0), TIMG_WDT_WKEY_VALUE, TIMG_WDT_WKEY_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, - [3] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TIMG_LINK(0x03), TIMG_WDTCONFIG0_REG(0), TIMG_WDT_CONF_UPDATE_EN, TIMG_WDT_CONF_UPDATE_EN_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, - [4] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TIMG_LINK(0x04), TIMG_T0UPDATE_REG(0), TIMG_T0_UPDATE, TIMG_T0_UPDATE_M, 0, 1), .owner = ENTRY(0) | ENTRY(2) }, - [5] = { .config = REGDMA_LINK_WAIT_INIT (REGDMA_TIMG_LINK(0x05), TIMG_T0UPDATE_REG(0), 0x0, TIMG_T0_UPDATE_M, 0, 1), .owner = ENTRY(0) | ENTRY(2) }, - [6] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TIMG_LINK(0x06), TIMG_T0LO_REG(0), TIMG_T0LOADLO_REG(0), 2, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, - [7] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TIMG_LINK(0x07), TIMG_T0LOAD_REG(0), 0x1, TIMG_T0_LOAD_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) } -}; -_Static_assert(ARRAY_SIZE(tg_regs_retention) == TIMG_RETENTION_LINK_LEN, "Inconsistent Timergroup 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/timer_periph.c b/components/soc/esp32c5/beta3/timer_periph.c index 4273eec72e..4ab27c7fdf 100644 --- a/components/soc/esp32c5/beta3/timer_periph.c +++ b/components/soc/esp32c5/beta3/timer_periph.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -22,3 +22,32 @@ const timer_group_signal_conn_t timer_group_periph_signals = { } } }; + +#if SOC_TIMER_SUPPORT_SLEEP_RETENTION +#define N_REGS_TGWDT 6 // TIMG_WDTCONFIG0_REG ... TIMG_WDTCONFIG5_REG & TIMG_INT_ENA_TIMERS_REG + +static const regdma_entries_config_t tg0_wdt_regs_retention[] = { + /*Timer group backup. should get of write project firstly. wdt used by RTOS.*/ + [0] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TG0_WDT_LINK(0x00), TIMG_WDTWPROTECT_REG(0), TIMG_WDT_WKEY_VALUE, TIMG_WDT_WKEY_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, + [1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG0_WDT_LINK(0x01), TIMG_WDTCONFIG0_REG(0), TIMG_WDTCONFIG0_REG(0), N_REGS_TGWDT, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [2] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TG0_WDT_LINK(0x03), TIMG_WDTCONFIG0_REG(0), TIMG_WDT_CONF_UPDATE_EN, TIMG_WDT_CONF_UPDATE_EN_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, + [3] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TG0_WDT_LINK(0x03), TIMG_WDTFEED_REG(0), TIMG_WDT_FEED, TIMG_WDT_FEED_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, + [4] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG0_WDT_LINK(0x02), TIMG_INT_ENA_TIMERS_REG(0),TIMG_INT_ENA_TIMERS_REG(0), 1, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [5] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TG0_WDT_LINK(0x04), TIMG_WDTWPROTECT_REG(0), 0, TIMG_WDT_WKEY_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, +}; + +static const regdma_entries_config_t tg1_wdt_regs_retention[] = { + /*Timer group0 backup. T0_wdt should get of write project firstly. wdt used by RTOS.*/ + [0] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TG1_WDT_LINK(0x00), TIMG_WDTWPROTECT_REG(1), TIMG_WDT_WKEY_VALUE, TIMG_WDT_WKEY_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, + [1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG1_WDT_LINK(0x02), TIMG_INT_ENA_TIMERS_REG(1),TIMG_INT_ENA_TIMERS_REG(1), 1, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [2] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG1_WDT_LINK(0x01), TIMG_WDTCONFIG0_REG(1), TIMG_WDTCONFIG0_REG(1), N_REGS_TGWDT, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [3] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TG1_WDT_LINK(0x03), TIMG_WDTCONFIG0_REG(1), TIMG_WDT_CONF_UPDATE_EN, TIMG_WDT_CONF_UPDATE_EN_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, + [4] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TG0_WDT_LINK(0x03), TIMG_WDTFEED_REG(1), TIMG_WDT_FEED, TIMG_WDT_FEED_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, + [5] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TG1_WDT_LINK(0x04), TIMG_WDTWPROTECT_REG(1), 0, TIMG_WDT_WKEY_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, +}; + +const tg_reg_ctx_link_t tg_wdt_regs_retention[SOC_TIMER_GROUPS] = { + [0] = {tg0_wdt_regs_retention, ARRAY_SIZE(tg0_wdt_regs_retention)}, + [1] = {tg1_wdt_regs_retention, ARRAY_SIZE(tg1_wdt_regs_retention)}, +}; +#endif diff --git a/components/soc/esp32c5/mp/include/soc/soc_caps.h b/components/soc/esp32c5/mp/include/soc/soc_caps.h index dc5e4d5f76..e4eb501367 100644 --- a/components/soc/esp32c5/mp/include/soc/soc_caps.h +++ b/components/soc/esp32c5/mp/include/soc/soc_caps.h @@ -439,6 +439,7 @@ // #define SOC_TIMER_GROUP_SUPPORT_RC_FAST (1) #define SOC_TIMER_GROUP_TOTAL_TIMERS (2) // #define SOC_TIMER_SUPPORT_ETM (1) +// #define SOC_TIMER_SUPPORT_SLEEP_RETENTION (1) /*--------------------------- WATCHDOG CAPS ---------------------------------------*/ // #define SOC_MWDT_SUPPORT_XTAL (1) diff --git a/components/soc/esp32c5/mp/timer_periph.c b/components/soc/esp32c5/mp/timer_periph.c index 4273eec72e..4ab27c7fdf 100644 --- a/components/soc/esp32c5/mp/timer_periph.c +++ b/components/soc/esp32c5/mp/timer_periph.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -22,3 +22,32 @@ const timer_group_signal_conn_t timer_group_periph_signals = { } } }; + +#if SOC_TIMER_SUPPORT_SLEEP_RETENTION +#define N_REGS_TGWDT 6 // TIMG_WDTCONFIG0_REG ... TIMG_WDTCONFIG5_REG & TIMG_INT_ENA_TIMERS_REG + +static const regdma_entries_config_t tg0_wdt_regs_retention[] = { + /*Timer group backup. should get of write project firstly. wdt used by RTOS.*/ + [0] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TG0_WDT_LINK(0x00), TIMG_WDTWPROTECT_REG(0), TIMG_WDT_WKEY_VALUE, TIMG_WDT_WKEY_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, + [1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG0_WDT_LINK(0x01), TIMG_WDTCONFIG0_REG(0), TIMG_WDTCONFIG0_REG(0), N_REGS_TGWDT, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [2] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TG0_WDT_LINK(0x03), TIMG_WDTCONFIG0_REG(0), TIMG_WDT_CONF_UPDATE_EN, TIMG_WDT_CONF_UPDATE_EN_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, + [3] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TG0_WDT_LINK(0x03), TIMG_WDTFEED_REG(0), TIMG_WDT_FEED, TIMG_WDT_FEED_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, + [4] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG0_WDT_LINK(0x02), TIMG_INT_ENA_TIMERS_REG(0),TIMG_INT_ENA_TIMERS_REG(0), 1, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [5] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TG0_WDT_LINK(0x04), TIMG_WDTWPROTECT_REG(0), 0, TIMG_WDT_WKEY_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, +}; + +static const regdma_entries_config_t tg1_wdt_regs_retention[] = { + /*Timer group0 backup. T0_wdt should get of write project firstly. wdt used by RTOS.*/ + [0] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TG1_WDT_LINK(0x00), TIMG_WDTWPROTECT_REG(1), TIMG_WDT_WKEY_VALUE, TIMG_WDT_WKEY_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, + [1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG1_WDT_LINK(0x02), TIMG_INT_ENA_TIMERS_REG(1),TIMG_INT_ENA_TIMERS_REG(1), 1, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [2] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG1_WDT_LINK(0x01), TIMG_WDTCONFIG0_REG(1), TIMG_WDTCONFIG0_REG(1), N_REGS_TGWDT, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [3] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TG1_WDT_LINK(0x03), TIMG_WDTCONFIG0_REG(1), TIMG_WDT_CONF_UPDATE_EN, TIMG_WDT_CONF_UPDATE_EN_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, + [4] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TG0_WDT_LINK(0x03), TIMG_WDTFEED_REG(1), TIMG_WDT_FEED, TIMG_WDT_FEED_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, + [5] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TG1_WDT_LINK(0x04), TIMG_WDTWPROTECT_REG(1), 0, TIMG_WDT_WKEY_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, +}; + +const tg_reg_ctx_link_t tg_wdt_regs_retention[SOC_TIMER_GROUPS] = { + [0] = {tg0_wdt_regs_retention, ARRAY_SIZE(tg0_wdt_regs_retention)}, + [1] = {tg1_wdt_regs_retention, ARRAY_SIZE(tg1_wdt_regs_retention)}, +}; +#endif diff --git a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in index 85387866e8..f3f3df1034 100644 --- a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in @@ -1111,6 +1111,10 @@ config SOC_TIMER_SUPPORT_ETM bool default y +config SOC_TIMER_SUPPORT_SLEEP_RETENTION + bool + default y + config SOC_MWDT_SUPPORT_XTAL 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 bd798e1903..47b3396017 100644 --- a/components/soc/esp32c6/include/soc/retention_periph_defs.h +++ b/components/soc/esp32c6/include/soc/retention_periph_defs.h @@ -18,25 +18,29 @@ typedef enum periph_retention_module { /* clock module, which includes system and modem */ SLEEP_RETENTION_MODULE_CLOCK_SYSTEM = 1, SLEEP_RETENTION_MODULE_CLOCK_MODEM = 2, - - /* modem module, which includes WiFi, BLE and 802.15.4 */ - SLEEP_RETENTION_MODULE_WIFI_MAC = 10, - SLEEP_RETENTION_MODULE_WIFI_BB = 11, - SLEEP_RETENTION_MODULE_BLE_MAC = 12, - SLEEP_RETENTION_MODULE_BT_BB = 13, - SLEEP_RETENTION_MODULE_802154_MAC = 14, - /* digital peripheral module, which includes Interrupt Matrix, HP_SYSTEM, - * TEE, APM, UART, Timer Group, IOMUX, SPIMEM, SysTimer, etc.. */ - SLEEP_RETENTION_MODULE_SYS_PERIPH = 16, - - SLEEP_RETENTION_MODULE_ADC = 17, - - SLEEP_RETENTION_MODULE_GDMA_CH0 = 24, - SLEEP_RETENTION_MODULE_GDMA_CH1 = 25, - SLEEP_RETENTION_MODULE_GDMA_CH2 = 26, - SLEEP_RETENTION_MODULE_I2C0 = 27, + * 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_TG1_WDT = 5, + SLEEP_RETENTION_MODULE_TG0_TIMER = 6, + SLEEP_RETENTION_MODULE_TG1_TIMER = 7, + /* GDMA by channel */ + SLEEP_RETENTION_MODULE_GDMA_CH0 = 8, + SLEEP_RETENTION_MODULE_GDMA_CH1 = 9, + SLEEP_RETENTION_MODULE_GDMA_CH2 = 10, + /* MISC Peripherals */ + SLEEP_RETENTION_MODULE_ADC = 11, + SLEEP_RETENTION_MODULE_I2C0 = 12, + SLEEP_RETENTION_MODULE_RMT0 = 13, + /* Modem module, which includes WiFi, BLE and 802.15.4 */ + SLEEP_RETENTION_MODULE_WIFI_MAC = 26, + SLEEP_RETENTION_MODULE_WIFI_BB = 27, + SLEEP_RETENTION_MODULE_BLE_MAC = 28, + SLEEP_RETENTION_MODULE_BT_BB = 29, + SLEEP_RETENTION_MODULE_802154_MAC = 30, SLEEP_RETENTION_MODULE_MAX = 31 } periph_retention_module_t; @@ -44,27 +48,45 @@ typedef enum periph_retention_module_bitmap { /* clock module, which includes system and modem */ SLEEP_RETENTION_MODULE_BM_CLOCK_SYSTEM = BIT(SLEEP_RETENTION_MODULE_CLOCK_SYSTEM), SLEEP_RETENTION_MODULE_BM_CLOCK_MODEM = BIT(SLEEP_RETENTION_MODULE_CLOCK_MODEM), - + /* digital peripheral module, which includes Interrupt Matrix, HP_SYSTEM, + * TEE, APM, UART, IOMUX, SPIMEM, SysTimer, etc.. */ + SLEEP_RETENTION_MODULE_BM_SYS_PERIPH = BIT(SLEEP_RETENTION_MODULE_SYS_PERIPH), + /* Timer Group by target*/ + SLEEP_RETENTION_MODULE_BM_TASK_WDT = BIT(SLEEP_RETENTION_MODULE_TG0_WDT), + SLEEP_RETENTION_MODULE_BM_INT_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), + /* GDMA by channel */ + SLEEP_RETENTION_MODULE_BM_GDMA_CH0 = BIT(SLEEP_RETENTION_MODULE_GDMA_CH0), + SLEEP_RETENTION_MODULE_BM_GDMA_CH1 = BIT(SLEEP_RETENTION_MODULE_GDMA_CH1), + SLEEP_RETENTION_MODULE_BM_GDMA_CH2 = BIT(SLEEP_RETENTION_MODULE_GDMA_CH2), + /* MISC Peripherals */ + 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), /* 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), SLEEP_RETENTION_MODULE_BM_BLE_MAC = BIT(SLEEP_RETENTION_MODULE_BLE_MAC), SLEEP_RETENTION_MODULE_BM_BT_BB = BIT(SLEEP_RETENTION_MODULE_BT_BB), SLEEP_RETENTION_MODULE_BM_802154_MAC = BIT(SLEEP_RETENTION_MODULE_802154_MAC), - - /* digital peripheral module, which includes Interrupt Matrix, HP_SYSTEM, - * TEE, APM, UART, Timer Group, IOMUX, SPIMEM, SysTimer, etc.. */ - SLEEP_RETENTION_MODULE_BM_SYS_PERIPH = BIT(SLEEP_RETENTION_MODULE_SYS_PERIPH), - - SLEEP_RETENTION_MODULE_BM_ADC = BIT(SLEEP_RETENTION_MODULE_ADC), - - SLEEP_RETENTION_MODULE_BM_GDMA_CH0 = BIT(SLEEP_RETENTION_MODULE_GDMA_CH0), - SLEEP_RETENTION_MODULE_BM_GDMA_CH1 = BIT(SLEEP_RETENTION_MODULE_GDMA_CH1), - SLEEP_RETENTION_MODULE_BM_GDMA_CH2 = BIT(SLEEP_RETENTION_MODULE_GDMA_CH2), - SLEEP_RETENTION_MODULE_BM_I2C0 = BIT(SLEEP_RETENTION_MODULE_I2C0), SLEEP_RETENTION_MODULE_BM_ALL = (uint32_t)-1 } periph_retention_module_bitmap_t; +#define TOP_DOMAIN_PERIPHERALS_BM (SLEEP_RETENTION_MODULE_BM_CLOCK_SYSTEM \ + | SLEEP_RETENTION_MODULE_BM_CLOCK_MODEM \ + | SLEEP_RETENTION_MODULE_BM_SYS_PERIPH \ + | SLEEP_RETENTION_MODULE_BM_TASK_WDT \ + | SLEEP_RETENTION_MODULE_BM_INT_WDT \ + | SLEEP_RETENTION_MODULE_BM_TG0_TIMER \ + | SLEEP_RETENTION_MODULE_BM_TG1_TIMER \ + | SLEEP_RETENTION_MODULE_BM_GDMA_CH0 \ + | SLEEP_RETENTION_MODULE_BM_GDMA_CH1 \ + | SLEEP_RETENTION_MODULE_BM_GDMA_CH2 \ + | SLEEP_RETENTION_MODULE_BM_ADC \ + | SLEEP_RETENTION_MODULE_BM_I2C0 \ + | SLEEP_RETENTION_MODULE_BM_RMT0) + #ifdef __cplusplus } #endif diff --git a/components/soc/esp32c6/include/soc/soc_caps.h b/components/soc/esp32c6/include/soc/soc_caps.h index 4ad24e4d17..c16ebceee4 100644 --- a/components/soc/esp32c6/include/soc/soc_caps.h +++ b/components/soc/esp32c6/include/soc/soc_caps.h @@ -440,6 +440,7 @@ #define SOC_TIMER_GROUP_SUPPORT_RC_FAST (1) #define SOC_TIMER_GROUP_TOTAL_TIMERS (2) #define SOC_TIMER_SUPPORT_ETM (1) +#define SOC_TIMER_SUPPORT_SLEEP_RETENTION (1) /*--------------------------- WATCHDOG CAPS ---------------------------------------*/ #define SOC_MWDT_SUPPORT_XTAL (1) diff --git a/components/soc/esp32c6/system_retention_periph.c b/components/soc/esp32c6/system_retention_periph.c index 8e65e7c355..b9645c39a4 100644 --- a/components/soc/esp32c6/system_retention_periph.c +++ b/components/soc/esp32c6/system_retention_periph.c @@ -54,21 +54,6 @@ const regdma_entries_config_t uart_regs_retention[] = { }; _Static_assert(ARRAY_SIZE(uart_regs_retention) == UART_RETENTION_LINK_LEN, "Inconsistent UART retention link length definitions"); -/* Timergroup Registers Context */ -#define N_REGS_TG() (((TIMG_REGCLK_REG(0) - REG_TIMG_BASE(0)) / 4) + 1) -const regdma_entries_config_t tg_regs_retention[] = { - /*Timer group0 backup. T0_wdt should get of write project firstly. wdt used by RTOS.*/ - [0] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TIMG_LINK(0x00), TIMG_WDTWPROTECT_REG(0), TIMG_WDT_WKEY_VALUE, TIMG_WDT_WKEY_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, /* TG0 */ - [1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TIMG_LINK(0x01), REG_TIMG_BASE(0), REG_TIMG_BASE(0), N_REGS_TG(), 0, 0), .owner = ENTRY(0) | ENTRY(2) }, - [2] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TIMG_LINK(0x02), TIMG_WDTWPROTECT_REG(0), TIMG_WDT_WKEY_VALUE, TIMG_WDT_WKEY_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, - [3] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TIMG_LINK(0x03), TIMG_WDTCONFIG0_REG(0), TIMG_WDT_CONF_UPDATE_EN, TIMG_WDT_CONF_UPDATE_EN_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, - [4] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TIMG_LINK(0x04), TIMG_T0UPDATE_REG(0), TIMG_T0_UPDATE, TIMG_T0_UPDATE_M, 0, 1), .owner = ENTRY(0) | ENTRY(2) }, - [5] = { .config = REGDMA_LINK_WAIT_INIT (REGDMA_TIMG_LINK(0x05), TIMG_T0UPDATE_REG(0), 0x0, TIMG_T0_UPDATE_M, 0, 1), .owner = ENTRY(0) | ENTRY(2) }, - [6] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TIMG_LINK(0x06), TIMG_T0LO_REG(0), TIMG_T0LOADLO_REG(0), 2, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, - [7] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TIMG_LINK(0x07), TIMG_T0LOAD_REG(0), 0x1, TIMG_T0_LOAD_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) } -}; -_Static_assert(ARRAY_SIZE(tg_regs_retention) == TIMG_RETENTION_LINK_LEN, "Inconsistent Timergroup 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/timer_periph.c b/components/soc/esp32c6/timer_periph.c index 089c80958f..7d338258de 100644 --- a/components/soc/esp32c6/timer_periph.c +++ b/components/soc/esp32c6/timer_periph.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -22,3 +22,30 @@ const timer_group_signal_conn_t timer_group_periph_signals = { } } }; + +#define N_REGS_TGWDT 6 // TIMG_WDTCONFIG0_REG ... TIMG_WDTCONFIG5_REG & TIMG_INT_ENA_TIMERS_REG + +static const regdma_entries_config_t tg0_wdt_regs_retention[] = { + /*Timer group backup. should get of write project firstly. wdt used by RTOS.*/ + [0] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TG0_WDT_LINK(0x00), TIMG_WDTWPROTECT_REG(0), TIMG_WDT_WKEY_VALUE, TIMG_WDT_WKEY_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, + [1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG0_WDT_LINK(0x01), TIMG_WDTCONFIG0_REG(0), TIMG_WDTCONFIG0_REG(0), N_REGS_TGWDT, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [2] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TG0_WDT_LINK(0x03), TIMG_WDTCONFIG0_REG(0), TIMG_WDT_CONF_UPDATE_EN, TIMG_WDT_CONF_UPDATE_EN_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, + [3] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TG0_WDT_LINK(0x03), TIMG_WDTFEED_REG(0), TIMG_WDT_FEED, TIMG_WDT_FEED_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, + [4] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG0_WDT_LINK(0x02), TIMG_INT_ENA_TIMERS_REG(0),TIMG_INT_ENA_TIMERS_REG(0), 1, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [5] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TG0_WDT_LINK(0x04), TIMG_WDTWPROTECT_REG(0), 0, TIMG_WDT_WKEY_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, +}; + +static const regdma_entries_config_t tg1_wdt_regs_retention[] = { + /*Timer group0 backup. T0_wdt should get of write project firstly. wdt used by RTOS.*/ + [0] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TG1_WDT_LINK(0x00), TIMG_WDTWPROTECT_REG(1), TIMG_WDT_WKEY_VALUE, TIMG_WDT_WKEY_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, + [1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG1_WDT_LINK(0x02), TIMG_INT_ENA_TIMERS_REG(1),TIMG_INT_ENA_TIMERS_REG(1), 1, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [2] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG1_WDT_LINK(0x01), TIMG_WDTCONFIG0_REG(1), TIMG_WDTCONFIG0_REG(1), N_REGS_TGWDT, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [3] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TG1_WDT_LINK(0x03), TIMG_WDTCONFIG0_REG(1), TIMG_WDT_CONF_UPDATE_EN, TIMG_WDT_CONF_UPDATE_EN_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, + [4] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TG0_WDT_LINK(0x03), TIMG_WDTFEED_REG(1), TIMG_WDT_FEED, TIMG_WDT_FEED_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, + [5] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TG1_WDT_LINK(0x04), TIMG_WDTWPROTECT_REG(1), 0, TIMG_WDT_WKEY_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, +}; + +const tg_reg_ctx_link_t tg_wdt_regs_retention[SOC_TIMER_GROUPS] = { + [0] = {tg0_wdt_regs_retention, ARRAY_SIZE(tg0_wdt_regs_retention)}, + [1] = {tg1_wdt_regs_retention, ARRAY_SIZE(tg1_wdt_regs_retention)}, +}; diff --git a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in index 5bc1cc4495..9ebdecb32c 100644 --- a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in @@ -1115,6 +1115,10 @@ config SOC_TIMER_SUPPORT_ETM bool default y +config SOC_TIMER_SUPPORT_SLEEP_RETENTION + bool + default y + config SOC_MWDT_SUPPORT_XTAL 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 5ac1e90c2a..353bc1c2bc 100644 --- a/components/soc/esp32h2/include/soc/retention_periph_defs.h +++ b/components/soc/esp32h2/include/soc/retention_periph_defs.h @@ -18,24 +18,28 @@ typedef enum periph_retention_module { /* clock module, which includes system and modem */ SLEEP_RETENTION_MODULE_CLOCK_SYSTEM = 1, SLEEP_RETENTION_MODULE_CLOCK_MODEM = 2, - - /* modem module, which includes BLE and 802.15.4 */ - SLEEP_RETENTION_MODULE_BLE_MAC = 12, - SLEEP_RETENTION_MODULE_BT_BB = 13, - SLEEP_RETENTION_MODULE_802154_MAC = 14, - /* digital peripheral module, which includes Interrupt Matrix, HP_SYSTEM, - * TEE, APM, UART, Timer Group, IOMUX, SPIMEM, SysTimer, etc.. */ - SLEEP_RETENTION_MODULE_SYS_PERIPH = 16, - - SLEEP_RETENTION_MODULE_ADC = 17, - - SLEEP_RETENTION_MODULE_GDMA_CH0 = 24, - SLEEP_RETENTION_MODULE_GDMA_CH1 = 25, - SLEEP_RETENTION_MODULE_GDMA_CH2 = 26, - SLEEP_RETENTION_MODULE_I2C0 = 27, - SLEEP_RETENTION_MODULE_I2C1 = 28, + * 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_TG1_WDT = 5, + SLEEP_RETENTION_MODULE_TG0_TIMER = 6, + SLEEP_RETENTION_MODULE_TG1_TIMER = 7, + /* GDMA by channel */ + SLEEP_RETENTION_MODULE_GDMA_CH0 = 8, + SLEEP_RETENTION_MODULE_GDMA_CH1 = 9, + SLEEP_RETENTION_MODULE_GDMA_CH2 = 10, + /* MISC Peripherals */ + SLEEP_RETENTION_MODULE_ADC = 11, + SLEEP_RETENTION_MODULE_I2C0 = 12, + SLEEP_RETENTION_MODULE_I2C1 = 13, + SLEEP_RETENTION_MODULE_RMT0 = 14, + /* Modem module, which includes BLE and 802.15.4 */ + SLEEP_RETENTION_MODULE_BLE_MAC = 28, + SLEEP_RETENTION_MODULE_BT_BB = 29, + SLEEP_RETENTION_MODULE_802154_MAC = 30, SLEEP_RETENTION_MODULE_MAX = 31 } periph_retention_module_t; @@ -43,27 +47,45 @@ typedef enum periph_retention_module_bitmap { /* clock module, which includes system and modem */ SLEEP_RETENTION_MODULE_BM_CLOCK_SYSTEM = BIT(SLEEP_RETENTION_MODULE_CLOCK_SYSTEM), SLEEP_RETENTION_MODULE_BM_CLOCK_MODEM = BIT(SLEEP_RETENTION_MODULE_CLOCK_MODEM), - + /* digital peripheral module, which includes Interrupt Matrix, HP_SYSTEM, + * TEE, APM, UART, Timer Group, IOMUX, SPIMEM, SysTimer, etc.. */ + SLEEP_RETENTION_MODULE_BM_SYS_PERIPH = BIT(SLEEP_RETENTION_MODULE_SYS_PERIPH), + /* Timer Group by target*/ + SLEEP_RETENTION_MODULE_BM_TASK_WDT = BIT(SLEEP_RETENTION_MODULE_TG0_WDT), + SLEEP_RETENTION_MODULE_BM_INT_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), + /* GDMA by channel */ + SLEEP_RETENTION_MODULE_BM_GDMA_CH0 = BIT(SLEEP_RETENTION_MODULE_GDMA_CH0), + SLEEP_RETENTION_MODULE_BM_GDMA_CH1 = BIT(SLEEP_RETENTION_MODULE_GDMA_CH1), + SLEEP_RETENTION_MODULE_BM_GDMA_CH2 = BIT(SLEEP_RETENTION_MODULE_GDMA_CH2), + /* MISC Peripherals */ + SLEEP_RETENTION_MODULE_BM_ADC = BIT(SLEEP_RETENTION_MODULE_ADC), + 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), /* 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), SLEEP_RETENTION_MODULE_BM_802154_MAC = BIT(SLEEP_RETENTION_MODULE_802154_MAC), - - /* digital peripheral module, which includes Interrupt Matrix, HP_SYSTEM, - * TEE, APM, UART, Timer Group, IOMUX, SPIMEM, SysTimer, etc.. */ - SLEEP_RETENTION_MODULE_BM_SYS_PERIPH = BIT(SLEEP_RETENTION_MODULE_SYS_PERIPH), - - SLEEP_RETENTION_MODULE_BM_ADC = BIT(SLEEP_RETENTION_MODULE_ADC), - - SLEEP_RETENTION_MODULE_BM_GDMA_CH0 = BIT(SLEEP_RETENTION_MODULE_GDMA_CH0), - SLEEP_RETENTION_MODULE_BM_GDMA_CH1 = BIT(SLEEP_RETENTION_MODULE_GDMA_CH1), - SLEEP_RETENTION_MODULE_BM_GDMA_CH2 = BIT(SLEEP_RETENTION_MODULE_GDMA_CH2), - SLEEP_RETENTION_MODULE_BM_I2C0 = BIT(SLEEP_RETENTION_MODULE_I2C0), - SLEEP_RETENTION_MODULE_BM_I2C1 = BIT(SLEEP_RETENTION_MODULE_I2C1), - - SLEEP_RETENTION_MODULE_BM_ALL = (uint32_t)-1 + SLEEP_RETENTION_MODULE_BM_ALL = (uint32_t) -1 } periph_retention_module_bitmap_t; +#define TOP_DOMAIN_PERIPHERALS_BM (SLEEP_RETENTION_MODULE_BM_CLOCK_SYSTEM \ + | SLEEP_RETENTION_MODULE_BM_CLOCK_MODEM \ + | SLEEP_RETENTION_MODULE_BM_SYS_PERIPH \ + | SLEEP_RETENTION_MODULE_BM_TASK_WDT \ + | SLEEP_RETENTION_MODULE_BM_INT_WDT \ + | SLEEP_RETENTION_MODULE_BM_TG0_TIMER \ + | SLEEP_RETENTION_MODULE_BM_TG1_TIMER \ + | SLEEP_RETENTION_MODULE_BM_GDMA_CH0 \ + | SLEEP_RETENTION_MODULE_BM_GDMA_CH1 \ + | SLEEP_RETENTION_MODULE_BM_GDMA_CH2 \ + | SLEEP_RETENTION_MODULE_BM_ADC \ + | SLEEP_RETENTION_MODULE_BM_I2C0 \ + | SLEEP_RETENTION_MODULE_BM_I2C1 \ + | SLEEP_RETENTION_MODULE_BM_RMT0) + #ifdef __cplusplus } #endif diff --git a/components/soc/esp32h2/include/soc/soc_caps.h b/components/soc/esp32h2/include/soc/soc_caps.h index 29599f99f7..8728e3f730 100644 --- a/components/soc/esp32h2/include/soc/soc_caps.h +++ b/components/soc/esp32h2/include/soc/soc_caps.h @@ -438,6 +438,7 @@ #define SOC_TIMER_GROUP_SUPPORT_RC_FAST (1) #define SOC_TIMER_GROUP_TOTAL_TIMERS (2) #define SOC_TIMER_SUPPORT_ETM (1) +#define SOC_TIMER_SUPPORT_SLEEP_RETENTION (1) /*--------------------------- WATCHDOG CAPS ---------------------------------------*/ #define SOC_MWDT_SUPPORT_XTAL (1) diff --git a/components/soc/esp32h2/system_retention_periph.c b/components/soc/esp32h2/system_retention_periph.c index fead39b123..da52fbe53f 100644 --- a/components/soc/esp32h2/system_retention_periph.c +++ b/components/soc/esp32h2/system_retention_periph.c @@ -54,21 +54,6 @@ const regdma_entries_config_t uart_regs_retention[] = { }; _Static_assert(ARRAY_SIZE(uart_regs_retention) == UART_RETENTION_LINK_LEN, "Inconsistent UART retention link length definitions"); -/* Timergroup Registers Context */ -#define N_REGS_TG() (((TIMG_REGCLK_REG(0) - REG_TIMG_BASE(0)) / 4) + 1) -const regdma_entries_config_t tg_regs_retention[] = { - /*Timer group0 backup. T0_wdt should get of write project firstly. wdt used by RTOS.*/ - [0] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TIMG_LINK(0x00), TIMG_WDTWPROTECT_REG(0), TIMG_WDT_WKEY_VALUE, TIMG_WDT_WKEY_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, /* TG0 */ - [1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TIMG_LINK(0x01), REG_TIMG_BASE(0), REG_TIMG_BASE(0), N_REGS_TG(), 0, 0), .owner = ENTRY(0) | ENTRY(2) }, - [2] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TIMG_LINK(0x02), TIMG_WDTWPROTECT_REG(0), TIMG_WDT_WKEY_VALUE, TIMG_WDT_WKEY_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, - [3] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TIMG_LINK(0x03), TIMG_WDTCONFIG0_REG(0), TIMG_WDT_CONF_UPDATE_EN, TIMG_WDT_CONF_UPDATE_EN_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, - [4] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TIMG_LINK(0x04), TIMG_T0UPDATE_REG(0), TIMG_T0_UPDATE, TIMG_T0_UPDATE_M, 0, 1), .owner = ENTRY(0) | ENTRY(2) }, - [5] = { .config = REGDMA_LINK_WAIT_INIT (REGDMA_TIMG_LINK(0x05), TIMG_T0UPDATE_REG(0), 0x0, TIMG_T0_UPDATE_M, 0, 1), .owner = ENTRY(0) | ENTRY(2) }, - [6] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TIMG_LINK(0x06), TIMG_T0LO_REG(0), TIMG_T0LOADLO_REG(0), 2, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, - [7] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TIMG_LINK(0x07), TIMG_T0LOAD_REG(0), 0x1, TIMG_T0_LOAD_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) } -}; -_Static_assert(ARRAY_SIZE(tg_regs_retention) == TIMG_RETENTION_LINK_LEN, "Inconsistent Timergroup 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/timer_periph.c b/components/soc/esp32h2/timer_periph.c index e2be270b18..7d338258de 100644 --- a/components/soc/esp32h2/timer_periph.c +++ b/components/soc/esp32h2/timer_periph.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -22,3 +22,30 @@ const timer_group_signal_conn_t timer_group_periph_signals = { } } }; + +#define N_REGS_TGWDT 6 // TIMG_WDTCONFIG0_REG ... TIMG_WDTCONFIG5_REG & TIMG_INT_ENA_TIMERS_REG + +static const regdma_entries_config_t tg0_wdt_regs_retention[] = { + /*Timer group backup. should get of write project firstly. wdt used by RTOS.*/ + [0] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TG0_WDT_LINK(0x00), TIMG_WDTWPROTECT_REG(0), TIMG_WDT_WKEY_VALUE, TIMG_WDT_WKEY_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, + [1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG0_WDT_LINK(0x01), TIMG_WDTCONFIG0_REG(0), TIMG_WDTCONFIG0_REG(0), N_REGS_TGWDT, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [2] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TG0_WDT_LINK(0x03), TIMG_WDTCONFIG0_REG(0), TIMG_WDT_CONF_UPDATE_EN, TIMG_WDT_CONF_UPDATE_EN_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, + [3] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TG0_WDT_LINK(0x03), TIMG_WDTFEED_REG(0), TIMG_WDT_FEED, TIMG_WDT_FEED_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, + [4] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG0_WDT_LINK(0x02), TIMG_INT_ENA_TIMERS_REG(0),TIMG_INT_ENA_TIMERS_REG(0), 1, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [5] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TG0_WDT_LINK(0x04), TIMG_WDTWPROTECT_REG(0), 0, TIMG_WDT_WKEY_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, +}; + +static const regdma_entries_config_t tg1_wdt_regs_retention[] = { + /*Timer group0 backup. T0_wdt should get of write project firstly. wdt used by RTOS.*/ + [0] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TG1_WDT_LINK(0x00), TIMG_WDTWPROTECT_REG(1), TIMG_WDT_WKEY_VALUE, TIMG_WDT_WKEY_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, + [1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG1_WDT_LINK(0x02), TIMG_INT_ENA_TIMERS_REG(1),TIMG_INT_ENA_TIMERS_REG(1), 1, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [2] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG1_WDT_LINK(0x01), TIMG_WDTCONFIG0_REG(1), TIMG_WDTCONFIG0_REG(1), N_REGS_TGWDT, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [3] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TG1_WDT_LINK(0x03), TIMG_WDTCONFIG0_REG(1), TIMG_WDT_CONF_UPDATE_EN, TIMG_WDT_CONF_UPDATE_EN_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, + [4] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TG0_WDT_LINK(0x03), TIMG_WDTFEED_REG(1), TIMG_WDT_FEED, TIMG_WDT_FEED_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, + [5] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TG1_WDT_LINK(0x04), TIMG_WDTWPROTECT_REG(1), 0, TIMG_WDT_WKEY_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, +}; + +const tg_reg_ctx_link_t tg_wdt_regs_retention[SOC_TIMER_GROUPS] = { + [0] = {tg0_wdt_regs_retention, ARRAY_SIZE(tg0_wdt_regs_retention)}, + [1] = {tg1_wdt_regs_retention, ARRAY_SIZE(tg1_wdt_regs_retention)}, +}; diff --git a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in index d58925194e..dd76fce1aa 100644 --- a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in @@ -1359,6 +1359,10 @@ config SOC_TIMER_SUPPORT_ETM bool default y +config SOC_TIMER_SUPPORT_SLEEP_RETENTION + bool + default y + config SOC_MWDT_SUPPORT_XTAL 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 fde9c3e687..34219a85e0 100644 --- a/components/soc/esp32p4/include/soc/retention_periph_defs.h +++ b/components/soc/esp32p4/include/soc/retention_periph_defs.h @@ -17,10 +17,14 @@ typedef enum periph_retention_module { SLEEP_RETENTION_MODULE_MIN = 0, /* clock module, which includes system and modem */ SLEEP_RETENTION_MODULE_CLOCK_SYSTEM = 1, - /* digital peripheral module, which includes Interrupt Matrix, HP_SYSTEM, - * TEE, APM, UART, Timer Group, IOMUX, SPIMEM, SysTimer, etc.. */ - SLEEP_RETENTION_MODULE_SYS_PERIPH = 16, + * TEE, APM, UART, IOMUX, SPIMEM, SysTimer, etc.. */ + SLEEP_RETENTION_MODULE_SYS_PERIPH = 2, + /* Timer Group by target*/ + SLEEP_RETENTION_MODULE_TG0_WDT = 3, + SLEEP_RETENTION_MODULE_TG1_WDT = 4, + SLEEP_RETENTION_MODULE_TG0_TIMER = 5, + SLEEP_RETENTION_MODULE_TG1_TIMER = 6, SLEEP_RETENTION_MODULE_MAX = 31 } periph_retention_module_t; @@ -28,14 +32,25 @@ typedef enum periph_retention_module { typedef enum periph_retention_module_bitmap { /* clock module, which includes system and modem */ SLEEP_RETENTION_MODULE_BM_CLOCK_SYSTEM = BIT(SLEEP_RETENTION_MODULE_CLOCK_SYSTEM), - /* digital peripheral module, which includes Interrupt Matrix, HP_SYSTEM, * TEE, APM, UART, Timer Group, IOMUX, SPIMEM, SysTimer, etc.. */ SLEEP_RETENTION_MODULE_BM_SYS_PERIPH = BIT(SLEEP_RETENTION_MODULE_SYS_PERIPH), + /* Timer Group by target*/ + SLEEP_RETENTION_MODULE_BM_TG0_WDT = BIT(SLEEP_RETENTION_MODULE_TG0_WDT), + 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), SLEEP_RETENTION_MODULE_BM_ALL = (uint32_t)-1 } periph_retention_module_bitmap_t; +#define TOP_DOMAIN_PERIPHERALS_BM (SLEEP_RETENTION_MODULE_BM_CLOCK_SYSTEM \ + | SLEEP_RETENTION_MODULE_BM_SYS_PERIPH \ + | SLEEP_RETENTION_MODULE_BM_TG0_WDT \ + | SLEEP_RETENTION_MODULE_BM_TG1_WDT \ + | SLEEP_RETENTION_MODULE_BM_TG0_TIMER \ + | SLEEP_RETENTION_MODULE_BM_TG1_TIMER) + #ifdef __cplusplus } #endif diff --git a/components/soc/esp32p4/include/soc/soc_caps.h b/components/soc/esp32p4/include/soc/soc_caps.h index 4a1f6cefd4..ce6770f1b6 100644 --- a/components/soc/esp32p4/include/soc/soc_caps.h +++ b/components/soc/esp32p4/include/soc/soc_caps.h @@ -536,6 +536,7 @@ #define SOC_TIMER_GROUP_SUPPORT_RC_FAST 1 #define SOC_TIMER_GROUP_TOTAL_TIMERS 4 #define SOC_TIMER_SUPPORT_ETM 1 +#define SOC_TIMER_SUPPORT_SLEEP_RETENTION 1 /*--------------------------- WATCHDOG CAPS ---------------------------------------*/ #define SOC_MWDT_SUPPORT_XTAL (1) diff --git a/components/soc/esp32p4/system_retention_periph.c b/components/soc/esp32p4/system_retention_periph.c index 855a47209f..381b20641a 100644 --- a/components/soc/esp32p4/system_retention_periph.c +++ b/components/soc/esp32p4/system_retention_periph.c @@ -52,21 +52,6 @@ const regdma_entries_config_t uart_regs_retention[] = { }; _Static_assert(ARRAY_SIZE(uart_regs_retention) == UART_RETENTION_LINK_LEN, "Inconsistent UART retention link length definitions"); -/* Timergroup Registers Context */ -#define N_REGS_TG0() (((TIMG_REGCLK_REG(0) - REG_TIMG_BASE(0)) / 4) + 1) -const regdma_entries_config_t tg_regs_retention[] = { - /*Timer group0 backup. T0_wdt should get of write project firstly. wdt used by RTOS.*/ - [0] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TIMG_LINK(0x00), TIMG_WDTWPROTECT_REG(0), TIMG_WDT_WKEY_VALUE, TIMG_WDT_WKEY_M, 1, 0), .owner = ENTRY(0) }, /* TG0 */ - [1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TIMG_LINK(0x01), REG_TIMG_BASE(0), REG_TIMG_BASE(0), N_REGS_TG0(), 0, 0), .owner = ENTRY(0) }, - [2] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TIMG_LINK(0x02), TIMG_WDTWPROTECT_REG(0), TIMG_WDT_WKEY_VALUE, TIMG_WDT_WKEY_M, 1, 0), .owner = ENTRY(0) }, - [3] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TIMG_LINK(0x03), TIMG_WDTCONFIG0_REG(0), TIMG_WDT_CONF_UPDATE_EN, TIMG_WDT_CONF_UPDATE_EN_M, 1, 0), .owner = ENTRY(0) }, - [4] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TIMG_LINK(0x04), TIMG_T0UPDATE_REG(0), TIMG_T0_UPDATE, TIMG_T0_UPDATE_M, 0, 1), .owner = ENTRY(0) }, - [5] = { .config = REGDMA_LINK_WAIT_INIT (REGDMA_TIMG_LINK(0x05), TIMG_T0UPDATE_REG(0), 0x0, TIMG_T0_UPDATE_M, 0, 1), .owner = ENTRY(0) }, - [6] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TIMG_LINK(0x06), TIMG_T0LO_REG(0), TIMG_T0LOADLO_REG(0), 2, 0, 0), .owner = ENTRY(0) }, - [7] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TIMG_LINK(0x07), TIMG_T0LOAD_REG(0), 0x1, TIMG_T0_LOAD_M, 1, 0), .owner = ENTRY(0) }, -}; -_Static_assert(ARRAY_SIZE(tg_regs_retention) == TIMG_RETENTION_LINK_LEN, "Inconsistent Timergroup 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/timer_periph.c b/components/soc/esp32p4/timer_periph.c index f799a91f7e..043ab9764f 100644 --- a/components/soc/esp32p4/timer_periph.c +++ b/components/soc/esp32p4/timer_periph.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -24,3 +24,30 @@ const timer_group_signal_conn_t timer_group_periph_signals = { } } }; + +#define N_REGS_TGWDT 6 // TIMG_WDTCONFIG0_REG ... TIMG_WDTCONFIG5_REG & TIMG_INT_ENA_TIMERS_REG + +static const regdma_entries_config_t tg0_wdt_regs_retention[] = { + /*Timer group backup. should get of write project firstly. wdt used by RTOS.*/ + [0] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TG0_WDT_LINK(0x00), TIMG_WDTWPROTECT_REG(0), TIMG_WDT_WKEY_VALUE, TIMG_WDT_WKEY_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, + [1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG0_WDT_LINK(0x01), TIMG_WDTCONFIG0_REG(0), TIMG_WDTCONFIG0_REG(0), N_REGS_TGWDT, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [2] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TG0_WDT_LINK(0x03), TIMG_WDTCONFIG0_REG(0), TIMG_WDT_CONF_UPDATE_EN, TIMG_WDT_CONF_UPDATE_EN_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, + [3] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TG0_WDT_LINK(0x03), TIMG_WDTFEED_REG(0), TIMG_WDT_FEED, TIMG_WDT_FEED_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, + [4] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG0_WDT_LINK(0x02), TIMG_INT_ENA_TIMERS_REG(0),TIMG_INT_ENA_TIMERS_REG(0), 1, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [5] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TG0_WDT_LINK(0x04), TIMG_WDTWPROTECT_REG(0), 0, TIMG_WDT_WKEY_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, +}; + +static const regdma_entries_config_t tg1_wdt_regs_retention[] = { + /*Timer group0 backup. T0_wdt should get of write project firstly. wdt used by RTOS.*/ + [0] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TG1_WDT_LINK(0x00), TIMG_WDTWPROTECT_REG(1), TIMG_WDT_WKEY_VALUE, TIMG_WDT_WKEY_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, + [1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG1_WDT_LINK(0x02), TIMG_INT_ENA_TIMERS_REG(1),TIMG_INT_ENA_TIMERS_REG(1), 1, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [2] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG1_WDT_LINK(0x01), TIMG_WDTCONFIG0_REG(1), TIMG_WDTCONFIG0_REG(1), N_REGS_TGWDT, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [3] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TG1_WDT_LINK(0x03), TIMG_WDTCONFIG0_REG(1), TIMG_WDT_CONF_UPDATE_EN, TIMG_WDT_CONF_UPDATE_EN_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, + [4] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TG0_WDT_LINK(0x03), TIMG_WDTFEED_REG(1), TIMG_WDT_FEED, TIMG_WDT_FEED_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, + [5] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TG1_WDT_LINK(0x04), TIMG_WDTWPROTECT_REG(1), 0, TIMG_WDT_WKEY_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, +}; + +const tg_reg_ctx_link_t tg_wdt_regs_retention[SOC_TIMER_GROUPS] = { + [0] = {tg0_wdt_regs_retention, ARRAY_SIZE(tg0_wdt_regs_retention)}, + [1] = {tg1_wdt_regs_retention, ARRAY_SIZE(tg1_wdt_regs_retention)}, +}; diff --git a/components/soc/include/soc/regdma.h b/components/soc/include/soc/regdma.h index 1662f733af..2243d1113a 100644 --- a/components/soc/include/soc/regdma.h +++ b/components/soc/include/soc/regdma.h @@ -37,15 +37,19 @@ extern "C" { #define REGDMA_TEEAPM_LINK(_pri) ((0x0f << 8) | _pri) #define REGDMA_UART_LINK(_pri) ((0x10 << 8) | _pri) -#define REGDMA_TIMG_LINK(_pri) ((0x11 << 8) | _pri) -#define REGDMA_IOMUX_LINK(_pri) ((0x12 << 8) | _pri) -#define REGDMA_SPIMEM_LINK(_pri) ((0x13 << 8) | _pri) -#define REGDMA_SYSTIMER_LINK(_pri) ((0x14 << 8) | _pri) -#define REGDMA_BLE_MAC_LINK(_pri) ((0x15 << 8) | _pri) -#define REGDMA_MODEM_BT_BB_LINK(_pri) ((0x16 << 8) | _pri) -#define REGDMA_MODEM_IEEE802154_LINK(_pri) ((0x17 << 8) | _pri) -#define REGDMA_GDMA_LINK(_pri) ((0x18 << 8) | _pri) -#define REGDMA_I2C_LINK(_pri) ((0x19 << 8) | _pri) +#define REGDMA_IOMUX_LINK(_pri) ((0x11 << 8) | _pri) +#define REGDMA_SPIMEM_LINK(_pri) ((0x12 << 8) | _pri) +#define REGDMA_SYSTIMER_LINK(_pri) ((0x13 << 8) | _pri) +#define REGDMA_BLE_MAC_LINK(_pri) ((0x14 << 8) | _pri) +#define REGDMA_MODEM_BT_BB_LINK(_pri) ((0x15 << 8) | _pri) +#define REGDMA_MODEM_IEEE802154_LINK(_pri) ((0x16 << 8) | _pri) +#define REGDMA_GDMA_LINK(_pri) ((0x17 << 8) | _pri) +#define REGDMA_I2C_LINK(_pri) ((0x18 << 8) | _pri) +#define REGDMA_RMT_LINK(_pri) ((0x19 << 8) | _pri) +#define REGDMA_TG0_WDT_LINK(_pri) ((0x1A << 8) | _pri) +#define REGDMA_TG1_WDT_LINK(_pri) ((0x1B << 8) | _pri) +#define REGDMA_TG0_TIMER_LINK(_pri) ((0x1C << 8) | _pri) +#define REGDMA_TG1_TIMER_LINK(_pri) ((0x1D << 8) | _pri) #define REGDMA_MODEM_FE_LINK(_pri) ((0xFF << 8) | _pri) #define REGDMA_LINK_PRI_SYS_CLK REGDMA_LINK_PRI_0 @@ -58,6 +62,7 @@ extern "C" { #define REGDMA_LINK_PRI_SYS_PERIPH_LOW REGDMA_LINK_PRI_6 // TG0 & IO MUX & SPI MEM & Systimer #define REGDMA_LINK_PRI_IEEE802154 REGDMA_LINK_PRI_7 #define REGDMA_LINK_PRI_GDMA REGDMA_LINK_PRI_7 +#define REGDMA_LINK_PRI_RMT REGDMA_LINK_PRI_7 typedef enum { REGDMA_LINK_PRI_0 = 0, diff --git a/components/soc/include/soc/timer_periph.h b/components/soc/include/soc/timer_periph.h index 883e69f787..1da11986e7 100644 --- a/components/soc/include/soc/timer_periph.h +++ b/components/soc/include/soc/timer_periph.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -11,6 +11,7 @@ #include "soc/timer_group_struct.h" #include "soc/soc_caps.h" #include "soc/periph_defs.h" +#include "soc/regdma.h" #ifdef __cplusplus extern "C" { @@ -28,6 +29,15 @@ typedef struct { extern const timer_group_signal_conn_t timer_group_periph_signals; +#if SOC_TIMER_SUPPORT_SLEEP_RETENTION && SOC_PAU_SUPPORTED +typedef struct { + const regdma_entries_config_t *link_list; + uint32_t link_num; +} tg_reg_ctx_link_t; + +extern const tg_reg_ctx_link_t tg_wdt_regs_retention[SOC_TIMER_GROUPS]; +#endif + #ifdef __cplusplus } #endif From 3785506ec15a664a03f7c5f69d1338a54026e6cc Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Thu, 23 May 2024 10:42:30 +0800 Subject: [PATCH 2/9] change(esp_driver_gptimer): do gptimer timer target retention by needs --- .../include/driver/gptimer.h | 3 + components/esp_driver_gptimer/src/gptimer.c | 75 ++++++++++++++++++- .../esp_driver_gptimer/src/gptimer_priv.h | 8 +- components/soc/esp32c5/beta3/timer_periph.c | 39 ++++++++++ components/soc/esp32c5/mp/timer_periph.c | 39 ++++++++++ components/soc/esp32c6/timer_periph.c | 39 ++++++++++ components/soc/esp32h2/timer_periph.c | 39 ++++++++++ components/soc/esp32p4/timer_periph.c | 49 ++++++++++++ components/soc/include/soc/timer_periph.h | 1 + 9 files changed, 288 insertions(+), 4 deletions(-) diff --git a/components/esp_driver_gptimer/include/driver/gptimer.h b/components/esp_driver_gptimer/include/driver/gptimer.h index b9c0b8b14b..825f93db79 100644 --- a/components/esp_driver_gptimer/include/driver/gptimer.h +++ b/components/esp_driver_gptimer/include/driver/gptimer.h @@ -28,6 +28,9 @@ typedef struct { if set to 0, the driver will try to allocate an interrupt with a relative low priority (1,2,3) */ struct { uint32_t intr_shared: 1; /*!< Set true, the timer interrupt number can be shared with other peripherals */ + uint32_t backup_before_sleep: 1; /*!< If set, the driver will backup/restore the GPTimer registers before/after entering/exist sleep mode. + By this approach, the system can power off GPTimer's power domain. + This can save power, but at the expense of more RAM being consumed */ } flags; /*!< GPTimer config flags*/ } gptimer_config_t; diff --git a/components/esp_driver_gptimer/src/gptimer.c b/components/esp_driver_gptimer/src/gptimer.c index f1d4af4664..6fd66b9b95 100644 --- a/components/esp_driver_gptimer/src/gptimer.c +++ b/components/esp_driver_gptimer/src/gptimer.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -30,6 +30,10 @@ #include "esp_clk_tree.h" #include "gptimer_priv.h" +#if GPTIMER_USE_RETENTION_LINK +#include "esp_private/sleep_retention.h" +#endif + static const char *TAG = "gptimer"; #if SOC_PERIPH_CLK_CTRL_SHARED @@ -52,6 +56,37 @@ static void gptimer_release_group_handle(gptimer_group_t *group); static esp_err_t gptimer_select_periph_clock(gptimer_t *timer, gptimer_clock_source_t src_clk, uint32_t resolution_hz); static void gptimer_default_isr(void *args); +#if GPTIMER_USE_RETENTION_LINK +static esp_err_t sleep_tg_timer_retention_link_cb(void *arg) +{ + uint32_t group_id = *(uint32_t *)arg; + esp_err_t err = sleep_retention_entries_create(tg_timer_regs_retention[group_id].link_list, + tg_timer_regs_retention[group_id].link_num, + REGDMA_LINK_PRI_6, + (group_id == 0) ? SLEEP_RETENTION_MODULE_TG0_TIMER : SLEEP_RETENTION_MODULE_TG1_TIMER); + if (err == ESP_OK) { + ESP_LOGD(TAG, "Timer group %ld retention initialization", group_id); + } + ESP_RETURN_ON_ERROR(err, TAG, "Failed to create sleep retention linked list for timer group %ld", group_id); + return err; +} + +static void gptimer_create_retention_module(gptimer_group_t *group) +{ + _lock_acquire(&s_platform.mutex); + int group_id = group->group_id; + if ((group->sleep_retention_initialized == true) && (group->retention_link_created == false)) { + esp_err_t err = sleep_retention_module_allocate((group_id == 0) ? SLEEP_RETENTION_MODULE_TG0_TIMER : SLEEP_RETENTION_MODULE_TG1_TIMER); + if (err != ESP_OK) { + ESP_LOGW(TAG, "Failed to allocate sleep retention linked list for timer group %d retention, power domain can't turn off", group_id); + } else { + group->retention_link_created = true; + } + } + _lock_release(&s_platform.mutex); +} +#endif + static esp_err_t gptimer_register_to_group(gptimer_t *timer) { gptimer_group_t *group = NULL; @@ -129,6 +164,12 @@ esp_err_t gptimer_new_timer(const gptimer_config_t *config, gptimer_handle_t *re int group_id = group->group_id; int timer_id = timer->timer_id; +#if GPTIMER_USE_RETENTION_LINK + if (config->flags.backup_before_sleep != 0) { + gptimer_create_retention_module(group); + } +#endif // GPTIMER_USE_RETENTION_LINK + // initialize HAL layer timer_hal_init(&timer->hal, group_id, timer_id); // select clock source, set clock resolution @@ -404,7 +445,6 @@ static gptimer_group_t *gptimer_acquire_group_handle(int group_id) // someone acquired the group handle means we have a new object that refer to this group s_platform.group_ref_counts[group_id]++; } - _lock_release(&s_platform.mutex); if (new_group) { // !!! HARDWARE SHARED RESOURCE !!! @@ -417,7 +457,28 @@ static gptimer_group_t *gptimer_acquire_group_handle(int group_id) } } ESP_LOGD(TAG, "new group (%d) @%p", group_id, group); +#if GPTIMER_USE_RETENTION_LINK + if (group->sleep_retention_initialized != true) { + sleep_retention_module_init_param_t init_param = { + .cbs = { + .create = { + .handle = sleep_tg_timer_retention_link_cb, + .arg = &group_id + }, + }, + .depends = BIT(SLEEP_RETENTION_MODULE_CLOCK_SYSTEM) + }; + esp_err_t err = sleep_retention_module_init((group_id == 0) ? SLEEP_RETENTION_MODULE_TG0_TIMER : SLEEP_RETENTION_MODULE_TG1_TIMER, &init_param); + + if (err == ESP_OK) { + group->sleep_retention_initialized = true; + } else { + ESP_LOGW(TAG, "Failed to allocate sleep retention linked list for timer group %d retention", group_id); + } + } +#endif // GPTIMER_USE_RETENTION_LINK } + _lock_release(&s_platform.mutex); return group; } @@ -434,7 +495,6 @@ static void gptimer_release_group_handle(gptimer_group_t *group) do_deinitialize = true; s_platform.groups[group_id] = NULL; } - _lock_release(&s_platform.mutex); if (do_deinitialize) { // disable bus clock for the timer group @@ -443,9 +503,18 @@ static void gptimer_release_group_handle(gptimer_group_t *group) timer_ll_enable_bus_clock(group_id, false); } } +#if GPTIMER_USE_RETENTION_LINK + if (group->retention_link_created) { + sleep_retention_module_free((group_id == 0) ? SLEEP_RETENTION_MODULE_TG0_TIMER : SLEEP_RETENTION_MODULE_TG1_TIMER); + } + if (group->sleep_retention_initialized) { + sleep_retention_module_deinit((group_id == 0) ? SLEEP_RETENTION_MODULE_TG0_TIMER : SLEEP_RETENTION_MODULE_TG1_TIMER); + } +#endif free(group); ESP_LOGD(TAG, "del group (%d)", group_id); } + _lock_release(&s_platform.mutex); } static esp_err_t gptimer_select_periph_clock(gptimer_t *timer, gptimer_clock_source_t src_clk, uint32_t resolution_hz) diff --git a/components/esp_driver_gptimer/src/gptimer_priv.h b/components/esp_driver_gptimer/src/gptimer_priv.h index 78428ce09c..fe072c85d4 100644 --- a/components/esp_driver_gptimer/src/gptimer_priv.h +++ b/components/esp_driver_gptimer/src/gptimer_priv.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -39,12 +39,18 @@ extern "C" { #define GPTIMER_PM_LOCK_NAME_LEN_MAX 16 +#define GPTIMER_USE_RETENTION_LINK (SOC_TIMER_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP) + typedef struct gptimer_t gptimer_t; typedef struct gptimer_group_t { int group_id; portMUX_TYPE spinlock; // to protect per-group register level concurrent access gptimer_t *timers[SOC_TIMER_GROUP_TIMERS_PER_GROUP]; +#if GPTIMER_USE_RETENTION_LINK + bool sleep_retention_initialized; // mark if the retention link is initialized + bool retention_link_created; // mark if the retention link is created +#endif } gptimer_group_t; typedef enum { diff --git a/components/soc/esp32c5/beta3/timer_periph.c b/components/soc/esp32c5/beta3/timer_periph.c index 4ab27c7fdf..7036e7ca81 100644 --- a/components/soc/esp32c5/beta3/timer_periph.c +++ b/components/soc/esp32c5/beta3/timer_periph.c @@ -46,8 +46,47 @@ static const regdma_entries_config_t tg1_wdt_regs_retention[] = { [5] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TG1_WDT_LINK(0x04), TIMG_WDTWPROTECT_REG(1), 0, TIMG_WDT_WKEY_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, }; +/* Registers in retention context: + * TIMG_T0CONFIG_REG + * TIMG_T0ALARMLO_REG + * TIMG_T0ALARMHI_REG + * TIMG_INT_ENA_TIMERS_REG + * TIMG_REGCLK_REG + */ +#define N_REGS_TG_TIMER_CFG 5 +static const uint32_t tg_timer_regs_map[4] = {0x10000031, 0x80000000, 0, 0}; + +const regdma_entries_config_t tg0_timer_regs_retention[] = { + [0] = { + .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_TG0_TIMER_LINK(0x00), TIMG_T0CONFIG_REG(0), TIMG_T0CONFIG_REG(0), N_REGS_TG_TIMER_CFG, 0, 0, \ + tg_timer_regs_map[0], tg_timer_regs_map[1], tg_timer_regs_map[2], tg_timer_regs_map[3]), .owner = ENTRY(0) | ENTRY(2) + }, + [1] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_TG0_TIMER_LINK(0x01), TIMG_T0UPDATE_REG(0), TIMG_T0_UPDATE, TIMG_T0_UPDATE_M, 0, 1), .owner = ENTRY(0) | ENTRY(2) }, + [2] = { .config = REGDMA_LINK_WAIT_INIT(REGDMA_TG0_TIMER_LINK(0x02), TIMG_T0UPDATE_REG(0), 0x0, TIMG_T0_UPDATE_M, 0, 1), .owner = ENTRY(0) | ENTRY(2) }, + [3] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG0_TIMER_LINK(0x03), TIMG_T0LO_REG(0), TIMG_T0LOADLO_REG(0), 2, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [4] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG0_TIMER_LINK(0x04), TIMG_T0HI_REG(0), TIMG_T0LOADHI_REG(0), 2, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [5] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_TG0_TIMER_LINK(0x05), TIMG_T0LOAD_REG(0), 0x1, TIMG_T0_LOAD_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, +}; + +const regdma_entries_config_t tg1_timer_regs_retention[] = { + [0] = { + .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_TG1_TIMER_LINK(0x00), TIMG_T0CONFIG_REG(1), TIMG_T0CONFIG_REG(1), N_REGS_TG_TIMER_CFG, 0, 0, \ + tg_timer_regs_map[0], tg_timer_regs_map[1], tg_timer_regs_map[2], tg_timer_regs_map[3]), .owner = ENTRY(0) | ENTRY(2) + }, + [1] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_TG1_TIMER_LINK(0x01), TIMG_T0UPDATE_REG(1), TIMG_T0_UPDATE, TIMG_T0_UPDATE_M, 0, 1), .owner = ENTRY(0) | ENTRY(2) }, + [2] = { .config = REGDMA_LINK_WAIT_INIT(REGDMA_TG0_TIMER_LINK(0x02), TIMG_T0UPDATE_REG(0), 0x0, TIMG_T0_UPDATE_M, 0, 1), .owner = ENTRY(0) | ENTRY(2) }, + [3] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG1_TIMER_LINK(0x03), TIMG_T0LO_REG(1), TIMG_T0LOADLO_REG(1), 2, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [4] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG1_TIMER_LINK(0x04), TIMG_T0HI_REG(1), TIMG_T0LOADHI_REG(1), 2, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [5] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_TG1_TIMER_LINK(0x05), TIMG_T0LOAD_REG(1), 0x1, TIMG_T0_LOAD_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, +}; + const tg_reg_ctx_link_t tg_wdt_regs_retention[SOC_TIMER_GROUPS] = { [0] = {tg0_wdt_regs_retention, ARRAY_SIZE(tg0_wdt_regs_retention)}, [1] = {tg1_wdt_regs_retention, ARRAY_SIZE(tg1_wdt_regs_retention)}, }; + +const tg_reg_ctx_link_t tg_timer_regs_retention[SOC_TIMER_GROUPS] = { + [0] = {tg0_timer_regs_retention, ARRAY_SIZE(tg0_timer_regs_retention)}, + [1] = {tg1_timer_regs_retention, ARRAY_SIZE(tg1_timer_regs_retention)}, +}; #endif diff --git a/components/soc/esp32c5/mp/timer_periph.c b/components/soc/esp32c5/mp/timer_periph.c index 4ab27c7fdf..7036e7ca81 100644 --- a/components/soc/esp32c5/mp/timer_periph.c +++ b/components/soc/esp32c5/mp/timer_periph.c @@ -46,8 +46,47 @@ static const regdma_entries_config_t tg1_wdt_regs_retention[] = { [5] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TG1_WDT_LINK(0x04), TIMG_WDTWPROTECT_REG(1), 0, TIMG_WDT_WKEY_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, }; +/* Registers in retention context: + * TIMG_T0CONFIG_REG + * TIMG_T0ALARMLO_REG + * TIMG_T0ALARMHI_REG + * TIMG_INT_ENA_TIMERS_REG + * TIMG_REGCLK_REG + */ +#define N_REGS_TG_TIMER_CFG 5 +static const uint32_t tg_timer_regs_map[4] = {0x10000031, 0x80000000, 0, 0}; + +const regdma_entries_config_t tg0_timer_regs_retention[] = { + [0] = { + .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_TG0_TIMER_LINK(0x00), TIMG_T0CONFIG_REG(0), TIMG_T0CONFIG_REG(0), N_REGS_TG_TIMER_CFG, 0, 0, \ + tg_timer_regs_map[0], tg_timer_regs_map[1], tg_timer_regs_map[2], tg_timer_regs_map[3]), .owner = ENTRY(0) | ENTRY(2) + }, + [1] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_TG0_TIMER_LINK(0x01), TIMG_T0UPDATE_REG(0), TIMG_T0_UPDATE, TIMG_T0_UPDATE_M, 0, 1), .owner = ENTRY(0) | ENTRY(2) }, + [2] = { .config = REGDMA_LINK_WAIT_INIT(REGDMA_TG0_TIMER_LINK(0x02), TIMG_T0UPDATE_REG(0), 0x0, TIMG_T0_UPDATE_M, 0, 1), .owner = ENTRY(0) | ENTRY(2) }, + [3] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG0_TIMER_LINK(0x03), TIMG_T0LO_REG(0), TIMG_T0LOADLO_REG(0), 2, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [4] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG0_TIMER_LINK(0x04), TIMG_T0HI_REG(0), TIMG_T0LOADHI_REG(0), 2, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [5] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_TG0_TIMER_LINK(0x05), TIMG_T0LOAD_REG(0), 0x1, TIMG_T0_LOAD_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, +}; + +const regdma_entries_config_t tg1_timer_regs_retention[] = { + [0] = { + .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_TG1_TIMER_LINK(0x00), TIMG_T0CONFIG_REG(1), TIMG_T0CONFIG_REG(1), N_REGS_TG_TIMER_CFG, 0, 0, \ + tg_timer_regs_map[0], tg_timer_regs_map[1], tg_timer_regs_map[2], tg_timer_regs_map[3]), .owner = ENTRY(0) | ENTRY(2) + }, + [1] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_TG1_TIMER_LINK(0x01), TIMG_T0UPDATE_REG(1), TIMG_T0_UPDATE, TIMG_T0_UPDATE_M, 0, 1), .owner = ENTRY(0) | ENTRY(2) }, + [2] = { .config = REGDMA_LINK_WAIT_INIT(REGDMA_TG0_TIMER_LINK(0x02), TIMG_T0UPDATE_REG(0), 0x0, TIMG_T0_UPDATE_M, 0, 1), .owner = ENTRY(0) | ENTRY(2) }, + [3] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG1_TIMER_LINK(0x03), TIMG_T0LO_REG(1), TIMG_T0LOADLO_REG(1), 2, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [4] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG1_TIMER_LINK(0x04), TIMG_T0HI_REG(1), TIMG_T0LOADHI_REG(1), 2, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [5] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_TG1_TIMER_LINK(0x05), TIMG_T0LOAD_REG(1), 0x1, TIMG_T0_LOAD_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, +}; + const tg_reg_ctx_link_t tg_wdt_regs_retention[SOC_TIMER_GROUPS] = { [0] = {tg0_wdt_regs_retention, ARRAY_SIZE(tg0_wdt_regs_retention)}, [1] = {tg1_wdt_regs_retention, ARRAY_SIZE(tg1_wdt_regs_retention)}, }; + +const tg_reg_ctx_link_t tg_timer_regs_retention[SOC_TIMER_GROUPS] = { + [0] = {tg0_timer_regs_retention, ARRAY_SIZE(tg0_timer_regs_retention)}, + [1] = {tg1_timer_regs_retention, ARRAY_SIZE(tg1_timer_regs_retention)}, +}; #endif diff --git a/components/soc/esp32c6/timer_periph.c b/components/soc/esp32c6/timer_periph.c index 7d338258de..422b536f37 100644 --- a/components/soc/esp32c6/timer_periph.c +++ b/components/soc/esp32c6/timer_periph.c @@ -45,7 +45,46 @@ static const regdma_entries_config_t tg1_wdt_regs_retention[] = { [5] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TG1_WDT_LINK(0x04), TIMG_WDTWPROTECT_REG(1), 0, TIMG_WDT_WKEY_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, }; +/* Registers in retention context: + * TIMG_T0CONFIG_REG + * TIMG_T0ALARMLO_REG + * TIMG_T0ALARMHI_REG + * TIMG_INT_ENA_TIMERS_REG + * TIMG_REGCLK_REG + */ +#define N_REGS_TG_TIMER_CFG 5 +static const uint32_t tg_timer_regs_map[4] = {0x10000031, 0x80000000, 0, 0}; + +const regdma_entries_config_t tg0_timer_regs_retention[] = { + [0] = { + .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_TG0_TIMER_LINK(0x00), TIMG_T0CONFIG_REG(0), TIMG_T0CONFIG_REG(0), N_REGS_TG_TIMER_CFG, 0, 0, \ + tg_timer_regs_map[0], tg_timer_regs_map[1], tg_timer_regs_map[2], tg_timer_regs_map[3]), .owner = ENTRY(0) | ENTRY(2) + }, + [1] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_TG0_TIMER_LINK(0x01), TIMG_T0UPDATE_REG(0), TIMG_T0_UPDATE, TIMG_T0_UPDATE_M, 0, 1), .owner = ENTRY(0) | ENTRY(2) }, + [2] = { .config = REGDMA_LINK_WAIT_INIT(REGDMA_TG0_TIMER_LINK(0x02), TIMG_T0UPDATE_REG(0), 0x0, TIMG_T0_UPDATE_M, 0, 1), .owner = ENTRY(0) | ENTRY(2) }, + [3] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG0_TIMER_LINK(0x03), TIMG_T0LO_REG(0), TIMG_T0LOADLO_REG(0), 2, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [4] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG0_TIMER_LINK(0x04), TIMG_T0HI_REG(0), TIMG_T0LOADHI_REG(0), 2, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [5] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_TG0_TIMER_LINK(0x05), TIMG_T0LOAD_REG(0), 0x1, TIMG_T0_LOAD_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, +}; + +const regdma_entries_config_t tg1_timer_regs_retention[] = { + [0] = { + .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_TG1_TIMER_LINK(0x00), TIMG_T0CONFIG_REG(1), TIMG_T0CONFIG_REG(1), N_REGS_TG_TIMER_CFG, 0, 0, \ + tg_timer_regs_map[0], tg_timer_regs_map[1], tg_timer_regs_map[2], tg_timer_regs_map[3]), .owner = ENTRY(0) | ENTRY(2) + }, + [1] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_TG1_TIMER_LINK(0x01), TIMG_T0UPDATE_REG(1), TIMG_T0_UPDATE, TIMG_T0_UPDATE_M, 0, 1), .owner = ENTRY(0) | ENTRY(2) }, + [2] = { .config = REGDMA_LINK_WAIT_INIT(REGDMA_TG0_TIMER_LINK(0x02), TIMG_T0UPDATE_REG(0), 0x0, TIMG_T0_UPDATE_M, 0, 1), .owner = ENTRY(0) | ENTRY(2) }, + [3] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG1_TIMER_LINK(0x03), TIMG_T0LO_REG(1), TIMG_T0LOADLO_REG(1), 2, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [4] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG1_TIMER_LINK(0x04), TIMG_T0HI_REG(1), TIMG_T0LOADHI_REG(1), 2, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [5] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_TG1_TIMER_LINK(0x05), TIMG_T0LOAD_REG(1), 0x1, TIMG_T0_LOAD_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, +}; + const tg_reg_ctx_link_t tg_wdt_regs_retention[SOC_TIMER_GROUPS] = { [0] = {tg0_wdt_regs_retention, ARRAY_SIZE(tg0_wdt_regs_retention)}, [1] = {tg1_wdt_regs_retention, ARRAY_SIZE(tg1_wdt_regs_retention)}, }; + +const tg_reg_ctx_link_t tg_timer_regs_retention[SOC_TIMER_GROUPS] = { + [0] = {tg0_timer_regs_retention, ARRAY_SIZE(tg0_timer_regs_retention)}, + [1] = {tg1_timer_regs_retention, ARRAY_SIZE(tg1_timer_regs_retention)}, +}; diff --git a/components/soc/esp32h2/timer_periph.c b/components/soc/esp32h2/timer_periph.c index 7d338258de..422b536f37 100644 --- a/components/soc/esp32h2/timer_periph.c +++ b/components/soc/esp32h2/timer_periph.c @@ -45,7 +45,46 @@ static const regdma_entries_config_t tg1_wdt_regs_retention[] = { [5] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TG1_WDT_LINK(0x04), TIMG_WDTWPROTECT_REG(1), 0, TIMG_WDT_WKEY_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, }; +/* Registers in retention context: + * TIMG_T0CONFIG_REG + * TIMG_T0ALARMLO_REG + * TIMG_T0ALARMHI_REG + * TIMG_INT_ENA_TIMERS_REG + * TIMG_REGCLK_REG + */ +#define N_REGS_TG_TIMER_CFG 5 +static const uint32_t tg_timer_regs_map[4] = {0x10000031, 0x80000000, 0, 0}; + +const regdma_entries_config_t tg0_timer_regs_retention[] = { + [0] = { + .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_TG0_TIMER_LINK(0x00), TIMG_T0CONFIG_REG(0), TIMG_T0CONFIG_REG(0), N_REGS_TG_TIMER_CFG, 0, 0, \ + tg_timer_regs_map[0], tg_timer_regs_map[1], tg_timer_regs_map[2], tg_timer_regs_map[3]), .owner = ENTRY(0) | ENTRY(2) + }, + [1] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_TG0_TIMER_LINK(0x01), TIMG_T0UPDATE_REG(0), TIMG_T0_UPDATE, TIMG_T0_UPDATE_M, 0, 1), .owner = ENTRY(0) | ENTRY(2) }, + [2] = { .config = REGDMA_LINK_WAIT_INIT(REGDMA_TG0_TIMER_LINK(0x02), TIMG_T0UPDATE_REG(0), 0x0, TIMG_T0_UPDATE_M, 0, 1), .owner = ENTRY(0) | ENTRY(2) }, + [3] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG0_TIMER_LINK(0x03), TIMG_T0LO_REG(0), TIMG_T0LOADLO_REG(0), 2, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [4] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG0_TIMER_LINK(0x04), TIMG_T0HI_REG(0), TIMG_T0LOADHI_REG(0), 2, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [5] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_TG0_TIMER_LINK(0x05), TIMG_T0LOAD_REG(0), 0x1, TIMG_T0_LOAD_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, +}; + +const regdma_entries_config_t tg1_timer_regs_retention[] = { + [0] = { + .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_TG1_TIMER_LINK(0x00), TIMG_T0CONFIG_REG(1), TIMG_T0CONFIG_REG(1), N_REGS_TG_TIMER_CFG, 0, 0, \ + tg_timer_regs_map[0], tg_timer_regs_map[1], tg_timer_regs_map[2], tg_timer_regs_map[3]), .owner = ENTRY(0) | ENTRY(2) + }, + [1] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_TG1_TIMER_LINK(0x01), TIMG_T0UPDATE_REG(1), TIMG_T0_UPDATE, TIMG_T0_UPDATE_M, 0, 1), .owner = ENTRY(0) | ENTRY(2) }, + [2] = { .config = REGDMA_LINK_WAIT_INIT(REGDMA_TG0_TIMER_LINK(0x02), TIMG_T0UPDATE_REG(0), 0x0, TIMG_T0_UPDATE_M, 0, 1), .owner = ENTRY(0) | ENTRY(2) }, + [3] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG1_TIMER_LINK(0x03), TIMG_T0LO_REG(1), TIMG_T0LOADLO_REG(1), 2, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [4] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG1_TIMER_LINK(0x04), TIMG_T0HI_REG(1), TIMG_T0LOADHI_REG(1), 2, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [5] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_TG1_TIMER_LINK(0x05), TIMG_T0LOAD_REG(1), 0x1, TIMG_T0_LOAD_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, +}; + const tg_reg_ctx_link_t tg_wdt_regs_retention[SOC_TIMER_GROUPS] = { [0] = {tg0_wdt_regs_retention, ARRAY_SIZE(tg0_wdt_regs_retention)}, [1] = {tg1_wdt_regs_retention, ARRAY_SIZE(tg1_wdt_regs_retention)}, }; + +const tg_reg_ctx_link_t tg_timer_regs_retention[SOC_TIMER_GROUPS] = { + [0] = {tg0_timer_regs_retention, ARRAY_SIZE(tg0_timer_regs_retention)}, + [1] = {tg1_timer_regs_retention, ARRAY_SIZE(tg1_timer_regs_retention)}, +}; diff --git a/components/soc/esp32p4/timer_periph.c b/components/soc/esp32p4/timer_periph.c index 043ab9764f..b94dacaefb 100644 --- a/components/soc/esp32p4/timer_periph.c +++ b/components/soc/esp32p4/timer_periph.c @@ -47,7 +47,56 @@ static const regdma_entries_config_t tg1_wdt_regs_retention[] = { [5] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TG1_WDT_LINK(0x04), TIMG_WDTWPROTECT_REG(1), 0, TIMG_WDT_WKEY_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, }; +/* Registers in retention context: + * TIMG_T0CONFIG_REG / TIMG_T1CONFIG_REG + * TIMG_T0ALARMLO_REG / TIMG_T1ALARMLO_REG + * TIMG_T0ALARMHI_REG / TIMG_T1ALARMHI_REG + * TIMG_INT_ENA_TIMERS_REG + * TIMG_REGCLK_REG + */ +#define N_REGS_TG_TIMER_CFG 8 +static const uint32_t tg_timer_regs_map[4] = {0x10006231, 0x80000000, 0x0, 0x0}; + +const regdma_entries_config_t tg0_timer_regs_retention[] = { + [0] = { + .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_TG0_TIMER_LINK(0x00), TIMG_T0CONFIG_REG(0), TIMG_T0CONFIG_REG(0), N_REGS_TG_TIMER_CFG, 0, 0, \ + tg_timer_regs_map[0], tg_timer_regs_map[1], tg_timer_regs_map[2], tg_timer_regs_map[3]), .owner = ENTRY(0) | ENTRY(2) + }, + [1] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_TG0_TIMER_LINK(0x01), TIMG_T0UPDATE_REG(0), TIMG_T0_UPDATE, TIMG_T0_UPDATE_M, 0, 1), .owner = ENTRY(0) | ENTRY(2) }, + [2] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_TG0_TIMER_LINK(0x02), TIMG_T1UPDATE_REG(0), TIMG_T1_UPDATE, TIMG_T1_UPDATE_M, 0, 1), .owner = ENTRY(0) | ENTRY(2) }, + [3] = { .config = REGDMA_LINK_WAIT_INIT(REGDMA_TG0_TIMER_LINK(0x03), TIMG_T0UPDATE_REG(0), 0x0, TIMG_T0_UPDATE_M, 0, 1), .owner = ENTRY(0) | ENTRY(2) }, + [4] = { .config = REGDMA_LINK_WAIT_INIT(REGDMA_TG0_TIMER_LINK(0x04), TIMG_T1UPDATE_REG(0), 0x0, TIMG_T1_UPDATE_M, 0, 1), .owner = ENTRY(0) | ENTRY(2) }, + [5] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG0_TIMER_LINK(0x05), TIMG_T0LO_REG(0), TIMG_T0LOADLO_REG(0), 2, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [6] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG0_TIMER_LINK(0x06), TIMG_T0HI_REG(0), TIMG_T0LOADHI_REG(0), 2, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [7] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG0_TIMER_LINK(0x07), TIMG_T1LO_REG(0), TIMG_T1LOADLO_REG(0), 2, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [8] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG0_TIMER_LINK(0x08), TIMG_T1HI_REG(0), TIMG_T1LOADHI_REG(0), 2, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [9] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_TG0_TIMER_LINK(0x09), TIMG_T0LOAD_REG(0), 0x1, TIMG_T0_LOAD_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, + [10] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_TG0_TIMER_LINK(0x0a), TIMG_T1LOAD_REG(0), 0x1, TIMG_T1_LOAD_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, +}; + +const regdma_entries_config_t tg1_timer_regs_retention[] = { + [0] = { + .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_TG1_TIMER_LINK(0x00), TIMG_T0CONFIG_REG(1), TIMG_T0CONFIG_REG(1), N_REGS_TG_TIMER_CFG, 0, 0, \ + tg_timer_regs_map[0], tg_timer_regs_map[1], tg_timer_regs_map[2], tg_timer_regs_map[3]), .owner = ENTRY(0) | ENTRY(2) + }, + [1] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_TG1_TIMER_LINK(0x01), TIMG_T0UPDATE_REG(1), TIMG_T0_UPDATE, TIMG_T0_UPDATE_M, 0, 1), .owner = ENTRY(0) | ENTRY(2) }, + [2] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_TG1_TIMER_LINK(0x02), TIMG_T1UPDATE_REG(1), TIMG_T1_UPDATE, TIMG_T1_UPDATE_M, 0, 1), .owner = ENTRY(0) | ENTRY(2) }, + [3] = { .config = REGDMA_LINK_WAIT_INIT(REGDMA_TG1_TIMER_LINK(0x03), TIMG_T0UPDATE_REG(1), 0x0, TIMG_T0_UPDATE_M, 0, 1), .owner = ENTRY(0) | ENTRY(2) }, + [4] = { .config = REGDMA_LINK_WAIT_INIT(REGDMA_TG1_TIMER_LINK(0x04), TIMG_T1UPDATE_REG(1), 0x0, TIMG_T1_UPDATE_M, 0, 1), .owner = ENTRY(0) | ENTRY(2) }, + [5] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG1_TIMER_LINK(0x05), TIMG_T0LO_REG(1), TIMG_T0LOADLO_REG(1), 2, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [6] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG1_TIMER_LINK(0x06), TIMG_T0HI_REG(1), TIMG_T0LOADHI_REG(1), 2, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [7] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG1_TIMER_LINK(0x07), TIMG_T1LO_REG(1), TIMG_T1LOADLO_REG(1), 2, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [8] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG1_TIMER_LINK(0x08), TIMG_T1HI_REG(1), TIMG_T1LOADHI_REG(1), 2, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [9] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_TG1_TIMER_LINK(0x09), TIMG_T0LOAD_REG(1), 0x1, TIMG_T0_LOAD_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, + [10] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_TG1_TIMER_LINK(0x0a), TIMG_T1LOAD_REG(1), 0x1, TIMG_T1_LOAD_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, +}; + const tg_reg_ctx_link_t tg_wdt_regs_retention[SOC_TIMER_GROUPS] = { [0] = {tg0_wdt_regs_retention, ARRAY_SIZE(tg0_wdt_regs_retention)}, [1] = {tg1_wdt_regs_retention, ARRAY_SIZE(tg1_wdt_regs_retention)}, }; + +const tg_reg_ctx_link_t tg_timer_regs_retention[SOC_TIMER_GROUPS] = { + [0] = {tg0_timer_regs_retention, ARRAY_SIZE(tg0_timer_regs_retention)}, + [1] = {tg1_timer_regs_retention, ARRAY_SIZE(tg1_timer_regs_retention)}, +}; diff --git a/components/soc/include/soc/timer_periph.h b/components/soc/include/soc/timer_periph.h index 1da11986e7..1d7cd219b3 100644 --- a/components/soc/include/soc/timer_periph.h +++ b/components/soc/include/soc/timer_periph.h @@ -36,6 +36,7 @@ typedef struct { } tg_reg_ctx_link_t; extern const tg_reg_ctx_link_t tg_wdt_regs_retention[SOC_TIMER_GROUPS]; +extern const tg_reg_ctx_link_t tg_timer_regs_retention[SOC_TIMER_GROUPS]; #endif #ifdef __cplusplus From 8093516420dd8ea43aeb3fe52589bacbe94b1bf9 Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Fri, 10 May 2024 16:47:06 +0800 Subject: [PATCH 3/9] ci(esp_system): add task watchdog pd_top sleep retention test case --- .../main/test_task_wdt.c | 41 ++++++++++++++++++- .../sdkconfig.ci.default | 2 + 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/components/esp_system/test_apps/esp_system_unity_tests/main/test_task_wdt.c b/components/esp_system/test_apps/esp_system_unity_tests/main/test_task_wdt.c index 08fbb40a4f..c924b5c5bb 100644 --- a/components/esp_system/test_apps/esp_system_unity_tests/main/test_task_wdt.c +++ b/components/esp_system/test_apps/esp_system_unity_tests/main/test_task_wdt.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -15,6 +15,13 @@ #include "test_utils.h" #include "soc/rtc.h" +#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && SOC_TIMER_SUPPORT_SLEEP_RETENTION +#include "esp_sleep.h" +#include "esp_private/esp_sleep_internal.h" +#include "esp_private/sleep_cpu.h" +#include "esp_private/esp_pmu.h" +#endif + #define TASK_WDT_TIMEOUT_MS 1000 static volatile bool timeout_flag; @@ -41,6 +48,36 @@ TEST_CASE("Task WDT task timeout", "[task_wdt]") TEST_ASSERT_EQUAL(ESP_OK, esp_task_wdt_deinit()); } +#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && SOC_TIMER_SUPPORT_SLEEP_RETENTION +TEST_CASE("Task WDT task timeout after peripheral powerdown lightsleep", "[task_wdt]") +{ + timeout_flag = false; + esp_task_wdt_config_t twdt_config = { + .timeout_ms = TASK_WDT_TIMEOUT_MS, + .idle_core_mask = 0, + .trigger_panic = false, + }; + TEST_ASSERT_EQUAL(ESP_OK, esp_task_wdt_init(&twdt_config)); + TEST_ASSERT_EQUAL(ESP_OK, esp_task_wdt_add(NULL)); + + TEST_ESP_OK(sleep_cpu_configure(true)); + esp_sleep_context_t sleep_ctx; + esp_sleep_set_sleep_context(&sleep_ctx); + esp_sleep_enable_timer_wakeup(10 * 1000); + esp_light_sleep_start(); + + TEST_ASSERT_EQUAL(PMU_SLEEP_PD_TOP, sleep_ctx.sleep_flags & PMU_SLEEP_PD_TOP); + TEST_ASSERT_EQUAL(0, sleep_ctx.sleep_request_result); + + // Short delay to allow timeout to occur + esp_rom_delay_us(TASK_WDT_TIMEOUT_MS * 1000); + TEST_ASSERT_EQUAL(true, timeout_flag); + TEST_ASSERT_EQUAL(ESP_OK, esp_task_wdt_delete(NULL)); + TEST_ASSERT_EQUAL(ESP_OK, esp_task_wdt_deinit()); + TEST_ESP_OK(sleep_cpu_configure(false)); +} +#endif + #if SOC_MWDT_SUPPORT_XTAL #if CONFIG_IDF_TARGET_ESP32H2 @@ -92,7 +129,7 @@ TEST_CASE("Task WDT inactive when no task to watch", "[task_wdt]") TEST_ASSERT_EQUAL(ESP_OK, esp_task_wdt_add(NULL)); esp_rom_delay_us(TASK_WDT_TIMEOUT_MS * 1000); TEST_ASSERT_EQUAL(true, timeout_flag); - /* Remove the task we just addded and make sure the WDT is stopped*/ + /* Remove the task we just added and make sure the WDT is stopped*/ timeout_flag = false; TEST_ASSERT_EQUAL(ESP_OK, esp_task_wdt_delete(NULL)); esp_rom_delay_us(2 * TASK_WDT_TIMEOUT_MS * 1000); diff --git a/components/esp_system/test_apps/esp_system_unity_tests/sdkconfig.ci.default b/components/esp_system/test_apps/esp_system_unity_tests/sdkconfig.ci.default index 31d50f6908..fcbda27d40 100644 --- a/components/esp_system/test_apps/esp_system_unity_tests/sdkconfig.ci.default +++ b/components/esp_system/test_apps/esp_system_unity_tests/sdkconfig.ci.default @@ -1,3 +1,5 @@ # Default configuration # Used for testing stack smashing protection CONFIG_COMPILER_STACK_CHECK=y +CONFIG_ESP_SLEEP_DEBUG=y +CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP=y From d917f0fa1b3d0bf2a7f667d8b122db10798c8682 Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Fri, 10 May 2024 16:46:27 +0800 Subject: [PATCH 4/9] ci(esp_driver_gptimer): add gptimer pd_top sleep retention test case --- .../test_apps/gptimer/main/test_gptimer.c | 90 ++++++++++++++++++- .../test_apps/gptimer/sdkconfig.ci.release | 3 + 2 files changed, 92 insertions(+), 1 deletion(-) diff --git a/components/esp_driver_gptimer/test_apps/gptimer/main/test_gptimer.c b/components/esp_driver_gptimer/test_apps/gptimer/main/test_gptimer.c index 04c08ce05e..4d3e6b4987 100644 --- a/components/esp_driver_gptimer/test_apps/gptimer/main/test_gptimer.c +++ b/components/esp_driver_gptimer/test_apps/gptimer/main/test_gptimer.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -13,6 +13,15 @@ #include "soc/soc_caps.h" #include "esp_attr.h" +#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && SOC_TIMER_SUPPORT_SLEEP_RETENTION +#include "esp_random.h" +#include "esp_rom_uart.h" +#include "esp_sleep.h" +#include "esp_private/esp_sleep_internal.h" +#include "esp_private/sleep_cpu.h" +#include "esp_private/esp_pmu.h" +#endif + #if CONFIG_GPTIMER_ISR_IRAM_SAFE #define TEST_ALARM_CALLBACK_ATTR IRAM_ATTR #else @@ -596,3 +605,82 @@ TEST_CASE("gptimer_trig_alarm_with_old_count", "[gptimer]") TEST_ESP_OK(gptimer_disable(timer)); TEST_ESP_OK(gptimer_del_timer(timer)); } + +#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && SOC_TIMER_SUPPORT_SLEEP_RETENTION +static gptimer_handle_t timers[SOC_TIMER_GROUP_TOTAL_TIMERS]; +static uint32_t timer_resolution_hz[SOC_TIMER_GROUP_TOTAL_TIMERS]; + +static void test_gptimer_retention(gptimer_config_t *timer_config) +{ + for (int i = 0; i < SOC_TIMER_GROUP_TOTAL_TIMERS; i++) { + TEST_ESP_OK(gptimer_new_timer(timer_config, &timers[i])); + TEST_ESP_OK(gptimer_get_resolution(timers[i], &timer_resolution_hz[i])); + + unsigned long long count_start_value = 0, count_end_value = 0; + + // Let gptimer run for a while + TEST_ESP_OK(gptimer_enable(timers[i])); + TEST_ESP_OK(gptimer_start(timers[i])); + vTaskDelay((esp_random() % 500) / portTICK_PERIOD_MS); + TEST_ESP_OK(gptimer_stop(timers[i])); + TEST_ESP_OK(gptimer_disable(timers[i])); + TEST_ESP_OK(gptimer_get_raw_count(timers[i], &count_start_value)); + + esp_sleep_context_t sleep_ctx; + esp_sleep_set_sleep_context(&sleep_ctx); + TEST_ESP_OK(sleep_cpu_configure(true)); + esp_rom_output_tx_wait_idle(0); + esp_sleep_enable_timer_wakeup(50 * 1000); + esp_light_sleep_start(); + + if (timer_config->flags.backup_before_sleep) { + TEST_ASSERT_EQUAL(PMU_SLEEP_PD_TOP, sleep_ctx.sleep_flags & PMU_SLEEP_PD_TOP); + } else { + TEST_ASSERT_EQUAL(0, sleep_ctx.sleep_flags & PMU_SLEEP_PD_TOP); + } + + TEST_ASSERT_EQUAL(0, sleep_ctx.sleep_request_result); + + TEST_ESP_OK(gptimer_enable(timers[i])); + TEST_ESP_OK(gptimer_start(timers[i])); + + uint32_t random_time_ms = 500 + esp_random() % 2000; + vTaskDelay(random_time_ms / portTICK_PERIOD_MS); + TEST_ESP_OK(gptimer_get_raw_count(timers[i], &count_end_value)); + + // Error tolerance is 2% + TEST_ASSERT_UINT_WITHIN(random_time_ms / 50, random_time_ms, 1000 * (count_end_value - count_start_value) / (unsigned long long)timer_resolution_hz[i]); + + TEST_ESP_OK(gptimer_stop(timers[i])); + TEST_ESP_OK(gptimer_disable(timers[i])); + TEST_ESP_OK(gptimer_del_timer(timers[i])); + TEST_ESP_OK(sleep_cpu_configure(false)); + } +} + +TEST_CASE("gptimer context kept after peripheral powerdown lightsleep with backup_before_sleep enable", "[gptimer]") +{ + printf("install gptimer driver\r\n"); + gptimer_config_t timer_config = { + .resolution_hz = 10 * 1000, // 10KHz, 1 tick = 0.1ms + .clk_src = GPTIMER_CLK_SRC_DEFAULT, + .direction = GPTIMER_COUNT_UP, + .flags.backup_before_sleep = true + }; + + test_gptimer_retention(&timer_config); +} + +TEST_CASE("gptimer context kept after peripheral powerdown lightsleep with backup_before_sleep disable", "[gptimer]") +{ + printf("install gptimer driver\r\n"); + gptimer_config_t timer_config = { + .resolution_hz = 10 * 1000, // 10KHz, 1 tick = 0.1ms + .clk_src = GPTIMER_CLK_SRC_DEFAULT, + .direction = GPTIMER_COUNT_UP, + .flags.backup_before_sleep = false + }; + + test_gptimer_retention(&timer_config); +} +#endif diff --git a/components/esp_driver_gptimer/test_apps/gptimer/sdkconfig.ci.release b/components/esp_driver_gptimer/test_apps/gptimer/sdkconfig.ci.release index 199b0cf97c..05634936f4 100644 --- a/components/esp_driver_gptimer/test_apps/gptimer/sdkconfig.ci.release +++ b/components/esp_driver_gptimer/test_apps/gptimer/sdkconfig.ci.release @@ -4,3 +4,6 @@ CONFIG_PM_DFS_INIT_AUTO=y CONFIG_COMPILER_OPTIMIZATION_SIZE=y CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y +# For TASK WDT timer PD_TOP sleep retention test +CONFIG_ESP_SLEEP_DEBUG=y +CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP=y From a6414289416481084f4eab12fd311c8db6ef72eb Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Fri, 10 May 2024 21:12:45 +0800 Subject: [PATCH 5/9] fix(ci): use esp_rom_crc32_le in sleep retention frame check --- .../lowpower/cpu_retention/port/esp32c3/sleep_cpu.c | 1 - .../lowpower/cpu_retention/port/esp32c5/sleep_cpu.c | 6 +++--- .../lowpower/cpu_retention/port/esp32c6/sleep_cpu.c | 6 +++--- .../lowpower/cpu_retention/port/esp32h2/sleep_cpu.c | 6 +++--- .../lowpower/cpu_retention/port/esp32p4/sleep_cpu.c | 6 +++--- .../lowpower/cpu_retention/port/esp32s3/sleep_cpu.c | 1 - 6 files changed, 12 insertions(+), 14 deletions(-) diff --git a/components/esp_hw_support/lowpower/cpu_retention/port/esp32c3/sleep_cpu.c b/components/esp_hw_support/lowpower/cpu_retention/port/esp32c3/sleep_cpu.c index 9fdd1d3a76..ebc050fa6f 100644 --- a/components/esp_hw_support/lowpower/cpu_retention/port/esp32c3/sleep_cpu.c +++ b/components/esp_hw_support/lowpower/cpu_retention/port/esp32c3/sleep_cpu.c @@ -14,7 +14,6 @@ #include "esp_check.h" #include "esp_sleep.h" #include "esp_log.h" -#include "esp_crc.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "esp_heap_caps.h" diff --git a/components/esp_hw_support/lowpower/cpu_retention/port/esp32c5/sleep_cpu.c b/components/esp_hw_support/lowpower/cpu_retention/port/esp32c5/sleep_cpu.c index fbb67fd089..2ed461d280 100644 --- a/components/esp_hw_support/lowpower/cpu_retention/port/esp32c5/sleep_cpu.c +++ b/components/esp_hw_support/lowpower/cpu_retention/port/esp32c5/sleep_cpu.c @@ -14,7 +14,7 @@ #include "esp_check.h" #include "esp_sleep.h" #include "esp_log.h" -#include "esp_crc.h" +#include "esp_rom_crc.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "esp_heap_caps.h" @@ -391,12 +391,12 @@ static IRAM_ATTR void cpu_domain_dev_regs_restore(cpu_domain_dev_sleep_frame_t * #if CONFIG_PM_CHECK_SLEEP_RETENTION_FRAME static IRAM_ATTR void update_retention_frame_crc(uint32_t *frame_ptr, uint32_t frame_check_size, uint32_t *frame_crc_ptr) { - *(frame_crc_ptr) = esp_crc32_le(0, (void *)frame_ptr, frame_check_size); + *(frame_crc_ptr) = esp_rom_crc32_le(0, (void *)frame_ptr, frame_check_size); } static IRAM_ATTR void validate_retention_frame_crc(uint32_t *frame_ptr, uint32_t frame_check_size, uint32_t *frame_crc_ptr) { - if(*(frame_crc_ptr) != esp_crc32_le(0, (void *)(frame_ptr), frame_check_size)){ + if(*(frame_crc_ptr) != esp_rom_crc32_le(0, (void *)(frame_ptr), frame_check_size)){ // resume uarts for (int i = 0; i < SOC_UART_NUM; ++i) { if (!uart_ll_is_enabled(i)) { diff --git a/components/esp_hw_support/lowpower/cpu_retention/port/esp32c6/sleep_cpu.c b/components/esp_hw_support/lowpower/cpu_retention/port/esp32c6/sleep_cpu.c index e97de1c0eb..8d0b0a2bc7 100644 --- a/components/esp_hw_support/lowpower/cpu_retention/port/esp32c6/sleep_cpu.c +++ b/components/esp_hw_support/lowpower/cpu_retention/port/esp32c6/sleep_cpu.c @@ -14,7 +14,7 @@ #include "esp_check.h" #include "esp_sleep.h" #include "esp_log.h" -#include "esp_crc.h" +#include "esp_rom_crc.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "esp_heap_caps.h" @@ -431,12 +431,12 @@ static IRAM_ATTR void cpu_domain_dev_regs_restore(cpu_domain_dev_sleep_frame_t * #if CONFIG_PM_CHECK_SLEEP_RETENTION_FRAME static IRAM_ATTR void update_retention_frame_crc(uint32_t *frame_ptr, uint32_t frame_check_size, uint32_t *frame_crc_ptr) { - *(frame_crc_ptr) = esp_crc32_le(0, (void *)frame_ptr, frame_check_size); + *(frame_crc_ptr) = esp_rom_crc32_le(0, (void *)frame_ptr, frame_check_size); } static IRAM_ATTR void validate_retention_frame_crc(uint32_t *frame_ptr, uint32_t frame_check_size, uint32_t *frame_crc_ptr) { - if(*(frame_crc_ptr) != esp_crc32_le(0, (void *)(frame_ptr), frame_check_size)){ + if(*(frame_crc_ptr) != esp_rom_crc32_le(0, (void *)(frame_ptr), frame_check_size)){ // resume uarts for (int i = 0; i < SOC_UART_NUM; ++i) { if (!uart_ll_is_enabled(i)) { diff --git a/components/esp_hw_support/lowpower/cpu_retention/port/esp32h2/sleep_cpu.c b/components/esp_hw_support/lowpower/cpu_retention/port/esp32h2/sleep_cpu.c index b30913b233..c020247710 100644 --- a/components/esp_hw_support/lowpower/cpu_retention/port/esp32h2/sleep_cpu.c +++ b/components/esp_hw_support/lowpower/cpu_retention/port/esp32h2/sleep_cpu.c @@ -15,7 +15,7 @@ #include "esp_check.h" #include "esp_sleep.h" #include "esp_log.h" -#include "esp_crc.h" +#include "esp_rom_crc.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "esp_heap_caps.h" @@ -431,12 +431,12 @@ static IRAM_ATTR void cpu_domain_dev_regs_restore(cpu_domain_dev_sleep_frame_t * #if CONFIG_PM_CHECK_SLEEP_RETENTION_FRAME static IRAM_ATTR void update_retention_frame_crc(uint32_t *frame_ptr, uint32_t frame_check_size, uint32_t *frame_crc_ptr) { - *(frame_crc_ptr) = esp_crc32_le(0, (void *)frame_ptr, frame_check_size); + *(frame_crc_ptr) = esp_rom_crc32_le(0, (void *)frame_ptr, frame_check_size); } static IRAM_ATTR void validate_retention_frame_crc(uint32_t *frame_ptr, uint32_t frame_check_size, uint32_t *frame_crc_ptr) { - if(*(frame_crc_ptr) != esp_crc32_le(0, (void *)(frame_ptr), frame_check_size)){ + if(*(frame_crc_ptr) != esp_rom_crc32_le(0, (void *)(frame_ptr), frame_check_size)){ // resume uarts for (int i = 0; i < SOC_UART_NUM; ++i) { if (!uart_ll_is_enabled(i)) { diff --git a/components/esp_hw_support/lowpower/cpu_retention/port/esp32p4/sleep_cpu.c b/components/esp_hw_support/lowpower/cpu_retention/port/esp32p4/sleep_cpu.c index e7ea617a9d..68f469a66e 100644 --- a/components/esp_hw_support/lowpower/cpu_retention/port/esp32p4/sleep_cpu.c +++ b/components/esp_hw_support/lowpower/cpu_retention/port/esp32p4/sleep_cpu.c @@ -15,7 +15,7 @@ #include "esp_ipc_isr.h" #include "esp_sleep.h" #include "esp_log.h" -#include "esp_crc.h" +#include "esp_rom_crc.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "esp_heap_caps.h" @@ -374,12 +374,12 @@ static TCM_IRAM_ATTR void cpu_domain_dev_regs_restore(cpu_domain_dev_sleep_frame #if CONFIG_PM_CHECK_SLEEP_RETENTION_FRAME static TCM_IRAM_ATTR void update_retention_frame_crc(uint32_t *frame_ptr, uint32_t frame_check_size, uint32_t *frame_crc_ptr) { - *(frame_crc_ptr) = esp_crc32_le(0, (void *)frame_ptr, frame_check_size); + *(frame_crc_ptr) = esp_rom_crc32_le(0, (void *)frame_ptr, frame_check_size); } static TCM_IRAM_ATTR void validate_retention_frame_crc(uint32_t *frame_ptr, uint32_t frame_check_size, uint32_t *frame_crc_ptr) { - if(*(frame_crc_ptr) != esp_crc32_le(0, (void *)(frame_ptr), frame_check_size)){ + if(*(frame_crc_ptr) != esp_rom_crc32_le(0, (void *)(frame_ptr), frame_check_size)){ // resume uarts for (int i = 0; i < SOC_UART_NUM; ++i) { if (!uart_ll_is_enabled(i)) { diff --git a/components/esp_hw_support/lowpower/cpu_retention/port/esp32s3/sleep_cpu.c b/components/esp_hw_support/lowpower/cpu_retention/port/esp32s3/sleep_cpu.c index 2e16de3c67..cba8f6ee30 100644 --- a/components/esp_hw_support/lowpower/cpu_retention/port/esp32s3/sleep_cpu.c +++ b/components/esp_hw_support/lowpower/cpu_retention/port/esp32s3/sleep_cpu.c @@ -15,7 +15,6 @@ #include "esp_ipc_isr.h" #include "esp_sleep.h" #include "esp_log.h" -#include "esp_crc.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "esp_heap_caps.h" From a27aa02fa3f608501735c56115d04abc380c0a07 Mon Sep 17 00:00:00 2001 From: Li Shuai Date: Sat, 11 May 2024 19:29:25 +0800 Subject: [PATCH 6/9] fix(esp_hw_support): use iterator for regdma_link_stats to save stack consume Closes https://github.com/espressif/esp-idf/issues/13288 --- components/esp_hw_support/port/regdma_link.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/components/esp_hw_support/port/regdma_link.c b/components/esp_hw_support/port/regdma_link.c index d2f0c908cf..14a766c8d8 100644 --- a/components/esp_hw_support/port/regdma_link.c +++ b/components/esp_hw_support/port/regdma_link.c @@ -445,9 +445,22 @@ static void regdma_link_update_stats_wrapper(void *link, int entry, int depth) regdma_link_update_stats(regdma_link_get_stats(link), entry, depth); } +static void regdma_link_iterator(void *link, int entry, void (*hook)(void *, int, int)) +{ + assert(entry < REGDMA_LINK_ENTRY_NUM); + + int iter = 0; + while (link) { + if (hook) { + (*hook)(link, entry, iter++); + } + link = regdma_link_get_next(link, entry); + } +} + void regdma_link_stats(void *link, int entry) { - regdma_link_recursive_impl(link, entry, 0, regdma_link_update_stats_wrapper); + regdma_link_iterator(link, entry, regdma_link_update_stats_wrapper); } static void regdma_link_destroy_wrapper(void *link, int entry, int depth) From 26cb10acbf322373d080760a2981171382a35ad2 Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Sat, 11 May 2024 16:50:29 +0800 Subject: [PATCH 7/9] feat(esp_hw_support): optimize retention link info dump --- .../include/esp_private/esp_regdma.h | 2 - components/esp_hw_support/port/regdma_link.c | 68 ++++++++++++------- components/esp_hw_support/sleep_retention.c | 2 - 3 files changed, 44 insertions(+), 28 deletions(-) diff --git a/components/esp_hw_support/include/esp_private/esp_regdma.h b/components/esp_hw_support/include/esp_private/esp_regdma.h index 57f2ccc487..03b551d64b 100644 --- a/components/esp_hw_support/include/esp_private/esp_regdma.h +++ b/components/esp_hw_support/include/esp_private/esp_regdma.h @@ -22,8 +22,6 @@ extern "C" { #if SOC_PAU_SUPPORTED #include "hal/pau_types.h" -#define REGDMA_LINK_DBG 0 /* Enable REGDMA link info dump apis*/ - /** * @brief Create a REGDMA continuous type linked list node without retention buffer and the retention buffer is passed in by the caller * @param backup Register address to be backed up by REGDMA diff --git a/components/esp_hw_support/port/regdma_link.c b/components/esp_hw_support/port/regdma_link.c index 14a766c8d8..0af808ae32 100644 --- a/components/esp_hw_support/port/regdma_link.c +++ b/components/esp_hw_support/port/regdma_link.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -8,6 +8,7 @@ #include #include #include +#include #include "esp_private/regdma_link.h" @@ -713,13 +714,17 @@ void * regdma_find_prev_module_link_tail(void *link, void *tail, int entry, uint return NULL; } -#if REGDMA_LINK_DBG static __attribute__((unused)) const char *TAG = "regdma_link"; +static const char* s_link_mode_str[] = { "CONTINUOUS", "ADDR_MAP", "WRITE", "WAIT" }; +static const char* s_boolean_str[] = { "false", "true" }; static void print_info_link_data(FILE *out, const uint32_t buf[], int len) { for (int i = 0; i < len; i++) { - fprintf(out, ((i + 1) % 8) ? "%08lx " : "%08lx\n", buf[i]); + if (i % 8 == 0) { + fprintf(out, "\t\t"); + } + fprintf(out, ((i + 1) % 8) ? "%08"PRIx32" " : "%08"PRIx32"\n", buf[i]); } if (len % 8) { fprintf(out, "\n"); @@ -730,9 +735,13 @@ static void print_info_continuous_wrapper(FILE *out, void *link) { regdma_link_head_t head = REGDMA_LINK_HEAD(link); regdma_link_continuous_t *cons = __containerof(link, regdma_link_continuous_t, head); - fprintf(out, "[%08lx/%04x] link:%p, head:%lx, next:%p, backup:%p, restore:%p, buff:%p\n", - cons->stat.module, cons->stat.id, link, *(uint32_t *)&cons->head, cons->body.next, - cons->body.backup, cons->body.restore, cons->body.mem); + assert((cons->stat.module & (cons->stat.module - 1)) == 0); + fprintf(out, LOG_COLOR_I " [%02d/%04x] link_ptr:%p, head: {mode:%s len:%d branch:%s skip_r:%s skip_b:%s eof:%s}, next:%p, backup start:%p, restore start:%p, buff_ptr:%p\n" LOG_RESET_COLOR, + __builtin_ffs(cons->stat.module) - 1, cons->stat.id, link, + s_link_mode_str[cons->head.mode], cons->head.length, s_boolean_str[cons->head.branch], s_boolean_str[cons->head.skip_r], s_boolean_str[cons->head.skip_b], s_boolean_str[cons->head.eof], + cons->body.next, + cons->body.backup, cons->body.restore, + cons->body.mem); print_info_link_data(out, (const uint32_t *)cons->body.mem, head.length); } @@ -740,18 +749,23 @@ static void print_info_addr_map_wrapper(FILE *out, void *link) { regdma_link_head_t head = REGDMA_LINK_HEAD(link); regdma_link_addr_map_t *map = __containerof(link, regdma_link_addr_map_t, head); - fprintf(out, "[%08lx/%04x] link:%p, head:%lx, next:%p, backup:%p, restore:%p, buff:%p, map:{%lx,%lx,%lx,%lx}\n", - map->stat.module, map->stat.id, link, *(uint32_t *)&map->head, map->body.next, map->body.backup, - map->body.restore, map->body.mem, map->body.map[0], map->body.map[1], - map->body.map[2], map->body.map[3]); + assert((map->stat.module & (map->stat.module - 1)) == 0); + fprintf(out, LOG_COLOR_I " [%02d/%04x] link_ptr:%p, head: {mode:%s len:%d branch:%s skip_r:%s skip_b:%s eof:%s}, next:%p, backup start:%p, restore start:%p, buff_ptr:%p, map:{%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32"}\n" LOG_RESET_COLOR, + __builtin_ffs(map->stat.module) - 1, map->stat.id, link, + s_link_mode_str[map->head.mode], map->head.length, s_boolean_str[map->head.branch], s_boolean_str[map->head.skip_r], s_boolean_str[map->head.skip_b], s_boolean_str[map->head.eof], + map->body.next, + map->body.backup, map->body.restore, + map->body.mem, map->body.map[0], map->body.map[1], map->body.map[2], map->body.map[3]); print_info_link_data(out, (const uint32_t *)map->body.mem, head.length); } static void print_info_write_wait_wrapper(FILE *out, void *link) { regdma_link_write_wait_t *ww = __containerof(link, regdma_link_write_wait_t, head); - fprintf(out, "[%08lx/%04x] link:%p, head:%lx, next:%p, backup:%p, value:%lx, mask:%lx\n", - ww->stat.module, ww->stat.id, link, *(uint32_t *)&ww->head, ww->body.next, + fprintf(out, LOG_COLOR_I " [%02d/%04x] link_ptr:%p, head: {mode:%s len:%d branch:%s skip_r:%s skip_b:%s eof:%s}, next:%p, backup start:%p, value:%"PRIx32", mask:%"PRIx32"\n" LOG_RESET_COLOR, + __builtin_ffs(ww->stat.module) - 1, ww->stat.id, link, + s_link_mode_str[ww->head.mode], ww->head.length, s_boolean_str[ww->head.branch], s_boolean_str[ww->head.skip_r], s_boolean_str[ww->head.skip_b], s_boolean_str[ww->head.eof], + ww->body.next, ww->body.backup, ww->body.value, ww->body.mask); } @@ -759,9 +773,12 @@ static void print_info_branch_continuous_wrapper(FILE *out, void *link) { regdma_link_head_t head = REGDMA_LINK_HEAD(link); regdma_link_branch_continuous_t *cons = __containerof(link, regdma_link_branch_continuous_t, head); - fprintf(out, "[%08lx/%04x] link:%p, head:%lx, next:{%p,%p,%p,%p}, backup:%p, restore:%p, buff:%p\n", - cons->stat.module, cons->stat.id, link, *(uint32_t *)&cons->head, cons->body.next[0], cons->body.next[1], - cons->body.next[2], cons->body.next[3], cons->body.backup, cons->body.restore, + assert((cons->stat.module & (cons->stat.module - 1)) == 0); + fprintf(out, LOG_COLOR_I " [%02d/%04x] link_ptr:%p, head: {mode:%s len:%d branch:%s skip_r:%s skip_b:%s eof:%s}, next:%p, backup start:%p, restore start:%p, buff_ptr:%p\n" LOG_RESET_COLOR, + __builtin_ffs(cons->stat.module) - 1, cons->stat.id, link, + s_link_mode_str[cons->head.mode], cons->head.length, s_boolean_str[cons->head.branch], s_boolean_str[cons->head.skip_r], s_boolean_str[cons->head.skip_b], s_boolean_str[cons->head.eof], + cons->body.next, + cons->body.backup, cons->body.restore, cons->body.mem); print_info_link_data(out, (const uint32_t *)cons->body.mem, head.length); } @@ -770,20 +787,24 @@ static void print_info_branch_addr_map_wrapper(FILE *out, void *link) { regdma_link_head_t head = REGDMA_LINK_HEAD(link); regdma_link_branch_addr_map_t *map = __containerof(link, regdma_link_branch_addr_map_t, head); - fprintf(out, "[%08lx/%04x] link:%p, head:%lx, next:{%p,%p,%p,%p}, backup:%p, restore:%p, buff:%p, map:{%lx,%lx,%lx,%lx}\n", - map->stat.module, map->stat.id, link, *(uint32_t *)&map->head, map->body.next[0], map->body.next[1], map->body.next[2], - map->body.next[3], map->body.backup, map->body.restore, map->body.mem, map->body.map[0], - map->body.map[1], map->body.map[2], map->body.map[3]); + assert((map->stat.module & (map->stat.module - 1)) == 0); + fprintf(out, LOG_COLOR_I " [%02d/%04x] link_ptr:%p, head: {mode:%s len:%d branch:%s skip_r:%s skip_b:%s eof:%s}, next:%p, backup start:%p, restore start:%p, buff_ptr:%p, map:{%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32"}\n" LOG_RESET_COLOR, + __builtin_ffs(map->stat.module) - 1, map->stat.id, link, + s_link_mode_str[map->head.mode], map->head.length, s_boolean_str[map->head.branch], s_boolean_str[map->head.skip_r], s_boolean_str[map->head.skip_b], s_boolean_str[map->head.eof], + map->body.next, + map->body.backup, map->body.restore, + map->body.mem, map->body.map[0], map->body.map[1], map->body.map[2], map->body.map[3]); print_info_link_data(out, (const uint32_t *)map->body.mem, head.length); } static void print_info_branch_write_wait_wrapper(FILE *out, void *link) { regdma_link_branch_write_wait_t *ww = __containerof(link, regdma_link_branch_write_wait_t, head); - fprintf(out, "[%08lx/%04x] link:%p, head:%lx, next:{%p,%p,%p,%p}, backup:%p, value:%lx, mask:%lx\n", - ww->stat.module, ww->stat.id, link, *(uint32_t *)&ww->head, ww->body.next[0], ww->body.next[1], - ww->body.next[2], ww->body.next[3], ww->body.backup, ww->body.value, - ww->body.mask); + fprintf(out, LOG_COLOR_I " [%02d/%04x] link_ptr:%p, head: {mode:%s len:%d branch:%s skip_r:%s skip_b:%s eof:%s}, next:%p, backup start:%p, value:%"PRIx32", mask:%"PRIx32"\n" LOG_RESET_COLOR, + __builtin_ffs(ww->stat.module) - 1, ww->stat.id, link, + s_link_mode_str[ww->head.mode], ww->head.length, s_boolean_str[ww->head.branch], s_boolean_str[ww->head.skip_r], s_boolean_str[ww->head.skip_b], s_boolean_str[ww->head.eof], + ww->body.next, + ww->body.backup, ww->body.value, ww->body.mask); } static void print_link_info(FILE *out, void *args, int entry, int depth) @@ -821,4 +842,3 @@ void regdma_link_dump(FILE *out, void *link, int entry) fprintf(out, "This REGDMA linked list is empty!\n"); } } -#endif diff --git a/components/esp_hw_support/sleep_retention.c b/components/esp_hw_support/sleep_retention.c index c7b88c648a..8f7a73bf69 100644 --- a/components/esp_hw_support/sleep_retention.c +++ b/components/esp_hw_support/sleep_retention.c @@ -303,7 +303,6 @@ static void sleep_retention_entries_stats(void) _lock_release_recursive(&s_retention.lock); } -#if REGDMA_LINK_DBG void sleep_retention_dump_entries(FILE *out) { _lock_acquire_recursive(&s_retention.lock); @@ -315,7 +314,6 @@ void sleep_retention_dump_entries(FILE *out) } _lock_release_recursive(&s_retention.lock); } -#endif void * sleep_retention_find_link_by_id(int id) { From 1854036f92faeba354572834f7f3af81bb18391a Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Wed, 22 May 2024 12:01:16 +0800 Subject: [PATCH 8/9] change(esp_hw_support): use union retention link priority definiation --- components/driver/i2c/i2c.c | 2 +- components/esp_driver_i2c/i2c_common.c | 2 +- components/esp_hw_support/sleep_system_peripheral.c | 4 ++-- components/esp_system/int_wdt.c | 2 +- .../esp_system/task_wdt/task_wdt_impl_timergroup.c | 2 +- components/soc/include/soc/regdma.h | 9 ++++++--- 6 files changed, 12 insertions(+), 9 deletions(-) diff --git a/components/driver/i2c/i2c.c b/components/driver/i2c/i2c.c index 591177dda8..eb315a4ec4 100644 --- a/components/driver/i2c/i2c.c +++ b/components/driver/i2c/i2c.c @@ -280,7 +280,7 @@ static void i2c_hw_enable(i2c_port_t i2c_num) static esp_err_t i2c_sleep_retention_init(void *arg) { i2c_port_t i2c_num = *(i2c_port_t *)arg; - esp_err_t ret = sleep_retention_entries_create(i2c_regs_retention[i2c_num].link_list, i2c_regs_retention[i2c_num].link_num, REGDMA_LINK_PRI_7, I2C_SLEEP_RETENTION_MODULE(i2c_num)); + esp_err_t ret = sleep_retention_entries_create(i2c_regs_retention[i2c_num].link_list, i2c_regs_retention[i2c_num].link_num, REGDMA_LINK_PRI_I2C, I2C_SLEEP_RETENTION_MODULE(i2c_num)); ESP_RETURN_ON_ERROR(ret, I2C_TAG, "failed to allocate mem for sleep retention"); return ret; } diff --git a/components/esp_driver_i2c/i2c_common.c b/components/esp_driver_i2c/i2c_common.c index f0daf1a3b8..8c3f86952e 100644 --- a/components/esp_driver_i2c/i2c_common.c +++ b/components/esp_driver_i2c/i2c_common.c @@ -52,7 +52,7 @@ static esp_err_t s_i2c_sleep_retention_init(void *arg) { i2c_bus_t *bus = (i2c_bus_t *)arg; i2c_port_num_t port_num = bus->port_num; - esp_err_t ret = sleep_retention_entries_create(i2c_regs_retention[port_num].link_list, i2c_regs_retention[port_num].link_num, REGDMA_LINK_PRI_7, I2C_SLEEP_RETENTION_MODULE(port_num)); + esp_err_t ret = sleep_retention_entries_create(i2c_regs_retention[port_num].link_list, i2c_regs_retention[port_num].link_num, REGDMA_LINK_PRI_I2C, I2C_SLEEP_RETENTION_MODULE(port_num)); ESP_RETURN_ON_ERROR(ret, TAG, "failed to allocate mem for sleep retention"); return ret; } diff --git a/components/esp_hw_support/sleep_system_peripheral.c b/components/esp_hw_support/sleep_system_peripheral.c index 531f3dd670..cd36fe7f52 100644 --- a/components/esp_hw_support/sleep_system_peripheral.c +++ b/components/esp_hw_support/sleep_system_peripheral.c @@ -84,7 +84,7 @@ static __attribute__((unused)) esp_err_t sleep_sys_periph_systimer_retention_ini #if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE esp_err_t sleep_sys_periph_l2_cache_retention_init(void) { - esp_err_t err = sleep_retention_entries_create(l2_cache_regs_retention, ARRAY_SIZE(l2_cache_regs_retention), REGDMA_LINK_PRI_5, SLEEP_RETENTION_MODULE_SYS_PERIPH); + esp_err_t err = sleep_retention_entries_create(l2_cache_regs_retention, ARRAY_SIZE(l2_cache_regs_retention), REGDMA_LINK_PRI_SYS_PERIPH_HIGH, SLEEP_RETENTION_MODULE_SYS_PERIPH); ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for digital peripherals (L2 Cache) retention"); ESP_LOGI(TAG, "L2 Cache sleep retention initialization"); return ESP_OK; @@ -94,7 +94,7 @@ esp_err_t sleep_sys_periph_l2_cache_retention_init(void) #if SOC_PAU_IN_TOP_DOMAIN esp_err_t sleep_pau_retention_init(void) { - esp_err_t err = sleep_retention_entries_create(pau_regs_retention, ARRAY_SIZE(pau_regs_retention), REGDMA_LINK_PRI_7, SLEEP_RETENTION_MODULE_SYS_PERIPH); + esp_err_t err = sleep_retention_entries_create(pau_regs_retention, ARRAY_SIZE(pau_regs_retention), REGDMA_LINK_PRI_SYS_PERIPH_LOW, SLEEP_RETENTION_MODULE_SYS_PERIPH); ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for system (PAU) retention"); ESP_LOGI(TAG, "PAU sleep retention initialization"); return ESP_OK; diff --git a/components/esp_system/int_wdt.c b/components/esp_system/int_wdt.c index 68d031d533..9a8db626f3 100644 --- a/components/esp_system/int_wdt.c +++ b/components/esp_system/int_wdt.c @@ -59,7 +59,7 @@ static esp_err_t sleep_int_wdt_retention_init(void *arg) uint32_t group_id = *(uint32_t *)arg; esp_err_t err = sleep_retention_entries_create(tg_wdt_regs_retention[group_id].link_list, tg_wdt_regs_retention[group_id].link_num, - REGDMA_LINK_PRI_6, + REGDMA_LINK_PRI_SYS_PERIPH_LOW, (group_id == 0) ? SLEEP_RETENTION_MODULE_TG0_WDT : SLEEP_RETENTION_MODULE_TG1_WDT); if (err == ESP_OK) { ESP_LOGD(TAG, "Interrupt watchdog timer retention initialization"); diff --git a/components/esp_system/task_wdt/task_wdt_impl_timergroup.c b/components/esp_system/task_wdt/task_wdt_impl_timergroup.c index 533a4f2461..8b8ed63180 100644 --- a/components/esp_system/task_wdt/task_wdt_impl_timergroup.c +++ b/components/esp_system/task_wdt/task_wdt_impl_timergroup.c @@ -52,7 +52,7 @@ static esp_err_t sleep_task_wdt_retention_init(void *arg) uint32_t group_id = *(uint32_t *)arg; esp_err_t err = sleep_retention_entries_create(tg_wdt_regs_retention[group_id].link_list, tg_wdt_regs_retention[group_id].link_num, - REGDMA_LINK_PRI_6, + REGDMA_LINK_PRI_SYS_PERIPH_LOW, (group_id == 0) ? SLEEP_RETENTION_MODULE_TG0_WDT : SLEEP_RETENTION_MODULE_TG1_WDT); if (err == ESP_OK) { ESP_LOGD(TAG, "Task watchdog timer retention initialization"); diff --git a/components/soc/include/soc/regdma.h b/components/soc/include/soc/regdma.h index 2243d1113a..b6fd9ff00e 100644 --- a/components/soc/include/soc/regdma.h +++ b/components/soc/include/soc/regdma.h @@ -60,9 +60,12 @@ extern "C" { #define REGDMA_LINK_PRI_BT_MAC_BB REGDMA_LINK_PRI_5 #define REGDMA_LINK_PRI_SYS_PERIPH_HIGH REGDMA_LINK_PRI_5 // INT_MTX & HP_SYSTEM & Console UART #define REGDMA_LINK_PRI_SYS_PERIPH_LOW REGDMA_LINK_PRI_6 // TG0 & IO MUX & SPI MEM & Systimer -#define REGDMA_LINK_PRI_IEEE802154 REGDMA_LINK_PRI_7 -#define REGDMA_LINK_PRI_GDMA REGDMA_LINK_PRI_7 -#define REGDMA_LINK_PRI_RMT REGDMA_LINK_PRI_7 +#define REGDMA_LINK_PRI_GENERAL_PERIPH REGDMA_LINK_PRI_7 // Low retenion priority for general peripherals +#define REGDMA_LINK_PRI_IEEE802154 REGDMA_LINK_PRI_GENERAL_PERIPH +#define REGDMA_LINK_PRI_GDMA REGDMA_LINK_PRI_GENERAL_PERIPH +#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 typedef enum { REGDMA_LINK_PRI_0 = 0, From 2ab144dc3a51010fc3cd741570e9c6b0715b9a4f Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Thu, 23 May 2024 20:07:56 +0800 Subject: [PATCH 9/9] fix(esp_hw_support): set pau entry backup configuration with link update --- components/esp_hw_support/port/esp32p4/pmu_sleep.c | 13 ------------- components/hal/esp32p4/pau_hal.c | 4 ++++ 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/components/esp_hw_support/port/esp32p4/pmu_sleep.c b/components/esp_hw_support/port/esp32p4/pmu_sleep.c index a2a55cf83b..3b0487157c 100644 --- a/components/esp_hw_support/port/esp32p4/pmu_sleep.c +++ b/components/esp_hw_support/port/esp32p4/pmu_sleep.c @@ -247,19 +247,6 @@ void pmu_sleep_init(const pmu_sleep_config_t *config, bool dslp) } pmu_sleep_analog_init(PMU_instance(), &config->analog, dslp); pmu_sleep_param_init(PMU_instance(), &config->param, dslp); - - // When light sleep (PD_TOP), the PAU will power down. so need use LP_SYS_BACKUP_DMA_CFG2_REG to store recover link address. - if (!dslp && PMU.hp_sys[PMU_MODE_HP_SLEEP].dig_power.top_pd_en) { - if (PMU.hp_sys[PMU_MODE_HP_SLEEP].backup.hp_active2sleep_backup_en || - PMU.hp_sys[PMU_MODE_HP_ACTIVE].backup.hp_sleep2active_backup_en) { - uint32_t link_sel = PMU.hp_sys[PMU_MODE_HP_SLEEP].backup.hp_active2sleep_backup_mode & 0x3; - uint32_t link_addr = REG_READ(PAU_REGDMA_LINK_0_ADDR_REG + link_sel * 4); - lp_sys_ll_set_pau_link_addr(link_addr); - pmu_sleep_enable_regdma_backup(); - } - } else { - pmu_sleep_disable_regdma_backup(); - } } void pmu_sleep_increase_ldo_volt(void) { diff --git a/components/hal/esp32p4/pau_hal.c b/components/hal/esp32p4/pau_hal.c index 38b98ba4e1..2852d99a92 100644 --- a/components/hal/esp32p4/pau_hal.c +++ b/components/hal/esp32p4/pau_hal.c @@ -20,6 +20,10 @@ void pau_hal_set_regdma_entry_link_addr(pau_hal_context_t *hal, pau_regdma_link_ pau_ll_set_regdma_link2_addr(hal->dev, (*link_addr)[2]); /* The link 3 of REGDMA is reserved, PMU state switching will not use * REGDMA link 3 */ + + // When light sleep (PD_TOP), the PAU will power down. so need use LP_SYS_BACKUP_DMA_CFG2_REG + // to store recover link address. We always use link0 as the default retention entry. + lp_sys_ll_set_pau_link_addr((uint32_t)(*link_addr)[0]); } void IRAM_ATTR pau_hal_start_regdma_modem_link(pau_hal_context_t *hal, bool backup_or_restore)