Merge branch 'feat/etm_sleep_retention' into 'master'

feat(etm): support sleep retention

Closes IDF-8462

See merge request espressif/esp-idf!33787
This commit is contained in:
morris
2024-10-11 21:28:01 +08:00
42 changed files with 566 additions and 63 deletions

View File

@@ -27,24 +27,21 @@ static esp_err_t gptimer_create_sleep_retention_link_cb(void *arg)
{
gptimer_group_t *group = (gptimer_group_t *)arg;
int group_id = group->group_id;
sleep_retention_module_t module = group->sleep_retention_module;
esp_err_t err = sleep_retention_entries_create(tg_timer_reg_retention_info[group_id].regdma_entry_array,
tg_timer_reg_retention_info[group_id].array_size,
REGDMA_LINK_PRI_GPTIMER, module);
ESP_RETURN_ON_ERROR(err, TAG, "create retention link failed");
return ESP_OK;
REGDMA_LINK_PRI_GPTIMER, tg_timer_reg_retention_info[group_id].module);
return err;
}
void gptimer_create_retention_module(gptimer_group_t *group)
{
sleep_retention_module_t module = group->sleep_retention_module;
int group_id = group->group_id;
sleep_retention_module_t module = tg_timer_reg_retention_info[group_id].module;
_lock_acquire(&s_platform.mutex);
if (group->retention_link_created == false) {
if ((sleep_retention_get_inited_modules() & BIT(module)) && !(sleep_retention_get_created_modules() & BIT(module))) {
if (sleep_retention_module_allocate(module) != ESP_OK) {
// even though the sleep retention module create failed, GPTimer driver should still work, so just warning here
ESP_LOGW(TAG, "create retention module for group %d retention, power domain can't turn off", group->group_id);
} else {
group->retention_link_created = true;
ESP_LOGW(TAG, "create retention link failed %d, power domain won't be turned off during sleep", group_id);
}
}
_lock_release(&s_platform.mutex);
@@ -97,9 +94,7 @@ gptimer_group_t *gptimer_acquire_group_handle(int group_id)
},
.depends = BIT(SLEEP_RETENTION_MODULE_CLOCK_SYSTEM)
};
if (sleep_retention_module_init(module, &init_param) == ESP_OK) {
group->sleep_retention_module = module;
} else {
if (sleep_retention_module_init(module, &init_param) != ESP_OK) {
// even though the sleep retention module init failed, RMT driver should still work, so just warning here
ESP_LOGW(TAG, "init sleep retention failed %d, power domain may be turned off during sleep", group_id);
}
@@ -132,11 +127,12 @@ void gptimer_release_group_handle(gptimer_group_t *group)
}
}
#if GPTIMER_USE_RETENTION_LINK
if (group->sleep_retention_module) {
if (group->retention_link_created) {
sleep_retention_module_free(group->sleep_retention_module);
}
sleep_retention_module_deinit(group->sleep_retention_module);
sleep_retention_module_t module = tg_timer_reg_retention_info[group_id].module;
if (sleep_retention_get_created_modules() & BIT(module)) {
sleep_retention_module_free(module);
}
if (sleep_retention_get_inited_modules() & BIT(module)) {
sleep_retention_module_deinit(module);
}
#endif
free(group);

View File

@@ -59,10 +59,6 @@ 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
sleep_retention_module_t sleep_retention_module; // sleep retention module
bool retention_link_created; // mark if the retention link is created
#endif
} gptimer_group_t;
typedef enum {

View File

@@ -10,6 +10,8 @@
#include "freertos/task.h"
#include "unity.h"
#include "driver/gptimer.h"
#include "driver/gpio_etm.h"
#include "driver/gpio.h"
#include "soc/soc_caps.h"
#include "esp_sleep.h"
#include "esp_private/sleep_cpu.h"
@@ -117,3 +119,135 @@ TEST_CASE("gptimer can work after light sleep", "[gptimer]")
test_gptimer_sleep_retention(true);
#endif
}
#if SOC_TIMER_SUPPORT_ETM
/**
* @brief Test the GPTimer and ETM subsystem can still work after light sleep
*
* @param back_up_before_sleep Whether to back up GPTimer registers before sleep
*/
static void test_gptimer_etm_sleep_retention(bool back_up_before_sleep)
{
const uint32_t output_gpio = 1;
// GPTimer alarm ---> ETM channel A ---> GPTimer alarm re-enable
// GPTimer alarm ---> ETM channel B ---> GPIO toggle
printf("allocate etm channel\r\n");
esp_etm_channel_config_t etm_config = {
.flags.allow_pd = back_up_before_sleep,
};
esp_etm_channel_handle_t etm_channel_a, etm_channel_b;
TEST_ESP_OK(esp_etm_new_channel(&etm_config, &etm_channel_a));
TEST_ESP_OK(esp_etm_new_channel(&etm_config, &etm_channel_b));
printf("initialize gpio\r\n");
gpio_config_t task_gpio_config = {
.intr_type = GPIO_INTR_DISABLE,
.mode = GPIO_MODE_OUTPUT,
.pin_bit_mask = 1ULL << output_gpio,
};
TEST_ESP_OK(gpio_config(&task_gpio_config));
printf("create a gptimer\r\n");
gptimer_handle_t gptimer = NULL;
gptimer_config_t timer_config = {
.clk_src = GPTIMER_CLK_SRC_DEFAULT,
.direction = GPTIMER_COUNT_UP,
.resolution_hz = 1 * 1000 * 1000, // 1MHz, 1 tick = 1us
.flags.backup_before_sleep = back_up_before_sleep,
};
TEST_ESP_OK(gptimer_new_timer(&timer_config, &gptimer));
printf("get gptimer etm event and task handle\r\n");
esp_etm_event_handle_t gptimer_event = NULL;
gptimer_etm_event_config_t gptimer_etm_event_conf = {
.event_type = GPTIMER_ETM_EVENT_ALARM_MATCH,
};
TEST_ESP_OK(gptimer_new_etm_event(gptimer, &gptimer_etm_event_conf, &gptimer_event));
esp_etm_task_handle_t gptimer_task = NULL;
gptimer_etm_task_config_t gptimer_etm_task_conf = {
.task_type = GPTIMER_ETM_TASK_EN_ALARM,
};
TEST_ESP_OK(gptimer_new_etm_task(gptimer, &gptimer_etm_task_conf, & gptimer_task));
printf("connect event and task to the channel a\r\n");
TEST_ESP_OK(esp_etm_channel_connect(etm_channel_a, gptimer_event, gptimer_task));
printf("enable etm channels\r\n");
TEST_ESP_OK(esp_etm_channel_enable(etm_channel_a));
TEST_ESP_OK(esp_etm_channel_enable(etm_channel_b));
printf("set timer alarm action\r\n");
gptimer_alarm_config_t alarm_config = {
.reload_count = 0,
.alarm_count = 100, // 100us per alarm event
.flags.auto_reload_on_alarm = true,
};
TEST_ESP_OK(gptimer_set_alarm_action(gptimer, &alarm_config));
// before going to sleep, ensure the gptimer is not enabled yet, otherwise it will acquire power management lock
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 GPTimer and ETM 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_RMT_SUPPORT_SLEEP_RETENTION
// check if the power domain also is powered down
TEST_ASSERT_EQUAL(back_up_before_sleep ? PMU_SLEEP_PD_TOP : 0, (sleep_ctx.sleep_flags) & PMU_SLEEP_PD_TOP);
#endif
esp_sleep_set_sleep_context(NULL);
printf("enable and start timer\r\n");
TEST_ESP_OK(gptimer_enable(gptimer));
TEST_ESP_OK(gptimer_start(gptimer));
printf("allocate GPIO etm task\r\n");
esp_etm_task_handle_t gpio_task = NULL;
gpio_etm_task_config_t gpio_task_config = {
.action = GPIO_ETM_TASK_ACTION_TOG,
};
TEST_ESP_OK(gpio_new_etm_task(&gpio_task_config, &gpio_task));
// set gpio number for the gpio etm primitives
TEST_ESP_OK(gpio_etm_task_add_gpio(gpio_task, output_gpio));
printf("connect event and task to the channel b\r\n");
TEST_ESP_OK(esp_etm_channel_connect(etm_channel_b, gptimer_event, gpio_task));
// delay sometime for us to view the waveform, should see a 5KHz square waveform
vTaskDelay(pdMS_TO_TICKS(1000));
// delete gptimer
TEST_ESP_OK(gptimer_stop(gptimer));
TEST_ESP_OK(gptimer_disable(gptimer));
TEST_ESP_OK(gptimer_del_timer(gptimer));
// delete etm primitives
TEST_ESP_OK(gpio_etm_task_rm_gpio(gpio_task, output_gpio));
TEST_ESP_OK(esp_etm_del_task(gpio_task));
TEST_ESP_OK(esp_etm_del_task(gptimer_task));
TEST_ESP_OK(esp_etm_del_event(gptimer_event));
TEST_ESP_OK(esp_etm_channel_disable(etm_channel_a));
TEST_ESP_OK(esp_etm_channel_disable(etm_channel_b));
TEST_ESP_OK(esp_etm_del_channel(etm_channel_a));
TEST_ESP_OK(esp_etm_del_channel(etm_channel_b));
}
TEST_CASE("gptimer and ETM can work after light sleep", "[gptimer]")
{
test_gptimer_etm_sleep_retention(false);
#if SOC_TIMER_SUPPORT_SLEEP_RETENTION && SOC_ETM_SUPPORT_SLEEP_RETENTION
test_gptimer_etm_sleep_retention(true);
#endif
}
#endif // SOC_TIMER_SUPPORT_ETM

