feat(sdm): add sleep retention support

This commit is contained in:
morris
2025-08-07 16:44:52 +08:00
parent 83512e3e7c
commit f808fb9eaf
27 changed files with 346 additions and 5 deletions

View File

@@ -29,6 +29,8 @@ typedef struct {
uint32_t sample_rate_hz; /*!< Over sample rate in Hz, it determines the frequency of the carrier pulses */ uint32_t sample_rate_hz; /*!< Over sample rate in Hz, it determines the frequency of the carrier pulses */
struct { struct {
uint32_t invert_out: 1; /*!< Whether to invert the output signal */ uint32_t invert_out: 1; /*!< Whether to invert the output signal */
uint32_t allow_pd: 1; /*!< If set, driver allows the power domain to be powered off when system enters sleep mode.
This can save power, but at the expense of more RAM being consumed to save register context. */
} flags; /*!< Extra flags */ } flags; /*!< Extra flags */
} sdm_config_t; } sdm_config_t;

View File

@@ -39,6 +39,8 @@
#define SDM_MEM_ALLOC_CAPS MALLOC_CAP_DEFAULT #define SDM_MEM_ALLOC_CAPS MALLOC_CAP_DEFAULT
#endif #endif
#define SDM_USE_RETENTION_LINK (SOC_SDM_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP)
///!< Logging settings ///!< Logging settings
#define TAG "sdm" #define TAG "sdm"
@@ -81,6 +83,31 @@ struct sdm_channel_t {
// sdm driver platform, it's always a singleton // sdm driver platform, it's always a singleton
static sdm_platform_t s_platform; static sdm_platform_t s_platform;
#if SDM_USE_RETENTION_LINK
static esp_err_t sdm_create_sleep_retention_link_cb(void *group)
{
int group_id = ((sdm_group_t *)group)->group_id;
esp_err_t err = sleep_retention_entries_create(soc_sdm_retention_infos[group_id].regdma_entry_array,
soc_sdm_retention_infos[group_id].array_size,
REGDMA_LINK_PRI_SDM, soc_sdm_retention_infos[group_id].module);
return err;
}
static void sdm_create_retention_module(sdm_group_t *group)
{
int group_id = group->group_id;
sleep_retention_module_t module = soc_sdm_retention_infos[group_id].module;
_lock_acquire(&s_platform.mutex);
if (sleep_retention_is_module_inited(module) && !sleep_retention_is_module_created(module)) {
if (sleep_retention_module_allocate(module) != ESP_OK) {
// even though the sleep retention module create failed, SDM driver should still work, so just warning here
ESP_LOGW(TAG, "create retention link failed on SDM Group%d, power domain won't be turned off during sleep", group_id);
}
}
_lock_release(&s_platform.mutex);
}
#endif // SDM_USE_RETENTION_LINK
static sdm_group_t *sdm_acquire_group_handle(int group_id, sdm_clock_source_t clk_src) static sdm_group_t *sdm_acquire_group_handle(int group_id, sdm_clock_source_t clk_src)
{ {
bool new_group = false; bool new_group = false;
@@ -97,6 +124,25 @@ static sdm_group_t *sdm_acquire_group_handle(int group_id, sdm_clock_source_t cl
group->group_id = group_id; group->group_id = group_id;
group->spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED; group->spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED;
group->clk_src = clk_src; group->clk_src = clk_src;
#if SDM_USE_RETENTION_LINK
sleep_retention_module_t module = soc_sdm_retention_infos[group->group_id].module;
sleep_retention_module_init_param_t init_param = {
.cbs = {
.create = {
.handle = sdm_create_sleep_retention_link_cb,
.arg = group,
},
},
.depends = RETENTION_MODULE_BITMAP_INIT(CLOCK_SYSTEM)
};
// retention module init must be called BEFORE the hal init
if (sleep_retention_module_init(module, &init_param) != ESP_OK) {
ESP_LOGW(TAG, "init sleep retention failed on SDM Group%d, power domain may be turned off during sleep", group->group_id);
}
#endif // SDM_USE_RETENTION_LINK
// [IDF-12975]: enable APB register clock explicitly
// initialize HAL context // initialize HAL context
sdm_hal_init_config_t hal_config = { sdm_hal_init_config_t hal_config = {
.group_id = group_id, .group_id = group_id,
@@ -142,6 +188,16 @@ static void sdm_release_group_handle(sdm_group_t *group)
do_deinitialize = true; do_deinitialize = true;
s_platform.groups[group_id] = NULL; // deregister from platform s_platform.groups[group_id] = NULL; // deregister from platform
sdm_hal_deinit(&group->hal); sdm_hal_deinit(&group->hal);
#if SDM_USE_RETENTION_LINK
sleep_retention_module_t module = soc_sdm_retention_infos[group_id].module;
if (sleep_retention_is_module_created(module)) {
sleep_retention_module_free(module);
}
if (sleep_retention_is_module_inited(module)) {
sleep_retention_module_deinit(module);
}
#endif // SDM_USE_RETENTION_LINK
} }
_lock_release(&s_platform.mutex); _lock_release(&s_platform.mutex);
@@ -216,6 +272,10 @@ esp_err_t sdm_new_channel(const sdm_config_t *config, sdm_channel_handle_t *ret_
ESP_RETURN_ON_FALSE(config && ret_chan, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); ESP_RETURN_ON_FALSE(config && ret_chan, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
ESP_RETURN_ON_FALSE(GPIO_IS_VALID_OUTPUT_GPIO(config->gpio_num), ESP_ERR_INVALID_ARG, TAG, "invalid GPIO number"); ESP_RETURN_ON_FALSE(GPIO_IS_VALID_OUTPUT_GPIO(config->gpio_num), ESP_ERR_INVALID_ARG, TAG, "invalid GPIO number");
[[maybe_unused]] bool allow_pd = config->flags.allow_pd == 1;
#if !SOC_SDM_SUPPORT_SLEEP_RETENTION
ESP_RETURN_ON_FALSE(allow_pd == false, ESP_ERR_NOT_SUPPORTED, TAG, "not able to power down in light sleep");
#endif // SOC_SDM_SUPPORT_SLEEP_RETENTION
// allocate channel memory from internal memory because it contains atomic variable // allocate channel memory from internal memory because it contains atomic variable
chan = heap_caps_calloc(1, sizeof(sdm_channel_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); chan = heap_caps_calloc(1, sizeof(sdm_channel_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
@@ -271,6 +331,12 @@ esp_err_t sdm_new_channel(const sdm_config_t *config, sdm_channel_handle_t *ret_
chan->spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED; chan->spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED;
atomic_init(&chan->fsm, SDM_FSM_INIT); // set the initial state to INIT atomic_init(&chan->fsm, SDM_FSM_INIT); // set the initial state to INIT
#if SDM_USE_RETENTION_LINK
if (allow_pd) {
sdm_create_retention_module(group);
}
#endif // SDM_USE_RETENTION_LINK
ESP_LOGD(TAG, "new sdm channel (%d,%d) at %p, gpio=%d, sample rate=%"PRIu32"Hz", group_id, chan_id, chan, chan->gpio_num, chan->sample_rate_hz); ESP_LOGD(TAG, "new sdm channel (%d,%d) at %p, gpio=%d, sample rate=%"PRIu32"Hz", group_id, chan_id, chan, chan->gpio_num, chan->sample_rate_hz);
*ret_chan = chan; *ret_chan = chan;
return ESP_OK; return ESP_OK;

View File

@@ -1,7 +1,7 @@
set(srcs "test_app_main.c") set(srcs "test_app_main.c" "test_sdm.cpp")
if(CONFIG_SOC_SDM_SUPPORTED) if(CONFIG_SOC_LIGHT_SLEEP_SUPPORTED AND CONFIG_PM_ENABLE)
list(APPEND srcs "test_sdm.cpp") list(APPEND srcs "test_sdm_sleep.cpp")
endif() endif()
# In order for the cases defined by `TEST_CASE` to be linked into the final elf, # In order for the cases defined by `TEST_CASE` to be linked into the final elf,

View File

@@ -22,6 +22,7 @@ TEST_CASE("sdm_channel_install_uninstall", "[sdm]")
.sample_rate_hz = 1000000, .sample_rate_hz = 1000000,
.flags = { .flags = {
.invert_out = false, .invert_out = false,
.allow_pd = false,
}, },
}; };
sdm_channel_handle_t chans[SOC_SDM_ATTR(INST_NUM)][SOC_SDM_ATTR(CHANS_PER_INST)] = {}; sdm_channel_handle_t chans[SOC_SDM_ATTR(INST_NUM)][SOC_SDM_ATTR(CHANS_PER_INST)] = {};
@@ -49,6 +50,7 @@ TEST_CASE("sdm_channel_set_pulse_density", "[sdm]")
.sample_rate_hz = 1000000, .sample_rate_hz = 1000000,
.flags = { .flags = {
.invert_out = false, .invert_out = false,
.allow_pd = false,
}, },
}; };
sdm_channel_handle_t chans[2] = {}; sdm_channel_handle_t chans[2] = {};

View File

@@ -0,0 +1,92 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdio.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "unity.h"
#include "driver/sdm.h"
#include "soc/soc_caps.h"
#include "esp_sleep.h"
#include "esp_private/sleep_cpu.h"
#include "esp_private/esp_sleep_internal.h"
#include "esp_private/esp_pmu.h"
/**
* @brief Test the SDM driver can still work after light sleep
*
* @param allow_pd Whether to allow power down the peripheral in light sleep
*/
static void test_sdm_sleep_retention(bool allow_pd)
{
const gpio_num_t sdm_chan_gpios[2] = {GPIO_NUM_0, GPIO_NUM_2};
sdm_config_t sdm_config = {
.gpio_num = GPIO_NUM_NC, // will be set later
.clk_src = SDM_CLK_SRC_DEFAULT,
.sample_rate_hz = 1000000,
.flags = {
.invert_out = false,
.allow_pd = allow_pd,
},
};
sdm_channel_handle_t chans[2] = {0};
for (int i = 0; i < 2; i++) {
sdm_config.gpio_num = sdm_chan_gpios[i];
TEST_ESP_OK(sdm_new_channel(&sdm_config, &chans[i]));
// should see a ~250KHz (sample_rate/4) square wave
TEST_ESP_OK(sdm_channel_set_pulse_density(chans[i], 0));
TEST_ESP_OK(sdm_channel_enable(chans[i]));
}
vTaskDelay(pdMS_TO_TICKS(500));
// Note: disable the sdm before going to sleep, ensure no power management lock is acquired by it
for (int i = 0; i < 2; i++) {
TEST_ESP_OK(sdm_channel_disable(chans[i]));
}
esp_sleep_context_t sleep_ctx;
esp_sleep_set_sleep_context(&sleep_ctx);
printf("go to light sleep for 2 seconds\r\n");
#if ESP_SLEEP_POWER_DOWN_CPU
TEST_ESP_OK(sleep_cpu_configure(true));
#endif
TEST_ESP_OK(esp_sleep_enable_timer_wakeup(2 * 1000 * 1000));
TEST_ESP_OK(esp_light_sleep_start());
printf("Waked up! Let's see if SDM driver can still work...\r\n");
#if ESP_SLEEP_POWER_DOWN_CPU
TEST_ESP_OK(sleep_cpu_configure(false));
#endif
printf("check if the sleep happened as expected\r\n");
TEST_ASSERT_EQUAL(0, sleep_ctx.sleep_request_result);
#if SOC_SDM_SUPPORT_SLEEP_RETENTION && !SOC_PM_TOP_PD_NOT_ALLOWED
// check if the power domain also is powered down
TEST_ASSERT_EQUAL(allow_pd ? PMU_SLEEP_PD_TOP : 0, (sleep_ctx.sleep_flags) & PMU_SLEEP_PD_TOP);
#endif
esp_sleep_set_sleep_context(NULL);
// re-enable the SDM channel
for (int i = 0; i < 2; i++) {
TEST_ESP_OK(sdm_channel_enable(chans[i]));
}
// should see a ~250KHz (sample_rate/4) square wave again
vTaskDelay(pdMS_TO_TICKS(500));
for (int i = 0; i < 2; i++) {
TEST_ESP_OK(sdm_channel_disable(chans[i]));
TEST_ESP_OK(sdm_del_channel(chans[i]));
}
}
TEST_CASE("sdm can work after light sleep", "[sdm]")
{
test_sdm_sleep_retention(false);
#if SOC_SDM_SUPPORT_SLEEP_RETENTION
test_sdm_sleep_retention(true);
#endif
}

View File

@@ -1,5 +1,7 @@
CONFIG_PM_ENABLE=y CONFIG_PM_ENABLE=y
CONFIG_FREERTOS_USE_TICKLESS_IDLE=y CONFIG_FREERTOS_USE_TICKLESS_IDLE=y
CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP=y
CONFIG_PM_DFS_INIT_AUTO=y
CONFIG_COMPILER_OPTIMIZATION_SIZE=y CONFIG_COMPILER_OPTIMIZATION_SIZE=y
CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y
CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y

View File

@@ -1,2 +1,5 @@
CONFIG_FREERTOS_HZ=1000 CONFIG_FREERTOS_HZ=1000
CONFIG_ESP_TASK_WDT_EN=n CONFIG_ESP_TASK_WDT_EN=n
# primitives for checking sleep internal state
CONFIG_ESP_SLEEP_DEBUG=y

View File

@@ -291,6 +291,10 @@ bool peripheral_domain_pd_allowed(void)
mask.bitmap[SLEEP_RETENTION_MODULE_MCPWM0 >> 5] |= BIT(SLEEP_RETENTION_MODULE_MCPWM0 % 32); mask.bitmap[SLEEP_RETENTION_MODULE_MCPWM0 >> 5] |= BIT(SLEEP_RETENTION_MODULE_MCPWM0 % 32);
#endif #endif
#if SOC_SDM_SUPPORT_SLEEP_RETENTION
mask.bitmap[SLEEP_RETENTION_MODULE_SDM0 >> 5] |= BIT(SLEEP_RETENTION_MODULE_SDM0 % 32);
#endif
const sleep_retention_module_bitmap_t peripheral_domain_inited_modules = sleep_retention_module_bitmap_and(inited_modules, mask); const sleep_retention_module_bitmap_t peripheral_domain_inited_modules = sleep_retention_module_bitmap_and(inited_modules, mask);
const sleep_retention_module_bitmap_t peripheral_domain_created_modules = sleep_retention_module_bitmap_and(created_modules, mask); const sleep_retention_module_bitmap_t peripheral_domain_created_modules = sleep_retention_module_bitmap_and(created_modules, mask);
return sleep_retention_module_bitmap_eq(peripheral_domain_inited_modules, peripheral_domain_created_modules); return sleep_retention_module_bitmap_eq(peripheral_domain_inited_modules, peripheral_domain_created_modules);

View File

@@ -638,9 +638,9 @@ FORCE_INLINE_ATTR uint32_t pmu_ll_hp_get_analog_wait_target_cycle(pmu_dev_t *hw)
return HAL_FORCE_READ_U32_REG_FIELD(hw->wakeup.cntl7, ana_wait_target); return HAL_FORCE_READ_U32_REG_FIELD(hw->wakeup.cntl7, ana_wait_target);
} }
FORCE_INLINE_ATTR uint32_t pmu_ll_hp_set_lite_wakeup_enable(pmu_dev_t *hw, bool wakeup_en) FORCE_INLINE_ATTR void pmu_ll_hp_set_lite_wakeup_enable(pmu_dev_t *hw, bool wakeup_en)
{ {
return hw->wakeup.cntl8.lp_lite_wakeup_ena = wakeup_en; hw->wakeup.cntl8.lp_lite_wakeup_ena = wakeup_en;
} }
FORCE_INLINE_ATTR void pmu_ll_hp_set_digital_power_supply_wait_cycle(pmu_dev_t *hw, uint32_t cycle) FORCE_INLINE_ATTR void pmu_ll_hp_set_digital_power_supply_wait_cycle(pmu_dev_t *hw, uint32_t cycle)

View File

@@ -647,6 +647,10 @@ config SOC_DEDIC_PERIPH_ALWAYS_ENABLE
bool bool
default y default y
config SOC_SDM_SUPPORT_SLEEP_RETENTION
bool
default y
config SOC_ANA_CMPR_NUM config SOC_ANA_CMPR_NUM
int int
default 1 default 1

View File

@@ -44,6 +44,7 @@ typedef enum periph_retention_module {
SLEEP_RETENTION_MODULE_GPSPI2 = 20, SLEEP_RETENTION_MODULE_GPSPI2 = 20,
SLEEP_RETENTION_MODULE_LEDC = 21, SLEEP_RETENTION_MODULE_LEDC = 21,
SLEEP_RETENTION_MODULE_MCPWM0 = 22, SLEEP_RETENTION_MODULE_MCPWM0 = 22,
SLEEP_RETENTION_MODULE_SDM0 = 23,
/* modem module, which includes WiFi, BLE and 802.15.4 */ /* modem module, which includes WiFi, BLE and 802.15.4 */
SLEEP_RETENTION_MODULE_WIFI_MAC = 26, SLEEP_RETENTION_MODULE_WIFI_MAC = 26,
@@ -80,6 +81,7 @@ typedef enum periph_retention_module {
: ((m) == SLEEP_RETENTION_MODULE_GPSPI2) ? true \ : ((m) == SLEEP_RETENTION_MODULE_GPSPI2) ? true \
: ((m) == SLEEP_RETENTION_MODULE_LEDC) ? true \ : ((m) == SLEEP_RETENTION_MODULE_LEDC) ? true \
: ((m) == SLEEP_RETENTION_MODULE_MCPWM0) ? true \ : ((m) == SLEEP_RETENTION_MODULE_MCPWM0) ? true \
: ((m) == SLEEP_RETENTION_MODULE_SDM0) ? true \
: false) : false)
#ifdef __cplusplus #ifdef __cplusplus

View File

@@ -267,6 +267,8 @@
#define SOC_DEDIC_GPIO_IN_CHANNELS_NUM (8) /*!< 8 inward channels on each CPU core */ #define SOC_DEDIC_GPIO_IN_CHANNELS_NUM (8) /*!< 8 inward channels on each CPU core */
#define SOC_DEDIC_PERIPH_ALWAYS_ENABLE (1) /*!< The dedicated GPIO (a.k.a. fast GPIO) is featured by some customized CPU instructions, which is always enabled */ #define SOC_DEDIC_PERIPH_ALWAYS_ENABLE (1) /*!< The dedicated GPIO (a.k.a. fast GPIO) is featured by some customized CPU instructions, which is always enabled */
#define SOC_SDM_SUPPORT_SLEEP_RETENTION 1
/*------------------------- Analog Comparator CAPS ---------------------------*/ /*------------------------- Analog Comparator CAPS ---------------------------*/
#define SOC_ANA_CMPR_NUM (1U) #define SOC_ANA_CMPR_NUM (1U)
#define SOC_ANA_CMPR_CAN_DISTINGUISH_EDGE (1) // Support positive/negative/any cross interrupt #define SOC_ANA_CMPR_CAN_DISTINGUISH_EDGE (1) // Support positive/negative/any cross interrupt

View File

@@ -6,6 +6,7 @@
#include "soc/sdm_periph.h" #include "soc/sdm_periph.h"
#include "soc/gpio_sig_map.h" #include "soc/gpio_sig_map.h"
#include "soc/gpio_ext_reg.h"
const soc_sdm_signal_desc_t soc_sdm_signals[1] = { const soc_sdm_signal_desc_t soc_sdm_signals[1] = {
[0] = { [0] = {
@@ -26,3 +27,32 @@ const soc_sdm_signal_desc_t soc_sdm_signals[1] = {
} }
} }
}; };
/**
* @brief Registers in retention context:
* GPIO_EXT_SIGMADELTA[x]_REG
* GPIO_EXT_SIGMADELTA_MISC_REG
*/
#define GPIO_EXT_RETENTION_REGS_CNT 5
#define GPIO_EXT_RETENTION_REGS_BASE (DR_REG_GPIO_EXT_BASE + 0x4)
static const uint32_t gpio_ext_regs_map[4] = {0x1f, 0x0, 0x0, 0x0};
static const regdma_entries_config_t gpio_ext_regdma_entries[] = {
// backup stage: save configuration and status registers
// restore stage: restore the configuration and status registers
[0] = {
.config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_SDM_LINK(0x00),
GPIO_EXT_RETENTION_REGS_BASE, GPIO_EXT_RETENTION_REGS_BASE,
GPIO_EXT_RETENTION_REGS_CNT, 0, 0,
gpio_ext_regs_map[0], gpio_ext_regs_map[1],
gpio_ext_regs_map[2], gpio_ext_regs_map[3]),
.owner = ENTRY(0) | ENTRY(2),
},
};
const soc_sdm_retention_desc_t soc_sdm_retention_infos[1] = {
[0] = {
.module = SLEEP_RETENTION_MODULE_SDM0,
.regdma_entry_array = gpio_ext_regdma_entries,
.array_size = ARRAY_SIZE(gpio_ext_regdma_entries)
}
};

View File

@@ -579,6 +579,10 @@ config SOC_DEDIC_PERIPH_ALWAYS_ENABLE
bool bool
default y default y
config SOC_SDM_SUPPORT_SLEEP_RETENTION
bool
default y
config SOC_I2C_NUM config SOC_I2C_NUM
int int
default 2 default 2

View File

@@ -46,6 +46,7 @@ typedef enum periph_retention_module {
SLEEP_RETENTION_MODULE_GPSPI2 = 22, SLEEP_RETENTION_MODULE_GPSPI2 = 22,
SLEEP_RETENTION_MODULE_LEDC = 23, SLEEP_RETENTION_MODULE_LEDC = 23,
SLEEP_RETENTION_MODULE_MCPWM0 = 24, SLEEP_RETENTION_MODULE_MCPWM0 = 24,
SLEEP_RETENTION_MODULE_SDM0 = 25,
/* Modem module, which includes WiFi, BLE and 802.15.4 */ /* Modem module, which includes WiFi, BLE and 802.15.4 */
SLEEP_RETENTION_MODULE_WIFI_MAC = 26, SLEEP_RETENTION_MODULE_WIFI_MAC = 26,
@@ -82,6 +83,7 @@ typedef enum periph_retention_module {
: ((m) == SLEEP_RETENTION_MODULE_GPSPI2) ? true \ : ((m) == SLEEP_RETENTION_MODULE_GPSPI2) ? true \
: ((m) == SLEEP_RETENTION_MODULE_LEDC) ? true \ : ((m) == SLEEP_RETENTION_MODULE_LEDC) ? true \
: ((m) == SLEEP_RETENTION_MODULE_MCPWM0) ? true \ : ((m) == SLEEP_RETENTION_MODULE_MCPWM0) ? true \
: ((m) == SLEEP_RETENTION_MODULE_SDM0) ? true \
: false) : false)
#ifdef __cplusplus #ifdef __cplusplus

View File

@@ -245,6 +245,8 @@
#define SOC_DEDIC_GPIO_IN_CHANNELS_NUM (8) /*!< 8 inward channels on each CPU core */ #define SOC_DEDIC_GPIO_IN_CHANNELS_NUM (8) /*!< 8 inward channels on each CPU core */
#define SOC_DEDIC_PERIPH_ALWAYS_ENABLE (1) /*!< The dedicated GPIO (a.k.a. fast GPIO) is featured by some customized CPU instructions, which is always enabled */ #define SOC_DEDIC_PERIPH_ALWAYS_ENABLE (1) /*!< The dedicated GPIO (a.k.a. fast GPIO) is featured by some customized CPU instructions, which is always enabled */
#define SOC_SDM_SUPPORT_SLEEP_RETENTION 1
/*-------------------------- I2C CAPS ----------------------------------------*/ /*-------------------------- I2C CAPS ----------------------------------------*/
// ESP32-C6 has 1 I2C // ESP32-C6 has 1 I2C
#define SOC_I2C_NUM (2U) // I2C_NUM = HP_I2C + LP_I2C #define SOC_I2C_NUM (2U) // I2C_NUM = HP_I2C + LP_I2C

View File

@@ -6,6 +6,7 @@
#include "soc/sdm_periph.h" #include "soc/sdm_periph.h"
#include "soc/gpio_sig_map.h" #include "soc/gpio_sig_map.h"
#include "soc/gpio_ext_reg.h"
const soc_sdm_signal_desc_t soc_sdm_signals[1] = { const soc_sdm_signal_desc_t soc_sdm_signals[1] = {
[0] = { [0] = {
@@ -26,3 +27,32 @@ const soc_sdm_signal_desc_t soc_sdm_signals[1] = {
} }
} }
}; };
/**
* @brief Registers in retention context:
* GPIO_EXT_SIGMADELTA[x]_REG
* GPIO_EXT_SIGMADELTA_MISC_REG
*/
#define GPIO_EXT_RETENTION_REGS_CNT 5
#define GPIO_EXT_RETENTION_REGS_BASE (DR_REG_GPIO_EXT_BASE + 0x0)
static const uint32_t gpio_ext_regs_map[4] = {0x20f, 0x0, 0x0, 0x0};
static const regdma_entries_config_t gpio_ext_regdma_entries[] = {
// backup stage: save configuration and status registers
// restore stage: restore the configuration and status registers
[0] = {
.config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_SDM_LINK(0x00),
GPIO_EXT_RETENTION_REGS_BASE, GPIO_EXT_RETENTION_REGS_BASE,
GPIO_EXT_RETENTION_REGS_CNT, 0, 0,
gpio_ext_regs_map[0], gpio_ext_regs_map[1],
gpio_ext_regs_map[2], gpio_ext_regs_map[3]),
.owner = ENTRY(0) | ENTRY(2),
},
};
const soc_sdm_retention_desc_t soc_sdm_retention_infos[1] = {
[0] = {
.module = SLEEP_RETENTION_MODULE_SDM0,
.regdma_entry_array = gpio_ext_regdma_entries,
.array_size = ARRAY_SIZE(gpio_ext_regdma_entries)
}
};

