Merge branch 'feature/support_esp32s3_cpu_tagmem_retention' into 'master'

support esp32s3 cpu + tagmem retention

See merge request espressif/esp-idf!14579
This commit is contained in:
Jiang Jiang Jian 2021-09-06 03:47:44 +00:00
commit 316988bd2d
19 changed files with 946 additions and 205 deletions

View File

@ -15,7 +15,12 @@ if(NOT BOOTLOADER_BUILD)
"intr_alloc.c"
"mac_addr.c"
"sleep_modes.c"
"sleep_gpio.c"
"sleep_mac_bb.c"
"regi2c_ctrl.c")
if(NOT CONFIG_IDF_TARGET_ESP32 AND NOT CONFIG_IDF_TARGET_ESP32S2)
list(APPEND srcs "sleep_retention.c")
endif()
list(APPEND requires esp_ipc)
else()
# Requires "_esp_error_check_failed()" function

View File

@ -6,6 +6,9 @@ ifdef IS_BOOTLOADER_BUILD
COMPONENT_OBJEXCLUDE += clk_ctrl_os.o \
intr_alloc.o \
sleep_modes.o \
sleep_gpio.o \
sleep_mac_bb.o \
sleep_retention.o \
esp_async_memcpy.o \
mac_addr.o \
regi2c_ctrl.o \
@ -16,4 +19,11 @@ COMPONENT_OBJEXCLUDE += clk_ctrl_os.o \
port/$(IDF_TARGET)/spiram_psram.o
endif
ifdef CONFIG_IDF_TARGET_ESP32
COMPONENT_OBJEXCLUDE += sleep_retention.o
endif
ifdef CONFIG_IDF_TARGET_ESP32S2
COMPONENT_OBJEXCLUDE += sleep_retention.o
endif
COMPONENT_OBJEXCLUDE += esp_async_memcpy.o

View File

@ -0,0 +1,46 @@
/*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#include "sdkconfig.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @file sleep_gpio.h
*
* This file contains declarations of GPIO related functions in light sleep mode.
*/
#if SOC_GPIO_SUPPORT_SLP_SWITCH && CONFIG_GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL
/**
* @brief Save GPIO pull-up and pull-down configuration information in the wake-up state
*
* In light sleep mode, the pull-up and pull-down resistors of GPIO will cause
* leakage current when the system sleeps. In order to reduce the power
* consumption of system sleep, it needs to save the configuration information
* of all GPIO pull-up and pull-down resistors and disable the pull-up and
* pull-down resistors of GPIO before the system enters sleep.
*/
void gpio_sleep_mode_config_apply(void);
/**
* @brief Restore GPIO pull-up and pull-down configuration information in the wake-up state
*
* In light sleep mode, after the system wakes up, it needs to restore all GPIO
* pull-up and pull-down configurations before the last sleep.
*/
void gpio_sleep_mode_config_unapply(void);
#endif // SOC_GPIO_SUPPORT_SLP_SWITCH && CONFIG_GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,43 @@
/*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#include "sdkconfig.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @file sleep_mac_bb.h
*
* This file contains declarations of MAC and baseband power consumption related functions in light sleep mode.
*/
#if CONFIG_MAC_BB_PD
/**
* @brief A callback function completes MAC and baseband power down operation
*
* In light sleep mode, execute Wi-Fi and Bluetooth module MAC and baseband
* power down and backup register configuration information operations.
*/
void mac_bb_power_down_cb_execute(void);
/**
* @brief A callback function completes MAC and baseband power up operation
*
* In light sleep mode, execute Wi-Fi and Bluetooth module MAC and baseband
* power up and restore register configuration information operations.
*/
void mac_bb_power_up_cb_execute(void);
#endif // CONFIG_MAC_BB_PD
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,55 @@
/*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#include "sdkconfig.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @file sleep_retention.h
*
* This file contains declarations of memory retention related functions in light sleeo mode.
*/
#if SOC_PM_SUPPORT_CPU_PD
/**
* @brief Whether to allow the cpu power domain to be powered off.
*
* In light sleep mode, only when the system can provide enough memory
* for cpu retention, the cpu power domain can be powered off.
*/
bool cpu_domain_pd_allowed(void);
#endif
#if SOC_PM_SUPPORT_CPU_PD || SOC_PM_SUPPORT_TAGMEM_PD
/**
* @brief Enable memory retention of some modules.
*
* In light sleep mode, before the system goes to sleep, enable the memory
* retention of modules such as CPU and I/D-cache tag memory.
*/
void sleep_enable_memory_retention(void);
/**
* @brief Disable memory retention of some modules.
*
* In light sleep mode, after the system exits sleep, disable the memory
* retention of moudles such as CPU and I/D-cache tag memory.
*/
void sleep_disable_memory_retention(void);
#endif // SOC_PM_SUPPORT_CPU_PD || SOC_PM_SUPPORT_TAGMEM_PD
#ifdef __cplusplus
}
#endif

View File

@ -41,7 +41,9 @@ typedef enum {
ESP_PD_DOMAIN_RTC_SLOW_MEM, //!< RTC slow memory
ESP_PD_DOMAIN_RTC_FAST_MEM, //!< RTC fast memory
ESP_PD_DOMAIN_XTAL, //!< XTAL oscillator
#if SOC_PM_SUPPORT_CPU_PD
ESP_PD_DOMAIN_CPU, //!< CPU core
#endif
ESP_PD_DOMAIN_VDDSDIO, //!< VDD_SDIO
ESP_PD_DOMAIN_MAX //!< Number of domains
} esp_sleep_pd_domain_t;

View File

@ -0,0 +1,72 @@
/*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stddef.h>
#include <string.h>
#include <sys/lock.h>
#include <sys/param.h>
#include "esp_attr.h"
#include "esp_sleep.h"
#include "esp_log.h"
#include "soc/soc_caps.h"
#include "sdkconfig.h"
#include "driver/gpio.h"
#include "esp_private/gpio.h"
#include "esp_private/sleep_gpio.h"
static const char *TAG = "sleep";
#if SOC_GPIO_SUPPORT_SLP_SWITCH
#if CONFIG_GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL
void gpio_sleep_mode_config_apply(void)
{
for (gpio_num_t gpio_num = GPIO_NUM_0; gpio_num < GPIO_NUM_MAX; gpio_num++) {
if (GPIO_IS_VALID_GPIO(gpio_num)) {
gpio_sleep_pupd_config_apply(gpio_num);
}
}
}
IRAM_ATTR void gpio_sleep_mode_config_unapply(void)
{
for (gpio_num_t gpio_num = GPIO_NUM_0; gpio_num < GPIO_NUM_MAX; gpio_num++) {
if (GPIO_IS_VALID_GPIO(gpio_num)) {
gpio_sleep_pupd_config_unapply(gpio_num);
}
}
}
#endif
void esp_sleep_config_gpio_isolate(void)
{
ESP_LOGI(TAG, "Configure to isolate all GPIO pins in sleep state");
for (gpio_num_t gpio_num = GPIO_NUM_0; gpio_num < GPIO_NUM_MAX; gpio_num++) {
if (GPIO_IS_VALID_GPIO(gpio_num)) {
gpio_sleep_set_direction(gpio_num, GPIO_MODE_DISABLE);
gpio_sleep_set_pull_mode(gpio_num, GPIO_FLOATING);
}
}
}
void esp_sleep_enable_gpio_switch(bool enable)
{
ESP_LOGI(TAG, "%s automatic switching of GPIO sleep configuration", enable ? "Enable" : "Disable");
for (gpio_num_t gpio_num = GPIO_NUM_0; gpio_num < GPIO_NUM_MAX; gpio_num++) {
if (GPIO_IS_VALID_GPIO(gpio_num)) {
if (enable) {
gpio_sleep_sel_en(gpio_num);
} else {
gpio_sleep_sel_dis(gpio_num);
}
}
}
}
#endif // SOC_GPIO_SUPPORT_SLP_SWITCH

View File

@ -0,0 +1,108 @@
/*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stddef.h>
#include <string.h>
#include <sys/lock.h>
#include <sys/param.h>
#include "esp_attr.h"
#include "esp_sleep.h"
#include "soc/soc_caps.h"
#include "esp_private/sleep_mac_bb.h"
#include "sdkconfig.h"
#if CONFIG_MAC_BB_PD
#define MAC_BB_POWER_DOWN_CB_NO (2)
#define MAC_BB_POWER_UP_CB_NO (2)
static DRAM_ATTR mac_bb_power_down_cb_t s_mac_bb_power_down_cb[MAC_BB_POWER_DOWN_CB_NO];
static DRAM_ATTR mac_bb_power_up_cb_t s_mac_bb_power_up_cb[MAC_BB_POWER_UP_CB_NO];
esp_err_t esp_register_mac_bb_pd_callback(mac_bb_power_down_cb_t cb)
{
int index = MAC_BB_POWER_DOWN_CB_NO;
for (int i = MAC_BB_POWER_DOWN_CB_NO - 1; i >= 0; i--) {
if (s_mac_bb_power_down_cb[i] == cb) {
return ESP_OK;
}
if (s_mac_bb_power_down_cb[i] == NULL) {
index = i;
}
}
if (index < MAC_BB_POWER_DOWN_CB_NO) {
s_mac_bb_power_down_cb[index] = cb;
return ESP_OK;
}
return ESP_ERR_NO_MEM;
}
esp_err_t esp_unregister_mac_bb_pd_callback(mac_bb_power_down_cb_t cb)
{
for (int i = MAC_BB_POWER_DOWN_CB_NO - 1; i >= 0; i--) {
if (s_mac_bb_power_down_cb[i] == cb) {
s_mac_bb_power_down_cb[i] = NULL;
return ESP_OK;
}
}
return ESP_ERR_INVALID_STATE;
}
void IRAM_ATTR mac_bb_power_down_cb_execute(void)
{
for (int i = 0; i < MAC_BB_POWER_DOWN_CB_NO; i++) {
if (s_mac_bb_power_down_cb[i]) {
s_mac_bb_power_down_cb[i]();
}
}
}
esp_err_t esp_register_mac_bb_pu_callback(mac_bb_power_up_cb_t cb)
{
int index = MAC_BB_POWER_UP_CB_NO;
for (int i = MAC_BB_POWER_UP_CB_NO - 1; i >= 0; i--) {
if (s_mac_bb_power_up_cb[i] == cb) {
return ESP_OK;
}
if (s_mac_bb_power_up_cb[i] == NULL) {
index = i;
}
}
if (index < MAC_BB_POWER_UP_CB_NO) {
s_mac_bb_power_up_cb[index] = cb;
return ESP_OK;
}
return ESP_ERR_NO_MEM;
}
esp_err_t esp_unregister_mac_bb_pu_callback(mac_bb_power_up_cb_t cb)
{
for (int i = MAC_BB_POWER_UP_CB_NO - 1; i >= 0; i--) {
if (s_mac_bb_power_up_cb[i] == cb) {
s_mac_bb_power_up_cb[i] = NULL;
return ESP_OK;
}
}
return ESP_ERR_INVALID_STATE;
}
void IRAM_ATTR mac_bb_power_up_cb_execute(void)
{
for (int i = 0; i < MAC_BB_POWER_UP_CB_NO; i++) {
if (s_mac_bb_power_up_cb[i]) {
s_mac_bb_power_up_cb[i]();
}
}
}
#endif ///CONFIG_MAC_BB_PD

View File

@ -43,12 +43,14 @@
#include "esp_rom_uart.h"
#include "esp_rom_sys.h"
#include "brownout.h"
#include "esp_private/sleep_retention.h"
#ifdef CONFIG_IDF_TARGET_ESP32
#include "esp32/rom/cache.h"
#include "esp32/rom/rtc.h"
#include "esp32/clk.h"
#include "esp_private/gpio.h"
#include "esp_private/sleep_gpio.h"
#elif CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/clk.h"
#include "esp32s2/rom/cache.h"
@ -60,18 +62,18 @@
#include "esp32s3/rom/cache.h"
#include "esp32s3/rom/rtc.h"
#include "soc/extmem_reg.h"
#include "esp_private/sleep_mac_bb.h"
#elif CONFIG_IDF_TARGET_ESP32C3
#include "esp32c3/clk.h"
#include "esp32c3/rom/cache.h"
#include "esp32c3/rom/rtc.h"
#include "soc/extmem_reg.h"
#include "esp_heap_caps.h"
#include "esp_private/sleep_mac_bb.h"
#elif CONFIG_IDF_TARGET_ESP32H2
#include "esp32h2/clk.h"
#include "esp32h2/rom/cache.h"
#include "esp32h2/rom/rtc.h"
#include "soc/extmem_reg.h"
#include "esp_heap_caps.h"
#endif
// If light sleep time is less than that, don't power down flash
@ -148,13 +150,16 @@ typedef struct {
uint32_t sleep_time_overhead_out;
uint32_t rtc_clk_cal_period;
uint64_t rtc_ticks_at_sleep_start;
#if SOC_PM_SUPPORT_CPU_PD
void *cpu_pd_mem;
#endif
} sleep_config_t;
static sleep_config_t s_config = {
.pd_options = { ESP_PD_OPTION_AUTO, ESP_PD_OPTION_AUTO, ESP_PD_OPTION_AUTO, ESP_PD_OPTION_AUTO, ESP_PD_OPTION_AUTO, ESP_PD_OPTION_AUTO },
.pd_options = {
ESP_PD_OPTION_AUTO, ESP_PD_OPTION_AUTO, ESP_PD_OPTION_AUTO, ESP_PD_OPTION_AUTO,
#if SOC_PM_SUPPORT_CPU_PD
ESP_PD_OPTION_AUTO,
#endif
ESP_PD_OPTION_AUTO
},
.ccount_ticks_record = 0,
.sleep_time_overhead_out = DEFAULT_SLEEP_OUT_OVERHEAD_US,
.wakeup_triggers = 0
@ -183,95 +188,6 @@ static void touch_wakeup_prepare(void);
static void esp_deep_sleep_wakeup_prepare(void);
#endif
#if CONFIG_MAC_BB_PD
#define MAC_BB_POWER_DOWN_CB_NO 2
#define MAC_BB_POWER_UP_CB_NO 2
static DRAM_ATTR mac_bb_power_down_cb_t s_mac_bb_power_down_cb[MAC_BB_POWER_DOWN_CB_NO];
static DRAM_ATTR mac_bb_power_up_cb_t s_mac_bb_power_up_cb[MAC_BB_POWER_UP_CB_NO];
esp_err_t esp_register_mac_bb_pd_callback(mac_bb_power_down_cb_t cb)
{
int index = MAC_BB_POWER_DOWN_CB_NO;
for (int i = MAC_BB_POWER_DOWN_CB_NO - 1; i >= 0; i--) {
if (s_mac_bb_power_down_cb[i] == cb) {
return ESP_OK;
}
if (s_mac_bb_power_down_cb[i] == NULL) {
index = i;
}
}
if (index < MAC_BB_POWER_DOWN_CB_NO) {
s_mac_bb_power_down_cb[index] = cb;
return ESP_OK;
}
return ESP_ERR_NO_MEM;
}
esp_err_t esp_unregister_mac_bb_pd_callback(mac_bb_power_down_cb_t cb)
{
for (int i = MAC_BB_POWER_DOWN_CB_NO - 1; i >= 0; i--) {
if (s_mac_bb_power_down_cb[i] == cb) {
s_mac_bb_power_down_cb[i] = NULL;
return ESP_OK;
}
}
return ESP_ERR_INVALID_STATE;
}
static IRAM_ATTR void mac_bb_power_down_cb_execute(void)
{
for (int i = 0; i < MAC_BB_POWER_DOWN_CB_NO; i++) {
if (s_mac_bb_power_down_cb[i]) {
s_mac_bb_power_down_cb[i]();
}
}
}
esp_err_t esp_register_mac_bb_pu_callback(mac_bb_power_up_cb_t cb)
{
int index = MAC_BB_POWER_UP_CB_NO;
for (int i = MAC_BB_POWER_UP_CB_NO - 1; i >= 0; i--) {
if (s_mac_bb_power_up_cb[i] == cb) {
return ESP_OK;
}
if (s_mac_bb_power_up_cb[i] == NULL) {
index = i;
}
}
if (index < MAC_BB_POWER_UP_CB_NO) {
s_mac_bb_power_up_cb[index] = cb;
return ESP_OK;
}
return ESP_ERR_NO_MEM;
}
esp_err_t esp_unregister_mac_bb_pu_callback(mac_bb_power_up_cb_t cb)
{
for (int i = MAC_BB_POWER_UP_CB_NO - 1; i >= 0; i--) {
if (s_mac_bb_power_up_cb[i] == cb) {
s_mac_bb_power_up_cb[i] = NULL;
return ESP_OK;
}
}
return ESP_ERR_INVALID_STATE;
}
static IRAM_ATTR void mac_bb_power_up_cb_execute(void)
{
for (int i = 0; i < MAC_BB_POWER_UP_CB_NO; i++) {
if (s_mac_bb_power_up_cb[i]) {
s_mac_bb_power_up_cb[i]();
}
}
}
#endif ///CONFIG_MAC_BB_PD
/* Wake from deep sleep stub
See esp_deepsleep.h esp_wake_deep_sleep() comments for details.
*/
@ -364,81 +280,33 @@ static void IRAM_ATTR resume_uarts(void)
}
}
inline static uint32_t IRAM_ATTR call_rtc_sleep_start(uint32_t reject_triggers, uint32_t lslp_mem_inf_fpu);
#if SOC_PM_SUPPORT_CPU_PD
esp_err_t esp_sleep_cpu_pd_low_init(bool enable)
inline static void IRAM_ATTR misc_modules_sleep_prepare(void)
{
if (enable) {
if (s_config.cpu_pd_mem == NULL) {
void *buf = heap_caps_aligned_alloc(SOC_RTC_CNTL_CPU_PD_DMA_ADDR_ALIGN,
SOC_RTC_CNTL_CPU_PD_RETENTION_MEM_SIZE + RTC_HAL_DMA_LINK_NODE_SIZE,
MALLOC_CAP_RETENTION | MALLOC_CAP_DEFAULT);
if (buf) {
memset(buf, 0, SOC_RTC_CNTL_CPU_PD_RETENTION_MEM_SIZE + RTC_HAL_DMA_LINK_NODE_SIZE);
s_config.cpu_pd_mem = rtc_cntl_hal_dma_link_init(buf,
buf + RTC_HAL_DMA_LINK_NODE_SIZE, SOC_RTC_CNTL_CPU_PD_RETENTION_MEM_SIZE, NULL);
} else {
return ESP_ERR_NO_MEM;
}
}
} else {
if (s_config.cpu_pd_mem) {
heap_caps_free(s_config.cpu_pd_mem);
s_config.cpu_pd_mem = NULL;
}
}
return ESP_OK;
}
#endif // SOC_PM_SUPPORT_CPU_PD
#if SOC_GPIO_SUPPORT_SLP_SWITCH
#if CONFIG_GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL
static inline void gpio_sleep_mode_config_apply(void)
{
for (gpio_num_t gpio_num = GPIO_NUM_0; gpio_num < GPIO_NUM_MAX; gpio_num++) {
if (GPIO_IS_VALID_GPIO(gpio_num)) {
gpio_sleep_pupd_config_apply(gpio_num);
}
}
}
static inline void gpio_sleep_mode_config_unapply(void)
{
for (gpio_num_t gpio_num = GPIO_NUM_0; gpio_num < GPIO_NUM_MAX; gpio_num++) {
if (GPIO_IS_VALID_GPIO(gpio_num)) {
gpio_sleep_pupd_config_unapply(gpio_num);
}
}
}
#if CONFIG_MAC_BB_PD
mac_bb_power_down_cb_execute();
#endif
#if CONFIG_GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL
gpio_sleep_mode_config_apply();
#endif
#if SOC_PM_SUPPORT_CPU_PD || SOC_PM_SUPPORT_TAGMEM_PD
sleep_enable_memory_retention();
#endif
void esp_sleep_config_gpio_isolate(void)
{
ESP_LOGI(TAG, "Configure to isolate all GPIO pins in sleep state");
for (gpio_num_t gpio_num = GPIO_NUM_0; gpio_num < GPIO_NUM_MAX; gpio_num++) {
if (GPIO_IS_VALID_GPIO(gpio_num)) {
gpio_sleep_set_direction(gpio_num, GPIO_MODE_DISABLE);
gpio_sleep_set_pull_mode(gpio_num, GPIO_FLOATING);
}
}
}
void esp_sleep_enable_gpio_switch(bool enable)
inline static void IRAM_ATTR misc_modules_wake_prepare(void)
{
ESP_LOGI(TAG, "%s automatic switching of GPIO sleep configuration", enable ? "Enable" : "Disable");
for (gpio_num_t gpio_num = GPIO_NUM_0; gpio_num < GPIO_NUM_MAX; gpio_num++) {
if (GPIO_IS_VALID_GPIO(gpio_num)) {
if (enable) {
gpio_sleep_sel_en(gpio_num);
} else {
gpio_sleep_sel_dis(gpio_num);
}
}
}
#if SOC_PM_SUPPORT_CPU_PD || SOC_PM_SUPPORT_TAGMEM_PD
sleep_disable_memory_retention();
#endif
#if CONFIG_GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL
gpio_sleep_mode_config_unapply();
#endif
#if CONFIG_MAC_BB_PD
mac_bb_power_up_cb_execute();
#endif
}
#endif // SOC_GPIO_SUPPORT_SLP_SWITCH
inline static uint32_t IRAM_ATTR call_rtc_sleep_start(uint32_t reject_triggers, uint32_t lslp_mem_inf_fpu);
static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags)
{
@ -467,10 +335,6 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags)
rtc_clk_cpu_freq_get_config(&cpu_freq_config);
rtc_clk_cpu_freq_set_xtal();
#if CONFIG_MAC_BB_PD
mac_bb_power_down_cb_execute();
#endif
#if SOC_PM_SUPPORT_EXT_WAKEUP
// Configure pins for external wakeup
if (s_config.wakeup_triggers & RTC_EXT0_TRIG_EN) {
@ -492,11 +356,10 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags)
if (s_config.wakeup_triggers & RTC_ULP_TRIG_EN) {
rtc_hal_ulp_wakeup_enable();
}
#if CONFIG_GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL
gpio_sleep_mode_config_apply();
#endif
#endif
misc_modules_sleep_prepare();
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
if (deep_sleep) {
if (s_config.wakeup_triggers & RTC_TOUCH_TRIG_EN) {
@ -576,17 +439,8 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags)
s_config.ccount_ticks_record = cpu_ll_get_cycle_count();
}
#if SOC_PM_SUPPORT_CPU_PD
rtc_cntl_hal_disable_cpu_retention();
#endif
misc_modules_wake_prepare();
#if CONFIG_GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL
gpio_sleep_mode_config_unapply();
#endif
#if CONFIG_MAC_BB_PD
mac_bb_power_up_cb_execute();
#endif
// re-enable UART output
resume_uarts();
@ -770,10 +624,6 @@ esp_err_t esp_light_sleep_start(void)
periph_inform_out_light_sleep_overhead(s_config.sleep_time_adjustment - sleep_time_overhead_in);
#if SOC_PM_SUPPORT_CPU_PD
rtc_cntl_hal_enable_cpu_retention(s_config.cpu_pd_mem);
#endif
rtc_vddsdio_config_t vddsdio_config = rtc_vddsdio_get_config();
// Safety net: enable WDT in case exit from light sleep fails
@ -1309,11 +1159,7 @@ static uint32_t get_power_down_flags(void)
}
#if SOC_PM_SUPPORT_CPU_PD
if (s_config.cpu_pd_mem == NULL) {
s_config.pd_options[ESP_PD_DOMAIN_CPU] = ESP_PD_OPTION_ON;
}
#else
if (s_config.pd_options[ESP_PD_DOMAIN_CPU] != ESP_PD_OPTION_ON) {
if (!cpu_domain_pd_allowed()) {
s_config.pd_options[ESP_PD_DOMAIN_CPU] = ESP_PD_OPTION_ON;
}
#endif

View File

@ -0,0 +1,227 @@
/*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stddef.h>
#include <string.h>
#include <sys/lock.h>
#include <sys/param.h>
#include "esp_attr.h"
#include "esp_sleep.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_heap_caps.h"
#include "soc/soc_caps.h"
#include "hal/rtc_hal.h"
#include "esp_private/sleep_retention.h"
#include "sdkconfig.h"
#ifdef CONFIG_IDF_TARGET_ESP32S3
#include "esp32s3/rom/cache.h"
#endif
static __attribute__((unused)) const char *TAG = "sleep";
/**
* Internal structure which holds all requested light sleep memory retention parameters
*/
typedef struct {
rtc_cntl_sleep_retent_t retent;
} sleep_retention_t;
static DRAM_ATTR sleep_retention_t s_retention;
#if SOC_PM_SUPPORT_TAGMEM_PD
#define TAGMEM_PD_MEM_TYPE_CAPS (MALLOC_CAP_DMA | MALLOC_CAP_DEFAULT)
#if CONFIG_PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP
static int cache_tagmem_retention_setup(uint32_t code_seg_vaddr, uint32_t code_seg_size, uint32_t data_seg_vaddr, uint32_t data_seg_size)
{
int sets; /* i/d-cache total set counts */
int index; /* virtual address mapping i/d-cache row offset */
int waysgrp;
int icache_tagmem_blk_gs, dcache_tagmem_blk_gs;
struct cache_mode imode = { .icache = 1 };
struct cache_mode dmode = { .icache = 0 };
/* calculate/prepare i-cache tag memory retention parameters */
Cache_Get_Mode(&imode);
sets = imode.cache_size / imode.cache_ways / imode.cache_line_size;
index = (code_seg_vaddr / imode.cache_line_size) % sets;
waysgrp = imode.cache_ways >> 2;
code_seg_size = ALIGNUP(imode.cache_line_size, code_seg_size);
s_retention.retent.tagmem.icache.start_point = index;
s_retention.retent.tagmem.icache.size = (sets * waysgrp) & 0xff;
s_retention.retent.tagmem.icache.vld_size = s_retention.retent.tagmem.icache.size;
if (code_seg_size < imode.cache_size / imode.cache_ways) {
s_retention.retent.tagmem.icache.vld_size = (code_seg_size / imode.cache_line_size) * waysgrp;
}
s_retention.retent.tagmem.icache.enable = (code_seg_size != 0) ? 1 : 0;
icache_tagmem_blk_gs = s_retention.retent.tagmem.icache.vld_size ? s_retention.retent.tagmem.icache.vld_size : sets * waysgrp;
icache_tagmem_blk_gs = ALIGNUP(4, icache_tagmem_blk_gs);
ESP_LOGD(TAG, "I-cache size:%d KiB, line size:%d B, ways:%d, sets:%d, index:%d, tag block groups:%d", (imode.cache_size>>10),
imode.cache_line_size, imode.cache_ways, sets, index, icache_tagmem_blk_gs);
/* calculate/prepare d-cache tag memory retention parameters */
Cache_Get_Mode(&dmode);
sets = dmode.cache_size / dmode.cache_ways / dmode.cache_line_size;
index = (data_seg_vaddr / dmode.cache_line_size) % sets;
waysgrp = dmode.cache_ways >> 2;
data_seg_size = ALIGNUP(dmode.cache_line_size, data_seg_size);
s_retention.retent.tagmem.dcache.start_point = index;
s_retention.retent.tagmem.dcache.size = (sets * waysgrp) & 0x1ff;
s_retention.retent.tagmem.dcache.vld_size = s_retention.retent.tagmem.dcache.size;
#ifndef CONFIG_ESP32S3_DATA_CACHE_16KB
if (data_seg_size < dmode.cache_size / dmode.cache_ways) {
s_retention.retent.tagmem.dcache.vld_size = (data_seg_size / dmode.cache_line_size) * waysgrp;
}
s_retention.retent.tagmem.dcache.enable = (data_seg_size != 0) ? 1 : 0;
#else
s_retention.retent.tagmem.dcache.enable = 1;
#endif
dcache_tagmem_blk_gs = s_retention.retent.tagmem.dcache.vld_size ? s_retention.retent.tagmem.dcache.vld_size : sets * waysgrp;
dcache_tagmem_blk_gs = ALIGNUP(4, dcache_tagmem_blk_gs);
ESP_LOGD(TAG, "D-cache size:%d KiB, line size:%d B, ways:%d, sets:%d, index:%d, tag block groups:%d", (dmode.cache_size>>10),
dmode.cache_line_size, dmode.cache_ways, sets, index, dcache_tagmem_blk_gs);
/* For I or D cache tagmem retention, backup and restore are performed through
* RTC DMA (its bus width is 128 bits), For I/D Cache tagmem blocks (i-cache
* tagmem blocks = 92 bits, d-cache tagmem blocks = 88 bits), RTC DMA automatically
* aligns its bit width to 96 bits, therefore, 3 times RTC DMA can transfer 4
* i/d-cache tagmem blocks (128 bits * 3 = 96 bits * 4) */
return (((icache_tagmem_blk_gs + dcache_tagmem_blk_gs) << 2) * 3);
}
#endif // CONFIG_PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP
static esp_err_t esp_sleep_tagmem_pd_low_init(bool enable)
{
if (enable) {
#if CONFIG_PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP
if (s_retention.retent.tagmem.link_addr == NULL) {
extern char _stext[], _etext[];
uint32_t code_start = (uint32_t)_stext;
uint32_t code_size = (uint32_t)(_etext - _stext);
#if !CONFIG_ESP32S3_SPIRAM_SUPPORT
extern char _rodata_start[], _rodata_reserved_end[];
uint32_t data_start = (uint32_t)_rodata_start;
uint32_t data_size = (uint32_t)(_rodata_reserved_end - _rodata_start);
#else
uint32_t data_start = SOC_DROM_LOW;
uint32_t data_size = (SOC_EXTRAM_DATA_HIGH-SOC_EXTRAM_DATA_LOW) + (SOC_DROM_HIGH-SOC_DROM_LOW);
#endif
ESP_LOGI(TAG, "Code start at %08x, total %.2f KiB, data start at %08x, total %.2f KiB",
code_start, (float)code_size/1024, data_start, (float)data_size/1024);
int tagmem_sz = cache_tagmem_retention_setup(code_start, code_size, data_start, data_size);
void *buf = heap_caps_aligned_alloc(SOC_RTC_CNTL_TAGMEM_PD_DMA_ADDR_ALIGN,
tagmem_sz + RTC_HAL_DMA_LINK_NODE_SIZE,
TAGMEM_PD_MEM_TYPE_CAPS);
if (buf) {
memset(buf, 0, tagmem_sz + RTC_HAL_DMA_LINK_NODE_SIZE);
s_retention.retent.tagmem.link_addr = rtc_cntl_hal_dma_link_init(buf,
buf + RTC_HAL_DMA_LINK_NODE_SIZE, tagmem_sz, NULL);
} else {
s_retention.retent.tagmem.icache.enable = 0;
s_retention.retent.tagmem.dcache.enable = 0;
s_retention.retent.tagmem.link_addr = NULL;
return ESP_ERR_NO_MEM;
}
}
#else // CONFIG_PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP
s_retention.retent.tagmem.icache.enable = 0;
s_retention.retent.tagmem.dcache.enable = 0;
s_retention.retent.tagmem.link_addr = NULL;
#endif // CONFIG_PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP
} else {
#if SOC_PM_SUPPORT_TAGMEM_PD
if (s_retention.retent.tagmem.link_addr) {
heap_caps_free(s_retention.retent.tagmem.link_addr);
s_retention.retent.tagmem.icache.enable = 0;
s_retention.retent.tagmem.dcache.enable = 0;
s_retention.retent.tagmem.link_addr = NULL;
}
#endif
}
return ESP_OK;
}
#endif // SOC_PM_SUPPORT_TAGMEM_PD
#if SOC_PM_SUPPORT_CPU_PD
#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2
#define CPU_PD_MEM_TYPE_CAPS (MALLOC_CAP_RETENTION | MALLOC_CAP_DEFAULT)
#else
#define CPU_PD_MEM_TYPE_CAPS (MALLOC_CAP_DMA | MALLOC_CAP_DEFAULT)
#endif
esp_err_t esp_sleep_cpu_pd_low_init(bool enable)
{
if (enable) {
if (s_retention.retent.cpu_pd_mem == NULL) {
void *buf = heap_caps_aligned_alloc(SOC_RTC_CNTL_CPU_PD_DMA_ADDR_ALIGN,
SOC_RTC_CNTL_CPU_PD_RETENTION_MEM_SIZE + RTC_HAL_DMA_LINK_NODE_SIZE,
CPU_PD_MEM_TYPE_CAPS);
if (buf) {
memset(buf, 0, SOC_RTC_CNTL_CPU_PD_RETENTION_MEM_SIZE + RTC_HAL_DMA_LINK_NODE_SIZE);
s_retention.retent.cpu_pd_mem = rtc_cntl_hal_dma_link_init(buf,
buf + RTC_HAL_DMA_LINK_NODE_SIZE, SOC_RTC_CNTL_CPU_PD_RETENTION_MEM_SIZE, NULL);
} else {
return ESP_ERR_NO_MEM;
}
}
} else {
if (s_retention.retent.cpu_pd_mem) {
heap_caps_free(s_retention.retent.cpu_pd_mem);
s_retention.retent.cpu_pd_mem = NULL;
}
}
#if SOC_PM_SUPPORT_TAGMEM_PD
if (esp_sleep_tagmem_pd_low_init(enable) != ESP_OK) {
#ifdef CONFIG_ESP32S3_DATA_CACHE_16KB
esp_sleep_cpu_pd_low_init(false);
return ESP_ERR_NO_MEM;
#endif
}
#endif
return ESP_OK;
}
bool cpu_domain_pd_allowed(void)
{
return (s_retention.retent.cpu_pd_mem != NULL);
}
#endif // SOC_PM_SUPPORT_CPU_PD
#if SOC_PM_SUPPORT_CPU_PD || SOC_PM_SUPPORT_TAGMEM_PD
void sleep_enable_memory_retention(void)
{
#if SOC_PM_SUPPORT_CPU_PD
rtc_cntl_hal_enable_cpu_retention(&s_retention.retent);
#endif
#if SOC_PM_SUPPORT_TAGMEM_PD
rtc_cntl_hal_enable_tagmem_retention(&s_retention.retent);
#endif
}
void IRAM_ATTR sleep_disable_memory_retention(void)
{
#if SOC_PM_SUPPORT_CPU_PD
rtc_cntl_hal_disable_cpu_retention(&s_retention.retent);
#endif
#if SOC_PM_SUPPORT_TAGMEM_PD
rtc_cntl_hal_disable_tagmem_retention(&s_retention.retent);
#endif
}
#endif // SOC_PM_SUPPORT_CPU_PD || SOC_PM_SUPPORT_TAGMEM_PD

View File

@ -96,10 +96,21 @@ menu "Power Management"
config PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP
bool "Power down CPU in light sleep"
depends on IDF_TARGET_ESP32C3
depends on IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S3
select PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP if ESP32S3_DATA_CACHE_16KB
default y
help
If enabled, the CPU will be powered down in light sleep. Enabling this option will consume
1.68 KB of internal RAM and will reduce sleep current consumption by about 100 uA.
If enabled, the CPU will be powered down in light sleep. On esp32c3 soc, enabling this
option will consume 1.68 KB of internal RAM and will reduce sleep current consumption
by about 100 uA. On esp32s3 soc, enabling this option will consume 8.58 KB of internal
RAM and will reduce sleep current consumption by about 650 uA.
config PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP
bool "Power down I/D-cache tag memory in light sleep"
depends on IDF_TARGET_ESP32S3 && PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP
default y
help
If enabled, the I/D-cache tag memory will be retained in light sleep. Depending on the the
cache configuration, if this option is enabled, it will consume up to 9 KB of internal RAM.
endmenu # "Power Management"

View File

@ -19,6 +19,11 @@ entries:
esp_clk:esp_clk_slowclk_cal_set (noflash)
esp_clk:esp_clk_slowclk_cal_get (noflash)
esp_clk:esp_rtc_get_time_us (noflash)
if GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL = y:
sleep_gpio:gpio_sleep_mode_config_apply (noflash)
if IDF_TARGET_ESP32 = n && IDF_TARGET_ESP32S2 = n:
sleep_retention:sleep_enable_memory_retention (noflash)
sleep_retention:cpu_domain_pd_allowed (noflash)
[mapping:esp_system_pm]
archive: libesp_system.a
@ -72,3 +77,5 @@ entries:
gpio_hal_workaround:gpio_hal_fun_pupd_restore (noflash)
if PM_SLP_IRAM_OPT = y && PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP = y:
rtc_cntl_hal:rtc_cntl_hal_enable_cpu_retention (noflash)
if PM_SLP_IRAM_OPT = y && PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP = y:
rtc_cntl_hal:rtc_cntl_hal_enable_tagmem_retention (noflash)

View File

@ -88,6 +88,7 @@ if(NOT BOOTLOADER_BUILD)
"esp32s3/hmac_hal.c"
"esp32s3/interrupt_descriptor_table.c"
"esp32s3/touch_sensor_hal.c"
"esp32s3/rtc_cntl_hal.c"
"usbh_hal.c")
endif()

View File

@ -47,12 +47,18 @@ static inline void rtc_cntl_ll_gpio_clear_wakeup_pins(void)
REG_SET_BIT(RTC_CNTL_GPIO_WAKEUP_REG, RTC_CNTL_GPIO_WAKEUP_STATUS_CLR);
}
static inline void rtc_cntl_ll_enable_cpu_retention(uint32_t addr)
static inline void rtc_cntl_ll_set_cpu_retention_link_addr(uint32_t addr)
{
/* write memory address to register */
REG_SET_FIELD(APB_CTRL_RETENTION_CTRL_REG, APB_CTRL_RETENTION_LINK_ADDR, (uint32_t)addr);
/* Enable clock */
}
static inline void rtc_cntl_ll_enable_cpu_retention_clock(void)
{
REG_SET_BIT(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN);
}
static inline void rtc_cntl_ll_enable_cpu_retention(void)
{
/* Enable retention when cpu sleep enable */
REG_SET_BIT(RTC_CNTL_RETENTION_CTRL_REG, RTC_CNTL_RETENTION_EN);
}

View File

@ -16,8 +16,10 @@
#include "soc/soc_caps.h"
#include "soc/lldesc.h"
#include "hal/dma_types.h"
#include "hal/rtc_hal.h"
#include "hal/assert.h"
#include "esp_attr.h"
#define RTC_CNTL_HAL_LINK_BUF_SIZE_MIN (SOC_RTC_CNTL_CPU_PD_DMA_BLOCK_SIZE) /* The minimum size of dma link buffer */
@ -34,7 +36,7 @@ void * rtc_cntl_hal_dma_link_init(void *elem, void *buff, int size, void *next)
lldesc_t *plink = (lldesc_t *)elem;
plink->eof = next ? 0 : 1;
plink->owner = 1;
plink->owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA;
plink->size = size >> 4; /* in unit of 16 bytes */
plink->length = size >> 4;
plink->buf = buff;
@ -44,18 +46,39 @@ void * rtc_cntl_hal_dma_link_init(void *elem, void *buff, int size, void *next)
return (void *)plink;
}
#if SOC_PM_SUPPORT_CPU_PD
void rtc_cntl_hal_enable_cpu_retention(void *addr)
{
rtc_cntl_sleep_retent_t *retent = (rtc_cntl_sleep_retent_t *)addr;
if (addr) {
lldesc_t *plink = (lldesc_t *)addr;
if (retent->cpu_pd_mem) {
lldesc_t *plink = (lldesc_t *)retent->cpu_pd_mem;
/* dma link buffer configure */
rtc_cntl_link_buf_conf_t *pbuf = (rtc_cntl_link_buf_conf_t *)plink->buf;
pbuf->cfg[0] = 0;
pbuf->cfg[1] = 0;
pbuf->cfg[2] = 0;
pbuf->cfg[3] = (uint32_t)-1;
/* dma link buffer configure */
rtc_cntl_link_buf_conf_t *pbuf = (rtc_cntl_link_buf_conf_t *)plink->buf;
pbuf->cfg[0] = 0;
pbuf->cfg[1] = 0;
pbuf->cfg[2] = 0;
pbuf->cfg[3] = (uint32_t)-1;
rtc_cntl_ll_enable_cpu_retention((uint32_t)addr);
rtc_cntl_ll_set_cpu_retention_link_addr((uint32_t)plink);
rtc_cntl_ll_enable_cpu_retention_clock();
rtc_cntl_ll_enable_cpu_retention();
}
}
}
void IRAM_ATTR rtc_cntl_hal_disable_cpu_retention(void *addr)
{
rtc_cntl_sleep_retent_t *retent = (rtc_cntl_sleep_retent_t *)addr;
if (addr) {
if (retent->cpu_pd_mem) {
rtc_cntl_ll_disable_cpu_retention();
}
}
}
#endif // SOC_PM_SUPPORT_CPU_PD

View File

@ -17,11 +17,15 @@
#include "soc/soc.h"
#include "soc/rtc.h"
#include "soc/rtc_cntl_reg.h"
#include "soc/apb_ctrl_reg.h"
#ifdef __cplusplus
extern "C" {
#endif
#define RTC_CNTL_LL_RETENTION_TARGET_CPU (BIT(0))
#define RTC_CNTL_LL_RETENTION_TARGET_TAGMEM (BIT(1))
static inline void rtc_cntl_ll_set_wakeup_timer(uint64_t t)
{
WRITE_PERI_REG(RTC_CNTL_SLP_TIMER0_REG, t & UINT32_MAX);
@ -53,6 +57,82 @@ static inline void rtc_cntl_ll_ulp_wakeup_enable(void)
SET_PERI_REG_BITS(RTC_CNTL_STATE0_REG, RTC_CNTL_WAKEUP_ENA_V, 0x800, RTC_CNTL_WAKEUP_ENA_S);
}
static inline void rtc_cntl_ll_set_tagmem_retention_link_addr(uint32_t link_addr)
{
REG_SET_FIELD(APB_CTRL_RETENTION_CTRL1_REG, APB_CTRL_RETENTION_TAG_LINK_ADDR, link_addr);
}
static inline void rtc_cntl_ll_enable_tagmem_retention(void)
{
/* Enable i/d-cache tagmem retenttion. cpu: 1, tagmem: 2, cpu + tagmem: 3 */
uint32_t target = REG_GET_FIELD(RTC_CNTL_RETENTION_CTRL_REG, RTC_CNTL_RETENTION_TARGET);
REG_SET_FIELD(RTC_CNTL_RETENTION_CTRL_REG, RTC_CNTL_RETENTION_TARGET, (target | RTC_CNTL_LL_RETENTION_TARGET_TAGMEM));
}
static inline void rtc_cntl_ll_enable_icache_tagmem_retention(uint32_t start_point, uint32_t vld_size, uint32_t size)
{
REG_SET_FIELD(APB_CTRL_RETENTION_CTRL2_REG, APB_CTRL_RET_ICACHE_START_POINT, start_point);
REG_SET_FIELD(APB_CTRL_RETENTION_CTRL2_REG, APB_CTRL_RET_ICACHE_VLD_SIZE, vld_size);
REG_SET_FIELD(APB_CTRL_RETENTION_CTRL2_REG, APB_CTRL_RET_ICACHE_SIZE, size);
REG_SET_BIT(APB_CTRL_RETENTION_CTRL2_REG, APB_CTRL_RET_ICACHE_ENABLE);
}
static inline void rtc_cntl_ll_enable_dcache_tagmem_retention(uint32_t start_point, uint32_t vld_size, uint32_t size)
{
REG_SET_FIELD(APB_CTRL_RETENTION_CTRL3_REG, APB_CTRL_RET_DCACHE_START_POINT, start_point);
REG_SET_FIELD(APB_CTRL_RETENTION_CTRL3_REG, APB_CTRL_RET_DCACHE_VLD_SIZE, vld_size);
REG_SET_FIELD(APB_CTRL_RETENTION_CTRL3_REG, APB_CTRL_RET_DCACHE_SIZE, size);
REG_SET_BIT(APB_CTRL_RETENTION_CTRL3_REG, APB_CTRL_RET_DCACHE_ENABLE);
}
static inline void rtc_cntl_ll_disable_tagmem_retention(void)
{
/* Enable i/d-cache tagmem retenttion. cpu: 1, tagmem: 2, cpu + tagmem: 3 */
uint32_t target = REG_GET_FIELD(RTC_CNTL_RETENTION_CTRL_REG, RTC_CNTL_RETENTION_TARGET);
REG_SET_FIELD(RTC_CNTL_RETENTION_CTRL_REG, RTC_CNTL_RETENTION_TARGET, (target & ~RTC_CNTL_LL_RETENTION_TARGET_TAGMEM));
}
static inline void rtc_cntl_ll_disable_icache_tagmem_retention(void)
{
REG_CLR_BIT(APB_CTRL_RETENTION_CTRL2_REG, APB_CTRL_RET_ICACHE_ENABLE);
}
static inline void rtc_cntl_ll_disable_dcache_tagmem_retention(void)
{
REG_CLR_BIT(APB_CTRL_RETENTION_CTRL3_REG, APB_CTRL_RET_DCACHE_ENABLE);
}
static inline void rtc_cntl_ll_set_cpu_retention_link_addr(uint32_t link_addr)
{
REG_SET_FIELD(APB_CTRL_RETENTION_CTRL_REG, APB_CTRL_RETENTION_CPU_LINK_ADDR, link_addr);
}
static inline void rtc_cntl_ll_enable_cpu_retention_clock(void)
{
REG_SET_BIT(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN); /* Enable internal 20 MHz clock */
}
static inline void rtc_cntl_ll_enable_cpu_retention(void)
{
uint32_t target = REG_GET_FIELD(RTC_CNTL_RETENTION_CTRL_REG, RTC_CNTL_RETENTION_TARGET);
REG_SET_FIELD(RTC_CNTL_RETENTION_CTRL_REG, RTC_CNTL_RETENTION_TARGET, (target | RTC_CNTL_LL_RETENTION_TARGET_CPU));
/* Enable retention when cpu sleep enable */
REG_SET_BIT(RTC_CNTL_RETENTION_CTRL_REG, RTC_CNTL_RETENTION_EN);
}
static inline void rtc_cntl_ll_config_cpu_retention_timing(int wait, int clkoff_wait, int done_wait)
{
REG_SET_FIELD(RTC_CNTL_RETENTION_CTRL_REG, RTC_CNTL_RETENTION_WAIT, wait);
REG_SET_FIELD(RTC_CNTL_RETENTION_CTRL_REG, RTC_CNTL_RETENTION_CLKOFF_WAIT, clkoff_wait);
REG_SET_FIELD(RTC_CNTL_RETENTION_CTRL_REG, RTC_CNTL_RETENTION_DONE_WAIT, done_wait);
}
static inline void rtc_cntl_ll_disable_cpu_retention(void)
{
REG_CLR_BIT(RTC_CNTL_RETENTION_CTRL_REG, RTC_CNTL_RETENTION_EN);
}
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,147 @@
/*
* SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
// The HAL layer for RTC CNTL (common part)
#include "hal/rtc_hal.h"
#include "soc/soc_caps.h"
#include "esp32s3/rom/lldesc.h"
#include "esp32s3/rom/cache.h"
#include "hal/dma_types.h"
#include "hal/assert.h"
#include "esp_attr.h"
#define RTC_CNTL_HAL_LINK_BUF_SIZE_MIN (SOC_RTC_CNTL_CPU_PD_DMA_BLOCK_SIZE) /* The minimum size of dma link buffer */
typedef struct rtc_cntl_link_buf_conf {
uint32_t cfg[4]; /* 4 word for dma link buffer configuration */
} rtc_cntl_link_buf_conf_t;
void * rtc_cntl_hal_dma_link_init(void *elem, void *buff, int size, void *next)
{
HAL_ASSERT(elem != NULL);
HAL_ASSERT(buff != NULL);
HAL_ASSERT(size >= RTC_CNTL_HAL_LINK_BUF_SIZE_MIN);
lldesc_t *plink = (lldesc_t *)elem;
plink->eof = next ? 0 : 1;
plink->owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA;
plink->size = size >> 4; /* in unit of 16 bytes */
plink->length = size >> 4;
plink->buf = buff;
plink->offset = 0;
plink->sosf = 0;
STAILQ_NEXT(plink, qe) = next;
return (void *)plink;
}
#if SOC_PM_SUPPORT_CPU_PD
#define DEFAULT_RETENTION_WAIT_CYCLES (0x7f)
#define DEFAULT_RETENTION_CLKOFF_WAIT_CYCLES (0xf)
#define DEFAULT_RETENTION_DONE_WAIT_CYCLES (0x7)
void rtc_cntl_hal_enable_cpu_retention(void *addr)
{
rtc_cntl_sleep_retent_t *retent = (rtc_cntl_sleep_retent_t *)addr;
if (addr) {
if (retent->cpu_pd_mem) {
lldesc_t *plink = (lldesc_t *)retent->cpu_pd_mem;
/* dma link buffer configure */
rtc_cntl_link_buf_conf_t *pbuf = (rtc_cntl_link_buf_conf_t *)plink->buf;
pbuf->cfg[0] = 0;
pbuf->cfg[1] = 0;
pbuf->cfg[2] = 0;
pbuf->cfg[3] = 0xfffe0000;
rtc_cntl_ll_set_cpu_retention_link_addr((uint32_t)plink);
rtc_cntl_ll_config_cpu_retention_timing(
DEFAULT_RETENTION_WAIT_CYCLES,
DEFAULT_RETENTION_CLKOFF_WAIT_CYCLES,
DEFAULT_RETENTION_DONE_WAIT_CYCLES
);
rtc_cntl_ll_enable_cpu_retention_clock();
rtc_cntl_ll_enable_cpu_retention();
}
}
}
void IRAM_ATTR rtc_cntl_hal_disable_cpu_retention(void *addr)
{
rtc_cntl_sleep_retent_t *retent = (rtc_cntl_sleep_retent_t *)addr;
if (addr) {
if (retent->cpu_pd_mem) {
/* I/d-cache tagmem retention has not been included or not
* been enabled, after the system wakes up, all the contents
* of i/d-cache need to be invalidated. */
#if SOC_PM_SUPPORT_TAGMEM_PD
if (!retent->tagmem.icache.enable) {
Cache_Invalidate_ICache_All();
}
if (!retent->tagmem.dcache.enable) {
Cache_Invalidate_DCache_All();
}
#else
Cache_Invalidate_ICache_All();
Cache_Invalidate_DCache_All();
#endif // SOC_PM_SUPPORT_TAGMEM_PD
rtc_cntl_ll_disable_cpu_retention();
}
}
}
#endif // SOC_PM_SUPPORT_CPU_PD
#if SOC_PM_SUPPORT_TAGMEM_PD
void rtc_cntl_hal_enable_tagmem_retention(void *addr)
{
rtc_cntl_sleep_retent_t *retent = (rtc_cntl_sleep_retent_t *)addr;
if (addr) {
if (retent->tagmem.link_addr) {
rtc_cntl_ll_set_tagmem_retention_link_addr((uint32_t)(retent->tagmem.link_addr));
rtc_cntl_ll_enable_tagmem_retention();
if (retent->tagmem.icache.enable) {
rtc_cntl_ll_enable_icache_tagmem_retention(
retent->tagmem.icache.start_point,
retent->tagmem.icache.vld_size,
retent->tagmem.icache.size
);
}
if (retent->tagmem.dcache.enable) {
rtc_cntl_ll_enable_dcache_tagmem_retention(
retent->tagmem.dcache.start_point,
retent->tagmem.dcache.vld_size,
retent->tagmem.dcache.size
);
}
}
}
}
void IRAM_ATTR rtc_cntl_hal_disable_tagmem_retention(void *addr)
{
rtc_cntl_sleep_retent_t *retent = (rtc_cntl_sleep_retent_t *)addr;
if (addr) {
if (retent->tagmem.link_addr) {
rtc_cntl_ll_disable_tagmem_retention();
if (retent->tagmem.icache.enable) {
rtc_cntl_ll_disable_icache_tagmem_retention();
}
if (retent->tagmem.dcache.enable) {
rtc_cntl_ll_disable_dcache_tagmem_retention();
}
}
}
}
#endif // SOC_PM_SUPPORT_TAGMEM_PD

View File

@ -14,12 +14,36 @@
#pragma once
#include "soc/soc_caps.h"
#include "hal/gpio_types.h"
#include "hal/rtc_cntl_ll.h"
#if !CONFIG_IDF_TARGET_ESP32C3 && !CONFIG_IDF_TARGET_ESP32H2
#include "hal/rtc_io_ll.h"
#endif
typedef struct rtc_cntl_sleep_retent {
#if SOC_PM_SUPPORT_CPU_PD
void *cpu_pd_mem; /* Internal ram address for cpu retention */
#endif // SOC_PM_SUPPORT_CPU_PD
#if SOC_PM_SUPPORT_TAGMEM_PD
struct {
void *link_addr; /* Internal ram address for tagmem retention */
struct {
uint32_t start_point: 8, /* the row of start for i-cache tag memory */
vld_size: 8, /* valid size of i-cache tag memory, unit: 4 i-cache tagmem blocks */
size: 8, /* i-cache tag memory size, unit: 4 i-cache tagmem blocks */
enable: 1; /* enable or disable i-cache tagmem retention */
} icache;
struct {
uint32_t start_point: 9, /* the row of start for d-cache tag memory */
vld_size: 9, /* valid size of d-cache tag memory, unit: 4 d-cache tagmem blocks */
size: 9, /* d-cache tag memory size, unit: 4 d-cache tagmem blocks */
enable: 1; /* enable or disable d-cache tagmem retention */
} dcache;
} tagmem;
#endif // SOC_PM_SUPPORT_TAGMEM_PD
} rtc_cntl_sleep_retent_t;
#define RTC_HAL_DMA_LINK_NODE_SIZE (16)
#if SOC_PM_SUPPORT_EXT_WAKEUP
@ -46,9 +70,21 @@
void * rtc_cntl_hal_dma_link_init(void *elem, void *buff, int size, void *next);
#if SOC_PM_SUPPORT_CPU_PD
void rtc_cntl_hal_enable_cpu_retention(void *addr);
#define rtc_cntl_hal_disable_cpu_retention() rtc_cntl_ll_disable_cpu_retention()
void rtc_cntl_hal_disable_cpu_retention(void *addr);
#endif
#if SOC_PM_SUPPORT_TAGMEM_PD
void rtc_cntl_hal_enable_tagmem_retention(void *addr);
void rtc_cntl_hal_disable_tagmem_retention(void *addr);
#endif
/*
* Enable wakeup from ULP coprocessor.

View File

@ -133,6 +133,18 @@
#define SOC_LCD_I80_BUS_WIDTH (16) /*!< Intel 8080 bus width */
#define SOC_LCD_RGB_DATA_WIDTH (16) /*!< Number of LCD data lines */
/*-------------------------- RTC CAPS --------------------------------------*/
#define SOC_RTC_CNTL_CPU_PD_DMA_BUS_WIDTH (128)
#define SOC_RTC_CNTL_CPU_PD_REG_FILE_NUM (549)
#define SOC_RTC_CNTL_CPU_PD_DMA_ADDR_ALIGN (SOC_RTC_CNTL_CPU_PD_DMA_BUS_WIDTH >> 3)
#define SOC_RTC_CNTL_CPU_PD_DMA_BLOCK_SIZE (SOC_RTC_CNTL_CPU_PD_DMA_BUS_WIDTH >> 3)
#define SOC_RTC_CNTL_CPU_PD_RETENTION_MEM_SIZE (SOC_RTC_CNTL_CPU_PD_REG_FILE_NUM * (SOC_RTC_CNTL_CPU_PD_DMA_BUS_WIDTH >> 3))
/* I/D Cache tag memory retention hardware parameters */
#define SOC_RTC_CNTL_TAGMEM_PD_DMA_BUS_WIDTH (128)
#define SOC_RTC_CNTL_TAGMEM_PD_DMA_ADDR_ALIGN (SOC_RTC_CNTL_TAGMEM_PD_DMA_BUS_WIDTH >> 3)
/*-------------------------- RTCIO CAPS --------------------------------------*/
#include "rtc_io_caps.h"
@ -242,6 +254,10 @@
#define SOC_PM_SUPPORT_BT_WAKEUP (1)
#define SOC_PM_SUPPORT_CPU_PD (1)
#define SOC_PM_SUPPORT_TAGMEM_PD (1)
/*-------------------------- Flash Encryption CAPS----------------------------*/
#define SOC_FLASH_ENCRYPTED_XTS_AES_BLOCK_MAX (64)