Merge branch 'feature/support_esp32c3_lightsleep_master' into 'master'

support esp32c3 lightsleep for master

Closes IDF-2106

See merge request espressif/esp-idf!11975
This commit is contained in:
Jiang Jiang Jian 2021-01-20 16:00:06 +08:00
commit 26ae354dc5
44 changed files with 818 additions and 144 deletions

View File

@ -462,7 +462,6 @@ esp_err_t gpio_sleep_sel_en(gpio_num_t gpio_num);
*
* @return
* - ESP_OK Success
*
*/
esp_err_t gpio_sleep_sel_dis(gpio_num_t gpio_num);
@ -477,7 +476,6 @@ esp_err_t gpio_sleep_sel_dis(gpio_num_t gpio_num);
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG GPIO error
*
*/
esp_err_t gpio_sleep_set_direction(gpio_num_t gpio_num, gpio_mode_t mode);
@ -492,7 +490,6 @@ esp_err_t gpio_sleep_set_direction(gpio_num_t gpio_num, gpio_mode_t mode);
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG : Parameter error
*
*/
esp_err_t gpio_sleep_set_pull_mode(gpio_num_t gpio_num, gpio_pull_mode_t pull);
@ -504,8 +501,7 @@ esp_err_t gpio_sleep_set_pull_mode(gpio_num_t gpio_num, gpio_pull_mode_t pull);
*
* @return
* - ESP_OK Success
*
* */
*/
esp_err_t gpio_sleep_pupd_config_apply(gpio_num_t gpio_num);
/**
@ -515,8 +511,7 @@ esp_err_t gpio_sleep_pupd_config_apply(gpio_num_t gpio_num);
*
* @return
* - ESP_OK Success
*
* */
*/
esp_err_t gpio_sleep_pupd_config_unapply(gpio_num_t gpio_num);
#endif
#endif

View File

@ -13,6 +13,7 @@
// limitations under the License.
#include <stdint.h>
#include <stdlib.h>
#include "soc/soc.h"
#include "soc/rtc.h"
#include "soc/rtc_cntl_reg.h"
@ -163,3 +164,8 @@ uint32_t rtc_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp
}
return reject;
}
uint32_t rtc_deep_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt)
{
abort(); // ESP32-C3 TODO IDF-2560
}

View File

@ -1,11 +1,3 @@
idf_build_get_property(target IDF_TARGET)
if(${target} STREQUAL "esp32c3")
# TODO ESP32-C3 IDF-2107 - include the headers to avoid compile errors, no functions available to link...
idf_component_register(SRCS "pm_impl_riscv_temp.c" INCLUDE_DIRS include)
return()
endif()
idf_component_register(SRCS "pm_locks.c" "pm_trace.c" "pm_impl.c"
INCLUDE_DIRS include
LDFRAGMENTS linker.lf)

View File

@ -0,0 +1,42 @@
// 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 <stdint.h>
#include <stdbool.h>
#include "esp_err.h"
#include "soc/rtc.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Power management config for ESP32C3
*
* Pass a pointer to this structure as an argument to esp_pm_configure function.
*/
typedef struct {
int max_freq_mhz; /*!< Maximum CPU frequency, in MHz */
int min_freq_mhz; /*!< Minimum CPU frequency to use when no locks are taken, in MHz */
bool light_sleep_enable; /*!< Enter light sleep when no locks are taken */
} esp_pm_config_esp32c3_t;
#ifdef __cplusplus
}
#endif

View File

@ -23,6 +23,8 @@
#include "esp32s2/pm.h"
#elif CONFIG_IDF_TARGET_ESP32S3
#include "esp32s3/pm.h"
#elif CONFIG_IDF_TARGET_ESP32C3
#include "esp32c3/pm.h"
#endif
#ifdef __cplusplus

View File

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

View File