View File

@@ -583,6 +583,10 @@ config SOC_DEDIC_PERIPH_ALWAYS_ENABLE
bool bool
default y default y
config SOC_SDM_SUPPORT_SLEEP_RETENTION
bool
default y
config SOC_ANA_CMPR_NUM config SOC_ANA_CMPR_NUM
int int
default 1 default 1

View File

@@ -46,6 +46,7 @@ typedef enum periph_retention_module {
SLEEP_RETENTION_MODULE_GPSPI2 = 22, SLEEP_RETENTION_MODULE_GPSPI2 = 22,
SLEEP_RETENTION_MODULE_LEDC = 23, SLEEP_RETENTION_MODULE_LEDC = 23,
SLEEP_RETENTION_MODULE_MCPWM0 = 24, SLEEP_RETENTION_MODULE_MCPWM0 = 24,
SLEEP_RETENTION_MODULE_SDM0 = 25,
/* Modem module, which includes BLE and 802.15.4 */ /* Modem module, which includes BLE and 802.15.4 */
SLEEP_RETENTION_MODULE_BLE_MAC = 28, SLEEP_RETENTION_MODULE_BLE_MAC = 28,
@@ -80,6 +81,7 @@ typedef enum periph_retention_module {
: ((m) == SLEEP_RETENTION_MODULE_GPSPI2) ? true \ : ((m) == SLEEP_RETENTION_MODULE_GPSPI2) ? true \
: ((m) == SLEEP_RETENTION_MODULE_LEDC) ? true \ : ((m) == SLEEP_RETENTION_MODULE_LEDC) ? true \
: ((m) == SLEEP_RETENTION_MODULE_MCPWM0) ? true \ : ((m) == SLEEP_RETENTION_MODULE_MCPWM0) ? true \
: ((m) == SLEEP_RETENTION_MODULE_SDM0) ? true \
: false) : false)
#ifdef __cplusplus #ifdef __cplusplus

