Merge branch 'feature/esp32c61_light_sleep_support_stage_3' into 'master'

feat(esp_hw_support): esp32c61 sleep support (Stage 3:  support system peripheral sleep retention)

Closes IDF-10384, IDF-10382, and IDF-11004

See merge request espressif/esp-idf!33298
This commit is contained in:
Jiang Jiang Jian 2024-09-21 16:09:36 +08:00
commit 945af68d74
33 changed files with 982 additions and 74 deletions

View File

@ -24,7 +24,7 @@ def test_app_update(dut: Dut) -> None:
@pytest.mark.supported_targets
# TODO: [ESP32C61] IDF-9245, IDF-9247, IDF-10983
# TODO: [ESP32C61] IDF-9245, IDF-10983
@pytest.mark.temp_skip_ci(targets=['esp32c61'], reason='C61 has not supported deep sleep')
@pytest.mark.generic
@pytest.mark.parametrize(

View File

@ -273,4 +273,13 @@ menu "Hardware Settings"
config ESP_SPI_BUS_LOCK_FUNCS_IN_IRAM
bool
default n
config ESP_CLK_RC32K_NOT_TO_USE
bool
default y if IDF_TARGET_ESP32C5 || IDF_TARGET_ESP32C61
default n
help
Due to the poor low-temperature characteristics of
RC32K (it cannot operate below -40 degrees Celsius),
please avoid using it whenever possible
endmenu

View File

@ -19,7 +19,7 @@ esp_err_t sleep_clock_system_retention_init(void *arg)
[0] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_PCR_LINK(0), PCR_AHB_FREQ_CONF_REG, 0, PCR_AHB_DIV_NUM, 1, 0), .owner = ENTRY(0) | ENTRY(1) }, /* Set AHB bus frequency to XTAL frequency */
[1] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_PCR_LINK(1), PCR_BUS_CLK_UPDATE_REG, 1, PCR_BUS_CLOCK_UPDATE, 1, 0), .owner = ENTRY(0) | ENTRY(1) },
#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
[2] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_PCR_LINK(2), DR_REG_PCR_BASE, DR_REG_PCR_BASE, 74, 0, 0, 0xffffffff, 0xffffffff, 0x7f7, 0x0), .owner = ENTRY(0) | ENTRY(1) },
[2] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_PCR_LINK(2), DR_REG_PCR_BASE, DR_REG_PCR_BASE, 75, 0, 0, 0xffffffff, 0xffffffff, 0x200007f7, 0x0), .owner = ENTRY(0) | ENTRY(1) },
#endif
};
esp_err_t err = sleep_retention_entries_create(pcr_regs_retention, ARRAY_SIZE(pcr_regs_retention), REGDMA_LINK_PRI_SYS_CLK, SLEEP_RETENTION_MODULE_CLOCK_SYSTEM);

View File

@ -0,0 +1,91 @@
/*
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "esp_private/sleep_clock.h"
#include "soc/pcr_reg.h"
#include "modem/modem_syscon_reg.h"
static const char *TAG = "sleep_clock";
esp_err_t sleep_clock_system_retention_init(void *arg)
{
const static sleep_retention_entries_config_t pcr_regs_retention[] = {
[0] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_PCR_LINK(0), DR_REG_PCR_BASE, DR_REG_PCR_BASE, 63, 0, 0, 0xfd73ffff, 0xfdffffff, 0xe001, 0x0), .owner = ENTRY(0) | ENTRY(1) },
};
esp_err_t err = sleep_retention_entries_create(pcr_regs_retention, ARRAY_SIZE(pcr_regs_retention), REGDMA_LINK_PRI_SYS_CLK, SLEEP_RETENTION_MODULE_CLOCK_SYSTEM);
ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for system (PCR) retention");
ESP_LOGI(TAG, "System Power, Clock and Reset sleep retention initialization");
return ESP_OK;
}
#if CONFIG_MAC_BB_PD || CONFIG_BT_LE_SLEEP_ENABLE || CONFIG_IEEE802154_SLEEP_ENABLE
esp_err_t sleep_clock_modem_retention_init(void *arg)
{
#define N_REGS_SYSCON() (((MODEM_SYSCON_MEM_CONF_REG - MODEM_SYSCON_TEST_CONF_REG) / 4) + 1)
const static sleep_retention_entries_config_t modem_regs_retention[] = {
[0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_MODEMSYSCON_LINK(0), MODEM_SYSCON_TEST_CONF_REG, MODEM_SYSCON_TEST_CONF_REG, N_REGS_SYSCON(), 0, 0), .owner = ENTRY(0) | ENTRY(1) }, /* MODEM SYSCON */
};
esp_err_t err = sleep_retention_entries_create(modem_regs_retention, ARRAY_SIZE(modem_regs_retention), REGDMA_LINK_PRI_MODEM_CLK, SLEEP_RETENTION_MODULE_CLOCK_MODEM);
ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for modem (SYSCON) retention, 1 level priority");
ESP_LOGI(TAG, "Modem Power, Clock and Reset sleep retention initialization");
return ESP_OK;
}
#endif
bool clock_domain_pd_allowed(void)
{
const uint32_t inited_modules = sleep_retention_get_inited_modules();
const uint32_t created_modules = sleep_retention_get_created_modules();
const uint32_t sys_clk_dep_modules = (const uint32_t) (BIT(SLEEP_RETENTION_MODULE_SYS_PERIPH));
/* The clock and reset of MODEM (WiFi, BLE and 15.4) modules are managed
* through MODEM_SYSCON, when one or more MODEMs are initialized, it is
* necessary to check the state of CLOCK_MODEM to determine MODEM domain on
* or off. The clock and reset of digital peripherals are managed through
* PCR, with TOP domain similar to MODEM domain. */
uint32_t modem_clk_dep_modules = 0;
#if SOC_WIFI_SUPPORTED
modem_clk_dep_modules |= BIT(SLEEP_RETENTION_MODULE_WIFI_MAC) | BIT(SLEEP_RETENTION_MODULE_WIFI_BB);
#endif
#if SOC_BT_SUPPORTED
modem_clk_dep_modules |= BIT(SLEEP_RETENTION_MODULE_BLE_MAC) | BIT(SLEEP_RETENTION_MODULE_BT_BB);
#endif
#if SOC_IEEE802154_SUPPORTED
modem_clk_dep_modules |= BIT(SLEEP_RETENTION_MODULE_802154_MAC) | BIT(SLEEP_RETENTION_MODULE_BT_BB);
#endif
uint32_t mask = 0;
if (inited_modules & sys_clk_dep_modules) {
mask |= BIT(SLEEP_RETENTION_MODULE_CLOCK_SYSTEM);
}
if (inited_modules & modem_clk_dep_modules) {
#if SOC_WIFI_SUPPORTED || SOC_BT_SUPPORTED || SOC_IEEE802154_SUPPORTED
mask |= BIT(SLEEP_RETENTION_MODULE_CLOCK_MODEM);
#endif
}
return ((inited_modules & mask) == (created_modules & mask));
}
ESP_SYSTEM_INIT_FN(sleep_clock_startup_init, SECONDARY, BIT(0), 106)
{
sleep_retention_module_init_param_t init_param = {
.cbs = { .create = { .handle = sleep_clock_system_retention_init, .arg = NULL } },
.attribute = SLEEP_RETENTION_MODULE_ATTR_PASSIVE
};
sleep_retention_module_init(SLEEP_RETENTION_MODULE_CLOCK_SYSTEM, &init_param);
#if CONFIG_MAC_BB_PD || CONFIG_BT_LE_SLEEP_ENABLE || CONFIG_IEEE802154_SLEEP_ENABLE
init_param = (sleep_retention_module_init_param_t) {
.cbs = { .create = { .handle = sleep_clock_modem_retention_init, .arg = NULL } },
.attribute = SLEEP_RETENTION_MODULE_ATTR_PASSIVE
};
sleep_retention_module_init(SLEEP_RETENTION_MODULE_CLOCK_MODEM, &init_param);
#endif
return ESP_OK;
}

View File

