mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-03 12:44:33 +02:00
light sleep: add cpu power down support for esp32c3
This commit is contained in:
@@ -72,3 +72,5 @@ entries:
|
||||
gpio_hal_workaround:gpio_hal_sleep_pupd_config_unapply (noflash)
|
||||
gpio_hal_workaround:gpio_hal_sleep_mode_setup_wrapper (noflash)
|
||||
gpio_hal_workaround:gpio_hal_fun_pupd_restore (noflash)
|
||||
if PM_SLP_IRAM_OPT = y && ESP_SYSTEM_PM_POWER_DOWN_CPU = y:
|
||||
rtc_cntl_hal:rtc_cntl_hal_enable_cpu_retention (noflash)
|
||||
|
@@ -60,6 +60,7 @@
|
||||
#include "esp32c3/clk.h"
|
||||
#include "esp32c3/pm.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_private/sleep_modes.h"
|
||||
#endif
|
||||
|
||||
#define MHZ (1000000)
|
||||
@@ -303,6 +304,13 @@ esp_err_t esp_pm_configure(const void* vconfig)
|
||||
esp_sleep_gpio_status_switch_configure(config->light_sleep_enable);
|
||||
#endif
|
||||
|
||||
#if CONFIG_ESP_SYSTEM_PM_POWER_DOWN_CPU && SOC_PM_SUPPORT_CPU_PD
|
||||
esp_err_t ret = esp_sleep_cpu_pd_low_init(config->light_sleep_enable);
|
||||
if (config->light_sleep_enable && ret != ESP_OK) {
|
||||
ESP_LOGW(TAG, "Failed to enable CPU power down during light sleep.");
|
||||
}
|
||||
#endif
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
@@ -87,4 +87,12 @@ menu "ESP System Settings"
|
||||
If enabled, chip will try to power down flash at light sleep, which costs more time when chip wakes up.
|
||||
Only can be enabled if there is no SPIRAM configured.
|
||||
|
||||
config ESP_SYSTEM_PM_POWER_DOWN_CPU
|
||||
bool "Power down CPU in light sleep"
|
||||
depends on IDF_TARGET_ESP32C3
|
||||
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.
|
||||
|
||||
endmenu # ESP System Settings
|
||||
|
40
components/esp_system/include/esp_private/sleep_modes.h
Normal file
40
components/esp_system/include/esp_private/sleep_modes.h
Normal file
@@ -0,0 +1,40 @@
|
||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "esp_err.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ESP_SYSTEM_PM_POWER_DOWN_CPU
|
||||
/**
|
||||
* @brief CPU Power down low-level initialize
|
||||
*
|
||||
* @param enable enable or disable CPU power down during light sleep
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
* - ESP_ERR_NO_MEM not enough retention memory
|
||||
*/
|
||||
esp_err_t esp_sleep_cpu_pd_low_init(bool enable);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@@ -42,6 +42,7 @@ 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
|
||||
ESP_PD_DOMAIN_CPU, //!< CPU core
|
||||
ESP_PD_DOMAIN_MAX //!< Number of domains
|
||||
} esp_sleep_pd_domain_t;
|
||||
|
||||
|
@@ -70,6 +70,9 @@
|
||||
#include "esp32s3/rom/cache.h"
|
||||
#include "esp32c3/rom/rtc.h"
|
||||
#include "soc/extmem_reg.h"
|
||||
#include "esp_heap_caps.h"
|
||||
#include "hal/rtc_hal.h"
|
||||
#include "soc/rtc_caps.h"
|
||||
#endif
|
||||
|
||||
// If light sleep time is less than that, don't power down flash
|
||||
@@ -141,10 +144,13 @@ 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 },
|
||||
.pd_options = { ESP_PD_OPTION_AUTO, ESP_PD_OPTION_AUTO, ESP_PD_OPTION_AUTO, ESP_PD_OPTION_AUTO, ESP_PD_OPTION_AUTO },
|
||||
.ccount_ticks_record = 0,
|
||||
.sleep_time_overhead_out = DEFAULT_SLEEP_OUT_OVERHEAD_US,
|
||||
.wakeup_triggers = 0
|
||||
@@ -259,6 +265,32 @@ static void IRAM_ATTR resume_uarts(void)
|
||||
|
||||
inline static uint32_t IRAM_ATTR call_rtc_sleep_start(uint32_t reject_triggers);
|
||||
|
||||
#if SOC_PM_SUPPORT_CPU_PD
|
||||
esp_err_t esp_sleep_cpu_pd_low_init(bool enable)
|
||||
{
|
||||
if (enable) {
|
||||
if (s_config.cpu_pd_mem == NULL) {
|
||||
void *buf = heap_caps_aligned_alloc(RTC_CNTL_CPU_PD_DMA_ADDR_ALIGN,
|
||||
RTC_CNTL_CPU_PD_RETENTION_MEM_SIZE + RTC_HAL_DMA_LINK_NODE_SIZE,
|
||||
MALLOC_CAP_RETENTION|MALLOC_CAP_DEFAULT);
|
||||
if (buf) {
|
||||
memset(buf, 0, 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, 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)
|
||||
@@ -434,6 +466,10 @@ 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
|
||||
|
||||
#if CONFIG_GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL
|
||||
gpio_sleep_mode_config_unapply();
|
||||
#endif
|
||||
@@ -591,6 +627,10 @@ 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
|
||||
@@ -1046,6 +1086,12 @@ static uint32_t get_power_down_flags(void)
|
||||
#endif // SOC_TOUCH_PAD_WAKE_SUPPORTED
|
||||
}
|
||||
|
||||
#if !SOC_PM_SUPPORT_CPU_PD
|
||||
if (s_config.pd_options[ESP_PD_DOMAIN_CPU] == ESP_PD_OPTION_AUTO) {
|
||||
s_config.pd_options[ESP_PD_DOMAIN_CPU] = ESP_PD_OPTION_ON;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (s_config.pd_options[ESP_PD_DOMAIN_XTAL] == ESP_PD_OPTION_AUTO) {
|
||||
s_config.pd_options[ESP_PD_DOMAIN_XTAL] = ESP_PD_OPTION_OFF;
|
||||
}
|
||||
@@ -1071,6 +1117,12 @@ static uint32_t get_power_down_flags(void)
|
||||
pd_flags |= RTC_SLEEP_PD_RTC_PERIPH;
|
||||
}
|
||||
|
||||
#if SOC_PM_SUPPORT_CPU_PD
|
||||
if (s_config.pd_options[ESP_PD_DOMAIN_CPU] != ESP_PD_OPTION_ON) {
|
||||
pd_flags |= RTC_SLEEP_PD_CPU;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
pd_flags |= RTC_SLEEP_PD_XTAL;
|
||||
#endif
|
||||
|
@@ -92,7 +92,8 @@ if(NOT BOOTLOADER_BUILD)
|
||||
"esp32c3/systimer_hal.c"
|
||||
"esp32c3/hmac_hal.c"
|
||||
"spi_flash_hal_gpspi.c"
|
||||
"spi_slave_hd_hal.c")
|
||||
"spi_slave_hd_hal.c"
|
||||
"esp32c3/rtc_cntl_hal.c")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
@@ -17,6 +17,7 @@
|
||||
#include "soc/soc.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "soc/rtc_cntl_reg.h"
|
||||
#include "soc/apb_ctrl_reg.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -47,6 +48,21 @@ static inline void rtc_cntl_ll_ext1_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)
|
||||
{
|
||||
/* write memory address to register */
|
||||
REG_SET_FIELD(APB_CTRL_RETENTION_CTRL_REG, APB_CTRL_RETENTION_LINK_ADDR, (uint32_t)addr);
|
||||
/* Enable clock */
|
||||
REG_SET_BIT(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN);
|
||||
/* Enable retention when cpu sleep enable */
|
||||
REG_SET_BIT(RTC_CNTL_RETENTION_CTRL_REG, RTC_CNTL_RETENTION_EN);
|
||||
}
|
||||
|
||||
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
|
||||
|
61
components/hal/esp32c3/rtc_cntl_hal.c
Normal file
61
components/hal/esp32c3/rtc_cntl_hal.c
Normal file
@@ -0,0 +1,61 @@
|
||||
// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// The HAL layer for RTC CNTL (common part)
|
||||
|
||||
#include "hal/rtc_hal.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#include "esp32c3/rom/lldesc.h"
|
||||
#include "esp_attr.h"
|
||||
|
||||
#define RTC_CNTL_HAL_LINK_BUF_SIZE_MIN (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)
|
||||
{
|
||||
assert(elem != NULL);
|
||||
assert(buff != NULL);
|
||||
assert(size >= RTC_CNTL_HAL_LINK_BUF_SIZE_MIN);
|
||||
|
||||
lldesc_t *plink = (lldesc_t *)elem;
|
||||
|
||||
plink->eof = next ? 0 : 1;
|
||||
plink->owner = 1;
|
||||
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;
|
||||
}
|
||||
|
||||
void rtc_cntl_hal_enable_cpu_retention(void *addr)
|
||||
{
|
||||
if (addr) {
|
||||
lldesc_t *plink = (lldesc_t *)addr;
|
||||
|
||||
/* 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);
|
||||
}
|
||||
}
|
@@ -18,6 +18,8 @@
|
||||
#include "hal/rtc_io_ll.h"
|
||||
#include "hal/rtc_cntl_ll.h"
|
||||
|
||||
#define RTC_HAL_DMA_LINK_NODE_SIZE (16)
|
||||
|
||||
#define rtc_hal_ext1_get_wakeup_pins() rtc_cntl_ll_ext1_get_wakeup_pins()
|
||||
|
||||
#define rtc_hal_ext1_set_wakeup_pins(mask, mode) rtc_cntl_ll_ext1_set_wakeup_pins(mask, mode)
|
||||
@@ -26,6 +28,12 @@
|
||||
|
||||
#define rtc_hal_set_wakeup_timer(ticks) rtc_cntl_ll_set_wakeup_timer(ticks)
|
||||
|
||||
void * rtc_cntl_hal_dma_link_init(void *elem, void *buff, int size, void *next);
|
||||
|
||||
void rtc_cntl_hal_enable_cpu_retention(void *addr);
|
||||
|
||||
#define rtc_cntl_hal_disable_cpu_retention() rtc_cntl_ll_disable_cpu_retention()
|
||||
|
||||
/*
|
||||
* Enable wakeup from ULP coprocessor.
|
||||
*/
|
||||
|
22
components/soc/esp32c3/include/soc/rtc_caps.h
Normal file
22
components/soc/esp32c3/include/soc/rtc_caps.h
Normal file
@@ -0,0 +1,22 @@
|
||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#define RTC_CNTL_CPU_PD_DMA_BUS_WIDTH (128)
|
||||
#define RTC_CNTL_CPU_PD_REG_FILE_NUM (108)
|
||||
#define RTC_CNTL_CPU_PD_DMA_ADDR_ALIGN (RTC_CNTL_CPU_PD_DMA_BUS_WIDTH >> 3)
|
||||
#define RTC_CNTL_CPU_PD_DMA_BLOCK_SIZE (RTC_CNTL_CPU_PD_DMA_BUS_WIDTH >> 3)
|
||||
|
||||
#define RTC_CNTL_CPU_PD_RETENTION_MEM_SIZE (RTC_CNTL_CPU_PD_REG_FILE_NUM * (RTC_CNTL_CPU_PD_DMA_BUS_WIDTH >> 3))
|
@@ -44,6 +44,7 @@
|
||||
#include "rmt_caps.h"
|
||||
#include "spi_caps.h"
|
||||
#include "uart_caps.h"
|
||||
#include "rtc_caps.h"
|
||||
|
||||
/*-------------------------- TOUCH SENSOR CAPS -------------------------------*/
|
||||
#define SOC_TOUCH_SENSOR_NUM (0) /*! No touch sensors on ESP32-C3 */
|
||||
@@ -126,3 +127,5 @@
|
||||
#define SOC_PM_SUPPORT_WIFI_WAKEUP (1)
|
||||
|
||||
#define SOC_PM_SUPPORT_BT_WAKEUP (1)
|
||||
|
||||
#define SOC_PM_SUPPORT_CPU_PD (1)
|
||||
|
Reference in New Issue
Block a user