View File

@@ -265,6 +265,8 @@
#define SOC_DEDIC_GPIO_IN_CHANNELS_NUM (8) /*!< 8 inward channels on each CPU core */ #define SOC_DEDIC_GPIO_IN_CHANNELS_NUM (8) /*!< 8 inward channels on each CPU core */
#define SOC_DEDIC_PERIPH_ALWAYS_ENABLE (1) /*!< The dedicated GPIO (a.k.a. fast GPIO) is featured by some customized CPU instructions, which is always enabled */ #define SOC_DEDIC_PERIPH_ALWAYS_ENABLE (1) /*!< The dedicated GPIO (a.k.a. fast GPIO) is featured by some customized CPU instructions, which is always enabled */
#define SOC_SDM_SUPPORT_SLEEP_RETENTION 1
/*------------------------- Analog Comparator CAPS ---------------------------*/ /*------------------------- Analog Comparator CAPS ---------------------------*/
#define SOC_ANA_CMPR_NUM (1U) #define SOC_ANA_CMPR_NUM (1U)
#define SOC_ANA_CMPR_INTR_SHARE_WITH_GPIO (1) #define SOC_ANA_CMPR_INTR_SHARE_WITH_GPIO (1)

View File

@@ -6,6 +6,7 @@
#include "soc/sdm_periph.h" #include "soc/sdm_periph.h"
#include "soc/gpio_sig_map.h" #include "soc/gpio_sig_map.h"
#include "soc/gpio_ext_reg.h"
const soc_sdm_signal_desc_t soc_sdm_signals[1] = { const soc_sdm_signal_desc_t soc_sdm_signals[1] = {
[0] = { [0] = {
@@ -26,3 +27,32 @@ const soc_sdm_signal_desc_t soc_sdm_signals[1] = {
} }
} }
}; };
/**
* @brief Registers in retention context:
* GPIO_EXT_SIGMADELTA[x]_REG
* GPIO_EXT_SIGMADELTA_MISC_REG
*/
#define GPIO_EXT_RETENTION_REGS_CNT 5
#define GPIO_EXT_RETENTION_REGS_BASE (DR_REG_GPIO_EXT_BASE + 0x0)
static const uint32_t gpio_ext_regs_map[4] = {0x20f, 0x0, 0x0, 0x0};
static const regdma_entries_config_t gpio_ext_regdma_entries[] = {
// backup stage: save configuration and status registers
// restore stage: restore the configuration and status registers
[0] = {
.config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_SDM_LINK(0x00),
GPIO_EXT_RETENTION_REGS_BASE, GPIO_EXT_RETENTION_REGS_BASE,
GPIO_EXT_RETENTION_REGS_CNT, 0, 0,
gpio_ext_regs_map[0], gpio_ext_regs_map[1],
gpio_ext_regs_map[2], gpio_ext_regs_map[3]),
.owner = ENTRY(0) | ENTRY(2),
},
};
const soc_sdm_retention_desc_t soc_sdm_retention_infos[1] = {
[0] = {
.module = SLEEP_RETENTION_MODULE_SDM0,
.regdma_entry_array = gpio_ext_regdma_entries,
.array_size = ARRAY_SIZE(gpio_ext_regdma_entries)
}
};