@ -0,0 +1,162 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stddef.h>
#include <string.h>
#include <inttypes.h>
#include "esp_attr.h"
#include "esp_check.h"
#include "esp_sleep.h"
#include "esp_log.h"
#include "esp_heap_caps.h"
#include "soc/soc_caps.h"
#include "sdkconfig.h"
#include "soc/spi_mem_reg.h"
#include "esp_private/startup_internal.h"
static const char *TAG = "sleep_mmu";
typedef struct {
uint32_t start;
uint32_t end;
} mmu_domain_dev_regs_region_t;
typedef struct {
mmu_domain_dev_regs_region_t *region;
int region_num;
uint32_t *regs_frame;
} mmu_domain_dev_sleep_frame_t;
/**
* Internal structure which holds all requested light sleep mmu retention parameters
*/
typedef struct {
struct {
mmu_domain_dev_sleep_frame_t *mmu_table_frame;
} retent;
} sleep_mmu_retention_t;
static DRAM_ATTR __attribute__((unused)) sleep_mmu_retention_t s_mmu_retention;
static void * mmu_domain_dev_sleep_frame_alloc_and_init(const mmu_domain_dev_regs_region_t *regions, const int region_num)
{
const int region_sz = sizeof(mmu_domain_dev_regs_region_t) * region_num;
int regs_frame_sz = 0;
for (int num = 0; num < region_num; num++) {
regs_frame_sz += regions[num].end - regions[num].start;
}
void *frame = heap_caps_malloc(sizeof(mmu_domain_dev_sleep_frame_t) + region_sz + regs_frame_sz, MALLOC_CAP_32BIT|MALLOC_CAP_INTERNAL);
if (frame) {
mmu_domain_dev_regs_region_t *region = (mmu_domain_dev_regs_region_t *)(frame + sizeof(mmu_domain_dev_sleep_frame_t));
memcpy(region, regions, region_num * sizeof(mmu_domain_dev_regs_region_t));
void *regs_frame = frame + sizeof(mmu_domain_dev_sleep_frame_t) + region_sz;
memset(regs_frame, 0, regs_frame_sz);
*(mmu_domain_dev_sleep_frame_t *)frame = (mmu_domain_dev_sleep_frame_t) {
.region = region,
.region_num = region_num,
.regs_frame = (uint32_t *)regs_frame
};
}
return frame;
}
static inline void * mmu_domain_mmu_table_sleep_frame_alloc_and_init(void)
{
#define MMU_TABLE_SIZE (512 * 4)
const static mmu_domain_dev_regs_region_t regions[] = {
{ .start = SPI_MEM_MMU_ITEM_CONTENT_REG(0), .end = SPI_MEM_MMU_ITEM_CONTENT_REG(0) + MMU_TABLE_SIZE}
};
return mmu_domain_dev_sleep_frame_alloc_and_init(regions, sizeof(regions) / sizeof(regions[0]));
}
static IRAM_ATTR void mmu_domain_dev_regs_save(mmu_domain_dev_sleep_frame_t *frame)
{
assert(frame);
mmu_domain_dev_regs_region_t *region = frame->region;
uint32_t *regs_frame = frame->regs_frame;
int offset = 0;
for (int i = 0; i < frame->region_num; i++) {
for (uint32_t addr = region[i].start; addr < region[i].end; addr+=4) {
REG_WRITE(SPI_MEM_MMU_ITEM_INDEX_REG(0), offset);
regs_frame[offset++] = REG_READ(SPI_MEM_MMU_ITEM_CONTENT_REG(0));
}
}
}
static IRAM_ATTR void mmu_domain_dev_regs_restore(mmu_domain_dev_sleep_frame_t *frame)
{
assert(frame);
mmu_domain_dev_regs_region_t *region = frame->region;
uint32_t *regs_frame = frame->regs_frame;
int offset = 0;
for (int i = 0; i < frame->region_num; i++) {
for (uint32_t addr = region[i].start; addr < region[i].end; addr+=4) {
REG_WRITE(SPI_MEM_MMU_ITEM_INDEX_REG(0), offset);
REG_WRITE(SPI_MEM_MMU_ITEM_CONTENT_REG(0),regs_frame[offset++]);
}
}
}
IRAM_ATTR void esp_sleep_mmu_retention(bool backup_or_restore)
{
if (backup_or_restore) {
mmu_domain_dev_regs_save(s_mmu_retention.retent.mmu_table_frame);
} else {
mmu_domain_dev_regs_restore(s_mmu_retention.retent.mmu_table_frame);
}
}
static esp_err_t esp_sleep_mmu_retention_deinit_impl(void)
{
if (s_mmu_retention.retent.mmu_table_frame) {
heap_caps_free((void *)s_mmu_retention.retent.mmu_table_frame);
s_mmu_retention.retent.mmu_table_frame = NULL;
}
return ESP_OK;
}
static esp_err_t esp_sleep_mmu_retention_init_impl(void)
{
if (s_mmu_retention.retent.mmu_table_frame == NULL) {
void *frame = mmu_domain_mmu_table_sleep_frame_alloc_and_init();
if (frame == NULL) {
goto err;
}
s_mmu_retention.retent.mmu_table_frame = (mmu_domain_dev_sleep_frame_t *)frame;
}
return ESP_OK;
err:
esp_sleep_mmu_retention_deinit();
return ESP_ERR_NO_MEM;
}
esp_err_t esp_sleep_mmu_retention_init(void)
{
return esp_sleep_mmu_retention_init_impl();
}
esp_err_t esp_sleep_mmu_retention_deinit(void)
{
return esp_sleep_mmu_retention_deinit_impl();
}
bool mmu_domain_pd_allowed(void)
{
return (s_mmu_retention.retent.mmu_table_frame != NULL);
}
ESP_SYSTEM_INIT_FN(sleep_mmu_startup_init, SECONDARY, BIT(0), 108)
{
esp_err_t ret;
ret = esp_sleep_mmu_retention_init();
if (ret != ESP_OK) {
ESP_EARLY_LOGW(TAG, "Failed to enable TOP power down during light sleep.");
}
return ESP_OK;
}

View File

