light sleep: dfs support for esp32c3

This commit is contained in:
Li Shuai
2020-12-04 10:19:39 +08:00
parent e39ed0ecf1
commit 355dd10257
14 changed files with 141 additions and 30 deletions

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" idf_component_register(SRCS "pm_locks.c" "pm_trace.c" "pm_impl.c"
INCLUDE_DIRS include INCLUDE_DIRS include
LDFRAGMENTS linker.lf) LDFRAGMENTS linker.lf)

View File

@@ -12,8 +12,31 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // 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
#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" #include "esp32s2/pm.h"
#elif CONFIG_IDF_TARGET_ESP32S3 #elif CONFIG_IDF_TARGET_ESP32S3
#include "esp32s3/pm.h" #include "esp32s3/pm.h"
#elif CONFIG_IDF_TARGET_ESP32C3
#include "esp32c3/pm.h"
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus

View File

@@ -31,8 +31,10 @@
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "freertos/task.h" #include "freertos/task.h"
#if __XTENSA__
#include "freertos/xtensa_timer.h" #include "freertos/xtensa_timer.h"
#include "xtensa/core-macros.h" #include "xtensa/core-macros.h"
#endif
#include "esp_private/pm_impl.h" #include "esp_private/pm_impl.h"
#include "esp_private/pm_trace.h" #include "esp_private/pm_trace.h"
@@ -54,10 +56,15 @@
#elif CONFIG_IDF_TARGET_ESP32S3 #elif CONFIG_IDF_TARGET_ESP32S3
#include "esp32s3/clk.h" #include "esp32s3/clk.h"
#include "esp32s3/pm.h" #include "esp32s3/pm.h"
#elif CONFIG_IDF_TARGET_ESP32C3
#include "esp32c3/clk.h"
#include "esp32c3/pm.h"
#include "driver/gpio.h"
#endif #endif
#define MHZ (1000000) #define MHZ (1000000)
#if __XTENSA__
/* CCOMPARE update timeout, in CPU cycles. Any value above ~600 cycles will work /* CCOMPARE update timeout, in CPU cycles. Any value above ~600 cycles will work
* for the purpose of detecting a deadlock. * for the purpose of detecting a deadlock.
*/ */
@@ -67,6 +74,7 @@
* than this. This is to prevent setting CCOMPARE below CCOUNT. * than this. This is to prevent setting CCOMPARE below CCOUNT.
*/ */
#define CCOMPARE_MIN_CYCLES_IN_FUTURE 1000 #define CCOMPARE_MIN_CYCLES_IN_FUTURE 1000
#endif
/* When light sleep is used, wake this number of microseconds earlier than /* When light sleep is used, wake this number of microseconds earlier than
* the next tick. * the next tick.
@@ -85,6 +93,9 @@
/* Minimal divider at which REF_CLK_FREQ can be obtained */ /* Minimal divider at which REF_CLK_FREQ can be obtained */
#define REF_CLK_DIV_MIN 2 #define REF_CLK_DIV_MIN 2
#define DEFAULT_CPU_FREQ CONFIG_ESP32S3_DEFAULT_CPU_FREQ_MHZ #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 #endif
#ifdef CONFIG_PM_PROFILING #ifdef CONFIG_PM_PROFILING
@@ -104,12 +115,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. */ /* Bit mask of locked modes. BIT(i) is set iff s_mode_lock_counts[i] > 0. */
static uint32_t s_mode_mask; 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 #if CONFIG_FREERTOS_USE_TICKLESS_IDLE
#define PERIPH_SKIP_LIGHT_SLEEP_NO 1 #define PERIPH_SKIP_LIGHT_SLEEP_NO 1
@@ -133,11 +138,6 @@ static bool s_skip_light_sleep[portNUM_PROCESSORS];
#endif // portNUM_PROCESSORS == 2 #endif // portNUM_PROCESSORS == 2
#endif // CONFIG_FREERTOS_USE_TICKLESS_IDLE #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; /* A flag indicating that Idle hook has run on a given CPU;
* Next interrupt on the same CPU will take s_rtos_lock_handle. * Next interrupt on the same CPU will take s_rtos_lock_handle.
*/ */
@@ -177,9 +177,23 @@ static const char* s_mode_names[] = {
}; };
#endif // WITH_PROFILING #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); static void update_ccompare(void);
#endif // __XTENSA__
static const char* TAG = "pm";
static void do_switch(pm_mode_t new_mode); static void do_switch(pm_mode_t new_mode);
static void leave_idle(void); static void leave_idle(void);
static void on_freq_update(uint32_t old_ticks_per_us, uint32_t ticks_per_us); static void on_freq_update(uint32_t old_ticks_per_us, uint32_t ticks_per_us);
@@ -211,6 +225,8 @@ esp_err_t esp_pm_configure(const void* vconfig)
const esp_pm_config_esp32s2_t* config = (const esp_pm_config_esp32s2_t*) vconfig; const esp_pm_config_esp32s2_t* config = (const esp_pm_config_esp32s2_t*) vconfig;
#elif CONFIG_IDF_TARGET_ESP32S3 #elif CONFIG_IDF_TARGET_ESP32S3
const esp_pm_config_esp32s3_t* config = (const esp_pm_config_esp32s3_t*) vconfig; 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 #endif
#ifndef CONFIG_FREERTOS_USE_TICKLESS_IDLE #ifndef CONFIG_FREERTOS_USE_TICKLESS_IDLE
@@ -256,7 +272,7 @@ esp_err_t esp_pm_configure(const void* vconfig)
*/ */
apb_max_freq = 80; 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 */ int apb_max_freq = MIN(max_freq_mhz, 80); /* CPU frequency in APB_MAX mode */
#endif #endif
@@ -357,8 +373,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); esp_timer_private_update_apb_freq(apb_ticks_per_us);
} }
#if __XTENSA__
#if XT_RTOS_TIMER_INT
/* Calculate new tick divisor */ /* Calculate new tick divisor */
_xt_tick_divisor = ticks_per_us * MHZ / XT_TICK_PER_SEC; _xt_tick_divisor = ticks_per_us * MHZ / XT_TICK_PER_SEC;
#endif
int core_id = xPortGetCoreID(); int core_id = xPortGetCoreID();
if (s_rtos_lock_handle[core_id] != NULL) { if (s_rtos_lock_handle[core_id] != NULL) {
@@ -391,6 +410,7 @@ static void IRAM_ATTR on_freq_update(uint32_t old_ticks_per_us, uint32_t ticks_p
s_ccount_div = 0; s_ccount_div = 0;
ESP_PM_TRACE_EXIT(CCOMPARE_UPDATE, core_id); ESP_PM_TRACE_EXIT(CCOMPARE_UPDATE, core_id);
} }
#endif // __XTENSA__
} }
/** /**
@@ -412,9 +432,11 @@ static void IRAM_ATTR do_switch(pm_mode_t new_mode)
portEXIT_CRITICAL_ISR(&s_switch_lock); portEXIT_CRITICAL_ISR(&s_switch_lock);
return; return;
} }
#if __XTENSA__
if (s_need_update_ccompare[core_id]) { if (s_need_update_ccompare[core_id]) {
s_need_update_ccompare[core_id] = false; s_need_update_ccompare[core_id] = false;
} }
#endif
portEXIT_CRITICAL_ISR(&s_switch_lock); portEXIT_CRITICAL_ISR(&s_switch_lock);
} while (true); } while (true);
s_new_mode = new_mode; s_new_mode = new_mode;
@@ -455,6 +477,7 @@ static void IRAM_ATTR do_switch(pm_mode_t new_mode)
portEXIT_CRITICAL_ISR(&s_switch_lock); portEXIT_CRITICAL_ISR(&s_switch_lock);
} }
#if __XTENSA__
/** /**
* @brief Calculate new CCOMPARE value based on s_ccount_{mul,div} * @brief Calculate new CCOMPARE value based on s_ccount_{mul,div}
* *
@@ -475,6 +498,7 @@ static void IRAM_ATTR update_ccompare(void)
} }
} }
} }
#endif // __XTENSA__
static void IRAM_ATTR leave_idle(void) static void IRAM_ATTR leave_idle(void)
{ {
@@ -578,6 +602,7 @@ void IRAM_ATTR vApplicationSleep( TickType_t xExpectedIdleTime )
/* Adjust RTOS tick count based on the amount of time spent in sleep */ /* Adjust RTOS tick count based on the amount of time spent in sleep */
vTaskStepTick(slept_ticks); vTaskStepTick(slept_ticks);
#if __XTENSA__
/* Trigger tick interrupt, since sleep time was longer /* Trigger tick interrupt, since sleep time was longer
* than portTICK_PERIOD_MS. Note that setting INTSET does not * than portTICK_PERIOD_MS. Note that setting INTSET does not
* work for timer interrupt, and changing CCOMPARE would clear * work for timer interrupt, and changing CCOMPARE would clear
@@ -587,6 +612,7 @@ void IRAM_ATTR vApplicationSleep( TickType_t xExpectedIdleTime )
while (!(XTHAL_GET_INTERRUPT() & BIT(XT_TIMER_INTNUM))) { while (!(XTHAL_GET_INTERRUPT() & BIT(XT_TIMER_INTNUM))) {
; ;
} }
#endif
} }
other_core_should_skip_light_sleep(core_id); other_core_should_skip_light_sleep(core_id);
} }
@@ -676,6 +702,8 @@ void esp_pm_impl_init(void)
esp_pm_config_esp32s2_t cfg = { esp_pm_config_esp32s2_t cfg = {
#elif CONFIG_IDF_TARGET_ESP32S3 #elif CONFIG_IDF_TARGET_ESP32S3
esp_pm_config_esp32s3_t cfg = { esp_pm_config_esp32s3_t cfg = {
#elif CONFIG_IDF_TARGET_ESP32C3
esp_pm_config_esp32c3_t cfg = {
#endif #endif
.max_freq_mhz = DEFAULT_CPU_FREQ, .max_freq_mhz = DEFAULT_CPU_FREQ,
.min_freq_mhz = xtal_freq, .min_freq_mhz = xtal_freq,
@@ -709,7 +737,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. * from happening in this section, since they will also call into esp_pm_impl_isr_hook.
*/ */
uint32_t state = portENTER_CRITICAL_NESTED(); uint32_t state = portENTER_CRITICAL_NESTED();
#if portNUM_PROCESSORS == 2 #if __XTENSA__ && (portNUM_PROCESSORS == 2)
if (s_need_update_ccompare[core_id]) { if (s_need_update_ccompare[core_id]) {
update_ccompare(); update_ccompare();
s_need_update_ccompare[core_id] = false; s_need_update_ccompare[core_id] = false;
@@ -728,7 +756,7 @@ void esp_pm_impl_waiti(void)
#if CONFIG_FREERTOS_USE_TICKLESS_IDLE #if CONFIG_FREERTOS_USE_TICKLESS_IDLE
int core_id = xPortGetCoreID(); int core_id = xPortGetCoreID();
if (s_skipped_light_sleep[core_id]) { 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] /* 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 * 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. * the lock so that vApplicationSleep can attempt to enter light sleep.
@@ -737,7 +765,7 @@ void esp_pm_impl_waiti(void)
s_skipped_light_sleep[core_id] = false; s_skipped_light_sleep[core_id] = false;
} }
#else #else
asm("waiti 0"); cpu_hal_waiti();
#endif // CONFIG_FREERTOS_USE_TICKLESS_IDLE #endif // CONFIG_FREERTOS_USE_TICKLESS_IDLE
} }

View File

@@ -21,12 +21,21 @@
* Feel free to change when debugging. * Feel free to change when debugging.
*/ */
static const int DRAM_ATTR s_trace_io[] = { static const int DRAM_ATTR s_trace_io[] = {
#ifndef CONFIG_IDF_TARGET_ESP32C3
BIT(4), BIT(5), // ESP_PM_TRACE_IDLE BIT(4), BIT(5), // ESP_PM_TRACE_IDLE
BIT(16), BIT(17), // ESP_PM_TRACE_TICK BIT(16), BIT(17), // ESP_PM_TRACE_TICK
BIT(18), BIT(18), // ESP_PM_TRACE_FREQ_SWITCH BIT(18), BIT(18), // ESP_PM_TRACE_FREQ_SWITCH
BIT(19), BIT(19), // ESP_PM_TRACE_CCOMPARE_UPDATE BIT(19), BIT(19), // ESP_PM_TRACE_CCOMPARE_UPDATE
BIT(25), BIT(26), // ESP_PM_TRACE_ISR_HOOK BIT(25), BIT(26), // ESP_PM_TRACE_ISR_HOOK
BIT(27), BIT(27), // ESP_PM_TRACE_SLEEP 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) void esp_pm_trace_init(void)

View File

@@ -96,6 +96,7 @@
#include "esp_attr.h" #include "esp_attr.h"
#include "esp_debug_helpers.h" #include "esp_debug_helpers.h"
#include "esp_log.h" #include "esp_log.h"
#include "esp_private/pm_trace.h"
/** /**
* @brief A variable is used to keep track of the critical section nesting. * @brief A variable is used to keep track of the critical section nesting.
@@ -215,6 +216,10 @@ IRAM_ATTR void vPortSysTickHandler(void *arg)
systimer_ll_clear_alarm_int(SYSTIMER_ALARM_0); systimer_ll_clear_alarm_int(SYSTIMER_ALARM_0);
#ifdef CONFIG_PM_TRACE
ESP_PM_TRACE_ENTER(TICK, xPortGetCoreID());
#endif
if (!uxSchedulerRunning) { if (!uxSchedulerRunning) {
return; return;
} }
@@ -222,6 +227,10 @@ IRAM_ATTR void vPortSysTickHandler(void *arg)
if (xTaskIncrementTick() != pdFALSE) { if (xTaskIncrementTick() != pdFALSE) {
vPortYieldFromISR(); vPortYieldFromISR();
} }
#ifdef CONFIG_PM_TRACE
ESP_PM_TRACE_EXIT(TICK, xPortGetCoreID());
#endif
} }
BaseType_t xPortStartScheduler(void) BaseType_t xPortStartScheduler(void)

View File

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

View File

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

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):); 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 #ifdef __cplusplus
} }
#endif #endif

View File

@@ -177,6 +177,11 @@ static inline void cpu_ll_set_vecbase(const void *vecbase)
asm volatile ("wsr %0, vecbase" :: "r" (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) static inline uint32_t cpu_ll_read_dedic_gpio_in(void)
{ {
uint32_t value = 0; uint32_t value = 0;

View File

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

View File

@@ -14,6 +14,8 @@
#include "soc/soc.h" #include "soc/soc.h"
#include "soc/interrupt_reg.h" #include "soc/interrupt_reg.h"
#include "riscv/rvruntime-frames.h" #include "riscv/rvruntime-frames.h"
#include "soc/soc_caps.h"
#include "sdkconfig.h"
.equ SAVE_REGS, 32 .equ SAVE_REGS, 32
@@ -243,6 +245,22 @@ _interrupt_handler:
li t0, 0x8 li t0, 0x8
csrrs t0, mstatus, t0 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 */ /* call the C dispatcher */
mv a0, sp /* argument 1, stack pointer */ mv a0, sp /* argument 1, stack pointer */
csrr a1, mcause /* argument 2, interrupt number */ csrr a1, mcause /* argument 2, interrupt number */

View File

@@ -43,6 +43,7 @@ menu "Example Configuration"
choice EXAMPLE_MAX_CPU_FREQ choice EXAMPLE_MAX_CPU_FREQ
prompt "Maximum CPU frequency" prompt "Maximum CPU frequency"
default EXAMPLE_MAX_CPU_FREQ_80 default EXAMPLE_MAX_CPU_FREQ_80
depends on PM_ENABLE
help help
Maximum CPU frequency to use for dynamic frequency scaling. Maximum CPU frequency to use for dynamic frequency scaling.
@@ -52,6 +53,7 @@ menu "Example Configuration"
bool "160 MHz" bool "160 MHz"
config EXAMPLE_MAX_CPU_FREQ_240 config EXAMPLE_MAX_CPU_FREQ_240
bool "240 MHz" bool "240 MHz"
depends on IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
endchoice endchoice
config EXAMPLE_MAX_CPU_FREQ_MHZ config EXAMPLE_MAX_CPU_FREQ_MHZ
@@ -64,19 +66,20 @@ menu "Example Configuration"
choice EXAMPLE_MIN_CPU_FREQ choice EXAMPLE_MIN_CPU_FREQ
prompt "Minimum CPU frequency" prompt "Minimum CPU frequency"
default EXAMPLE_MIN_CPU_FREQ_10M default EXAMPLE_MIN_CPU_FREQ_10M
depends on PM_ENABLE
help help
Minimum CPU frequency to use for dynamic frequency scaling. Minimum CPU frequency to use for dynamic frequency scaling.
Should be set to XTAL frequency or XTAL frequency divided by integer. Should be set to XTAL frequency or XTAL frequency divided by integer.
config EXAMPLE_MIN_CPU_FREQ_40M config EXAMPLE_MIN_CPU_FREQ_40M
bool "40 MHz (use with 40MHz XTAL)" 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 config EXAMPLE_MIN_CPU_FREQ_20M
bool "20 MHz (use with 40MHz XTAL)" 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 config EXAMPLE_MIN_CPU_FREQ_10M
bool "10 MHz (use with 40MHz XTAL)" 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 config EXAMPLE_MIN_CPU_FREQ_26M
bool "26 MHz (use with 26MHz XTAL)" bool "26 MHz (use with 26MHz XTAL)"
depends on ESP32_XTAL_FREQ_26 || ESP32_XTAL_FREQ_AUTO 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 = { esp_pm_config_esp32_t pm_config = {
#elif CONFIG_IDF_TARGET_ESP32S2 #elif CONFIG_IDF_TARGET_ESP32S2
esp_pm_config_esp32s2_t pm_config = { esp_pm_config_esp32s2_t pm_config = {
#elif CONFIG_IDF_TARGET_ESP32C3
esp_pm_config_esp32c3_t pm_config = {
#endif #endif
.max_freq_mhz = CONFIG_EXAMPLE_MAX_CPU_FREQ_MHZ, .max_freq_mhz = CONFIG_EXAMPLE_MAX_CPU_FREQ_MHZ,
.min_freq_mhz = CONFIG_EXAMPLE_MIN_CPU_FREQ_MHZ, .min_freq_mhz = CONFIG_EXAMPLE_MIN_CPU_FREQ_MHZ,