View File

@@ -767,6 +767,10 @@ config SOC_DEDIC_PERIPH_ALWAYS_ENABLE
bool bool
default y default y
config SOC_SDM_SUPPORT_SLEEP_RETENTION
bool
default y
config SOC_ANA_CMPR_NUM config SOC_ANA_CMPR_NUM
int int
default 2 default 2

View File

@@ -59,6 +59,7 @@ typedef enum periph_retention_module {
SLEEP_RETENTION_MODULE_LEDC = 33, SLEEP_RETENTION_MODULE_LEDC = 33,
SLEEP_RETENTION_MODULE_MCPWM0 = 34, SLEEP_RETENTION_MODULE_MCPWM0 = 34,
SLEEP_RETENTION_MODULE_MCPWM1 = 35, SLEEP_RETENTION_MODULE_MCPWM1 = 35,
SLEEP_RETENTION_MODULE_SDM0 = 36,
SLEEP_RETENTION_MODULE_MAX = SOC_PM_RETENTION_MODULE_NUM - 1 SLEEP_RETENTION_MODULE_MAX = SOC_PM_RETENTION_MODULE_NUM - 1
} periph_retention_module_t; } periph_retention_module_t;
@@ -100,6 +101,7 @@ typedef enum periph_retention_module {
: ((m) == SLEEP_RETENTION_MODULE_LEDC) ? true \ : ((m) == SLEEP_RETENTION_MODULE_LEDC) ? true \
: ((m) == SLEEP_RETENTION_MODULE_MCPWM0) ? true \ : ((m) == SLEEP_RETENTION_MODULE_MCPWM0) ? true \
: ((m) == SLEEP_RETENTION_MODULE_MCPWM1) ? true \ : ((m) == SLEEP_RETENTION_MODULE_MCPWM1) ? true \
: ((m) == SLEEP_RETENTION_MODULE_SDM0) ? true \
: false) : false)
#ifdef __cplusplus #ifdef __cplusplus