@ -423,7 +423,7 @@ void modem_clock_select_lp_clock_source(periph_module_t module, modem_clock_lpcl
esp_sleep_pd_domain_t pd_domain = (esp_sleep_pd_domain_t) (
(last_src == MODEM_CLOCK_LPCLK_SRC_RC_FAST) ? ESP_PD_DOMAIN_RC_FAST :
(last_src == MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL) ? ESP_PD_DOMAIN_XTAL :
#if !SOC_CLK_RC32K_NOT_TO_USE
#if !CONFIG_ESP_CLK_RC32K_NOT_TO_USE
(last_src == MODEM_CLOCK_LPCLK_SRC_RC32K) ? ESP_PD_DOMAIN_RC32K :
#endif
(last_src == MODEM_CLOCK_LPCLK_SRC_XTAL32K) ? ESP_PD_DOMAIN_XTAL32K :
@ -431,7 +431,7 @@ void modem_clock_select_lp_clock_source(periph_module_t module, modem_clock_lpcl
esp_sleep_pd_domain_t pu_domain = (esp_sleep_pd_domain_t) (
(src == MODEM_CLOCK_LPCLK_SRC_RC_FAST) ? ESP_PD_DOMAIN_RC_FAST :
(src == MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL) ? ESP_PD_DOMAIN_XTAL :
#if !SOC_CLK_RC32K_NOT_TO_USE
#if !CONFIG_ESP_CLK_RC32K_NOT_TO_USE
(src == MODEM_CLOCK_LPCLK_SRC_RC32K) ? ESP_PD_DOMAIN_RC32K :
#endif
(src == MODEM_CLOCK_LPCLK_SRC_XTAL32K) ? ESP_PD_DOMAIN_XTAL32K :
@ -486,7 +486,7 @@ void modem_clock_deselect_lp_clock_source(periph_module_t module)
esp_sleep_pd_domain_t pd_domain = (esp_sleep_pd_domain_t) (
(last_src == MODEM_CLOCK_LPCLK_SRC_RC_FAST) ? ESP_PD_DOMAIN_RC_FAST :
(last_src == MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL) ? ESP_PD_DOMAIN_XTAL :
#if !SOC_CLK_RC32K_NOT_TO_USE
#if !CONFIG_ESP_CLK_RC32K_NOT_TO_USE
(last_src == MODEM_CLOCK_LPCLK_SRC_RC32K) ? ESP_PD_DOMAIN_RC32K :
#endif
(last_src == MODEM_CLOCK_LPCLK_SRC_XTAL32K) ? ESP_PD_DOMAIN_XTAL32K :

View File

@ -17,7 +17,7 @@ if(NOT BOOTLOADER_BUILD)
endif()
# TODO: [ESP32C61] IDF-9250
# TODO: [ESP32C61] IDF-9304
if(CONFIG_IDF_TARGET_ESP32C61)
list(REMOVE_ITEM srcs
"sar_periph_ctrl.c"

View File

@ -10,8 +10,6 @@
extern "C" {
#endif
// TODO: IDF-9247
#define PMU_EXT0_WAKEUP_EN BIT(0)
#define PMU_EXT1_WAKEUP_EN BIT(1)
#define PMU_GPIO_WAKEUP_EN BIT(2)

View File

@ -476,12 +476,12 @@ typedef struct pmu_sleep_machine_constant {
.reset_wait_time_us = 1, \
.power_supply_wait_time_us = 20, \
.power_up_wait_time_us = 2, \
.regdma_s2m_work_time_us = 172, \
.regdma_s2a_work_time_us = 480, \
.regdma_m2a_work_time_us = 278, \
.regdma_a2s_work_time_us = 382, \
.regdma_rf_on_work_time_us = 70, \
.regdma_rf_off_work_time_us = 23, \
.regdma_s2m_work_time_us = 270, \
.regdma_s2a_work_time_us = 666, \
.regdma_m2a_work_time_us = 296, \
.regdma_a2s_work_time_us = 586, \
.regdma_rf_on_work_time_us = 138, \
.regdma_rf_off_work_time_us = 28, \
.xtal_wait_stable_time_us = 250, \
.pll_wait_stable_time_us = 1 \
} \

View File

@ -157,8 +157,8 @@
#define DEFAULT_SLEEP_OUT_OVERHEAD_US (318)
#define DEFAULT_HARDWARE_OUT_OVERHEAD_US (56)
#elif CONFIG_IDF_TARGET_ESP32C61
#define DEFAULT_SLEEP_OUT_OVERHEAD_US (318)
#define DEFAULT_HARDWARE_OUT_OVERHEAD_US (56)
#define DEFAULT_SLEEP_OUT_OVERHEAD_US (1148) //TODO: PM-231
#define DEFAULT_HARDWARE_OUT_OVERHEAD_US (107)
#elif CONFIG_IDF_TARGET_ESP32H2
#define DEFAULT_SLEEP_OUT_OVERHEAD_US (118)
#define DEFAULT_HARDWARE_OUT_OVERHEAD_US (9)
@ -189,8 +189,12 @@
#endif
#if SOC_PM_MMU_TABLE_RETENTION_WHEN_TOP_PD
#if CONFIG_IDF_TARGET_ESP32C61
#define SLEEP_MMU_TABLE_RETENTION_OVERHEAD_US (1232)
#elif CONFIG_IDF_TARGET_ESP32C5
#define SLEEP_MMU_TABLE_RETENTION_OVERHEAD_US (1220)
#endif
#endif
// Minimal amount of time we can sleep for
#define LIGHT_SLEEP_MIN_TIME_US 200
@ -705,7 +709,7 @@ FORCE_INLINE_ATTR void misc_modules_wake_prepare(uint32_t pd_flags)
#if SOC_USB_SERIAL_JTAG_SUPPORTED && !SOC_USB_SERIAL_JTAG_SUPPORT_LIGHT_SLEEP
sleep_console_usj_pad_restore();
#endif
#if !CONFIG_IDF_TARGET_ESP32C61
#if !CONFIG_IDF_TARGET_ESP32C61 // TODO: IDF-9304
sar_periph_ctrl_power_enable();
#endif
#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP && SOC_PM_CPU_RETENTION_BY_RTCCNTL
@ -2359,7 +2363,7 @@ static uint32_t get_power_down_flags(void)
}
#endif
#if SOC_PM_SUPPORT_RC32K_PD
#if !SOC_CLK_RC32K_NOT_TO_USE
#if !CONFIG_ESP_CLK_RC32K_NOT_TO_USE
if (s_config.domain[ESP_PD_DOMAIN_RC32K].pd_option != ESP_PD_OPTION_ON) {
pd_flags |= PMU_SLEEP_PD_RC32K;
}

View File

@ -82,10 +82,12 @@ SECONDARY: 103: esp_security_init in components/esp_security/src/init.c on BIT(0
SECONDARY: 105: esp_sleep_startup_init in components/esp_hw_support/sleep_gpio.c on BIT(0)
SECONDARY: 106: sleep_clock_startup_init in components/esp_hw_support/lowpower/port/esp32c5/sleep_clock.c on BIT(0)
SECONDARY: 106: sleep_clock_startup_init in components/esp_hw_support/lowpower/port/esp32c6/sleep_clock.c on BIT(0)
SECONDARY: 106: sleep_clock_startup_init in components/esp_hw_support/lowpower/port/esp32c61/sleep_clock.c on BIT(0)
SECONDARY: 106: sleep_clock_startup_init in components/esp_hw_support/lowpower/port/esp32h2/sleep_clock.c on BIT(0)
SECONDARY: 106: sleep_clock_startup_init in components/esp_hw_support/lowpower/port/esp32p4/sleep_clock.c on BIT(0)
SECONDARY: 107: sleep_sys_periph_startup_init in components/esp_hw_support/sleep_system_peripheral.c on BIT(0)
SECONDARY: 108: sleep_mmu_startup_init in components/esp_hw_support/lowpower/port/esp32c5/sleep_mmu.c on BIT(0)
SECONDARY: 108: sleep_mmu_startup_init in components/esp_hw_support/lowpower/port/esp32c61/sleep_mmu.c on BIT(0)
# app_trace has to be initialized before systemview
SECONDARY: 115: esp_apptrace_init in components/app_trace/app_trace.c on ESP_SYSTEM_INIT_ALL_CORES

View File

@ -0,0 +1,172 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
// The LL layer for ESP32-C61 PAU(Power Assist Unit) register operations
#pragma once
#include <stdlib.h>
#include <stdbool.h>
#include "soc/soc.h"
#include "soc/pau_reg.h"
#include "soc/pau_struct.h"
#include "soc/pcr_struct.h"
#include "hal/pau_types.h"
#include "hal/assert.h"
#ifdef __cplusplus
extern "C" {
#endif
static inline void pau_ll_enable_bus_clock(bool enable)
{
if (enable) {
PCR.regdma_conf.regdma_clk_en = 1;
PCR.regdma_conf.regdma_rst_en = 0;
} else {
PCR.regdma_conf.regdma_clk_en = 0;
PCR.regdma_conf.regdma_rst_en = 1;
}
}
static inline uint32_t pau_ll_get_regdma_backup_flow_error(pau_dev_t *dev)
{
return dev->regdma_conf.flow_err;
}
static inline void pau_ll_select_regdma_entry_link(pau_dev_t *dev, int link)
{
dev->regdma_conf.link_sel = link;
}
static inline void pau_ll_set_regdma_entry_link_backup_direction(pau_dev_t *dev, bool to_mem)
{
dev->regdma_conf.to_mem = to_mem ? 1 : 0;
}
static inline void pau_ll_set_regdma_entry_link_backup_start_enable(pau_dev_t *dev)
{
dev->regdma_conf.start = 1;
}
static inline void pau_ll_set_regdma_entry_link_backup_start_disable(pau_dev_t *dev)
{
dev->regdma_conf.start = 0;
}
static inline void pau_ll_set_regdma_select_wifimac_link(pau_dev_t *dev)
{
dev->regdma_conf.sel_mac = 1;
}
static inline void pau_ll_set_regdma_deselect_wifimac_link(pau_dev_t *dev)
{
dev->regdma_conf.sel_mac = 0;
}
static inline void pau_ll_set_regdma_wifimac_link_backup_direction(pau_dev_t *dev, bool to_mem)
{
dev->regdma_conf.to_mem_mac = to_mem ? 1 : 0;
}
static inline void pau_ll_set_regdma_wifimac_link_backup_start_enable(pau_dev_t *dev)
{
dev->regdma_conf.start_mac = 1;
}
static inline void pau_ll_set_regdma_wifimac_link_backup_start_disable(pau_dev_t *dev)
{
dev->regdma_conf.start_mac = 0;
}
static inline void pau_ll_set_regdma_link0_addr(pau_dev_t *dev, void *link_addr)
{
dev->regdma_link_0_addr.val = (uint32_t)link_addr;
}
static inline void pau_ll_set_regdma_link1_addr(pau_dev_t *dev, void *link_addr)
{
dev->regdma_link_1_addr.val = (uint32_t)link_addr;
}
static inline void pau_ll_set_regdma_link2_addr(pau_dev_t *dev, void *link_addr)
{
dev->regdma_link_2_addr.val = (uint32_t)link_addr;
}
static inline void pau_ll_set_regdma_link3_addr(pau_dev_t *dev, void *link_addr)
{
dev->regdma_link_3_addr.val = (uint32_t)link_addr;
}
static inline void pau_ll_set_regdma_wifimac_link_addr(pau_dev_t *dev, void *link_addr)
{
dev->regdma_link_mac_addr.val = (uint32_t)link_addr;
}
static inline uint32_t pau_ll_get_regdma_current_link_addr(pau_dev_t *dev)
{
return dev->regdma_current_link_addr.val;
}
static inline uint32_t pau_ll_get_regdma_backup_addr(pau_dev_t *dev)
{
return dev->regdma_backup_addr.val;
}
static inline uint32_t pau_ll_get_regdma_memory_addr(pau_dev_t *dev)
{
return dev->regdma_mem_addr.val;
}
static inline uint32_t pau_ll_get_regdma_intr_raw_signal(pau_dev_t *dev)
{
return dev->int_raw.val;
}
static inline uint32_t pau_ll_get_regdma_intr_status(pau_dev_t *dev)
{
return dev->int_st.val;
}
static inline void pau_ll_set_regdma_backup_done_intr_enable(pau_dev_t *dev)
{
dev->int_ena.done_int_ena = 1;
}
static inline void pau_ll_set_regdma_backup_done_intr_disable(pau_dev_t *dev)
{
dev->int_ena.done_int_ena = 0;
}
static inline void pau_ll_set_regdma_backup_error_intr_enable(pau_dev_t *dev, bool enable)
{
dev->int_ena.error_int_ena = enable;
}
static inline void pau_ll_clear_regdma_backup_done_intr_state(pau_dev_t *dev)
{
dev->int_clr.done_int_clr = 1;
}
static inline void pau_ll_clear_regdma_backup_error_intr_state(pau_dev_t *dev)
{
dev->int_clr.error_int_clr = 1;
}
static inline void pau_ll_set_regdma_link_wait_retry_count(pau_dev_t *dev, int count)
{
dev->regdma_bkp_conf.link_tout_thres = count;
}
static inline void pau_ll_set_regdma_link_wait_read_interval(pau_dev_t *dev, int interval)
{
dev->regdma_bkp_conf.read_interval = interval;
}
#ifdef __cplusplus
}
#endif

View File

@ -24,6 +24,7 @@ extern "C" {
// Get timer group register base address with giving group number
#define TIMER_LL_GET_HW(group_id) ((group_id == 0) ? (&TIMERG0) : (&TIMERG1))
#define TIMER_LL_EVENT_ALARM(timer_id) (1 << (timer_id))
#define TIMER_LL_SLEEP_RETENTION_MODULE_ID(group_id) ((group_id == 0) ? SLEEP_RETENTION_MODULE_TG0_TIMER: SLEEP_RETENTION_MODULE_TG1_TIMER)
#define TIMER_LL_ETM_TASK_TABLE(group, timer, task) \
(uint32_t [2][1][GPTIMER_ETM_TASK_MAX]){{{ \

View File

@ -64,6 +64,10 @@ extern "C" {
((hw) == &UART1) ? PCR.uart1_##reg_suffix.uart1_##field_suffix : \
PCR.uart2_##reg_suffix.uart2_##field_suffix)
// UART sleep retention module
#define UART_LL_SLEEP_RETENTION_MODULE_ID(uart_num) ((uart_num == UART_NUM_0) ? SLEEP_RETENTION_MODULE_UART0 : \
(uart_num == UART_NUM_1) ? SLEEP_RETENTION_MODULE_UART1 : -1)
// Define UART interrupts
typedef enum {
UART_INTR_RXFIFO_FULL = (0x1 << 0),

View File

@ -4,8 +4,6 @@
* SPDX-License-Identifier: Apache-2.0
*/
// The HAL layer for PAU (ESP32-C61 specific part)
#include "soc/soc.h"
#include "esp_attr.h"
#include "hal/pau_hal.h"
@ -59,3 +57,14 @@ void IRAM_ATTR pau_hal_stop_regdma_extra_link(pau_hal_context_t *hal)
pau_ll_select_regdma_entry_link(hal->dev, 0); /* restore link select to default */
pau_ll_clear_regdma_backup_done_intr_state(hal->dev);
}
void pau_hal_set_regdma_work_timeout(pau_hal_context_t *hal, uint32_t loop_num, uint32_t time)
{
}
void pau_hal_set_regdma_wait_timeout(pau_hal_context_t *hal, int count, int interval)
{
HAL_ASSERT(count > 0 && interval > 0);
pau_ll_set_regdma_link_wait_retry_count(hal->dev, count);
pau_ll_set_regdma_link_wait_read_interval(hal->dev, interval);
}

View File

@ -4,7 +4,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
// The LL layer for ESP32-C6 PAU(Power Assist Unit) register operations
// The LL layer for ESP32-P4 PAU(Power Assist Unit) register operations
#pragma once

View File

@ -1359,10 +1359,6 @@ config SOC_CLK_LP_FAST_SUPPORT_XTAL
bool
default y
config SOC_CLK_RC32K_NOT_TO_USE
bool
default y
config SOC_RCC_IS_INDEPENDENT
bool
default y

View File

@ -579,7 +579,6 @@
#define SOC_CLK_XTAL32K_SUPPORTED (1) /*!< Support to connect an external low frequency crystal */
#define SOC_CLK_OSC_SLOW_SUPPORTED (1) /*!< Support to connect an external oscillator, not a crystal */
#define SOC_CLK_LP_FAST_SUPPORT_XTAL (1) /*!< Support XTAL clock as the LP_FAST clock source */
#define SOC_CLK_RC32K_NOT_TO_USE (1) /*!< Due to the poor low-temperature characteristics of RC32K (it cannot operate below -40 degrees Celsius), please avoid using it whenever possible. */
#define SOC_RCC_IS_INDEPENDENT 1 /*!< Reset and Clock Control is independent, thanks to the PCR registers */
/*-------------------------- Temperature Sensor CAPS -------------------------------------*/

View File

@ -131,6 +131,10 @@ config SOC_REG_I2C_SUPPORTED
bool
default y
config SOC_PAU_SUPPORTED
bool
default y
config SOC_LIGHT_SLEEP_SUPPORTED
bool
default y
@ -671,6 +675,14 @@ config SOC_TIMER_GROUP_SUPPORT_RC_FAST
bool
default y
config SOC_TIMER_SUPPORT_SLEEP_RETENTION
bool
default y
config SOC_MWDT_SUPPORT_SLEEP_RETENTION
bool
default y
config SOC_EFUSE_DIS_DOWNLOAD_ICACHE
bool
default n
@ -771,6 +783,10 @@ config SOC_UART_SUPPORT_WAKEUP_INT
bool
default y
config SOC_UART_SUPPORT_SLEEP_RETENTION
bool
default y
config SOC_UART_SUPPORT_FSM_TX_WAIT_SEND
bool
default y
@ -827,6 +843,10 @@ config SOC_PM_SUPPORT_VDDSDIO_PD
bool
default y
config SOC_PM_SUPPORT_TOP_PD
bool
default y
config SOC_PM_SUPPORT_HP_AON_PD
bool
default y
@ -849,16 +869,32 @@ config SOC_PM_CPU_RETENTION_BY_SW
config SOC_PM_MODEM_RETENTION_BY_REGDMA
bool
default n
default y
config SOC_EXT_MEM_CACHE_TAG_IN_CPU_DOMAIN
bool
default y
config SOC_PM_MMU_TABLE_RETENTION_WHEN_TOP_PD
bool
default y
config SOC_PM_PAU_LINK_NUM
int
default 4
config SOC_PM_PAU_REGDMA_LINK_MULTI_ADDR
bool
default y
config SOC_PM_PAU_REGDMA_LINK_WIFIMAC
bool
default y
config SOC_PM_PAU_REGDMA_UPDATE_CACHE_BEFORE_WAIT_COMPARE
bool
default y
config SOC_CLK_RC_FAST_SUPPORT_CALIBRATION
bool
default y
@ -879,10 +915,6 @@ config SOC_CLK_LP_FAST_SUPPORT_XTAL
bool
default y
config SOC_CLK_RC32K_NOT_TO_USE
bool
default y
config SOC_RCC_IS_INDEPENDENT
bool
default y

View File

@ -35,7 +35,7 @@
#define DR_REG_PAU_BASE 0x60093000
#define DR_REG_HP_SYSTEM_BASE 0x60095000
#define DR_REG_PCR_BASE 0x60096000
#define DR_REG_TEE_REG_BASE 0x60098000
#define DR_REG_TEE_BASE 0x60098000
#define DR_REG_HP_APM_BASE 0x60099000
#define DR_REG_MISC_BASE 0x6009F000
#define DR_REG_MODEM0_BASE 0x600A0000
@ -61,4 +61,3 @@
#define DR_REG_INTPRI_BASE 0x600C5000
#define DR_REG_CACHE_BASE 0x600C8000
#define DR_REG_CLINT_M_BASE 0x20000000
#define DR_REG_TEE_BASE DR_REG_TEE_REG_BASE

View File

@ -18,23 +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_GDMA_CH0 = 24,
SLEEP_RETENTION_MODULE_GDMA_CH1 = 25,
SLEEP_RETENTION_MODULE_GDMA_CH2 = 26,
SLEEP_RETENTION_MODULE_I2C0 = 27,
* TEE, APM, 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_I2C0 = 12,
SLEEP_RETENTION_MODULE_UART0 = 14,
SLEEP_RETENTION_MODULE_UART1 = 15,
/* Modem module, which includes WiFi, BLE and 802.15.4 */
SLEEP_RETENTION_MODULE_WIFI_MAC = 26,
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;
@ -42,26 +48,44 @@ 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, 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_I2C0 = BIT(SLEEP_RETENTION_MODULE_I2C0),
SLEEP_RETENTION_MODULE_BM_UART0 = BIT(SLEEP_RETENTION_MODULE_UART0),
SLEEP_RETENTION_MODULE_BM_UART1 = BIT(SLEEP_RETENTION_MODULE_UART1),
/* modem module, which includes WiFi, BLE and 802.15.4 */
SLEEP_RETENTION_MODULE_BM_WIFI_MAC = BIT(SLEEP_RETENTION_MODULE_WIFI_MAC),
SLEEP_RETENTION_MODULE_BM_WIFI_BB = BIT(SLEEP_RETENTION_MODULE_WIFI_BB),
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_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_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_I2C0 \
| SLEEP_RETENTION_MODULE_BM_UART0 \
| SLEEP_RETENTION_MODULE_BM_UART1 \
)
#ifdef __cplusplus
}
#endif

View File

@ -59,7 +59,7 @@
#define SOC_REG_I2C_SUPPORTED 1
// \#define SOC_ETM_SUPPORTED 0
// \#define SOC_SDIO_SLAVE_SUPPORTED 0
// \#define SOC_PAU_SUPPORTED 0
#define SOC_PAU_SUPPORTED 1
#define SOC_LIGHT_SLEEP_SUPPORTED 1
#define SOC_DEEP_SLEEP_SUPPORTED 1
#define SOC_PM_SUPPORTED 1
@ -349,10 +349,12 @@
#define SOC_TIMER_GROUP_COUNTER_BIT_WIDTH (54)
#define SOC_TIMER_GROUP_SUPPORT_XTAL (1)
#define SOC_TIMER_GROUP_SUPPORT_RC_FAST (1)
#define SOC_TIMER_SUPPORT_SLEEP_RETENTION (1)
// #define SOC_TIMER_SUPPORT_ETM (1)
/*--------------------------- WATCHDOG CAPS ---------------------------------------*/
// #define SOC_MWDT_SUPPORT_XTAL (1)
#define SOC_MWDT_SUPPORT_SLEEP_RETENTION (1)
/*-------------------------- eFuse CAPS----------------------------*/
#define SOC_EFUSE_DIS_DOWNLOAD_ICACHE 0
@ -391,7 +393,7 @@
#define SOC_UART_SUPPORT_RTC_CLK (1) /*!< Support RTC clock as the clock source */
#define SOC_UART_SUPPORT_XTAL_CLK (1) /*!< Support XTAL clock as the clock source */
#define SOC_UART_SUPPORT_WAKEUP_INT (1) /*!< Support UART wakeup interrupt */
#define SOC_UART_SUPPORT_SLEEP_RETENTION (1)
// UART has an extra TX_WAIT_SEND state when the FIFO is not empty and XOFF is enabled
#define SOC_UART_SUPPORT_FSM_TX_WAIT_SEND (1)
@ -423,7 +425,7 @@
#define SOC_PM_SUPPORT_RC32K_PD (1)
#define SOC_PM_SUPPORT_RC_FAST_PD (1)
#define SOC_PM_SUPPORT_VDDSDIO_PD (1)
// \#define SOC_PM_SUPPORT_TOP_PD (1)
#define SOC_PM_SUPPORT_TOP_PD (1)
#define SOC_PM_SUPPORT_HP_AON_PD (1)
#define SOC_PM_SUPPORT_MAC_BB_PD (1)
#define SOC_PM_SUPPORT_RTC_PERIPH_PD (1)
@ -433,9 +435,15 @@
#define MAC_SUPPORT_PMU_MODEM_STATE SOC_PM_SUPPORT_PMU_MODEM_STATE
#define SOC_PM_CPU_RETENTION_BY_SW (1)
#define SOC_PM_MODEM_RETENTION_BY_REGDMA (0)
#define SOC_PM_MODEM_RETENTION_BY_REGDMA (1)
#define SOC_EXT_MEM_CACHE_TAG_IN_CPU_DOMAIN (1)
#define SOC_PM_MMU_TABLE_RETENTION_WHEN_TOP_PD (1)
#define SOC_PM_PAU_LINK_NUM (4)
#define SOC_PM_PAU_REGDMA_LINK_MULTI_ADDR (1)
#define SOC_PM_PAU_REGDMA_LINK_WIFIMAC (1)
#define SOC_PM_PAU_REGDMA_UPDATE_CACHE_BEFORE_WAIT_COMPARE (1)
/*-------------------------- CLOCK SUBSYSTEM CAPS ----------------------------------------*/
#define SOC_CLK_RC_FAST_SUPPORT_CALIBRATION (1)
@ -444,7 +452,6 @@
#define SOC_CLK_XTAL32K_SUPPORTED (1) /*!< Support to connect an external low frequency crystal */
#define SOC_CLK_OSC_SLOW_SUPPORTED (1) /*!< Support to connect an external oscillator, not a crystal */
#define SOC_CLK_LP_FAST_SUPPORT_XTAL (1) /*!< Support XTAL clock as the LP_FAST clock source */
#define SOC_CLK_RC32K_NOT_TO_USE (1) /*!< Due to the poor low-temperature characteristics of RC32K (it cannot operate below -40 degrees Celsius), please avoid using it whenever possible. */
#define SOC_RCC_IS_INDEPENDENT 1 /*!< Reset and Clock Control is independent, thanks to the PCR registers */
/*-------------------------- Temperature Sensor CAPS -------------------------------------*/

View File

@ -0,0 +1,82 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#include "soc/soc_caps.h"
#include "soc/regdma.h"
#ifdef __cplusplus
extern "C"
{
#endif
/**
* @brief Provide access to interrupt matrix configuration registers retention
* context definition.
*
* This is an internal function of the sleep retention driver, and is not
* useful for external use.
*/
#define INT_MTX_RETENTION_LINK_LEN 1
extern const regdma_entries_config_t intr_matrix_regs_retention[INT_MTX_RETENTION_LINK_LEN];
/**
* @brief Provide access to hp_system configuration registers retention
* context definition.
*
* This is an internal function of the sleep retention driver, and is not
* useful for external use.
*/
#define HP_SYSTEM_RETENTION_LINK_LEN 1
extern const regdma_entries_config_t hp_system_regs_retention[HP_SYSTEM_RETENTION_LINK_LEN];
/**
* @brief Provide access to TEE_APM configuration registers retention
* context definition.
*
* This is an internal function of the sleep retention driver, and is not
* useful for external use.
*/
#define TEE_APM_RETENTION_LINK_LEN 2
extern const regdma_entries_config_t tee_apm_regs_retention[TEE_APM_RETENTION_LINK_LEN];
#define TEE_APM_HIGH_PRI_RETENTION_LINK_LEN 1
extern const regdma_entries_config_t tee_apm_highpri_regs_retention[TEE_APM_HIGH_PRI_RETENTION_LINK_LEN];
/**
* @brief Provide access to IOMUX configuration registers retention
* context definition.
*
* This is an internal function of the sleep retention driver, and is not
* useful for external use.
*/
#define IOMUX_RETENTION_LINK_LEN 7
extern const regdma_entries_config_t iomux_regs_retention[IOMUX_RETENTION_LINK_LEN];
/**
* @brief Provide access to spimem configuration registers retention
* context definition.
*
* This is an internal function of the sleep retention driver, and is not
* useful for external use.
*/
#define SPIMEM_RETENTION_LINK_LEN 8
extern const regdma_entries_config_t flash_spimem_regs_retention[SPIMEM_RETENTION_LINK_LEN];
/**
* @brief Provide access to systimer configuration registers retention
* context definition.
*
* This is an internal function of the sleep retention driver, and is not
* useful for external use.
*/
#define SYSTIMER_RETENTION_LINK_LEN 19
extern const regdma_entries_config_t systimer_regs_retention[SYSTIMER_RETENTION_LINK_LEN];
#ifdef __cplusplus
}
#endif

View File

@ -769,9 +769,9 @@ extern "C" {
* Version control register
*/
#define TEE_DATE 0x0FFFFFFFU
#define TEE_DATE_REG_M (TEE_DATE_REG_V << TEE_DATE_REG_S)
#define TEE_DATE_REG_V 0x0FFFFFFFU
#define TEE_DATE_REG_S 0
#define TEE_DATE_M (TEE_DATE_REG_V << TEE_DATE_REG_S)
#define TEE_DATE_V 0x0FFFFFFFU
#define TEE_DATE_S 0
#ifdef __cplusplus
}

View File

@ -0,0 +1,121 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "soc/regdma.h"
#include "soc/system_periph_retention.h"
#include "soc/timer_periph.h"
#include "soc/uart_reg.h"
#include "soc/systimer_reg.h"
#include "soc/timer_group_reg.h"
#include "soc/spi_mem_reg.h"
#include "soc/hp_system_reg.h"
#include "soc/tee_reg.h"
#include "soc/hp_apm_reg.h"
#include "soc/gpio_reg.h"
#include "soc/io_mux_reg.h"
#include "soc/interrupt_matrix_reg.h"
/* Interrupt Matrix Registers Context */
#define N_REGS_INTR_MATRIX() (((INTERRUPT_CORE0_CLOCK_GATE_REG - DR_REG_INTERRUPT_CORE0_BASE) / 4) + 1)
const regdma_entries_config_t intr_matrix_regs_retention[] = {
[0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_INTMTX_LINK(0), DR_REG_INTERRUPT_CORE0_BASE, DR_REG_INTERRUPT_CORE0_BASE, N_REGS_INTR_MATRIX(), 0, 0), .owner = ENTRY(0) | ENTRY(2) } /* intr matrix */
};
_Static_assert(ARRAY_SIZE(intr_matrix_regs_retention) == INT_MTX_RETENTION_LINK_LEN, "Inconsistent INT_MTX retention link length definitions");
/* HP System Registers Context */
#define N_REGS_HP_SYSTEM() (((HP_SYSTEM_CLOCK_GATE_REG - DR_REG_HP_SYSTEM_BASE) / 4) + 1)
const regdma_entries_config_t hp_system_regs_retention[] = {
[0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_HPSYS_LINK(0), DR_REG_HP_SYSTEM_BASE, DR_REG_HP_SYSTEM_BASE, N_REGS_HP_SYSTEM(), 0, 0), .owner = ENTRY(0) | ENTRY(2) } /* hp system */
};
_Static_assert(ARRAY_SIZE(hp_system_regs_retention) == HP_SYSTEM_RETENTION_LINK_LEN, "Inconsistent HP_SYSTEM retention link length definitions");
/* TEE/APM Registers Context */
#define N_REGS_TEE() (((TEE_CLOCK_GATE_REG - DR_REG_TEE_BASE) / 4) + 1)
#define N_REGS_APM() (((HP_APM_CLOCK_GATE_REG - DR_REG_HP_APM_BASE) / 4) + 1)
const regdma_entries_config_t tee_apm_regs_retention[] = {
[0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TEEAPM_LINK(0), DR_REG_HP_APM_BASE, DR_REG_HP_APM_BASE, N_REGS_APM(), 0, 0), .owner = ENTRY(0) | ENTRY(2) }, /* apm */
[1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TEEAPM_LINK(1), DR_REG_TEE_BASE, DR_REG_TEE_BASE, N_REGS_TEE(), 0, 0), .owner = ENTRY(0) | ENTRY(2) } /* tee */
};
const regdma_entries_config_t tee_apm_highpri_regs_retention[] = {
[0] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_TEEAPM_LINK(2), TEE_M4_MODE_CTRL_REG, 0x0, 0xffffffff, 1, 0), .owner = ENTRY(2) }
};
_Static_assert((ARRAY_SIZE(tee_apm_regs_retention) == TEE_APM_RETENTION_LINK_LEN) && (ARRAY_SIZE(tee_apm_highpri_regs_retention) == TEE_APM_HIGH_PRI_RETENTION_LINK_LEN), "Inconsistent TEE_APM retention link length definitions");
/* IO MUX Registers Context */
#define N_REGS_IOMUX_0() (((PERIPHS_IO_MUX_U_PAD_SPID - REG_IO_MUX_BASE) / 4) + 1)
#define N_REGS_IOMUX_1() (((GPIO_FUNC21_OUT_SEL_CFG_REG - GPIO_FUNC0_OUT_SEL_CFG_REG) / 4) + 1)
#define N_REGS_IOMUX_2() (((GPIO_FUNC121_IN_SEL_CFG_REG - GPIO_FUNC0_IN_SEL_CFG_REG) / 4) + 1)
#define N_REGS_IOMUX_3() (((GPIO_PIN21_REG - GPIO_PIN0_REG) / 4) + 1)
#define N_REGS_IOMUX_4() (1)
#define N_REGS_IOMUX_5() (1)
#define N_REGS_IOMUX_6() (1)
const regdma_entries_config_t iomux_regs_retention[] = {
[0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x00), REG_IO_MUX_BASE, REG_IO_MUX_BASE, N_REGS_IOMUX_0(), 0, 0), .owner = ENTRY(0) | ENTRY(2) }, /* io_mux */
[1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x01), GPIO_FUNC0_OUT_SEL_CFG_REG, GPIO_FUNC0_OUT_SEL_CFG_REG, N_REGS_IOMUX_1(), 0, 0), .owner = ENTRY(0) | ENTRY(2) },
[2] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x02), GPIO_FUNC0_IN_SEL_CFG_REG, GPIO_FUNC0_IN_SEL_CFG_REG, N_REGS_IOMUX_2(), 0, 0), .owner = ENTRY(0) | ENTRY(2) },
[3] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x03), GPIO_PIN0_REG, GPIO_PIN0_REG, N_REGS_IOMUX_3(), 0, 0), .owner = ENTRY(0) | ENTRY(2) },
[4] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x04), GPIO_STATUS_REG, GPIO_STATUS_REG, N_REGS_IOMUX_4(), 0, 0), .owner = ENTRY(0) | ENTRY(2) },
[5] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x05), GPIO_ENABLE_REG, GPIO_ENABLE_REG, N_REGS_IOMUX_5(), 0, 0), .owner = ENTRY(0) | ENTRY(2) },
[6] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x06), GPIO_OUT_REG, GPIO_OUT_REG, N_REGS_IOMUX_6(), 0, 0), .owner = ENTRY(0) | ENTRY(2) }
};
_Static_assert(ARRAY_SIZE(iomux_regs_retention) == IOMUX_RETENTION_LINK_LEN, "Inconsistent IOMUX retention link length definitions");
/* Memory SPI Registers Context */
#define N_REGS_SPI1_MEM_0() (((SPI_SMEM_DDR_REG(1) - REG_SPI_MEM_BASE(1)) / 4) + 1)
#define N_REGS_SPI1_MEM_1() (1)
#define N_REGS_SPI1_MEM_2() (1)
#define N_REGS_SPI0_MEM_0() (((SPI_SMEM_DDR_REG(0) - REG_SPI_MEM_BASE(0)) / 4) + 1)
#define N_REGS_SPI0_MEM_1() (((SPI_SMEM_AC_REG(0) - SPI_FMEM_PMS0_ATTR_REG(0)) / 4) + 1)
#define N_REGS_SPI0_MEM_2() (1)
#define N_REGS_SPI0_MEM_3() (((SPI_MEM_XTS_PSEUDO_ROUND_CONF_REG(0) - SPI_MEM_MMU_POWER_CTRL_REG(0)) / 4) + 1)
const regdma_entries_config_t flash_spimem_regs_retention[] = {
/* Note: SPI mem should not to write mmu SPI_MEM_MMU_ITEM_CONTENT_REG and SPI_MEM_MMU_ITEM_INDEX_REG */
[0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x00), REG_SPI_MEM_BASE(1), REG_SPI_MEM_BASE(1), N_REGS_SPI1_MEM_0(), 0, 0), .owner = ENTRY(0) | ENTRY(2) }, /* spi1_mem */
[1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x01), SPI_MEM_TIMING_CALI_REG(1), SPI_MEM_TIMING_CALI_REG(1), N_REGS_SPI1_MEM_1(), 0, 0), .owner = ENTRY(0) | ENTRY(2) },
[2] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x02), SPI_MEM_CLOCK_GATE_REG(1), SPI_MEM_CLOCK_GATE_REG(1), N_REGS_SPI1_MEM_2(), 0, 0), .owner = ENTRY(0) | ENTRY(2) },
/* Note: SPI mem should not to write mmu SPI_MEM_MMU_ITEM_CONTENT_REG and SPI_MEM_MMU_ITEM_INDEX_REG */
[3] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x03), REG_SPI_MEM_BASE(0), REG_SPI_MEM_BASE(0), N_REGS_SPI0_MEM_0(), 0, 0), .owner = ENTRY(0) | ENTRY(2) }, /* spi0_mem */
[4] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x04), SPI_FMEM_PMS0_ATTR_REG(0), SPI_FMEM_PMS0_ATTR_REG(0), N_REGS_SPI0_MEM_1(), 0, 0), .owner = ENTRY(0) | ENTRY(2) },
[5] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x05), SPI_MEM_CLOCK_GATE_REG(0), SPI_MEM_CLOCK_GATE_REG(0), N_REGS_SPI0_MEM_2(), 0, 0), .owner = ENTRY(0) | ENTRY(2) },
[6] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x06), SPI_MEM_MMU_POWER_CTRL_REG(0), SPI_MEM_MMU_POWER_CTRL_REG(0), N_REGS_SPI0_MEM_3(), 0, 0), .owner = ENTRY(0) | ENTRY(2) },
/* Note: spimem register should set update reg to make the configuration take effect */
[7] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_SPIMEM_LINK(0x07), SPI_MEM_TIMING_CALI_REG(0), SPI_MEM_TIMING_CALI_UPDATE, SPI_MEM_TIMING_CALI_UPDATE_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }
};
_Static_assert(ARRAY_SIZE(flash_spimem_regs_retention) == SPIMEM_RETENTION_LINK_LEN, "Inconsistent SPI Mem retention link length definitions");
/* Systimer Registers Context */
#define N_REGS_SYSTIMER_0() (((SYSTIMER_TARGET2_CONF_REG - SYSTIMER_TARGET0_HI_REG) / 4) + 1)
const regdma_entries_config_t systimer_regs_retention[] = {
[0] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_SYSTIMER_LINK(0x00), SYSTIMER_UNIT0_OP_REG, SYSTIMER_TIMER_UNIT0_UPDATE_M, SYSTIMER_TIMER_UNIT0_UPDATE_M, 0, 1), .owner = ENTRY(0) | ENTRY(2) }, /* Systimer */
[1] = { .config = REGDMA_LINK_WAIT_INIT (REGDMA_SYSTIMER_LINK(0x01), SYSTIMER_UNIT0_OP_REG, SYSTIMER_TIMER_UNIT0_VALUE_VALID, SYSTIMER_TIMER_UNIT0_VALUE_VALID, 0, 1), .owner = ENTRY(0) | ENTRY(2) },
[2] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SYSTIMER_LINK(0x02), SYSTIMER_UNIT0_VALUE_HI_REG, SYSTIMER_UNIT0_LOAD_HI_REG, 2, 0, 0), .owner = ENTRY(0) | ENTRY(2) },
[3] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_SYSTIMER_LINK(0x03), SYSTIMER_UNIT0_LOAD_REG, SYSTIMER_TIMER_UNIT0_LOAD_M, SYSTIMER_TIMER_UNIT0_LOAD_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) },
[4] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_SYSTIMER_LINK(0x04), SYSTIMER_UNIT1_OP_REG, SYSTIMER_TIMER_UNIT1_UPDATE_M, SYSTIMER_TIMER_UNIT1_UPDATE_M, 0, 1), .owner = ENTRY(0) | ENTRY(2) },
[5] = { .config = REGDMA_LINK_WAIT_INIT (REGDMA_SYSTIMER_LINK(0x05), SYSTIMER_UNIT1_OP_REG, SYSTIMER_TIMER_UNIT1_VALUE_VALID, SYSTIMER_TIMER_UNIT1_VALUE_VALID, 0, 1), .owner = ENTRY(0) | ENTRY(2) },
[6] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SYSTIMER_LINK(0x06), SYSTIMER_UNIT1_VALUE_HI_REG, SYSTIMER_UNIT1_LOAD_HI_REG, 2, 0, 0), .owner = ENTRY(0) | ENTRY(2) },
[7] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_SYSTIMER_LINK(0x07), SYSTIMER_UNIT1_LOAD_REG, SYSTIMER_TIMER_UNIT1_LOAD_M, SYSTIMER_TIMER_UNIT1_LOAD_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) },
[8] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SYSTIMER_LINK(0x08), SYSTIMER_TARGET0_HI_REG, SYSTIMER_TARGET0_HI_REG, N_REGS_SYSTIMER_0(), 0, 0), .owner = ENTRY(0) | ENTRY(2) }, /* Systimer target value & period */
[9] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_SYSTIMER_LINK(0x09), SYSTIMER_COMP0_LOAD_REG, SYSTIMER_TIMER_COMP0_LOAD, SYSTIMER_TIMER_COMP0_LOAD, 1, 0), .owner = ENTRY(0) | ENTRY(2) },
[10] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_SYSTIMER_LINK(0x0a), SYSTIMER_COMP1_LOAD_REG, SYSTIMER_TIMER_COMP1_LOAD, SYSTIMER_TIMER_COMP1_LOAD, 1, 0), .owner = ENTRY(0) | ENTRY(2) },
[11] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_SYSTIMER_LINK(0x0b), SYSTIMER_COMP2_LOAD_REG, SYSTIMER_TIMER_COMP2_LOAD, SYSTIMER_TIMER_COMP2_LOAD, 1, 0), .owner = ENTRY(0) | ENTRY(2) },
[12] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_SYSTIMER_LINK(0x0c), SYSTIMER_TARGET0_CONF_REG, 0, SYSTIMER_TARGET0_PERIOD_MODE_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) },
[13] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_SYSTIMER_LINK(0x0d), SYSTIMER_TARGET0_CONF_REG, SYSTIMER_TARGET0_PERIOD_MODE_M, SYSTIMER_TARGET0_PERIOD_MODE_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) },
[14] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_SYSTIMER_LINK(0x0e), SYSTIMER_TARGET1_CONF_REG, 0, SYSTIMER_TARGET1_PERIOD_MODE_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) },
[15] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_SYSTIMER_LINK(0x0f), SYSTIMER_TARGET1_CONF_REG, SYSTIMER_TARGET1_PERIOD_MODE_M, SYSTIMER_TARGET1_PERIOD_MODE_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) },
[16] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_SYSTIMER_LINK(0x10), SYSTIMER_TARGET2_CONF_REG, 0, SYSTIMER_TARGET2_PERIOD_MODE_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) },
[17] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SYSTIMER_LINK(0x11), SYSTIMER_CONF_REG, SYSTIMER_CONF_REG, 1, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, /* Systimer work enable */
[18] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SYSTIMER_LINK(0x12), SYSTIMER_INT_ENA_REG, SYSTIMER_INT_ENA_REG, 1, 0, 0), .owner = ENTRY(0) | ENTRY(2) } /* Systimer intr enable */
};
_Static_assert(ARRAY_SIZE(systimer_regs_retention) == SYSTIMER_RETENTION_LINK_LEN, "Inconsistent Systimer retention link length definitions");