@ -31,8 +31,10 @@
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#if __XTENSA__
#include "freertos/xtensa_timer.h"
#include "xtensa/core-macros.h"
#endif
#include "esp_private/pm_impl.h"
#include "esp_private/pm_trace.h"
@ -54,10 +56,16 @@
#elif CONFIG_IDF_TARGET_ESP32S3
#include "esp32s3/clk.h"
#include "esp32s3/pm.h"
#elif CONFIG_IDF_TARGET_ESP32C3
#include "esp32c3/clk.h"
#include "esp32c3/pm.h"
#include "driver/gpio.h"
#include "esp_private/sleep_modes.h"
#endif
#define MHZ (1000000)
#if __XTENSA__
/* CCOMPARE update timeout, in CPU cycles. Any value above ~600 cycles will work
* for the purpose of detecting a deadlock.
*/
@ -67,6 +75,7 @@
* than this. This is to prevent setting CCOMPARE below CCOUNT.
*/
#define CCOMPARE_MIN_CYCLES_IN_FUTURE 1000
#endif
/* When light sleep is used, wake this number of microseconds earlier than
* the next tick.
@ -85,6 +94,9 @@
/* Minimal divider at which REF_CLK_FREQ can be obtained */
#define REF_CLK_DIV_MIN 2
#define DEFAULT_CPU_FREQ CONFIG_ESP32S3_DEFAULT_CPU_FREQ_MHZ
#elif CONFIG_IDF_TARGET_ESP32C3
#define REF_CLK_DIV_MIN 2
#define DEFAULT_CPU_FREQ CONFIG_ESP32C3_DEFAULT_CPU_FREQ_MHZ
#endif
#ifdef CONFIG_PM_PROFILING
@ -104,12 +116,6 @@ static size_t s_mode_lock_counts[PM_MODE_COUNT];
/* Bit mask of locked modes. BIT(i) is set iff s_mode_lock_counts[i] > 0. */
static uint32_t s_mode_mask;
/* Divider and multiplier used to adjust (ccompare - ccount) duration.
* Only set to non-zero values when switch is in progress.
*/
static uint32_t s_ccount_div;
static uint32_t s_ccount_mul;
#if CONFIG_FREERTOS_USE_TICKLESS_IDLE
#define PERIPH_SKIP_LIGHT_SLEEP_NO 1
@ -133,11 +139,6 @@ static bool s_skip_light_sleep[portNUM_PROCESSORS];
#endif // portNUM_PROCESSORS == 2
#endif // CONFIG_FREERTOS_USE_TICKLESS_IDLE
/* Indicates to the ISR hook that CCOMPARE needs to be updated on the given CPU.
* Used in conjunction with cross-core interrupt to update CCOMPARE on the other CPU.
*/
static volatile bool s_need_update_ccompare[portNUM_PROCESSORS];
/* A flag indicating that Idle hook has run on a given CPU;
* Next interrupt on the same CPU will take s_rtos_lock_handle.
*/
@ -177,9 +178,23 @@ static const char* s_mode_names[] = {
};
#endif // WITH_PROFILING
static const char* TAG = "pm_" CONFIG_IDF_TARGET;
#if __XTENSA__
/* Indicates to the ISR hook that CCOMPARE needs to be updated on the given CPU.
* Used in conjunction with cross-core interrupt to update CCOMPARE on the other CPU.
*/
static volatile bool s_need_update_ccompare[portNUM_PROCESSORS];
/* Divider and multiplier used to adjust (ccompare - ccount) duration.
* Only set to non-zero values when switch is in progress.
*/
static uint32_t s_ccount_div;
static uint32_t s_ccount_mul;
static void update_ccompare(void);
#endif // __XTENSA__
static const char* TAG = "pm";
static void do_switch(pm_mode_t new_mode);
static void leave_idle(void);
static void on_freq_update(uint32_t old_ticks_per_us, uint32_t ticks_per_us);
@ -211,6 +226,8 @@ esp_err_t esp_pm_configure(const void* vconfig)
const esp_pm_config_esp32s2_t* config = (const esp_pm_config_esp32s2_t*) vconfig;
#elif CONFIG_IDF_TARGET_ESP32S3
const esp_pm_config_esp32s3_t* config = (const esp_pm_config_esp32s3_t*) vconfig;
#elif CONFIG_IDF_TARGET_ESP32C3
const esp_pm_config_esp32c3_t* config = (const esp_pm_config_esp32c3_t*) vconfig;
#endif
#ifndef CONFIG_FREERTOS_USE_TICKLESS_IDLE
@ -256,7 +273,7 @@ esp_err_t esp_pm_configure(const void* vconfig)
*/
apb_max_freq = 80;
}
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
#else
int apb_max_freq = MIN(max_freq_mhz, 80); /* CPU frequency in APB_MAX mode */
#endif
@ -287,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;
}
@ -357,8 +381,11 @@ static void IRAM_ATTR on_freq_update(uint32_t old_ticks_per_us, uint32_t ticks_p
esp_timer_private_update_apb_freq(apb_ticks_per_us);
}
#if __XTENSA__
#if XT_RTOS_TIMER_INT
/* Calculate new tick divisor */
_xt_tick_divisor = ticks_per_us * MHZ / XT_TICK_PER_SEC;
#endif
int core_id = xPortGetCoreID();
if (s_rtos_lock_handle[core_id] != NULL) {
@ -391,6 +418,7 @@ static void IRAM_ATTR on_freq_update(uint32_t old_ticks_per_us, uint32_t ticks_p
s_ccount_div = 0;
ESP_PM_TRACE_EXIT(CCOMPARE_UPDATE, core_id);
}
#endif // __XTENSA__
}
/**
@ -412,9 +440,11 @@ static void IRAM_ATTR do_switch(pm_mode_t new_mode)
portEXIT_CRITICAL_ISR(&s_switch_lock);
return;
}
#if __XTENSA__
if (s_need_update_ccompare[core_id]) {
s_need_update_ccompare[core_id] = false;
}
#endif
portEXIT_CRITICAL_ISR(&s_switch_lock);
} while (true);
s_new_mode = new_mode;
@ -455,6 +485,7 @@ static void IRAM_ATTR do_switch(pm_mode_t new_mode)
portEXIT_CRITICAL_ISR(&s_switch_lock);
}
#if __XTENSA__
/**
* @brief Calculate new CCOMPARE value based on s_ccount_{mul,div}
*
@ -475,6 +506,7 @@ static void IRAM_ATTR update_ccompare(void)
}
}
}
#endif // __XTENSA__
static void IRAM_ATTR leave_idle(void)
{
@ -578,6 +610,7 @@ void IRAM_ATTR vApplicationSleep( TickType_t xExpectedIdleTime )
/* Adjust RTOS tick count based on the amount of time spent in sleep */
vTaskStepTick(slept_ticks);
#if __XTENSA__
/* Trigger tick interrupt, since sleep time was longer
* than portTICK_PERIOD_MS. Note that setting INTSET does not
* work for timer interrupt, and changing CCOMPARE would clear
@ -587,6 +620,9 @@ void IRAM_ATTR vApplicationSleep( TickType_t xExpectedIdleTime )
while (!(XTHAL_GET_INTERRUPT() & BIT(XT_TIMER_INTNUM))) {
;
}
#elif __riscv
portYIELD_WITHIN_API();
#endif
}
other_core_should_skip_light_sleep(core_id);
}
@ -676,6 +712,8 @@ void esp_pm_impl_init(void)
esp_pm_config_esp32s2_t cfg = {
#elif CONFIG_IDF_TARGET_ESP32S3
esp_pm_config_esp32s3_t cfg = {
#elif CONFIG_IDF_TARGET_ESP32C3
esp_pm_config_esp32c3_t cfg = {
#endif
.max_freq_mhz = DEFAULT_CPU_FREQ,
.min_freq_mhz = xtal_freq,
@ -709,7 +747,7 @@ void IRAM_ATTR esp_pm_impl_isr_hook(void)
* from happening in this section, since they will also call into esp_pm_impl_isr_hook.
*/
uint32_t state = portENTER_CRITICAL_NESTED();
#if portNUM_PROCESSORS == 2
#if __XTENSA__ && (portNUM_PROCESSORS == 2)
if (s_need_update_ccompare[core_id]) {
update_ccompare();
s_need_update_ccompare[core_id] = false;
@ -728,7 +766,7 @@ void esp_pm_impl_waiti(void)
#if CONFIG_FREERTOS_USE_TICKLESS_IDLE
int core_id = xPortGetCoreID();
if (s_skipped_light_sleep[core_id]) {
asm("waiti 0");
cpu_hal_waiti();
/* Interrupt took the CPU out of waiti and s_rtos_lock_handle[core_id]
* is now taken. However since we are back to idle task, we can release
* the lock so that vApplicationSleep can attempt to enter light sleep.
@ -737,7 +775,7 @@ void esp_pm_impl_waiti(void)
s_skipped_light_sleep[core_id] = false;
}
#else
asm("waiti 0");
cpu_hal_waiti();
#endif // CONFIG_FREERTOS_USE_TICKLESS_IDLE
}

View File

@ -21,12 +21,21 @@
* Feel free to change when debugging.
*/
static const int DRAM_ATTR s_trace_io[] = {
#ifndef CONFIG_IDF_TARGET_ESP32C3
BIT(4), BIT(5), // ESP_PM_TRACE_IDLE
BIT(16), BIT(17), // ESP_PM_TRACE_TICK
BIT(18), BIT(18), // ESP_PM_TRACE_FREQ_SWITCH
BIT(19), BIT(19), // ESP_PM_TRACE_CCOMPARE_UPDATE
BIT(25), BIT(26), // ESP_PM_TRACE_ISR_HOOK
BIT(27), BIT(27), // ESP_PM_TRACE_SLEEP
#else
BIT(2), BIT(3), // ESP_PM_TRACE_IDLE
BIT(4), BIT(5), // ESP_PM_TRACE_TICK
BIT(6), BIT(6), // ESP_PM_TRACE_FREQ_SWITCH
BIT(7), BIT(7), // ESP_PM_TRACE_CCOMPARE_UPDATE
BIT(8), BIT(9), // ESP_PM_TRACE_ISR_HOOK
BIT(18), BIT(18), // ESP_PM_TRACE_SLEEP
#endif
};
void esp_pm_trace_init(void)

View File

@ -1838,7 +1838,7 @@ rom_pbus_workmode = 0x400019a0;
rom_pbus_xpd_rx_off = 0x400019a4;
rom_pbus_xpd_rx_on = 0x400019a8;
rom_pbus_xpd_tx_off = 0x400019ac;
rom_pbus_xpd_tx_on = 0x400019b0;
/* rom_pbus_xpd_tx_on = 0x400019b0; */
rom_phy_byte_to_word = 0x400019b4;
rom_phy_disable_cca = 0x400019b8;
rom_phy_enable_cca = 0x400019bc;
@ -1855,7 +1855,7 @@ rom_set_loopback_gain = 0x400019e4;
rom_set_noise_floor = 0x400019e8;
rom_set_rxclk_en = 0x400019ec;
rom_set_tx_dig_gain = 0x400019f0;
rom_set_txcap_reg = 0x400019f4;
/* rom_set_txcap_reg = 0x400019f4; */
rom_set_txclk_en = 0x400019f8;
rom_spur_cal = 0x400019fc;
rom_spur_reg_write_one_tone = 0x40001a00;
@ -1879,21 +1879,21 @@ rom_tx_paon_set = 0x40001a44;
rom_i2cmst_reg_init = 0x40001a48;
rom_iq_corr_enable = 0x40001a4c;
rom_fe_reg_init = 0x40001a50;
rom_agc_reg_init = 0x40001a54;
rom_bb_reg_init = 0x40001a58;
/* rom_agc_reg_init = 0x40001a54; */
/* rom_bb_reg_init = 0x40001a58; */
rom_mac_enable_bb = 0x40001a5c;
rom_bb_wdg_cfg = 0x40001a60;
rom_force_txon = 0x40001a64;
rom_fe_txrx_reset = 0x40001a68;
rom_set_rx_comp = 0x40001a6c;
rom_set_pbus_reg = 0x40001a70;
/* rom_set_pbus_reg = 0x40001a70; */
rom_write_chan_freq = 0x40001a74;
rom_phy_xpd_rf = 0x40001a78;
/* rom_phy_xpd_rf = 0x40001a78; */
rom_set_xpd_sar = 0x40001a7c;
rom_write_dac_gain2 = 0x40001a80;
rom_rtc_sar2_init = 0x40001a84;
rom_get_target_power_offset = 0x40001a88;
rom_write_txrate_power_offset = 0x40001a8c;
/* rom_write_txrate_power_offset = 0x40001a8c; */
rom_get_rate_fcc_index = 0x40001a90;
rom_get_rate_target_power = 0x40001a94;
rom_write_wifi_dig_gain = 0x40001a98;
@ -1903,7 +1903,7 @@ rom_read_sar2_code = 0x40001aa4;
rom_get_sar2_vol = 0x40001aa8;
rom_get_pll_vol = 0x40001aac;
rom_get_phy_target_power = 0x40001ab0;
rom_temp_to_power = 0x40001ab4;
/* rom_temp_to_power = 0x40001ab4; */
rom_phy_track_pll_cap = 0x40001ab8;
rom_phy_pwdet_always_en = 0x40001abc;
rom_phy_pwdet_onetime_en = 0x40001ac0;
@ -1920,13 +1920,13 @@ rom_i2c_paral_write_num = 0x40001ae8;
rom_i2c_paral_write_mask = 0x40001aec;
rom_bb_bss_cbw40_ana = 0x40001af0;
rom_chan_to_freq = 0x40001af4;
rom_open_i2c_xpd = 0x40001af8;
/* rom_open_i2c_xpd = 0x40001af8; */
rom_dac_rate_set = 0x40001afc;
rom_tsens_read_init = 0x40001b00;
rom_tsens_code_read = 0x40001b04;
/* rom_tsens_read_init = 0x40001b00; */
/* rom_tsens_code_read = 0x40001b04; */
rom_tsens_index_to_dac = 0x40001b08;
rom_tsens_index_to_offset = 0x40001b0c;
rom_tsens_dac_cal = 0x40001b10;
/* rom_tsens_dac_cal = 0x40001b10; */
rom_code_to_temp = 0x40001b14;
rom_write_pll_cap_mem = 0x40001b18;
rom_pll_correct_dcap = 0x40001b1c;

View File

@ -1,17 +1,10 @@
idf_build_get_property(target IDF_TARGET)
# Remove when sleep is brought up on master for C3 TODO ESP32-C3 IDF-2571
if(NOT (${target} STREQUAL "esp32c3") )
list(APPEND sleep_src "sleep_modes.c")
endif()
idf_component_register(SRCS "intr_alloc.c"
"esp_async_memcpy.c"
"panic.c"
"system_api.c"
"startup.c"
"system_time.c"
"${sleep_src}"
"sleep_modes.c"
INCLUDE_DIRS include
PRIV_REQUIRES spi_flash
# [refactor-todo] requirements due to init code,

View File

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

View 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

View File

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

View File

@ -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
@ -82,42 +85,32 @@
#define RTC_CLK_SRC_CAL_CYCLES (10)
#ifdef CONFIG_IDF_TARGET_ESP32
#define DEFAULT_CPU_FREQ_MHZ CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ
#define DEFAULT_SLEEP_OUT_OVERHEAD_US (212)
#define DEFAULT_HARDWARE_OUT_OVERHEAD_US (60)
#define DEFAULT_CPU_FREQ_MHZ CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ
#define DEFAULT_SLEEP_OUT_OVERHEAD_US (212)
#define DEFAULT_HARDWARE_OUT_OVERHEAD_US (60)
#elif CONFIG_IDF_TARGET_ESP32S2
#define DEFAULT_CPU_FREQ_MHZ CONFIG_ESP32S2_DEFAULT_CPU_FREQ_MHZ
#define DEFAULT_SLEEP_OUT_OVERHEAD_US (147)
#define DEFAULT_HARDWARE_OUT_OVERHEAD_US (28)
#define DEFAULT_CPU_FREQ_MHZ CONFIG_ESP32S2_DEFAULT_CPU_FREQ_MHZ
#define DEFAULT_SLEEP_OUT_OVERHEAD_US (147)
#define DEFAULT_HARDWARE_OUT_OVERHEAD_US (28)
#elif CONFIG_IDF_TARGET_ESP32S3
#define DEFAULT_CPU_FREQ_MHZ CONFIG_ESP32S3_DEFAULT_CPU_FREQ_MHZ
#define DEFAULT_SLEEP_OUT_OVERHEAD_US (0)
#define DEFAULT_HARDWARE_OUT_OVERHEAD_US (0)
#define DEFAULT_CPU_FREQ_MHZ CONFIG_ESP32S3_DEFAULT_CPU_FREQ_MHZ
#define DEFAULT_SLEEP_OUT_OVERHEAD_US (0)
#define DEFAULT_HARDWARE_OUT_OVERHEAD_US (0)
#elif CONFIG_IDF_TARGET_ESP32C3
#define DEFAULT_CPU_FREQ_MHZ CONFIG_ESP32C3_DEFAULT_CPU_FREQ_MHZ
#define DEFAULT_CPU_FREQ_MHZ CONFIG_ESP32C3_DEFAULT_CPU_FREQ_MHZ
#define DEFAULT_SLEEP_OUT_OVERHEAD_US (105)
#define DEFAULT_HARDWARE_OUT_OVERHEAD_US (37)
#endif
#if defined(CONFIG_IDF_TARGET_ESP32) || defined(CONFIG_IDF_TARGET_ESP32S2)
#define LIGHT_SLEEP_TIME_OVERHEAD_US DEFAULT_HARDWARE_OUT_OVERHEAD_US
#if defined(CONFIG_ESP32_RTC_CLK_SRC_EXT_CRYS) || defined (CONFIG_ESP32S2_RTC_CLK_SRC_EXT_CRYS)
#define DEEP_SLEEP_TIME_OVERHEAD_US (650 + 100 * 240 / DEFAULT_CPU_FREQ_MHZ)
#define LIGHT_SLEEP_TIME_OVERHEAD_US DEFAULT_HARDWARE_OUT_OVERHEAD_US
#if defined(CONFIG_ESP32_RTC_CLK_SRC_EXT_CRYS) || \
defined(CONFIG_ESP32S2_RTC_CLK_SRC_EXT_CRYS) || \
defined(CONFIG_ESP32C3_RTC_CLK_SRC_EXT_CRYS) || \
defined(CONFIG_ESP32S3_RTC_CLK_SRC_EXT_CRYS)
#define DEEP_SLEEP_TIME_OVERHEAD_US (650 + 100 * 240 / DEFAULT_CPU_FREQ_MHZ)
#else
#define DEEP_SLEEP_TIME_OVERHEAD_US (250 + 100 * 240 / DEFAULT_CPU_FREQ_MHZ)
#endif // defined(CONFIG_ESP32_RTC_CLK_SRC_EXT_CRYS) || defined (CONFIG_ESP32S2_RTC_CLK_SRC_EXT_CRYS)
#elif defined(CONFIG_IDF_TARGET_ESP32C3)
#ifdef CONFIG_ESP32C3_RTC_CLK_SRC_EXT_CRYS
#define LIGHT_SLEEP_TIME_OVERHEAD_US (650 + 30 * 240 / CONFIG_ESP32C3_DEFAULT_CPU_FREQ_MHZ)
#define DEEP_SLEEP_TIME_OVERHEAD_US (650 + 100 * 240 / CONFIG_ESP32C3_DEFAULT_CPU_FREQ_MHZ)
#else
#define LIGHT_SLEEP_TIME_OVERHEAD_US (250 + 30 * 240 / CONFIG_ESP32C3_DEFAULT_CPU_FREQ_MHZ)
#define DEEP_SLEEP_TIME_OVERHEAD_US (250 + 100 * 240 / CONFIG_ESP32C3_DEFAULT_CPU_FREQ_MHZ)
#endif // CONFIG_ESP32C3_RTC_CLK_SRC_EXT_CRYS
#else // other target
#define LIGHT_SLEEP_TIME_OVERHEAD_US 0
#define DEEP_SLEEP_TIME_OVERHEAD_US 0
#endif // CONFIG_IDF_TARGET_*
#define DEEP_SLEEP_TIME_OVERHEAD_US (250 + 100 * 240 / DEFAULT_CPU_FREQ_MHZ)
#endif
#if defined(CONFIG_IDF_TARGET_ESP32) && defined(CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY)
#define DEEP_SLEEP_WAKEUP_DELAY CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY
@ -151,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
@ -171,8 +167,10 @@ static portMUX_TYPE spinlock_rtc_deep_sleep = portMUX_INITIALIZER_UNLOCKED;
static const char* TAG = "sleep";
static uint32_t get_power_down_flags(void);
#if SOC_PM_SUPPORT_EXT_WAKEUP
static void ext0_wakeup_prepare(void);
static void ext1_wakeup_prepare(void);
#endif
static void timer_wakeup_prepare(void);
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
static void touch_wakeup_prepare(void);
@ -240,20 +238,17 @@ static void IRAM_ATTR flush_uarts(void)
static void IRAM_ATTR suspend_uarts(void)
{
for (int i = 0; i < SOC_UART_NUM; ++i) {
#ifdef CONFIG_IDF_TARGET_ESP32
/* Note: Set `UART_FORCE_XOFF` can't stop new Tx request. */
REG_SET_BIT(UART_FLOW_CONF_REG(i), UART_FORCE_XOFF);
while (REG_GET_FIELD(UART_STATUS_REG(i), UART_ST_UTX_OUT) != 0) {
;
}
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
if (periph_ll_periph_enabled(PERIPH_UART0_MODULE + i)) {
REG_CLR_BIT(UART_FLOW_CONF_REG(i), UART_FORCE_XON);
REG_SET_BIT(UART_FLOW_CONF_REG(i), UART_SW_FLOW_CON_EN | UART_FORCE_XOFF);
while (REG_GET_FIELD(UART_FSM_STATUS_REG(i), UART_ST_UTX_OUT) != 0) {
;
}
}
#ifndef CONFIG_IDF_TARGET_ESP32
if (!periph_ll_periph_enabled(PERIPH_UART0_MODULE + i)) continue;
#endif
uart_ll_force_xoff(i);
#if SOC_UART_SUPPORT_FSM_TX_WAIT_SEND
uint32_t uart_fsm = 0;
do {
uart_fsm = uart_ll_get_fsm_status(i);
} while (!(uart_fsm == UART_FSM_IDLE || uart_fsm == UART_FSM_TX_WAIT_SEND));
#else
while (uart_ll_get_fsm_status(i) != 0) {}
#endif
}
}
@ -261,22 +256,41 @@ static void IRAM_ATTR suspend_uarts(void)
static void IRAM_ATTR resume_uarts(void)
{
for (int i = 0; i < SOC_UART_NUM; ++i) {
#ifdef CONFIG_IDF_TARGET_ESP32
REG_CLR_BIT(UART_FLOW_CONF_REG(i), UART_FORCE_XOFF);
REG_SET_BIT(UART_FLOW_CONF_REG(i), UART_FORCE_XON);
REG_CLR_BIT(UART_FLOW_CONF_REG(i), UART_FORCE_XON);
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
if (periph_ll_periph_enabled(PERIPH_UART0_MODULE + i)) {
REG_CLR_BIT(UART_FLOW_CONF_REG(i), UART_FORCE_XOFF);
REG_SET_BIT(UART_FLOW_CONF_REG(i), UART_FORCE_XON);
REG_CLR_BIT(UART_FLOW_CONF_REG(i), UART_SW_FLOW_CON_EN | UART_FORCE_XON);
}
#ifndef CONFIG_IDF_TARGET_ESP32
if (!periph_ll_periph_enabled(PERIPH_UART0_MODULE + i)) continue;
#endif
uart_ll_force_xon(i);
}
}
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)
@ -326,8 +340,7 @@ void esp_sleep_gpio_status_switch_configure(bool enable)
}
}
}
#endif
#endif // SOC_GPIO_SUPPORT_SLP_SWITCH
static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags)
{
@ -356,6 +369,7 @@ 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 SOC_PM_SUPPORT_EXT_WAKEUP
// Configure pins for external wakeup
if (s_config.wakeup_triggers & RTC_EXT0_TRIG_EN) {
ext0_wakeup_prepare();
@ -363,6 +377,7 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags)
if (s_config.wakeup_triggers & RTC_EXT1_TRIG_EN) {
ext1_wakeup_prepare();
}
#endif
#ifdef CONFIG_IDF_TARGET_ESP32
// Enable ULP wakeup
@ -407,6 +422,7 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags)
// Enter sleep
rtc_sleep_config_t config = RTC_SLEEP_CONFIG_DEFAULT(pd_flags);
rtc_sleep_init(config);
rtc_sleep_low_init(s_config.rtc_clk_cal_period);
// Set state machine time for light sleep
if(!deep_sleep) {
@ -450,9 +466,14 @@ 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
// re-enable UART output
resume_uarts();
@ -549,7 +570,7 @@ esp_err_t esp_light_sleep_start(void)
uint32_t pd_flags = get_power_down_flags();
// Re-calibrate the RTC Timer clock
#if defined(CONFIG_ESP32_RTC_CLK_SRC_EXT_CRYS) || defined(CONFIG_ESP32S2_RTC_CLK_SRC_EXT_CRYS)
#if defined(CONFIG_ESP32_RTC_CLK_SRC_EXT_CRYS) || defined(CONFIG_ESP32S2_RTC_CLK_SRC_EXT_CRYS) || defined(CONFIG_ESP32C3_RTC_CLK_SRC_EXT_CRYS)
uint64_t time_per_us = 1000000ULL;
s_config.rtc_clk_cal_period = (time_per_us << RTC_CLK_CAL_FRACT) / rtc_clk_slow_freq_get_hz();
#elif defined(CONFIG_ESP32S2_RTC_CLK_SRC_INT_RC)
@ -606,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
@ -627,8 +652,17 @@ esp_err_t esp_light_sleep_start(void)
s_light_sleep_wakeup = true;
// FRC1 has been clock gated for the duration of the sleep, correct for that.
#ifdef CONFIG_IDF_TARGET_ESP32C3
/**
* On esp32c3, rtc_time_get() is non-blocking, esp_system_get_time() is
* blocking, and the measurement data shows that this order is better.
*/
uint64_t frc_time_at_end = esp_system_get_time();
uint64_t rtc_ticks_at_end = rtc_time_get();
#else
uint64_t rtc_ticks_at_end = rtc_time_get();
uint64_t frc_time_at_end = esp_system_get_time();
#endif
uint64_t rtc_time_diff = rtc_time_slowclk_to_us(rtc_ticks_at_end - s_config.rtc_ticks_at_sleep_start, s_config.rtc_clk_cal_period);
uint64_t frc_time_diff = frc_time_at_end - frc_time_at_start;
@ -665,6 +699,7 @@ esp_err_t esp_sleep_disable_wakeup_source(esp_sleep_source_t source)
} else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_TIMER, RTC_TIMER_TRIG_EN)) {
s_config.wakeup_triggers &= ~RTC_TIMER_TRIG_EN;
s_config.sleep_duration = 0;
#if SOC_PM_SUPPORT_EXT_WAKEUP
} else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_EXT0, RTC_EXT0_TRIG_EN)) {
s_config.ext0_rtc_gpio_num = 0;
s_config.ext0_trigger_level = 0;
@ -673,8 +708,11 @@ esp_err_t esp_sleep_disable_wakeup_source(esp_sleep_source_t source)
s_config.ext1_rtc_gpio_mask = 0;
s_config.ext1_trigger_mode = 0;
s_config.wakeup_triggers &= ~RTC_EXT1_TRIG_EN;
#endif
#if SOC_TOUCH_PAD_WAKE_SUPPORTED
} else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_TOUCHPAD, RTC_TOUCH_TRIG_EN)) {
s_config.wakeup_triggers &= ~RTC_TOUCH_TRIG_EN;
#endif
} else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_GPIO, RTC_GPIO_TRIG_EN)) {
s_config.wakeup_triggers &= ~RTC_GPIO_TRIG_EN;
} else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_UART, (RTC_UART0_TRIG_EN | RTC_UART1_TRIG_EN))) {
@ -712,6 +750,8 @@ esp_err_t esp_sleep_enable_ulp_wakeup(void)
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
s_config.wakeup_triggers |= (RTC_ULP_TRIG_EN | RTC_COCPU_TRIG_EN | RTC_COCPU_TRAP_TRIG_EN);
return ESP_OK;
#else
return ESP_ERR_NOT_SUPPORTED;
#endif
}
@ -733,7 +773,6 @@ static void timer_wakeup_prepare(void)
rtc_hal_set_wakeup_timer(s_config.rtc_ticks_at_sleep_start + ticks);
}
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
/* In deep sleep mode, only the sleep channel is supported, and other touch channels should be turned off. */
static void touch_wakeup_prepare(void)
@ -749,6 +788,7 @@ static void touch_wakeup_prepare(void)
}
#endif
#if SOC_TOUCH_SENSOR_NUM > 0
esp_err_t esp_sleep_enable_touchpad_wakeup(void)
{
#if ((defined CONFIG_ESP32_RTC_EXT_CRYST_ADDIT_CURRENT) || (defined CONFIG_ESP32_RTC_EXT_CRYST_ADDIT_CURRENT_V2))
@ -773,6 +813,7 @@ touch_pad_t esp_sleep_get_touchpad_wakeup_status(void)
assert(ret == ESP_OK && "wakeup reason is RTC_TOUCH_TRIG_EN but SENS_TOUCH_MEAS_EN is zero");
return pad_num;
}
#endif // SOC_TOUCH_SENSOR_NUM > 0
bool esp_sleep_is_valid_wakeup_gpio(gpio_num_t gpio_num)
{
@ -783,6 +824,7 @@ bool esp_sleep_is_valid_wakeup_gpio(gpio_num_t gpio_num)
#endif
}
#if SOC_PM_SUPPORT_EXT_WAKEUP
esp_err_t esp_sleep_enable_ext0_wakeup(gpio_num_t gpio_num, int level)
{
if (level < 0 || level > 1) {
@ -889,6 +931,7 @@ uint64_t esp_sleep_get_ext1_wakeup_status(void)
}
return gpio_mask;
}
#endif // SOC_PM_SUPPORT_EXT_WAKEUP
esp_err_t esp_sleep_enable_gpio_wakeup(void)
{
@ -917,14 +960,11 @@ esp_err_t esp_sleep_enable_uart_wakeup(int uart_num)
esp_err_t esp_sleep_enable_wifi_wakeup(void)
{
#if CONFIG_IDF_TARGET_ESP32
return ESP_ERR_NOT_SUPPORTED;
#elif CONFIG_IDF_TARGET_ESP32S2
#if SOC_PM_SUPPORT_WIFI_WAKEUP
s_config.wakeup_triggers |= RTC_WIFI_TRIG_EN;
return ESP_OK;
#elif CONFIG_IDF_TARGET_ESP32S3
s_config.wakeup_triggers |= RTC_MAC_TRIG_EN;
return ESP_OK;
#else
return ESP_ERR_NOT_SUPPORTED;
#endif
}
@ -937,29 +977,39 @@ esp_sleep_wakeup_cause_t esp_sleep_get_wakeup_cause(void)
#ifdef CONFIG_IDF_TARGET_ESP32
uint32_t wakeup_cause = REG_GET_FIELD(RTC_CNTL_WAKEUP_STATE_REG, RTC_CNTL_WAKEUP_CAUSE);
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
#else
uint32_t wakeup_cause = REG_GET_FIELD(RTC_CNTL_SLP_WAKEUP_CAUSE_REG, RTC_CNTL_WAKEUP_CAUSE);
#endif
if (wakeup_cause & RTC_EXT0_TRIG_EN) {
return ESP_SLEEP_WAKEUP_EXT0;
} else if (wakeup_cause & RTC_EXT1_TRIG_EN) {
return ESP_SLEEP_WAKEUP_EXT1;
} else if (wakeup_cause & RTC_TIMER_TRIG_EN) {
if (wakeup_cause & RTC_TIMER_TRIG_EN) {
return ESP_SLEEP_WAKEUP_TIMER;
} else if (wakeup_cause & RTC_TOUCH_TRIG_EN) {
return ESP_SLEEP_WAKEUP_TOUCHPAD;
#if SOC_ULP_SUPPORTED
} else if (wakeup_cause & RTC_ULP_TRIG_EN) {
return ESP_SLEEP_WAKEUP_ULP;
#endif
} else if (wakeup_cause & RTC_GPIO_TRIG_EN) {
return ESP_SLEEP_WAKEUP_GPIO;
} else if (wakeup_cause & (RTC_UART0_TRIG_EN | RTC_UART1_TRIG_EN)) {
return ESP_SLEEP_WAKEUP_UART;
#if CONFIG_IDF_TARGET_ESP32S2
#if SOC_PM_SUPPORT_EXT_WAKEUP
} else if (wakeup_cause & RTC_EXT0_TRIG_EN) {
return ESP_SLEEP_WAKEUP_EXT0;
} else if (wakeup_cause & RTC_EXT1_TRIG_EN) {
return ESP_SLEEP_WAKEUP_EXT1;
#endif
#if SOC_TOUCH_PAD_WAKE_SUPPORTED
} else if (wakeup_cause & RTC_TOUCH_TRIG_EN) {
return ESP_SLEEP_WAKEUP_TOUCHPAD;
#endif
#if SOC_ULP_SUPPORTED
} else if (wakeup_cause & RTC_ULP_TRIG_EN) {
return ESP_SLEEP_WAKEUP_ULP;
#endif
#if SOC_PM_SUPPORT_WIFI_WAKEUP
} else if (wakeup_cause & RTC_WIFI_TRIG_EN) {
return ESP_SLEEP_WAKEUP_WIFI;
#endif
#if SOC_PM_SUPPORT_BT_WAKEUP
} else if (wakeup_cause & RTC_BT_TRIG_EN) {
return ESP_SLEEP_WAKEUP_BT;
#endif
#if CONFIG_IDF_TARGET_ESP32S2
} else if (wakeup_cause & RTC_COCPU_TRIG_EN) {
return ESP_SLEEP_WAKEUP_ULP;
} else if (wakeup_cause & RTC_COCPU_TRAP_TRIG_EN) {
@ -1036,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;
}
@ -1061,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

View File

@ -73,6 +73,13 @@ void phy_wakeup_init(void);
*/
void phy_close_rf(void);
#if CONFIG_IDF_TARGET_ESP32C3
/**
* @brief Disable PHY temperature sensor.
*/
void phy_xpd_tsens(void);
#endif
#if CONFIG_MAC_BB_PD
/**
* @brief Store and load baseband registers.

@ -1 +1 @@
Subproject commit 7a3e28bf73aa80977575980e1c47af087b6eb23b
Subproject commit c5cf57a2d0d61fa18dc847a4d13cd678c43bc7f5

View File

@ -239,6 +239,10 @@ IRAM_ATTR void esp_phy_disable(void)
if (s_phy_access_ref == 0) {
// Disable PHY and RF.
phy_close_rf();
#if CONFIG_IDF_TARGET_ESP32C3
// Disable PHY temperature sensor
phy_xpd_tsens();
#endif
#if CONFIG_IDF_TARGET_ESP32
// Update WiFi MAC time before disalbe WiFi/BT common peripheral clock
phy_update_wifi_mac_time(true, esp_timer_get_time());

View File

@ -96,6 +96,7 @@
#include "esp_attr.h"
#include "esp_debug_helpers.h"
#include "esp_log.h"
#include "esp_private/pm_trace.h"
/**
* @brief A variable is used to keep track of the critical section nesting.
@ -151,11 +152,11 @@ void vPortSetupTimer(void)
/* configure the timer */
systimer_hal_init();
systimer_hal_connect_alarm_counter(SYSTIMER_ALARM_0, SYSTIMER_COUNTER_1);
systimer_hal_enable_counter(SYSTIMER_COUNTER_1);
systimer_hal_set_alarm_period(SYSTIMER_ALARM_0, 1000000UL / CONFIG_FREERTOS_HZ);
systimer_hal_select_alarm_mode(SYSTIMER_ALARM_0, SYSTIMER_ALARM_MODE_PERIOD);
systimer_hal_enable_alarm_int(SYSTIMER_ALARM_0);
systimer_hal_connect_alarm_counter(SYSTIMER_ALARM_0, SYSTIMER_COUNTER_1);
}
void prvTaskExitError(void)
@ -215,6 +216,10 @@ IRAM_ATTR void vPortSysTickHandler(void *arg)
systimer_ll_clear_alarm_int(SYSTIMER_ALARM_0);
#ifdef CONFIG_PM_TRACE
ESP_PM_TRACE_ENTER(TICK, xPortGetCoreID());
#endif
if (!uxSchedulerRunning) {
return;
}
@ -222,6 +227,10 @@ IRAM_ATTR void vPortSysTickHandler(void *arg)
if (xTaskIncrementTick() != pdFALSE) {
vPortYieldFromISR();
}
#ifdef CONFIG_PM_TRACE
ESP_PM_TRACE_EXIT(TICK, xPortGetCoreID());
#endif
}
BaseType_t xPortStartScheduler(void)

