feat(etm): support sleep retention

This commit is contained in:
morris
2024-09-24 18:42:00 +08:00
parent 6846245815
commit 0722aa8209
28 changed files with 397 additions and 13 deletions

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

@@ -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

@@ -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

@@ -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

@@ -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;
@@ -103,6 +105,7 @@ typedef enum periph_retention_module_bitmap {
| 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

@@ -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

@@ -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