View File

@ -22,3 +22,112 @@ const timer_group_signal_conn_t timer_group_periph_signals = {
}
}
};
/* Registers in retention context:
* TIMG_T0CONFIG_REG
* TIMG_T0ALARMLO_REG
* TIMG_T0ALARMHI_REG
* TIMG_T0LOADLO_REG
* TIMG_T0LOADHI_REG
* TIMG_INT_ENA_TIMERS_REG
* TIMG_REGCLK_REG
*/
#define TG_TIMER_RETENTION_REGS_CNT 7
static const uint32_t tg_timer_regs_map[4] = {0x100000f1, 0x80000000, 0x0, 0x0};
const regdma_entries_config_t tg0_timer_regdma_entries[] = {
// backup stage: trigger a soft capture
[0] = {
.config = REGDMA_LINK_WRITE_INIT(REGDMA_TG0_TIMER_LINK(0x00),
TIMG_T0UPDATE_REG(0), TIMG_T0_UPDATE, TIMG_T0_UPDATE_M, 0, 1),
.owner = TIMG_RETENTION_ENTRY
},
// backup stage: wait for the capture done
[1] = {
.config = REGDMA_LINK_WAIT_INIT(REGDMA_TG0_TIMER_LINK(0x01),
TIMG_T0UPDATE_REG(0), 0x0, TIMG_T0_UPDATE_M, 0, 1),
.owner = TIMG_RETENTION_ENTRY
},
// backup stage: save the captured counter value
// restore stage: store the captured counter value to the loader register
[2] = {
.config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG0_TIMER_LINK(0x02),
TIMG_T0LO_REG(0), TIMG_T0LOADLO_REG(0), 2, 0, 0),
.owner = TIMG_RETENTION_ENTRY
},
[3] = {
.config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG0_TIMER_LINK(0x03),
TIMG_T0HI_REG(0), TIMG_T0LOADHI_REG(0), 2, 0, 0),
.owner = TIMG_RETENTION_ENTRY
},
// restore stage: trigger a soft reload, so the timer can continue from where it was backed up
[4] = {
.config = REGDMA_LINK_WRITE_INIT(REGDMA_TG0_TIMER_LINK(0x04),
TIMG_T0LOAD_REG(0), 0x1, TIMG_T0_LOAD_M, 1, 0),
.owner = TIMG_RETENTION_ENTRY
},
// backup stage: save other configuration and status registers
// restore stage: restore the configuration and status registers
[5] = {
.config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_TG0_TIMER_LINK(0x05),
TIMG_T0CONFIG_REG(0), TIMG_T0CONFIG_REG(0),
TG_TIMER_RETENTION_REGS_CNT, 0, 0,
tg_timer_regs_map[0], tg_timer_regs_map[1],
tg_timer_regs_map[2], tg_timer_regs_map[3]),
.owner = TIMG_RETENTION_ENTRY
},
};
const regdma_entries_config_t tg1_timer_regdma_entries[] = {
// backup stage: trigger a soft capture
[0] = {
.config = REGDMA_LINK_WRITE_INIT(REGDMA_TG1_TIMER_LINK(0x00),
TIMG_T0UPDATE_REG(1), TIMG_T0_UPDATE, TIMG_T0_UPDATE_M, 0, 1),
.owner = TIMG_RETENTION_ENTRY
},
// backup stage: wait for the capture done
[1] = {
.config = REGDMA_LINK_WAIT_INIT(REGDMA_TG1_TIMER_LINK(0x01),
TIMG_T0UPDATE_REG(1), 0x0, TIMG_T0_UPDATE_M, 0, 1),
.owner = TIMG_RETENTION_ENTRY
},
// backup stage: save the captured counter value
// restore stage: store the captured counter value to the loader register
[2] = {
.config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG1_TIMER_LINK(0x02),
TIMG_T0LO_REG(1), TIMG_T0LOADLO_REG(1), 2, 0, 0),
.owner = TIMG_RETENTION_ENTRY
},
[3] = {
.config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG1_TIMER_LINK(0x03),
TIMG_T0HI_REG(1), TIMG_T0LOADHI_REG(1), 2, 0, 0),
.owner = TIMG_RETENTION_ENTRY
},
// restore stage: trigger a soft reload, so the timer can continue from where it was backed up
[4] = {
.config = REGDMA_LINK_WRITE_INIT(REGDMA_TG1_TIMER_LINK(0x04),
TIMG_T0LOAD_REG(1), 0x1, TIMG_T0_LOAD_M, 1, 0),
.owner = TIMG_RETENTION_ENTRY
},
// backup stage: save other configuration and status registers
// restore stage: restore the configuration and status registers
[5] = {
.config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_TG1_TIMER_LINK(0x05),
TIMG_T0CONFIG_REG(1), TIMG_T0CONFIG_REG(1),
TG_TIMER_RETENTION_REGS_CNT, 0, 0,
tg_timer_regs_map[0], tg_timer_regs_map[1],
tg_timer_regs_map[2], tg_timer_regs_map[3]),
.owner = TIMG_RETENTION_ENTRY
},
};
const tg_timer_reg_retention_info_t tg_timer_reg_retention_info[SOC_TIMER_GROUPS] = {
[0] = {
.regdma_entry_array = tg0_timer_regdma_entries,
.array_size = ARRAY_SIZE(tg0_timer_regdma_entries)
},
[1] = {
.regdma_entry_array = tg1_timer_regdma_entries,
.array_size = ARRAY_SIZE(tg1_timer_regdma_entries)
},
};

View File

@ -5,6 +5,7 @@
*/
#include "soc/uart_periph.h"
#include "soc/uart_reg.h"
/*
Bunch of constants for every UART peripheral: GPIO signals, irqs, hw addr of registers etc
@ -108,3 +109,52 @@ const uart_signal_conn_t uart_periph_signal[SOC_UART_NUM] = {
.irq = ETS_UART2_INTR_SOURCE,
},
};
/**
* UART registers to be saved during sleep retention
*
* Reset TXFIFO and RXFIFO
* UART registers require set the reg_update bit to make the configuration take effect
*
* UART_INT_ENA_REG, UART_CLKDIV_SYNC_REG, UART_RX_FILT_REG, UART_CONF0_SYNC_REG, UART_CONF1_REG,
* UART_HWFC_CONF_SYNC_REG, UART_SLEEP_CONF0_REG, UART_SLEEP_CONF1_REG, UART_SLEEP_CONF2_REG,
* UART_SWFC_CONF0_SYNC_REG, UART_SWFC_CONF1_REG, UART_TXBRK_CONF_SYNC_REG, UART_IDLE_CONF_SYNC_REG,
* UART_RS485_CONF_SYNC_REG, UART_AT_CMD_PRECNT_SYNC_REG, UART_AT_CMD_POSTCNT_SYNC_REG, UART_AT_CMD_GAPTOUT_SYNC_REG,
* UART_AT_CMD_CHAR_SYNC_REG, UART_MEM_CONF_REG, UART_TOUT_CONF_SYNC_REG, UART_ID_REG
*/
#define UART_RETENTION_ADDR_MAP_REGS_CNT 21
#define UART_RETENTION_REGS_BASE(i) UART_INT_ENA_REG(i)
static const uint32_t uart_regs_map[4] = {0x7fff6d, 0x10, 0x0, 0x0};
#define UART_SLEEP_RETENTION_ENTRIES(uart_num) { \
[0] = {.config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_UART_LINK(0x00), \
UART_RETENTION_REGS_BASE(uart_num), UART_RETENTION_REGS_BASE(uart_num), \
UART_RETENTION_ADDR_MAP_REGS_CNT, 0, 0, \
uart_regs_map[0], uart_regs_map[1], \
uart_regs_map[2], uart_regs_map[3] \
), \
.owner = ENTRY(0) | ENTRY(2) }, \
[1] = {.config = REGDMA_LINK_WRITE_INIT(REGDMA_UART_LINK(0x01), \
UART_REG_UPDATE_REG(uart_num), UART_REG_UPDATE, \
UART_REG_UPDATE_M, 1, 0 \
), \
.owner = ENTRY(0) | ENTRY(2) }, \
[2] = {.config = REGDMA_LINK_WAIT_INIT(REGDMA_UART_LINK(0x02), \
UART_REG_UPDATE_REG(uart_num), 0x0, \
UART_REG_UPDATE_M, 1, 0 \
), \
.owner = ENTRY(0) | ENTRY(2) }, \
}
static const regdma_entries_config_t uart0_regdma_entries[] = UART_SLEEP_RETENTION_ENTRIES(0);
static const regdma_entries_config_t uart1_regdma_entries[] = UART_SLEEP_RETENTION_ENTRIES(1);
const uart_reg_retention_info_t uart_reg_retention_info[SOC_UART_HP_NUM] = {
[0] = {
.regdma_entry_array = uart0_regdma_entries,
.array_size = ARRAY_SIZE(uart0_regdma_entries),
},
[1] = {
.regdma_entry_array = uart1_regdma_entries,
.array_size = ARRAY_SIZE(uart1_regdma_entries),
},
};