View File

@@ -298,6 +298,8 @@
#define SOC_DEDIC_GPIO_IN_CHANNELS_NUM (8) /*!< 8 inward channels on each CPU core */ #define SOC_DEDIC_GPIO_IN_CHANNELS_NUM (8) /*!< 8 inward channels on each CPU core */
#define SOC_DEDIC_PERIPH_ALWAYS_ENABLE (1) /*!< The dedicated GPIO (a.k.a. fast GPIO) is featured by some customized CPU instructions, which is always enabled */ #define SOC_DEDIC_PERIPH_ALWAYS_ENABLE (1) /*!< The dedicated GPIO (a.k.a. fast GPIO) is featured by some customized CPU instructions, which is always enabled */
#define SOC_SDM_SUPPORT_SLEEP_RETENTION 1
/*------------------------- Analog Comparator CAPS ---------------------------*/ /*------------------------- Analog Comparator CAPS ---------------------------*/
#define SOC_ANA_CMPR_NUM (2) #define SOC_ANA_CMPR_NUM (2)
#define SOC_ANA_CMPR_CAN_DISTINGUISH_EDGE (1) // Support positive/negative/any cross interrupt #define SOC_ANA_CMPR_CAN_DISTINGUISH_EDGE (1) // Support positive/negative/any cross interrupt