View File

@@ -75,7 +75,7 @@ rmt_group_t *rmt_acquire_group_handle(int group_id)
rmt_ll_reset_register(group_id);
}
#if RMT_USE_RETENTION_LINK
sleep_retention_module_t module = RMT_LL_SLEEP_RETENTION_MODULE_ID(group_id);
sleep_retention_module_t module = rmt_reg_retention_info[group_id].module;
sleep_retention_module_init_param_t init_param = {
.cbs = {
.create = {
@@ -85,9 +85,7 @@ rmt_group_t *rmt_acquire_group_handle(int group_id)
},
.depends = BIT(SLEEP_RETENTION_MODULE_CLOCK_SYSTEM)
};
if (sleep_retention_module_init(module, &init_param) == ESP_OK) {
group->sleep_retention_module = module;
} else {
if (sleep_retention_module_init(module, &init_param) != ESP_OK) {
// even though the sleep retention module init failed, RMT driver should still work, so just warning here
ESP_LOGW(TAG, "init sleep retention failed %d, power domain may be turned off during sleep", group_id);
}
@@ -147,11 +145,12 @@ void rmt_release_group_handle(rmt_group_t *group)
if (do_deinitialize) {
#if RMT_USE_RETENTION_LINK
if (group->sleep_retention_module) {
if (group->retention_link_created) {
sleep_retention_module_free(group->sleep_retention_module);
}
sleep_retention_module_deinit(group->sleep_retention_module);
sleep_retention_module_t module = rmt_reg_retention_info[group_id].module;
if (sleep_retention_get_created_modules() & BIT(module)) {
sleep_retention_module_free(module);
}
if (sleep_retention_get_inited_modules() & BIT(module)) {
sleep_retention_module_deinit(module);
}
#endif
free(group);
@@ -303,24 +302,21 @@ static esp_err_t rmt_create_sleep_retention_link_cb(void *arg)
{
rmt_group_t *group = (rmt_group_t *)arg;
int group_id = group->group_id;
sleep_retention_module_t module = group->sleep_retention_module;
esp_err_t err = sleep_retention_entries_create(rmt_reg_retention_info[group_id].regdma_entry_array,
rmt_reg_retention_info[group_id].array_size,
REGDMA_LINK_PRI_RMT, module);
REGDMA_LINK_PRI_RMT, rmt_reg_retention_info[group_id].module);
return err;
}
void rmt_create_retention_module(rmt_group_t *group)
{
sleep_retention_module_t module = group->sleep_retention_module;
int group_id = group->group_id;
sleep_retention_module_t module = rmt_reg_retention_info[group_id].module;
_lock_acquire(&s_platform.mutex);
if (group->retention_link_created == false) {
if ((sleep_retention_get_inited_modules() & BIT(module)) && !(sleep_retention_get_created_modules() & BIT(module))) {
if (sleep_retention_module_allocate(module) != ESP_OK) {
// even though the sleep retention module create failed, RMT driver should still work, so just warning here
ESP_LOGW(TAG, "create retention link failed, power domain can't be turned off");
} else {
group->retention_link_created = true;
ESP_LOGW(TAG, "create retention link failed, power domain won't be turned off during sleep");
}
}
_lock_release(&s_platform.mutex);

View File

@@ -119,10 +119,6 @@ struct rmt_group_t {
rmt_rx_channel_t *rx_channels[SOC_RMT_RX_CANDIDATES_PER_GROUP]; // array of RMT RX channels
rmt_sync_manager_t *sync_manager; // sync manager, this can be extended into an array if there're more sync controllers in one RMT group
int intr_priority; // RMT interrupt priority
#if RMT_USE_RETENTION_LINK
sleep_retention_module_t sleep_retention_module; // sleep retention module
bool retention_link_created; // mark if the retention link is created
#endif
};
struct rmt_channel_t {

View File

@@ -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
*/
@@ -16,7 +16,7 @@
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "soc/soc_caps.h"
#include "soc/periph_defs.h"
#include "soc/etm_periph.h"
#include "esp_log.h"
#include "esp_check.h"
#include "esp_heap_caps.h"
@@ -25,10 +25,13 @@
#include "hal/etm_ll.h"
#include "esp_private/periph_ctrl.h"
#include "esp_private/etm_interface.h"
#include "esp_private/sleep_retention.h"
#define ETM_MEM_ALLOC_CAPS MALLOC_CAP_DEFAULT
#if CONFIG_IDF_TARGET_ESP32P4
#define ETM_USE_RETENTION_LINK (SOC_ETM_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP)
#if !SOC_RCC_IS_INDEPENDENT
// Reset and Clock Control registers are mixing with other peripherals, so we need to use a critical section
#define ETM_RCC_ATOMIC() PERIPH_RCC_ATOMIC()
#else
@@ -70,6 +73,32 @@ struct esp_etm_channel_t {
// ETM driver platform, it's always a singleton
static etm_platform_t s_platform;
#if ETM_USE_RETENTION_LINK
static esp_err_t etm_create_sleep_retention_link_cb(void *arg)
{
etm_group_t *group = (etm_group_t *)arg;
int group_id = group->group_id;
esp_err_t err = sleep_retention_entries_create(etm_reg_retention_info[group_id].regdma_entry_array,
etm_reg_retention_info[group_id].array_size,
REGDMA_LINK_PRI_ETM, etm_reg_retention_info[group_id].module);
return err;
}
static void etm_create_retention_module(etm_group_t *group)
{
int group_id = group->group_id;
sleep_retention_module_t module = etm_reg_retention_info[group_id].module;
_lock_acquire(&s_platform.mutex);
if ((sleep_retention_get_inited_modules() & BIT(module)) && !(sleep_retention_get_created_modules() & BIT(module))) {
if (sleep_retention_module_allocate(module) != ESP_OK) {
// even though the sleep retention module create failed, ETM driver should still work, so just warning here
ESP_LOGW(TAG, "create retention link failed %d, power domain won't be turned off during sleep", group_id);
}
}
_lock_release(&s_platform.mutex);
}
#endif // ETM_USE_RETENTION_LINK
static etm_group_t *etm_acquire_group_handle(int group_id)
{
bool new_group = false;
@@ -90,7 +119,22 @@ static etm_group_t *etm_acquire_group_handle(int group_id)
etm_ll_enable_bus_clock(group_id, true);
etm_ll_reset_register(group_id);
}
#if ETM_USE_RETENTION_LINK
sleep_retention_module_t module = etm_reg_retention_info[group_id].module;
sleep_retention_module_init_param_t init_param = {
.cbs = {
.create = {
.handle = etm_create_sleep_retention_link_cb,
.arg = group,
},
},
.depends = BIT(SLEEP_RETENTION_MODULE_CLOCK_SYSTEM)
};
if (sleep_retention_module_init(module, &init_param) != ESP_OK) {
// even though the sleep retention module init failed, ETM driver may still work, so just warning here
ESP_LOGW(TAG, "init sleep retention failed %d, power domain may be turned off during sleep", group_id);
}
#endif // ETM_USE_RETENTION_LINK
// initialize HAL context
etm_hal_init(&group->hal);
}
@@ -129,6 +173,15 @@ static void etm_release_group_handle(etm_group_t *group)
_lock_release(&s_platform.mutex);
if (do_deinitialize) {
#if ETM_USE_RETENTION_LINK
sleep_retention_module_t module = etm_reg_retention_info[group_id].module;
if (sleep_retention_get_created_modules() & BIT(module)) {
sleep_retention_module_free(module);
}
if (sleep_retention_get_inited_modules() & BIT(module)) {
sleep_retention_module_deinit(module);
}
#endif
free(group);
ESP_LOGD(TAG, "del group (%d)", group_id);
}
@@ -192,6 +245,9 @@ esp_err_t esp_etm_new_channel(const esp_etm_channel_config_t *config, esp_etm_ch
esp_err_t ret = ESP_OK;
esp_etm_channel_t *chan = NULL;
ESP_GOTO_ON_FALSE(config && ret_chan, ESP_ERR_INVALID_ARG, err, TAG, "invalid args");
#if !SOC_ETM_SUPPORT_SLEEP_RETENTION
ESP_RETURN_ON_FALSE(config->flags.allow_pd == 0, ESP_ERR_NOT_SUPPORTED, TAG, "not able to power down in light sleep");
#endif // SOC_ETM_SUPPORT_SLEEP_RETENTION
chan = heap_caps_calloc(1, sizeof(esp_etm_channel_t), ETM_MEM_ALLOC_CAPS);
ESP_GOTO_ON_FALSE(chan, ESP_ERR_NO_MEM, err, TAG, "no mem for channel");
@@ -201,6 +257,12 @@ esp_err_t esp_etm_new_channel(const esp_etm_channel_config_t *config, esp_etm_ch
int group_id = group->group_id;
int chan_id = chan->chan_id;
#if ETM_USE_RETENTION_LINK
if (config->flags.allow_pd != 0) {
etm_create_retention_module(group);
}
#endif // ETM_USE_RETENTION_LINK
chan->fsm = ETM_CHAN_FSM_INIT;
ESP_LOGD(TAG, "new etm channel (%d,%d) at %p", group_id, chan_id, chan);
*ret_chan = chan;

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -32,7 +32,11 @@ typedef struct esp_etm_task_t *esp_etm_task_handle_t;
* @brief ETM channel configuration
*/
typedef struct {
/// Extra configuration flags for ETM channel
struct etm_chan_flags {
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; /*!< ETM channel flags */
} esp_etm_channel_config_t;
/**

View File

@@ -38,8 +38,6 @@ extern "C" {
#define RMT_LL_MAX_FILTER_VALUE 255
#define RMT_LL_MAX_IDLE_VALUE 32767
#define RMT_LL_SLEEP_RETENTION_MODULE_ID(group_id) (SLEEP_RETENTION_MODULE_RMT0)
typedef enum {
RMT_LL_MEM_OWNER_SW = 0,
RMT_LL_MEM_OWNER_HW = 1,

View File

@@ -38,8 +38,6 @@ extern "C" {
#define RMT_LL_MAX_FILTER_VALUE 255
#define RMT_LL_MAX_IDLE_VALUE 32767
#define RMT_LL_SLEEP_RETENTION_MODULE_ID(group_id) (SLEEP_RETENTION_MODULE_RMT0)
typedef enum {
RMT_LL_MEM_OWNER_SW = 0,
RMT_LL_MEM_OWNER_HW = 1,

View File

@@ -38,8 +38,6 @@ extern "C" {
#define RMT_LL_MAX_FILTER_VALUE 255
#define RMT_LL_MAX_IDLE_VALUE 32767
#define RMT_LL_SLEEP_RETENTION_MODULE_ID(group_id) (SLEEP_RETENTION_MODULE_RMT0)
typedef enum {
RMT_LL_MEM_OWNER_SW = 0,
RMT_LL_MEM_OWNER_HW = 1,

View File

@@ -33,8 +33,6 @@ extern "C" {
#define RMT_LL_EVENT_TX_MASK(channel) (RMT_LL_EVENT_TX_DONE(channel) | RMT_LL_EVENT_TX_THRES(channel) | RMT_LL_EVENT_TX_LOOP_END(channel))
#define RMT_LL_EVENT_RX_MASK(channel) (RMT_LL_EVENT_RX_DONE(channel) | RMT_LL_EVENT_RX_THRES(channel))
#define RMT_LL_SLEEP_RETENTION_MODULE_ID(group_id) (SLEEP_RETENTION_MODULE_RMT0)
#define RMT_LL_MAX_LOOP_COUNT_PER_BATCH 1023
#define RMT_LL_MAX_FILTER_VALUE 255
#define RMT_LL_MAX_IDLE_VALUE 32767

View File

@@ -47,6 +47,10 @@ if(CONFIG_SOC_EMAC_SUPPORTED)
list(APPEND srcs "${target_folder}/emac_periph.c")
endif()
if(CONFIG_SOC_ETM_SUPPORTED)
list(APPEND srcs "${target_folder}/etm_periph.c")
endif()
if(CONFIG_SOC_GDMA_SUPPORTED)
list(APPEND srcs "${target_folder}/gdma_periph.c")
endif()

View File

@@ -0,0 +1,44 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "soc/etm_periph.h"
#include "soc/soc_etm_reg.h"
/**
* ETM Registers to be saved during sleep retention
* - Channel configuration registers, e.g.: SOC_ETM_CH0_EVT_ID_REG, SOC_ETM_CH0_TASK_ID_REG
*/
#define ETM_RETENTION_REGS_CNT ((SOC_ETM_CH49_TASK_ID_REG - SOC_ETM_CH0_EVT_ID_REG) / 4 + 1)
static const regdma_entries_config_t etm_regdma_entries[] = {
// backup stage: save the status of enabled channels
// restore stage: store the enabled channels
[0] = {
.config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_ETM_LINK(0x00),
SOC_ETM_CH_ENA_AD0_REG, SOC_ETM_CH_ENA_AD0_SET_REG, 1, 0, 0),
.owner = ENTRY(0) | ENTRY(2),
},
[1] = {
.config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_ETM_LINK(0x01),
SOC_ETM_CH_ENA_AD1_REG, SOC_ETM_CH_ENA_AD1_SET_REG, 1, 0, 0),
.owner = ENTRY(0) | ENTRY(2),
},
// backup stage: save configuration registers
// restore stage: restore the configuration registers
[2] = {
.config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_ETM_LINK(0x02),
SOC_ETM_CH0_EVT_ID_REG, SOC_ETM_CH0_EVT_ID_REG, ETM_RETENTION_REGS_CNT, 0, 0),
.owner = ENTRY(0) | ENTRY(2),
},
};
const etm_reg_retention_info_t etm_reg_retention_info[SOC_ETM_GROUPS] = {
[0] = {
.module = SLEEP_RETENTION_MODULE_ETM0,
.regdma_entry_array = etm_regdma_entries,
.array_size = ARRAY_SIZE(etm_regdma_entries)
},
};

View File

@@ -463,6 +463,10 @@ config SOC_ETM_CHANNELS_PER_GROUP
int
default 50
config SOC_ETM_SUPPORT_SLEEP_RETENTION
bool
default y
config SOC_GPIO_PORT
int
default 1

View File

@@ -37,6 +37,7 @@ typedef enum periph_retention_module {
SLEEP_RETENTION_MODULE_UART0 = 14,
SLEEP_RETENTION_MODULE_UART1 = 15,
SLEEP_RETENTION_MODULE_I2S0 = 16,
SLEEP_RETENTION_MODULE_ETM0 = 17,
/* modem module, which includes WiFi, BLE and 802.15.4 */
SLEEP_RETENTION_MODULE_WIFI_MAC = 26,
@@ -76,6 +77,7 @@ typedef enum periph_retention_module_bitmap {
SLEEP_RETENTION_MODULE_BM_UART0 = BIT(SLEEP_RETENTION_MODULE_UART0),
SLEEP_RETENTION_MODULE_BM_UART1 = BIT(SLEEP_RETENTION_MODULE_UART1),
SLEEP_RETENTION_MODULE_BM_I2S0 = BIT(SLEEP_RETENTION_MODULE_I2S0),
SLEEP_RETENTION_MODULE_BM_ETM0 = BIT(SLEEP_RETENTION_MODULE_ETM0),
SLEEP_RETENTION_MODULE_BM_GDMA_CH0 = BIT(SLEEP_RETENTION_MODULE_GDMA_CH0),
SLEEP_RETENTION_MODULE_BM_GDMA_CH1 = BIT(SLEEP_RETENTION_MODULE_GDMA_CH1),
@@ -97,6 +99,7 @@ typedef enum periph_retention_module_bitmap {
| SLEEP_RETENTION_MODULE_BM_UART0 \
| SLEEP_RETENTION_MODULE_BM_UART1 \
| SLEEP_RETENTION_MODULE_BM_I2S0 \
| SLEEP_RETENTION_MODULE_BM_ETM0 \
)
#ifdef __cplusplus
}

View File

@@ -191,6 +191,7 @@
/*-------------------------- ETM CAPS --------------------------------------*/
#define SOC_ETM_GROUPS 1U // Number of ETM groups
#define SOC_ETM_CHANNELS_PER_GROUP 50 // Number of ETM channels in the group
#define SOC_ETM_SUPPORT_SLEEP_RETENTION 1 // Support sleep retention
/*-------------------------- GPIO CAPS ---------------------------------------*/
// ESP32-C5 has 1 GPIO peripheral

View File

@@ -60,6 +60,7 @@ static const regdma_entries_config_t rmt_regdma_entries[] = {
const rmt_reg_retention_info_t rmt_reg_retention_info[SOC_RMT_GROUPS] = {
[0] = {
.module = SLEEP_RETENTION_MODULE_RMT0,
.regdma_entry_array = rmt_regdma_entries,
.array_size = ARRAY_SIZE(rmt_regdma_entries)
},

View File

@@ -0,0 +1,44 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "soc/etm_periph.h"
#include "soc/soc_etm_reg.h"
/**
* ETM Registers to be saved during sleep retention
* - Channel configuration registers, e.g.: SOC_ETM_CH0_EVT_ID_REG, SOC_ETM_CH0_TASK_ID_REG
*/
#define ETM_RETENTION_REGS_CNT ((SOC_ETM_CH49_TASK_ID_REG - SOC_ETM_CH0_EVT_ID_REG) / 4 + 1)
static const regdma_entries_config_t etm_regdma_entries[] = {
// backup stage: save the status of enabled channels
// restore stage: store the enabled channels
[0] = {
.config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_ETM_LINK(0x00),
SOC_ETM_CH_ENA_AD0_REG, SOC_ETM_CH_ENA_AD0_SET_REG, 1, 0, 0),
.owner = ENTRY(0) | ENTRY(2),
},
[1] = {
.config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_ETM_LINK(0x01),
SOC_ETM_CH_ENA_AD1_REG, SOC_ETM_CH_ENA_AD1_SET_REG, 1, 0, 0),
.owner = ENTRY(0) | ENTRY(2),
},
// backup stage: save configuration registers
// restore stage: restore the configuration registers
[2] = {
.config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_ETM_LINK(0x02),
SOC_ETM_CH0_EVT_ID_REG, SOC_ETM_CH0_EVT_ID_REG, ETM_RETENTION_REGS_CNT, 0, 0),
.owner = ENTRY(0) | ENTRY(2),
},
};
const etm_reg_retention_info_t etm_reg_retention_info[SOC_ETM_GROUPS] = {
[0] = {
.module = SLEEP_RETENTION_MODULE_ETM0,
.regdma_entry_array = etm_regdma_entries,
.array_size = ARRAY_SIZE(etm_regdma_entries)
},
};

View File

@@ -459,6 +459,10 @@ config SOC_ETM_CHANNELS_PER_GROUP
int
default 50
config SOC_ETM_SUPPORT_SLEEP_RETENTION
bool
default y
config SOC_GPIO_PORT
int
default 1

View File

@@ -37,6 +37,7 @@ typedef enum periph_retention_module {
SLEEP_RETENTION_MODULE_UART0 = 14,
SLEEP_RETENTION_MODULE_UART1 = 15,
SLEEP_RETENTION_MODULE_I2S0 = 16,
SLEEP_RETENTION_MODULE_ETM0 = 17,
/* Modem module, which includes WiFi, BLE and 802.15.4 */
SLEEP_RETENTION_MODULE_WIFI_MAC = 26,
@@ -70,6 +71,7 @@ typedef enum periph_retention_module_bitmap {
SLEEP_RETENTION_MODULE_BM_UART0 = BIT(SLEEP_RETENTION_MODULE_UART0),
SLEEP_RETENTION_MODULE_BM_UART1 = BIT(SLEEP_RETENTION_MODULE_UART1),
SLEEP_RETENTION_MODULE_BM_I2S0 = BIT(SLEEP_RETENTION_MODULE_I2S0),
SLEEP_RETENTION_MODULE_BM_ETM0 = BIT(SLEEP_RETENTION_MODULE_ETM0),
/* 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),
@@ -93,6 +95,7 @@ typedef enum periph_retention_module_bitmap {
| SLEEP_RETENTION_MODULE_BM_UART0 \
| SLEEP_RETENTION_MODULE_BM_UART1 \
| SLEEP_RETENTION_MODULE_BM_I2S0 \
| SLEEP_RETENTION_MODULE_BM_ETM0 \
)
#ifdef __cplusplus

View File

@@ -178,6 +178,7 @@
/*-------------------------- ETM CAPS --------------------------------------*/
#define SOC_ETM_GROUPS 1U // Number of ETM groups
#define SOC_ETM_CHANNELS_PER_GROUP 50 // Number of ETM channels in the group
#define SOC_ETM_SUPPORT_SLEEP_RETENTION 1 // Support sleep retention
/*-------------------------- GPIO CAPS ---------------------------------------*/
// ESP32-C6 has 1 GPIO peripheral

View File

@@ -60,6 +60,7 @@ static const regdma_entries_config_t rmt_regdma_entries[] = {
const rmt_reg_retention_info_t rmt_reg_retention_info[SOC_RMT_GROUPS] = {
[0] = {
.module = SLEEP_RETENTION_MODULE_RMT0,
.regdma_entry_array = rmt_regdma_entries,
.array_size = ARRAY_SIZE(rmt_regdma_entries)
},

View File

@@ -0,0 +1,44 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "soc/etm_periph.h"
#include "soc/soc_etm_reg.h"
/**
* ETM Registers to be saved during sleep retention
* - Channel configuration registers, e.g.: SOC_ETM_CH0_EVT_ID_REG, SOC_ETM_CH0_TASK_ID_REG
*/
#define ETM_RETENTION_REGS_CNT ((SOC_ETM_CH49_TASK_ID_REG - SOC_ETM_CH0_EVT_ID_REG) / 4 + 1)
static const regdma_entries_config_t etm_regdma_entries[] = {
// backup stage: save the status of enabled channels
// restore stage: store the enabled channels
[0] = {
.config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_ETM_LINK(0x00),
SOC_ETM_CH_ENA_AD0_REG, SOC_ETM_CH_ENA_AD0_SET_REG, 1, 0, 0),
.owner = ENTRY(0) | ENTRY(2),
},
[1] = {
.config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_ETM_LINK(0x01),
SOC_ETM_CH_ENA_AD1_REG, SOC_ETM_CH_ENA_AD1_SET_REG, 1, 0, 0),
.owner = ENTRY(0) | ENTRY(2),
},
// backup stage: save configuration registers
// restore stage: restore the configuration registers
[2] = {
.config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_ETM_LINK(0x02),
SOC_ETM_CH0_EVT_ID_REG, SOC_ETM_CH0_EVT_ID_REG, ETM_RETENTION_REGS_CNT, 0, 0),
.owner = ENTRY(0) | ENTRY(2),
},
};
const etm_reg_retention_info_t etm_reg_retention_info[SOC_ETM_GROUPS] = {
[0] = {
.module = SLEEP_RETENTION_MODULE_ETM0,
.regdma_entry_array = etm_regdma_entries,
.array_size = ARRAY_SIZE(etm_regdma_entries)
},
};

View File

@@ -33,6 +33,7 @@ typedef enum periph_retention_module {
SLEEP_RETENTION_MODULE_I2C0 = 12,
SLEEP_RETENTION_MODULE_UART0 = 14,
SLEEP_RETENTION_MODULE_UART1 = 15,
SLEEP_RETENTION_MODULE_ETM0 = 16,
/* Modem module, which includes WiFi, BLE and 802.15.4 */
SLEEP_RETENTION_MODULE_WIFI_MAC = 26,
@@ -62,6 +63,7 @@ typedef enum periph_retention_module_bitmap {
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),
SLEEP_RETENTION_MODULE_BM_ETM0 = BIT(SLEEP_RETENTION_MODULE_ETM0),
/* 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),
@@ -81,6 +83,7 @@ typedef enum periph_retention_module_bitmap {
| SLEEP_RETENTION_MODULE_BM_I2C0 \
| SLEEP_RETENTION_MODULE_BM_UART0 \
| SLEEP_RETENTION_MODULE_BM_UART1 \
| SLEEP_RETENTION_MODULE_BM_ETM0 \
)
#ifdef __cplusplus

View File

@@ -154,6 +154,7 @@
/*-------------------------- ETM CAPS --------------------------------------*/
#define SOC_ETM_GROUPS 1U // Number of ETM groups
#define SOC_ETM_CHANNELS_PER_GROUP 50 // Number of ETM channels in the group
// #define SOC_ETM_SUPPORT_SLEEP_RETENTION 1 // Support sleep retention
/*-------------------------- GPIO CAPS ---------------------------------------*/
// ESP32-C61 has 1 GPIO peripheral

View File

@@ -0,0 +1,44 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "soc/etm_periph.h"
#include "soc/soc_etm_reg.h"
/**
* ETM Registers to be saved during sleep retention
* - Channel configuration registers, e.g.: SOC_ETM_CH0_EVT_ID_REG, SOC_ETM_CH0_TASK_ID_REG
*/
#define ETM_RETENTION_REGS_CNT ((SOC_ETM_CH49_TASK_ID_REG - SOC_ETM_CH0_EVT_ID_REG) / 4 + 1)
static const regdma_entries_config_t etm_regdma_entries[] = {
// backup stage: save the status of enabled channels
// restore stage: store the enabled channels
[0] = {
.config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_ETM_LINK(0x00),
SOC_ETM_CH_ENA_AD0_REG, SOC_ETM_CH_ENA_AD0_SET_REG, 1, 0, 0),
.owner = ENTRY(0) | ENTRY(2),
},
[1] = {
.config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_ETM_LINK(0x01),
SOC_ETM_CH_ENA_AD1_REG, SOC_ETM_CH_ENA_AD1_SET_REG, 1, 0, 0),
.owner = ENTRY(0) | ENTRY(2),
},
// backup stage: save configuration registers
// restore stage: restore the configuration registers
[2] = {
.config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_ETM_LINK(0x02),
SOC_ETM_CH0_EVT_ID_REG, SOC_ETM_CH0_EVT_ID_REG, ETM_RETENTION_REGS_CNT, 0, 0),
.owner = ENTRY(0) | ENTRY(2),
},
};
const etm_reg_retention_info_t etm_reg_retention_info[SOC_ETM_GROUPS] = {
[0] = {
.module = SLEEP_RETENTION_MODULE_ETM0,
.regdma_entry_array = etm_regdma_entries,
.array_size = ARRAY_SIZE(etm_regdma_entries)
},
};

View File

@@ -467,6 +467,10 @@ config SOC_ETM_CHANNELS_PER_GROUP
int
default 50
config SOC_ETM_SUPPORT_SLEEP_RETENTION
bool
default y
config SOC_GPIO_PORT
int
default 1

View File

@@ -38,6 +38,7 @@ typedef enum periph_retention_module {
SLEEP_RETENTION_MODULE_UART0 = 15,
SLEEP_RETENTION_MODULE_UART1 = 16,
SLEEP_RETENTION_MODULE_I2S0 = 17,
SLEEP_RETENTION_MODULE_ETM0 = 18,
/* Modem module, which includes BLE and 802.15.4 */
SLEEP_RETENTION_MODULE_BLE_MAC = 28,
@@ -70,6 +71,7 @@ typedef enum periph_retention_module_bitmap {
SLEEP_RETENTION_MODULE_BM_UART0 = BIT(SLEEP_RETENTION_MODULE_UART0),
SLEEP_RETENTION_MODULE_BM_UART1 = BIT(SLEEP_RETENTION_MODULE_UART1),
SLEEP_RETENTION_MODULE_BM_I2S0 = BIT(SLEEP_RETENTION_MODULE_I2S0),
SLEEP_RETENTION_MODULE_BM_ETM0 = BIT(SLEEP_RETENTION_MODULE_ETM0),
/* 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),
@@ -92,6 +94,7 @@ typedef enum periph_retention_module_bitmap {
| SLEEP_RETENTION_MODULE_BM_UART0 \
| SLEEP_RETENTION_MODULE_BM_UART1 \
| SLEEP_RETENTION_MODULE_BM_I2S0 \
| SLEEP_RETENTION_MODULE_BM_ETM0 \
)
#ifdef __cplusplus

View File

@@ -181,6 +181,7 @@
/*-------------------------- ETM CAPS --------------------------------------*/
#define SOC_ETM_GROUPS 1U // Number of ETM groups
#define SOC_ETM_CHANNELS_PER_GROUP 50 // Number of ETM channels in the group
#define SOC_ETM_SUPPORT_SLEEP_RETENTION 1 // Support sleep retention
/*-------------------------- GPIO CAPS ---------------------------------------*/
// ESP32-H2 has 1 GPIO peripheral

View File

@@ -60,6 +60,7 @@ static const regdma_entries_config_t rmt_regdma_entries[] = {
const rmt_reg_retention_info_t rmt_reg_retention_info[SOC_RMT_GROUPS] = {
[0] = {
.module = SLEEP_RETENTION_MODULE_RMT0,
.regdma_entry_array = rmt_regdma_entries,
.array_size = ARRAY_SIZE(rmt_regdma_entries)
},

View File

@@ -0,0 +1,44 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "soc/etm_periph.h"
#include "soc/soc_etm_reg.h"
/**
* ETM Registers to be saved during sleep retention
* - Channel configuration registers, e.g.: SOC_ETM_CH0_EVT_ID_REG, SOC_ETM_CH0_TASK_ID_REG
*/
#define ETM_RETENTION_REGS_CNT ((SOC_ETM_CH49_TASK_ID_REG - SOC_ETM_CH0_EVT_ID_REG) / 4 + 1)
static const regdma_entries_config_t etm_regdma_entries[] = {
// backup stage: save the status of enabled channels
// restore stage: store the enabled channels
[0] = {
.config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_ETM_LINK(0x00),
SOC_ETM_CH_ENA_AD0_REG, SOC_ETM_CH_ENA_AD0_SET_REG, 1, 0, 0),
.owner = ENTRY(0),
},
[1] = {
.config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_ETM_LINK(0x01),
SOC_ETM_CH_ENA_AD1_REG, SOC_ETM_CH_ENA_AD1_SET_REG, 1, 0, 0),
.owner = ENTRY(0),
},
// backup stage: save configuration registers
// restore stage: restore the configuration registers
[2] = {
.config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_ETM_LINK(0x02),
SOC_ETM_CH0_EVT_ID_REG, SOC_ETM_CH0_EVT_ID_REG, ETM_RETENTION_REGS_CNT, 0, 0),
.owner = ENTRY(0),
},
};
const etm_reg_retention_info_t etm_reg_retention_info[SOC_ETM_GROUPS] = {
[0] = {
.module = SLEEP_RETENTION_MODULE_ETM0,
.regdma_entry_array = etm_regdma_entries,
.array_size = ARRAY_SIZE(etm_regdma_entries)
},
};

View File

@@ -595,6 +595,10 @@ config SOC_ETM_CHANNELS_PER_GROUP
int
default 50
config SOC_ETM_SUPPORT_SLEEP_RETENTION
bool
default y
config SOC_GPIO_PORT
int
default 1

View File

@@ -46,6 +46,7 @@ typedef enum periph_retention_module {
SLEEP_RETENTION_MODULE_I2S2 = 21,
SLEEP_RETENTION_MODULE_I2C0 = 22,
SLEEP_RETENTION_MODULE_I2C1 = 23,
SLEEP_RETENTION_MODULE_ETM0 = 24,
SLEEP_RETENTION_MODULE_MAX = 31
} periph_retention_module_t;
@@ -79,6 +80,7 @@ typedef enum periph_retention_module_bitmap {
SLEEP_RETENTION_MODULE_BM_I2S0 = BIT(SLEEP_RETENTION_MODULE_I2S0),
SLEEP_RETENTION_MODULE_BM_I2S1 = BIT(SLEEP_RETENTION_MODULE_I2S1),
SLEEP_RETENTION_MODULE_BM_I2S2 = BIT(SLEEP_RETENTION_MODULE_I2S2),
SLEEP_RETENTION_MODULE_BM_ETM0 = BIT(SLEEP_RETENTION_MODULE_ETM0),
SLEEP_RETENTION_MODULE_BM_ALL = (uint32_t)-1
} periph_retention_module_bitmap_t;
@@ -100,9 +102,10 @@ typedef enum periph_retention_module_bitmap {
| SLEEP_RETENTION_MODULE_BM_UART3 \
| SLEEP_RETENTION_MODULE_BM_UART4 \
| SLEEP_RETENTION_MODULE_BM_RMT0 \
| SLEEP_RETENTION_MODULE_BM_I2S0 \
| SLEEP_RETENTION_MODULE_BM_I2S1 \
| SLEEP_RETENTION_MODULE_BM_I2S2 \
| SLEEP_RETENTION_MODULE_BM_I2S0 \
| SLEEP_RETENTION_MODULE_BM_I2S1 \
| SLEEP_RETENTION_MODULE_BM_I2S2 \
| SLEEP_RETENTION_MODULE_BM_ETM0 \
)
#ifdef __cplusplus

View File

@@ -221,6 +221,7 @@
/*-------------------------- ETM CAPS --------------------------------------*/
#define SOC_ETM_GROUPS 1U // Number of ETM groups
#define SOC_ETM_CHANNELS_PER_GROUP 50 // Number of ETM channels in the group
#define SOC_ETM_SUPPORT_SLEEP_RETENTION 1 // Support sleep retention
/*-------------------------- GPIO CAPS ---------------------------------------*/
// ESP32-P4 has 1 GPIO peripheral

View File

@@ -76,6 +76,7 @@ static const regdma_entries_config_t rmt_regdma_entries[] = {
const rmt_reg_retention_info_t rmt_reg_retention_info[SOC_RMT_GROUPS] = {
[0] = {
.module = SLEEP_RETENTION_MODULE_RMT0,
.regdma_entry_array = rmt_regdma_entries,
.array_size = ARRAY_SIZE(rmt_regdma_entries)
},

View File

@@ -0,0 +1,32 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "soc/soc_caps.h"
#include "soc/regdma.h"
#if SOC_ETM_SUPPORT_SLEEP_RETENTION
#include "soc/retention_periph_defs.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
#if SOC_ETM_SUPPORT_SLEEP_RETENTION
typedef struct {
periph_retention_module_t module;
const regdma_entries_config_t *regdma_entry_array;
uint32_t array_size;
} etm_reg_retention_info_t;
extern const etm_reg_retention_info_t etm_reg_retention_info[SOC_ETM_GROUPS];
#endif // SOC_ETM_SUPPORT_SLEEP_RETENTION
#ifdef __cplusplus
}
#endif

View File

@@ -54,6 +54,7 @@ extern "C" {
#define REGDMA_TG0_TIMER_LINK(_pri) ((0x1C << 8) | _pri)
#define REGDMA_TG1_TIMER_LINK(_pri) ((0x1D << 8) | _pri)
#define REGDMA_I2S_LINK(_pri) ((0x1E << 8) | _pri)
#define REGDMA_ETM_LINK(_pri) ((0x1F << 8) | _pri)
#define REGDMA_MODEM_FE_LINK(_pri) ((0xFF << 8) | _pri)
#define REGDMA_LINK_PRI_SYS_CLK REGDMA_LINK_PRI_0
@@ -68,6 +69,7 @@ extern "C" {
#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_ETM REGDMA_LINK_PRI_GENERAL_PERIPH
#define REGDMA_LINK_PRI_GPTIMER REGDMA_LINK_PRI_GENERAL_PERIPH
#define REGDMA_LINK_PRI_I2C REGDMA_LINK_PRI_GENERAL_PERIPH
#define REGDMA_LINK_PRI_I2S REGDMA_LINK_PRI_GENERAL_PERIPH

View File

@@ -10,6 +10,10 @@
#include "soc/periph_defs.h"
#include "soc/regdma.h"
#if SOC_RMT_SUPPORT_SLEEP_RETENTION
#include "soc/retention_periph_defs.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
@@ -32,6 +36,7 @@ extern const rmt_signal_conn_t rmt_periph_signals;
#if SOC_RMT_SUPPORT_SLEEP_RETENTION
typedef struct {
periph_retention_module_t module;
const regdma_entries_config_t *regdma_entry_array;
uint32_t array_size;
} rmt_reg_retention_info_t;

View File

@@ -32,6 +32,7 @@ The following sections of this document cover the typical steps to configure and
- :ref:`etm-event` - describes how to allocate a new ETM event handle or fetch an existing handle from various peripherals.
- :ref:`etm-task` - describes how to allocate a new ETM task handle or fetch an existing handle from various peripherals.
- :ref:`etm-channel-control` - describes common ETM channel control functions.
- :ref:`etm-power-management` - describes the options and strategies provided by the driver in order to save power.
- :ref:`etm-thread-safety` - lists which APIs are guaranteed to be thread-safe by the driver.
- :ref:`etm-kconfig-options` - lists the supported Kconfig options that can be used to make a different effect on driver behavior.
@@ -131,6 +132,17 @@ To check if the ETM channels are set with proper events and tasks, you can call
The digital ID printed in the dump information is defined in the ``soc/soc_etm_source.h`` file.
.. _etm-power-management:
Power Management
^^^^^^^^^^^^^^^^
When power management is enabled, i.e., :ref:`CONFIG_PM_ENABLE` is on, the system may adjust or disable the clock source, and power off the ETM peripheral before going to sleep. As a result, the existing connection between events and tasks will be lost, and the ETM channels can't work correctly after wake up. So by default, the driver will acquire a power management lock internally to forbid the system from powering off the ETM peripheral.
.. only:: SOC_ETM_SUPPORT_SLEEP_RETENTION
If you want to save more power, you can set :cpp:member:`esp_etm_channel_config_t::etm_chan_flags::allow_pd` to ``true``. Then ETM registers will be backed up before sleep and restored after wake up. Please note, enabling this option will increase the memory consumption for saving the register context.
.. _etm-thread-safety:
Thread Safety

View File

@@ -148,10 +148,11 @@ The following peripheral drivers are not aware of DFS yet. Applications need to
- INT_MTX
- TEE/APM
- IO_MUX / GPIO
- Timer Group 0 & Timer Group 1
- SPI0/1
- SYSTIMER
:SOC_TIMER_SUPPORT_SLEEP_RETENTION: - GPTimer
:SOC_RMT_SUPPORT_SLEEP_RETENTION: - RMT
:SOC_ETM_SUPPORT_SLEEP_RETENTION: - ETM
:SOC_I2C_SUPPORT_SLEEP_RETENTION: - I2C
:SOC_I2S_SUPPORT_SLEEP_RETENTION: - I2S
:SOC_UART_SUPPORT_SLEEP_RETENTION: - All UARTs
@@ -160,7 +161,6 @@ The following peripheral drivers are not aware of DFS yet. Applications need to
.. list::
- ETM
- ASSIST_DEBUG
- Trace
- Crypto: AES/ECC/HMAC/RSA/SHA/DS/XTA_AES/ECDSA

View File

@@ -32,6 +32,7 @@ ETM 模块具有多个通道,这些通道支持用户根据需要进行配置
- :ref:`etm-event` - 介绍如何分配新的 ETM 事件句柄,以及如何从不同外设获取现有句柄。
- :ref:`etm-task` - 介绍如何分配新的 ETM 任务句柄,以及如何从不同外设获取现有句柄。
- :ref:`etm-channel-control` - 介绍常见的 ETM 通道控制函数。
- :ref:`etm-power-management` - 介绍了驱动针对功耗管理提供的选项和策略。
- :ref:`etm-thread-safety` - 列出了驱动程序中始终线程安全的 API。
- :ref:`etm-kconfig-options` - 列出了 ETM 支持的 Kconfig 选项,这些选项对驱动程序的行为会产生不同影响。
@@ -131,6 +132,17 @@ ETM 通道分析
以上输出信息打印的数字 ID 在 ``soc/soc_etm_source.h`` 文件中定义。
.. _etm-power-management:
电源管理
^^^^^^^^
当启用电源管理时,即 :ref:`CONFIG_PM_ENABLE` 打开的时候,系统可能会调整或禁用时钟源,并在进入睡眠前关闭 ETM 外设依赖的电源。这会导致事件和任务之间的连接信息被丢失ETM 通道在唤醒后无法正常工作。因此,默认情况下,驱动程序会获取电源管理锁,以禁止系统关闭 ETM 外设。
.. only:: SOC_ETM_SUPPORT_SLEEP_RETENTION
如果你想节省更多电量,可以将 :cpp:member:`esp_etm_channel_config_t::etm_chan_flags::allow_pd` 设置为 ``true``。ETM 寄存器将在睡眠前备份,并在唤醒后恢复。请注意,启用此选项会增加内存消耗,用于保存寄存器上下文。
.. _etm-thread-safety:
线程安全

View File

@@ -148,19 +148,19 @@ ESP-IDF 中集成的电源管理算法可以根据应用程序组件的需求,
- INT_MTX
- TEE/APM
- IO_MUX / GPIO
- Timer Group 0 & Timer Group 1
- SPI0/1
- SYSTIMER
:SOC_TIMER_SUPPORT_SLEEP_RETENTION: - GPTimer
:SOC_RMT_SUPPORT_SLEEP_RETENTION: - RMT
:SOC_I2C_SUPPORT_SLEEP_RETENTION: - I2C
:SOC_I2S_SUPPORT_SLEEP_RETENTION: - I2S
:SOC_ETM_SUPPORT_SLEEP_RETENTION: - ETM
:SOC_UART_SUPPORT_SLEEP_RETENTION: - All UARTs
以下外设尚未支持:
.. list::
- ETM
- ASSIST_DEBUG
- Trace
- Crypto: AES/ECC/HMAC/RSA/SHA/DS/XTA_AES/ECDSA