View File

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

View File

@ -178,6 +178,11 @@ static inline void cpu_ll_set_vecbase(const void* vecbase)
asm volatile ("wsr %0, vecbase" :: "r" (vecbase));
}
static inline void cpu_ll_waiti(void)
{
asm volatile ("waiti 0\n");
}
#ifdef __cplusplus
}
#endif

View File

@ -894,6 +894,45 @@ static inline uint16_t uart_ll_max_tout_thrd(uart_dev_t *hw)
return tout_thrd;
}
/**
* @brief Force UART xoff.
*
* @param uart_num UART port number, the max port number is (UART_NUM_MAX -1).
*
* @return None.
*/
static inline void uart_ll_force_xoff(uart_port_t uart_num)
{
/* Note: Set `UART_FORCE_XOFF` can't stop new Tx request. */
REG_SET_BIT(UART_FLOW_CONF_REG(uart_num), UART_FORCE_XOFF);
}
/**
* @brief Force UART xon.
*
* @param uart_num UART port number, the max port number is (UART_NUM_MAX -1).
*
* @return None.
*/
static inline void uart_ll_force_xon(uart_port_t uart_num)
{
REG_CLR_BIT(UART_FLOW_CONF_REG(uart_num), UART_FORCE_XOFF);
REG_SET_BIT(UART_FLOW_CONF_REG(uart_num), UART_FORCE_XON);
REG_CLR_BIT(UART_FLOW_CONF_REG(uart_num), UART_FORCE_XON);
}
/**
* @brief Get UART final state machine status.
*
* @param uart_num UART port number, the max port number is (UART_NUM_MAX -1).
*
* @return UART module FSM status.
*/
static inline uint32_t uart_ll_get_fsm_status(uart_port_t uart_num)
{
return REG_GET_FIELD(UART_STATUS_REG(uart_num), UART_ST_UTX_OUT);
}
#undef UART_LL_TOUT_REF_FACTOR_DEFAULT
#ifdef __cplusplus