View File

@ -5,3 +5,28 @@
*/
#include "soc/wdt_periph.h"
#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[] = {
[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(0x02), 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(0x04), 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(0x05), 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[] = {
[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(0x01), 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(0x02), 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(0x04), 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(0x05), 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)},
};

View File

@ -71,7 +71,8 @@ void app_main(void)
int64_t t2 = esp_timer_get_time();
ESP_LOGI(TAG, "Woke up from light sleep, time since boot: %lld us", t2);
assert(llabs((t2 - t1) - 500000) < 1200);
// TODO: PM-232
assert(((t2 - t1 - 500000) < 1000) && ((t2 - t1 - 500000) > -2000));
#endif
/* Let the timer run for a little bit more */

View File

@ -81,7 +81,7 @@ def test_esp_timer(dut: Dut) -> None:
logging.info('Enter sleep: {}, exit sleep: {}, slept: {}'.format(
sleep_enter_time, sleep_exit_time, sleep_time))
assert abs(sleep_time - LIGHT_SLEEP_TIME) < 1200
assert -2000 < sleep_time - LIGHT_SLEEP_TIME < 1000
for i in range(5, 7):
match = dut.expect(PERIODIC_TIMER_REGEX, timeout=2)

View File

@ -62,5 +62,6 @@ def test_light_sleep(dut: Dut) -> None:
logging.info('Went to sleep again')
match = dut.expect(EXIT_SLEEP_REGEX)
assert match.group(1).decode('utf8') == 'timer' and int(match.group(3)) >= WAKEUP_INTERVAL_MS - 1 and int(match.group(3)) <= WAKEUP_INTERVAL_MS + 1
# TODO: Need to support dynamically change retention overhead for chips which support pmu (PM-232)
assert match.group(1).decode('utf8') == 'timer' and int(match.group(3)) >= WAKEUP_INTERVAL_MS - 2 and int(match.group(3)) <= WAKEUP_INTERVAL_MS + 1
logging.info('Woke up from timer again')

View File

@ -57,12 +57,22 @@ examples/wifi/itwt:
examples/wifi/power_save:
<<: *wifi_depends_default
disable:
- if: (SOC_WIFI_SUPPORTED != 1)
- if: SOC_WIFI_SUPPORTED != 1
- if: IDF_TARGET in ["esp32c61"]
temporary: true
reason: PM-234
disable_test:
- if: IDF_TARGET == "esp32c61"
temporary: true
reason: lack of runners
depends_components:
- esp_wifi
- esp_phy
- esp_netif
- lwip
- esp_event
- esp_coex
- wpa_supplicant
- esp_driver_uart
examples/wifi/wifi_aware:

View File

@ -1,5 +1,5 @@
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- |
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- |
# Wifi Power Save Example