View File

@@ -6,6 +6,7 @@
#include "soc/sdm_periph.h" #include "soc/sdm_periph.h"
#include "soc/gpio_sig_map.h" #include "soc/gpio_sig_map.h"
#include "soc/gpio_ext_reg.h"
const soc_sdm_signal_desc_t soc_sdm_signals[1] = { const soc_sdm_signal_desc_t soc_sdm_signals[1] = {
[0] = { [0] = {
@@ -38,3 +39,32 @@ const soc_sdm_signal_desc_t soc_sdm_signals[1] = {
} }
} }
}; };
/**
* @brief Registers in retention context:
* GPIO_EXT_SIGMADELTA[x]_REG
* GPIO_EXT_SIGMADELTA_MISC_REG
*/
#define GPIO_EXT_RETENTION_REGS_CNT 9
#define GPIO_EXT_RETENTION_REGS_BASE (DR_REG_GPIO_EXT_BASE + 0x0)
static const uint32_t gpio_ext_regs_map[4] = {0x2ff, 0x0, 0x0, 0x0};
static const regdma_entries_config_t gpio_ext_regdma_entries[] = {
// backup stage: save configuration and status registers
// restore stage: restore the configuration and status registers
[0] = {
.config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_SDM_LINK(0x00),
GPIO_EXT_RETENTION_REGS_BASE, GPIO_EXT_RETENTION_REGS_BASE,
GPIO_EXT_RETENTION_REGS_CNT, 0, 0,
gpio_ext_regs_map[0], gpio_ext_regs_map[1],
gpio_ext_regs_map[2], gpio_ext_regs_map[3]),
.owner = ENTRY(0),
},
};
const soc_sdm_retention_desc_t soc_sdm_retention_infos[1] = {
[0] = {
.module = SLEEP_RETENTION_MODULE_SDM0,
.regdma_entry_array = gpio_ext_regdma_entries,
.array_size = ARRAY_SIZE(gpio_ext_regdma_entries)
}
};