View File

@ -151,6 +151,11 @@ static inline void cpu_ll_set_vecbase(const void* vecbase)
RV_WRITE_CSR(mtvec, vecbase_int);
}
static inline void cpu_ll_waiti(void)
{
asm volatile ("wfi\n");
}
#ifdef __cplusplus
}
#endif

View File

@ -399,6 +399,117 @@ static inline void gpio_ll_force_unhold_all(gpio_dev_t *hw)
SET_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_CLR_DG_PAD_AUTOHOLD);
}
/**
* @brief Enable GPIO pin used for wakeup from sleep.
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number
*/
static inline void gpio_ll_sleep_sel_en(gpio_dev_t *hw, gpio_num_t gpio_num)
{
PIN_SLP_SEL_ENABLE(GPIO_PIN_MUX_REG[gpio_num]);
}
/**
* @brief Disable GPIO pin used for wakeup from sleep.
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number
*/
static inline void gpio_ll_sleep_sel_dis(gpio_dev_t *hw, gpio_num_t gpio_num)
{
PIN_SLP_SEL_DISABLE(GPIO_PIN_MUX_REG[gpio_num]);
}
/**
* @brief Disable GPIO pull-up in sleep mode.
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number
*/
static inline void gpio_ll_sleep_pullup_dis(gpio_dev_t *hw, gpio_num_t gpio_num)
{
PIN_SLP_PULLUP_DISABLE(GPIO_PIN_MUX_REG[gpio_num]);
}
/**
* @brief Enable GPIO pull-up in sleep mode.
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number
*/
static inline void gpio_ll_sleep_pullup_en(gpio_dev_t *hw, gpio_num_t gpio_num)
{
PIN_SLP_PULLUP_ENABLE(GPIO_PIN_MUX_REG[gpio_num]);
}
/**
* @brief Enable GPIO pull-down in sleep mode.
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number
*/
static inline void gpio_ll_sleep_pulldown_en(gpio_dev_t *hw, gpio_num_t gpio_num)
{
PIN_SLP_PULLDOWN_ENABLE(GPIO_PIN_MUX_REG[gpio_num]);
}
/**
* @brief Disable GPIO pull-down in sleep mode.
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number
*/
static inline void gpio_ll_sleep_pulldown_dis(gpio_dev_t *hw, gpio_num_t gpio_num)
{
PIN_SLP_PULLDOWN_DISABLE(GPIO_PIN_MUX_REG[gpio_num]);
}
/**
* @brief Disable GPIO input in sleep mode.
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number
*/
static inline void gpio_ll_sleep_input_disable(gpio_dev_t *hw, gpio_num_t gpio_num)
{
PIN_SLP_INPUT_DISABLE(GPIO_PIN_MUX_REG[gpio_num]);
}
/**
* @brief Enable GPIO input in sleep mode.
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number
*/
static inline void gpio_ll_sleep_input_enable(gpio_dev_t *hw, gpio_num_t gpio_num)
{
PIN_SLP_INPUT_ENABLE(GPIO_PIN_MUX_REG[gpio_num]);
}
/**
* @brief Disable GPIO output in sleep mode.
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number
*/
static inline void gpio_ll_sleep_output_disable(gpio_dev_t *hw, gpio_num_t gpio_num)
{
PIN_SLP_OUTPUT_DISABLE(GPIO_PIN_MUX_REG[gpio_num]);
}
/**
* @brief Enable GPIO output in sleep mode.
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number
*/
static inline void gpio_ll_sleep_output_enable(gpio_dev_t *hw, gpio_num_t gpio_num)
{
PIN_SLP_OUTPUT_ENABLE(GPIO_PIN_MUX_REG[gpio_num]);
}
#ifdef __cplusplus
}
#endif

View File

@ -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" {
@ -24,7 +25,11 @@ extern "C" {
static inline void rtc_cntl_ll_set_wakeup_timer(uint64_t t)
{
abort(); // ESP32-C3 TODO IDF-2106
WRITE_PERI_REG(RTC_CNTL_SLP_TIMER0_REG, t & UINT32_MAX);
WRITE_PERI_REG(RTC_CNTL_SLP_TIMER1_REG, t >> 32);
SET_PERI_REG_MASK(RTC_CNTL_INT_CLR_REG, RTC_CNTL_MAIN_TIMER_INT_CLR_M);
SET_PERI_REG_MASK(RTC_CNTL_SLP_TIMER1_REG, RTC_CNTL_MAIN_TIMER_ALARM_EN_M);
}
static inline uint32_t rtc_cntl_ll_ext1_get_wakeup_pins(void)
@ -43,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

View File

@ -884,6 +884,47 @@ static inline uint16_t uart_ll_max_tout_thrd(uart_dev_t *hw)
return UART_RX_TOUT_THRHD_V;
}
/**
* @brief Force UART xoff.
*
* @param uart_num UART port number, the max port number is (UART_NUM_MAX -1).
*
* @return None.
*/
static inline void uart_ll_force_xoff(uart_port_t uart_num)
{
REG_CLR_BIT(UART_FLOW_CONF_REG(uart_num), UART_FORCE_XON);
REG_SET_BIT(UART_FLOW_CONF_REG(uart_num), UART_SW_FLOW_CON_EN | UART_FORCE_XOFF);
REG_SET_BIT(UART_ID_REG(uart_num), UART_UPDATE);
}
/**
* @brief Force UART xon.
*
* @param uart_num UART port number, the max port number is (UART_NUM_MAX -1).
*
* @return None.
*/
static inline void uart_ll_force_xon(uart_port_t uart_num)
{
REG_CLR_BIT(UART_FLOW_CONF_REG(uart_num), UART_FORCE_XOFF);
REG_SET_BIT(UART_FLOW_CONF_REG(uart_num), UART_FORCE_XON);
REG_CLR_BIT(UART_FLOW_CONF_REG(uart_num), UART_SW_FLOW_CON_EN | UART_FORCE_XON);
REG_SET_BIT(UART_ID_REG(uart_num), UART_UPDATE);
}
/**
* @brief Get UART final state machine status.
*
* @param uart_num UART port number, the max port number is (UART_NUM_MAX -1).
*
* @return UART module FSM status.
*/
static inline uint32_t uart_ll_get_fsm_status(uart_port_t uart_num)
{
return REG_GET_FIELD(UART_FSM_STATUS_REG(uart_num), UART_ST_UTX_OUT);
}
#ifdef __cplusplus
}
#endif

View 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);
}
}

View File

@ -197,6 +197,11 @@ static inline void cpu_ll_write_dedic_gpio_mask(uint32_t mask, uint32_t value)
asm volatile("wr_mask_gpio_out %0, %1" : : "r"(value), "r"(mask):);
}
static inline void cpu_ll_waiti(void)
{
asm volatile ("waiti 0\n");
}
#ifdef __cplusplus
}
#endif

View File

@ -826,6 +826,45 @@ static inline uint16_t uart_ll_max_tout_thrd(uart_dev_t *hw)
return UART_RX_TOUT_THRHD_V;
}
/**
* @brief Force UART xoff.
*
* @param uart_num UART port number, the max port number is (UART_NUM_MAX -1).
*
* @return None.
*/
static inline void uart_ll_force_xoff(uart_port_t uart_num)
{
REG_CLR_BIT(UART_FLOW_CONF_REG(uart_num), UART_FORCE_XON);
REG_SET_BIT(UART_FLOW_CONF_REG(uart_num), UART_SW_FLOW_CON_EN | UART_FORCE_XOFF);
}
/**
* @brief Force UART xon.
*
* @param uart_num UART port number, the max port number is (UART_NUM_MAX -1).
*
* @return None.
*/
static inline void uart_ll_force_xon(uart_port_t uart_num)
{
REG_CLR_BIT(UART_FLOW_CONF_REG(uart_num), UART_FORCE_XOFF);
REG_SET_BIT(UART_FLOW_CONF_REG(uart_num), UART_FORCE_XON);
REG_CLR_BIT(UART_FLOW_CONF_REG(uart_num), UART_SW_FLOW_CON_EN | UART_FORCE_XON);
}
/**
* @brief Get UART final state machine status.
*
* @param uart_num UART port number, the max port number is (UART_NUM_MAX -1).
*
* @return UART module FSM status.
*/
static inline uint32_t uart_ll_get_fsm_status(uart_port_t uart_num)
{
return REG_GET_FIELD(UART_FSM_STATUS_REG(uart_num), UART_ST_UTX_OUT);
}
#ifdef __cplusplus
}
#endif

View File

@ -177,6 +177,11 @@ static inline void cpu_ll_set_vecbase(const void *vecbase)
asm volatile ("wsr %0, vecbase" :: "r" (vecbase));
}
static inline void cpu_ll_waiti(void)
{
asm volatile ("waiti 0\n");
}
static inline uint32_t cpu_ll_read_dedic_gpio_in(void)
{
uint32_t value = 0;

View File

@ -852,6 +852,45 @@ static inline uint16_t uart_ll_max_tout_thrd(uart_dev_t *hw)
return UART_RX_TOUT_THRHD_V;
}
/**
* @brief Force UART xoff.
*
* @param uart_num UART port number, the max port number is (UART_NUM_MAX -1).
*
* @return None.
*/
static inline void uart_ll_force_xoff(uart_port_t uart_num)
{
REG_CLR_BIT(UART_FLOW_CONF_REG(uart_num), UART_FORCE_XON);
REG_SET_BIT(UART_FLOW_CONF_REG(uart_num), UART_SW_FLOW_CON_EN | UART_FORCE_XOFF);
}
/**
* @brief Force UART xon.
*
* @param uart_num UART port number, the max port number is (UART_NUM_MAX -1).
*
* @return None.
*/
static inline void uart_ll_force_xon(uart_port_t uart_num)
{
REG_CLR_BIT(UART_FLOW_CONF_REG(uart_num), UART_FORCE_XOFF);
REG_SET_BIT(UART_FLOW_CONF_REG(uart_num), UART_FORCE_XON);
REG_CLR_BIT(UART_FLOW_CONF_REG(uart_num), UART_SW_FLOW_CON_EN | UART_FORCE_XON);
}
/**
* @brief Get UART final state machine status.
*
* @param uart_num UART port number, the max port number is (UART_NUM_MAX -1).
*
* @return UART module FSM status.
*/
static inline uint32_t uart_ll_get_fsm_status(uart_port_t uart_num)
{
return REG_GET_FIELD(UART_FSM_STATUS_REG(uart_num), UART_ST_UTX_OUT);
}
#ifdef __cplusplus
}
#endif

View File

@ -73,6 +73,11 @@ extern "C" {
*/
#define cpu_hal_break() cpu_ll_break()
/**
* Wait for interrupt.
*/
#define cpu_hal_waiti() cpu_ll_waiti()
#if SOC_CPU_BREAKPOINTS_NUM > 0
/**

View File

@ -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.
*/

View File

@ -14,6 +14,8 @@
#include "soc/soc.h"
#include "soc/interrupt_reg.h"
#include "riscv/rvruntime-frames.h"
#include "soc/soc_caps.h"
#include "sdkconfig.h"
.equ SAVE_REGS, 32
@ -243,6 +245,22 @@ _interrupt_handler:
li t0, 0x8
csrrs t0, mstatus, t0
#ifdef CONFIG_PM_TRACE
li a0, 0 /* = ESP_PM_TRACE_IDLE */
#if SOC_CPU_CORES_NUM == 1
li a1, 0 /* No need to check core ID on single core hardware */
#else
csrr a1, mhartid
#endif
la t0, esp_pm_trace_exit
jalr t0 /* absolute jump, avoid the 1 MiB range constraint */
#endif
#ifdef CONFIG_PM_ENABLE
la t0, esp_pm_impl_isr_hook
jalr t0 /* absolute jump, avoid the 1 MiB range constraint */
#endif
/* call the C dispatcher */
mv a0, sp /* argument 1, stack pointer */
csrr a1, mcause /* argument 2, interrupt number */

View File

@ -268,6 +268,9 @@
#define SOC_AES_SUPPORT_AES_192 (1)
#define SOC_AES_SUPPORT_AES_256 (1)
/*-------------------------- Power Management CAPS ---------------------------*/
#define SOC_PM_SUPPORT_EXT_WAKEUP (1)
/* ---------------------------- Compatibility ------------------------------- */
#define SOC_CAN_SUPPORTED SOC_TWAI_SUPPORTED
#define CAN_BRP_MIN SOC_TWAI_BRP_MIN

View File

@ -36,6 +36,9 @@ extern "C" {
#define SOC_GPIO_VALID_GPIO_MASK ((1U<<SOC_GPIO_PIN_COUNT) - 1)
#define SOC_GPIO_VALID_OUTPUT_GPIO_MASK SOC_GPIO_VALID_GPIO_MASK
// Support to configure slept status
#define SOC_GPIO_SUPPORT_SLP_SWITCH (1)
#ifdef __cplusplus
}
#endif

View File

@ -103,9 +103,10 @@ extern "C" {
#define RTC_CNTL_SCK_DCAP_DEFAULT 255
/* Various delays to be programmed into power control state machines */
#define RTC_CNTL_XTL_BUF_WAIT_SLP_US (1000)
#define RTC_CNTL_PLL_BUF_WAIT_SLP_CYCLES (2)
#define RTC_CNTL_XTL_BUF_WAIT_SLP_US (250)
#define RTC_CNTL_PLL_BUF_WAIT_SLP_CYCLES (1)
#define RTC_CNTL_CK8M_WAIT_SLP_CYCLES (4)
#define RTC_CNTL_WAKEUP_DELAY_CYCLES (5)
#define RTC_CNTL_OTHER_BLOCKS_POWERUP_CYCLES (1)
#define RTC_CNTL_OTHER_BLOCKS_WAIT_CYCLES (1)
@ -722,7 +723,7 @@ void rtc_sleep_set_wakeup_time(uint64_t t);
#define RTC_GPIO_TRIG_EN BIT(2) //!< GPIO wakeup
#define RTC_TIMER_TRIG_EN BIT(3) //!< Timer wakeup
#define RTC_MAC_TRIG_EN BIT(5) //!< MAC wakeup (light sleep only)
#define RTC_WIFI_TRIG_EN BIT(5) //!< WIFI wakeup (light sleep only)
#define RTC_UART0_TRIG_EN BIT(6) //!< UART0 wakeup (light sleep only)
#define RTC_UART1_TRIG_EN BIT(7) //!< UART1 wakeup (light sleep only)
#define RTC_BT_TRIG_EN BIT(10) //!< BT wakeup (light sleep only)
@ -757,6 +758,29 @@ void rtc_sleep_set_wakeup_time(uint64_t t);
*/
uint32_t rtc_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp_mem_inf_fpu);
/**
* @brief Enter deep sleep mode
*
* Similar to rtc_sleep_start(), but additionally uses hardware to calculate the CRC value
* of RTC FAST memory. On wake, this CRC is used to determine if a deep sleep wake
* stub is valid to execute (if a wake address is set).
*
* No RAM is accessed while calculating the CRC and going into deep sleep, which makes
* this function safe to use even if the caller's stack is in RTC FAST memory.
*
* @note If no deep sleep wake stub address is set then calling rtc_sleep_start() will
* have the same effect and takes less time as CRC calculation is skipped.
*
* @note This function should only be called after rtc_sleep_init() has been called to
* configure the system for deep sleep.
*
* @param wakeup_opt - same as for rtc_sleep_start
* @param reject_opt - same as for rtc_sleep_start
*
* @return non-zero if sleep was rejected by hardware
*/
uint32_t rtc_deep_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt);
/**
* RTC power and clock control initialization settings
*/

View File

@ -12,8 +12,11 @@
// See the License for the specific language governing permissions and
// limitations under the License.
/* TODO ESP32-C3 Placeholder until IDF-2107 when this file can be dropped */
void esp_pm_impl_waiti(void)
{
#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))

View File

@ -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 */
@ -121,3 +122,10 @@
/*-------------------------- COEXISTENCE HARDWARE PTI CAPS -------------------------------*/
#define SOC_COEX_HW_PTI (1)
/*-------------------------- Power Management CAPS ----------------------------*/
#define SOC_PM_SUPPORT_WIFI_WAKEUP (1)
#define SOC_PM_SUPPORT_BT_WAKEUP (1)
#define SOC_PM_SUPPORT_CPU_PD (1)

View File

@ -27,6 +27,11 @@ extern "C" {
// ESP32-C3 have 2 UART
#define SOC_UART_NUM (2)
// UART has an extra TX_WAIT_SEND state when the FIFO is not empty and XOFF is enabled
#define SOC_UART_SUPPORT_FSM_TX_WAIT_SEND (1)
#define UART_FSM_IDLE (0x0)
#define UART_FSM_TX_WAIT_SEND (0xf)
#ifdef __cplusplus
}
#endif

View File

@ -295,6 +295,10 @@
/*-------------------------- WI-FI HARDWARE TSF CAPS -------------------------------*/
#define SOC_WIFI_HW_TSF (1)
/*-------------------------- Power Management CAPS ---------------------------*/
#define SOC_PM_SUPPORT_EXT_WAKEUP (1)
#define SOC_PM_SUPPORT_WIFI_WAKEUP (1)
/* ---------------------------- Compatibility ------------------------------- */
// No contents

View File

@ -718,7 +718,7 @@ void rtc_sleep_set_wakeup_time(uint64_t t);
#define RTC_GPIO_TRIG_EN BIT(2) //!< GPIO wakeup (light sleep only)
#define RTC_TIMER_TRIG_EN BIT(3) //!< Timer wakeup
#define RTC_SDIO_TRIG_EN BIT(4) //!< SDIO wakeup (light sleep only)
#define RTC_MAC_TRIG_EN BIT(5) //!< MAC wakeup (light sleep only)
#define RTC_WIFI_TRIG_EN BIT(5) //!< WIFI wakeup (light sleep only)
#define RTC_UART0_TRIG_EN BIT(6) //!< UART0 wakeup (light sleep only)
#define RTC_UART1_TRIG_EN BIT(7) //!< UART1 wakeup (light sleep only)
#define RTC_TOUCH_TRIG_EN BIT(8) //!< Touch wakeup

View File

@ -143,6 +143,13 @@
/*-------------------------- AES CAPS -----------------------------------------*/
#define SOC_AES_SUPPORT_DMA (1)
/*-------------------------- Power Management CAPS ---------------------------*/
#define SOC_PM_SUPPORT_EXT_WAKEUP (1)
#define SOC_PM_SUPPORT_WIFI_WAKEUP (1)
#define SOC_PM_SUPPORT_BT_WAKEUP (1)
/* Has a centralized DMA, which is shared with all peripherals */
#define SOC_AES_GENERAL_DMA (1)

View File

@ -43,6 +43,7 @@ menu "Example Configuration"
choice EXAMPLE_MAX_CPU_FREQ
prompt "Maximum CPU frequency"
default EXAMPLE_MAX_CPU_FREQ_80
depends on PM_ENABLE
help
Maximum CPU frequency to use for dynamic frequency scaling.
@ -52,6 +53,7 @@ menu "Example Configuration"
bool "160 MHz"
config EXAMPLE_MAX_CPU_FREQ_240
bool "240 MHz"
depends on IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
endchoice
config EXAMPLE_MAX_CPU_FREQ_MHZ
@ -64,19 +66,20 @@ menu "Example Configuration"
choice EXAMPLE_MIN_CPU_FREQ
prompt "Minimum CPU frequency"
default EXAMPLE_MIN_CPU_FREQ_10M
depends on PM_ENABLE
help
Minimum CPU frequency to use for dynamic frequency scaling.
Should be set to XTAL frequency or XTAL frequency divided by integer.
config EXAMPLE_MIN_CPU_FREQ_40M
bool "40 MHz (use with 40MHz XTAL)"
depends on IDF_TARGET_ESP32S2 || ESP32_XTAL_FREQ_40 || ESP32_XTAL_FREQ_AUTO
depends on IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32C3 || ESP32_XTAL_FREQ_40 || ESP32_XTAL_FREQ_AUTO
config EXAMPLE_MIN_CPU_FREQ_20M
bool "20 MHz (use with 40MHz XTAL)"
depends on IDF_TARGET_ESP32S2 || ESP32_XTAL_FREQ_40 || ESP32_XTAL_FREQ_AUTO
depends on IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32C3 || ESP32_XTAL_FREQ_40 || ESP32_XTAL_FREQ_AUTO
config EXAMPLE_MIN_CPU_FREQ_10M
bool "10 MHz (use with 40MHz XTAL)"
depends on IDF_TARGET_ESP32S2 || ESP32_XTAL_FREQ_40 || ESP32_XTAL_FREQ_AUTO
depends on IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32C3 || ESP32_XTAL_FREQ_40 || ESP32_XTAL_FREQ_AUTO
config EXAMPLE_MIN_CPU_FREQ_26M
bool "26 MHz (use with 26MHz XTAL)"
depends on ESP32_XTAL_FREQ_26 || ESP32_XTAL_FREQ_AUTO

View File

@ -99,6 +99,8 @@ void app_main(void)
esp_pm_config_esp32_t pm_config = {
#elif CONFIG_IDF_TARGET_ESP32S2
esp_pm_config_esp32s2_t pm_config = {
#elif CONFIG_IDF_TARGET_ESP32C3
esp_pm_config_esp32c3_t pm_config = {
#endif
.max_freq_mhz = CONFIG_EXAMPLE_MAX_CPU_FREQ_MHZ,
.min_freq_mhz = CONFIG_EXAMPLE_MIN_CPU_FREQ_MHZ,