View File

@@ -64,6 +64,7 @@ extern "C" {
#define REGDMA_GPSPI_LINK(_pri) ((0x23 << 8) | _pri) #define REGDMA_GPSPI_LINK(_pri) ((0x23 << 8) | _pri)
#define REGDMA_LEDC_LINK(_pri) ((0x24 << 8) | _pri) #define REGDMA_LEDC_LINK(_pri) ((0x24 << 8) | _pri)
#define REGDMA_MCPWM_LINK(_pri) ((0x25 << 8) | _pri) #define REGDMA_MCPWM_LINK(_pri) ((0x25 << 8) | _pri)
#define REGDMA_SDM_LINK(_pri) ((0x26 << 8) | _pri)
#define REGDMA_MODEM_FE_LINK(_pri) ((0xFF << 8) | _pri) #define REGDMA_MODEM_FE_LINK(_pri) ((0xFF << 8) | _pri)
@@ -90,6 +91,7 @@ extern "C" {
#define REGDMA_LINK_PRI_GPSPI REGDMA_LINK_PRI_GENERAL_PERIPH #define REGDMA_LINK_PRI_GPSPI REGDMA_LINK_PRI_GENERAL_PERIPH
#define REGDMA_LINK_PRI_LEDC REGDMA_LINK_PRI_GENERAL_PERIPH #define REGDMA_LINK_PRI_LEDC REGDMA_LINK_PRI_GENERAL_PERIPH
#define REGDMA_LINK_PRI_MCPWM REGDMA_LINK_PRI_GENERAL_PERIPH #define REGDMA_LINK_PRI_MCPWM REGDMA_LINK_PRI_GENERAL_PERIPH
#define REGDMA_LINK_PRI_SDM REGDMA_LINK_PRI_GENERAL_PERIPH
typedef enum { typedef enum {
REGDMA_LINK_PRI_0 = 0, REGDMA_LINK_PRI_0 = 0,

View File

@@ -23,6 +23,8 @@
extern "C" { extern "C" {
#endif #endif
#if SOC_HAS(SDM)
typedef struct { typedef struct {
const char *module_name; // Module name const char *module_name; // Module name
struct { struct {
@@ -32,6 +34,20 @@ typedef struct {
extern const soc_sdm_signal_desc_t soc_sdm_signals[SOC_SDM_ATTR(INST_NUM)]; extern const soc_sdm_signal_desc_t soc_sdm_signals[SOC_SDM_ATTR(INST_NUM)];
#if SOC_HAS(PAU)
typedef struct {
const periph_retention_module_t module; // ID of the SDM as a retention module
const regdma_entries_config_t *regdma_entry_array; // Array of regdma entries for retention
const size_t array_size; // Size of the regdma_entry_array
} soc_sdm_retention_desc_t;
extern const soc_sdm_retention_desc_t soc_sdm_retention_infos[SOC_SDM_ATTR(INST_NUM)];
#endif // SOC_HAS(PAU)
#endif // SOC_HAS(SDM)
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif