diff --git a/docs/en/api-reference/system/power_management.rst b/docs/en/api-reference/system/power_management.rst index fca73437450..179a655e5bf 100644 --- a/docs/en/api-reference/system/power_management.rst +++ b/docs/en/api-reference/system/power_management.rst @@ -130,6 +130,11 @@ These functions are particularly useful for: To enable profiling features (timing information for individual locks), enable the :ref:`CONFIG_PM_PROFILING` option in menuconfig. +Application Example +------------------- + +The :example:`lowpower/power_management` example demonstrates dynamic frequency scaling, automatic Light-sleep, and power management locks. + Dynamic Frequency Scaling and Peripheral Drivers ------------------------------------------------ diff --git a/docs/zh_CN/api-reference/system/power_management.rst b/docs/zh_CN/api-reference/system/power_management.rst index bf8b5dd9896..cc92a277b70 100644 --- a/docs/zh_CN/api-reference/system/power_management.rst +++ b/docs/zh_CN/api-reference/system/power_management.rst @@ -130,6 +130,11 @@ ESP-IDF 使用预测性时间补偿机制来实现自动 Light-sleep。系统会 要启用性能分析功能(单个锁的计时信息),请在 menuconfig 中启用 :ref:`CONFIG_PM_PROFILING` 选项。 +应用示例 +------------------- + +:example:`lowpower/power_management` 示例演示了动态调频、自动 Light-sleep 与电源管理锁。 + 动态调频和外设驱动 ------------------------------------------------ diff --git a/examples/lowpower/.build-test-rules.yml b/examples/lowpower/.build-test-rules.yml index b0f238afb26..32a805bef2d 100644 --- a/examples/lowpower/.build-test-rules.yml +++ b/examples/lowpower/.build-test-rules.yml @@ -1,5 +1,14 @@ # Documentation: .gitlab/ci/README.md#manifest-file-to-control-the-buildtest-apps +examples/lowpower/power_management: + disable: + - if: CONFIG_NAME == "pd_top" and SOC_PM_SUPPORT_TOP_PD != 1 + - if: SOC_PM_SUPPORTED != 1 + temporary: true + reason: not supported yet # TODO: [ESP32H21] IDF-11522, [ESP32H4] IDF-12286 [ESP32S31] IDF-14645 + depends_components: + - esp_pm + examples/lowpower/vbat: enable: - if: SOC_VBAT_SUPPORTED == 1 diff --git a/examples/lowpower/README.md b/examples/lowpower/README.md index d71b05f1ca1..3d4b275743a 100644 --- a/examples/lowpower/README.md +++ b/examples/lowpower/README.md @@ -1,7 +1,7 @@ | Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 | | ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | -------- | -# System Examples +# Low Power Examples Configuration and management of ESP chips lowpower related features. diff --git a/examples/lowpower/power_management/CMakeLists.txt b/examples/lowpower/power_management/CMakeLists.txt new file mode 100644 index 00000000000..c996255f4a3 --- /dev/null +++ b/examples/lowpower/power_management/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following lines of boilerplate have to be in your project's CMakeLists +# in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.22) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +# "Trim" the build. Include the minimal set of components, main, and anything it depends on. +idf_build_set_property(MINIMAL_BUILD ON) +project(power_management_example) diff --git a/examples/lowpower/power_management/README.md b/examples/lowpower/power_management/README.md new file mode 100644 index 00000000000..313c27f354a --- /dev/null +++ b/examples/lowpower/power_management/README.md @@ -0,0 +1,66 @@ +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | -------- | + +# Power Management Example + +(See the README.md file in the upper level 'examples' directory for more information about examples.) + +This example demonstrates power management (PM) locks with multiple tasks: one task holds `ESP_PM_CPU_FREQ_MAX` during a short critical section, another holds `ESP_PM_NO_LIGHT_SLEEP` during a short awake window, and a third task periodically dumps PM config and lock/mode stats. Locks are used only where needed so the system can lower CPU frequency or enter light sleep the rest of the time. + +## How to Use Example + +### Hardware Required + +Any supported ESP development board. + +### Configure the Project + +Run `idf.py menuconfig`. Under **Example Configuration** you can set: + +- **Max CPU frequency (MHz)** — CPU frequency when ESP_PM_CPU_FREQ_MAX PM lock is held. +- **Min CPU frequency (MHz)** — CPU frequency when no PM lock is held. +- **Enable automatic light sleep when idle** — When enabled (and tickless idle is enabled), the chip may enter light sleep when no PM lock is held. Default is on if tickless idle is enabled. + +Enable PM under **Component config → Power Management → Support for power management**. The example uses `sdkconfig.defaults` to set `CONFIG_PM_ENABLE` and `CONFIG_FREERTOS_USE_TICKLESS_IDLE`. PM is not supported with SMP FreeRTOS; the example sets `CONFIG_FREERTOS_SMP=n`. + +### Build and Flash + +Build the project, flash it to the board, and run the serial monitor: + +``` +idf.py -p PORT flash monitor +``` + +(Replace PORT with your serial port. Exit monitor with `Ctrl-]`.) + +## Example Output + +At startup the example prints the PM config. The **pm_dump** task then prints PM config and lock/mode stats every 10 seconds; the two demo tasks do not log. + +``` +=== Power Management Example (multi-task) === +I (319) pm: Frequency switching config: CPU_MAX: 400, APB_MAX: 100, APB_MIN: 40, Light sleep: ENABLED +PM configured: max=400 min=40 MHz, light_sleep_enable=1 +I (330) main_task: Returned from app_main() + +--- PM: max_freq=400 min_freq=40 MHz, light_sleep=1 --- +Time since boot up: 10044534 us +Lock stats: +Name Type Arg Active Total_count Time(us) Time(%) +background NO_LIGHT_SLEEP 0 0 20 2998011 30 % +critical_work CPU_FREQ_MAX 0 1 21 1000507 10 % +rtos1 CPU_FREQ_MAX 0 1 4087 141343 2 % +rtos0 CPU_FREQ_MAX 0 0 4076 184970 2 % + +Mode stats: +Mode CPU_freq Time(us) Time(%) +SLEEP 40 M 5958343 59% +APB_MIN 40 M 2848902 28% +APB_MAX 100M 0 0 % +CPU_MAX 400M 1205696 11% + +Sleep stats: +light_sleep_counts:40 light_sleep_reject_counts:0 +``` + +The same block repeats every 10 seconds. diff --git a/examples/lowpower/power_management/main/CMakeLists.txt b/examples/lowpower/power_management/main/CMakeLists.txt new file mode 100644 index 00000000000..f65c064f22a --- /dev/null +++ b/examples/lowpower/power_management/main/CMakeLists.txt @@ -0,0 +1,6 @@ +set(srcs "power_management_example_main.c") +set(includes ".") + +idf_component_register(SRCS ${srcs} + PRIV_REQUIRES esp_pm + INCLUDE_DIRS ${includes}) diff --git a/examples/lowpower/power_management/main/Kconfig.esp32.supported_freq b/examples/lowpower/power_management/main/Kconfig.esp32.supported_freq new file mode 100644 index 00000000000..dce3f21be62 --- /dev/null +++ b/examples/lowpower/power_management/main/Kconfig.esp32.supported_freq @@ -0,0 +1,51 @@ +choice EXAMPLE_PM_MAX_FREQ_MHZ + prompt "Max CPU frequency (MHz)" + default EXAMPLE_PM_MAX_FREQ_MHZ_240 + config EXAMPLE_PM_MAX_FREQ_MHZ_10 + bool "10" + config EXAMPLE_PM_MAX_FREQ_MHZ_20 + bool "20" + config EXAMPLE_PM_MAX_FREQ_MHZ_40 + bool "40" + config EXAMPLE_PM_MAX_FREQ_MHZ_80 + bool "80" + config EXAMPLE_PM_MAX_FREQ_MHZ_160 + bool "160" + config EXAMPLE_PM_MAX_FREQ_MHZ_240 + bool "240" +endchoice + +config EXAMPLE_PM_MAX_FREQ + int + default 10 if EXAMPLE_PM_MAX_FREQ_MHZ_10 + default 20 if EXAMPLE_PM_MAX_FREQ_MHZ_20 + default 40 if EXAMPLE_PM_MAX_FREQ_MHZ_40 + default 80 if EXAMPLE_PM_MAX_FREQ_MHZ_80 + default 160 if EXAMPLE_PM_MAX_FREQ_MHZ_160 + default 240 if EXAMPLE_PM_MAX_FREQ_MHZ_240 + +choice EXAMPLE_PM_MIN_FREQ_MHZ + prompt "Min CPU frequency (MHz)" + default EXAMPLE_PM_MIN_FREQ_MHZ_40 + config EXAMPLE_PM_MIN_FREQ_MHZ_10 + bool "10" + config EXAMPLE_PM_MIN_FREQ_MHZ_20 + bool "20" + config EXAMPLE_PM_MIN_FREQ_MHZ_40 + bool "40" + config EXAMPLE_PM_MIN_FREQ_MHZ_80 + bool "80" + config EXAMPLE_PM_MIN_FREQ_MHZ_160 + bool "160" + config EXAMPLE_PM_MIN_FREQ_MHZ_240 + bool "240" +endchoice + +config EXAMPLE_PM_MIN_FREQ + int + default 10 if EXAMPLE_PM_MIN_FREQ_MHZ_10 + default 20 if EXAMPLE_PM_MIN_FREQ_MHZ_20 + default 40 if EXAMPLE_PM_MIN_FREQ_MHZ_40 + default 80 if EXAMPLE_PM_MIN_FREQ_MHZ_80 + default 160 if EXAMPLE_PM_MIN_FREQ_MHZ_160 + default 240 if EXAMPLE_PM_MIN_FREQ_MHZ_240 diff --git a/examples/lowpower/power_management/main/Kconfig.esp32c2.supported_freq b/examples/lowpower/power_management/main/Kconfig.esp32c2.supported_freq new file mode 100644 index 00000000000..93a6a05875c --- /dev/null +++ b/examples/lowpower/power_management/main/Kconfig.esp32c2.supported_freq @@ -0,0 +1,45 @@ +choice EXAMPLE_PM_MAX_FREQ_MHZ + prompt "Max CPU frequency (MHz)" + default EXAMPLE_PM_MAX_FREQ_MHZ_120 + config EXAMPLE_PM_MAX_FREQ_MHZ_10 + bool "10" + config EXAMPLE_PM_MAX_FREQ_MHZ_20 + bool "20" + config EXAMPLE_PM_MAX_FREQ_MHZ_40 + bool "40" + config EXAMPLE_PM_MAX_FREQ_MHZ_80 + bool "80" + config EXAMPLE_PM_MAX_FREQ_MHZ_120 + bool "120" +endchoice + +config EXAMPLE_PM_MAX_FREQ + int + default 10 if EXAMPLE_PM_MAX_FREQ_MHZ_10 + default 20 if EXAMPLE_PM_MAX_FREQ_MHZ_20 + default 40 if EXAMPLE_PM_MAX_FREQ_MHZ_40 + default 80 if EXAMPLE_PM_MAX_FREQ_MHZ_80 + default 120 if EXAMPLE_PM_MAX_FREQ_MHZ_120 + +choice EXAMPLE_PM_MIN_FREQ_MHZ + prompt "Min CPU frequency (MHz)" + default EXAMPLE_PM_MIN_FREQ_MHZ_40 + config EXAMPLE_PM_MIN_FREQ_MHZ_10 + bool "10" + config EXAMPLE_PM_MIN_FREQ_MHZ_20 + bool "20" + config EXAMPLE_PM_MIN_FREQ_MHZ_40 + bool "40" + config EXAMPLE_PM_MIN_FREQ_MHZ_80 + bool "80" + config EXAMPLE_PM_MIN_FREQ_MHZ_120 + bool "120" +endchoice + +config EXAMPLE_PM_MIN_FREQ + int + default 10 if EXAMPLE_PM_MIN_FREQ_MHZ_10 + default 20 if EXAMPLE_PM_MIN_FREQ_MHZ_20 + default 40 if EXAMPLE_PM_MIN_FREQ_MHZ_40 + default 80 if EXAMPLE_PM_MIN_FREQ_MHZ_80 + default 120 if EXAMPLE_PM_MIN_FREQ_MHZ_120 diff --git a/examples/lowpower/power_management/main/Kconfig.esp32c3.supported_freq b/examples/lowpower/power_management/main/Kconfig.esp32c3.supported_freq new file mode 100644 index 00000000000..c4a4958fc3a --- /dev/null +++ b/examples/lowpower/power_management/main/Kconfig.esp32c3.supported_freq @@ -0,0 +1,45 @@ +choice EXAMPLE_PM_MAX_FREQ_MHZ + prompt "Max CPU frequency (MHz)" + default EXAMPLE_PM_MAX_FREQ_MHZ_160 + config EXAMPLE_PM_MAX_FREQ_MHZ_10 + bool "10" + config EXAMPLE_PM_MAX_FREQ_MHZ_20 + bool "20" + config EXAMPLE_PM_MAX_FREQ_MHZ_40 + bool "40" + config EXAMPLE_PM_MAX_FREQ_MHZ_80 + bool "80" + config EXAMPLE_PM_MAX_FREQ_MHZ_160 + bool "160" +endchoice + +config EXAMPLE_PM_MAX_FREQ + int + default 10 if EXAMPLE_PM_MAX_FREQ_MHZ_10 + default 20 if EXAMPLE_PM_MAX_FREQ_MHZ_20 + default 40 if EXAMPLE_PM_MAX_FREQ_MHZ_40 + default 80 if EXAMPLE_PM_MAX_FREQ_MHZ_80 + default 160 if EXAMPLE_PM_MAX_FREQ_MHZ_160 + +choice EXAMPLE_PM_MIN_FREQ_MHZ + prompt "Min CPU frequency (MHz)" + default EXAMPLE_PM_MIN_FREQ_MHZ_40 + config EXAMPLE_PM_MIN_FREQ_MHZ_10 + bool "10" + config EXAMPLE_PM_MIN_FREQ_MHZ_20 + bool "20" + config EXAMPLE_PM_MIN_FREQ_MHZ_40 + bool "40" + config EXAMPLE_PM_MIN_FREQ_MHZ_80 + bool "80" + config EXAMPLE_PM_MIN_FREQ_MHZ_160 + bool "160" +endchoice + +config EXAMPLE_PM_MIN_FREQ + int + default 10 if EXAMPLE_PM_MIN_FREQ_MHZ_10 + default 20 if EXAMPLE_PM_MIN_FREQ_MHZ_20 + default 40 if EXAMPLE_PM_MIN_FREQ_MHZ_40 + default 80 if EXAMPLE_PM_MIN_FREQ_MHZ_80 + default 160 if EXAMPLE_PM_MIN_FREQ_MHZ_160 diff --git a/examples/lowpower/power_management/main/Kconfig.esp32c5.supported_freq b/examples/lowpower/power_management/main/Kconfig.esp32c5.supported_freq new file mode 100644 index 00000000000..69da1de7442 --- /dev/null +++ b/examples/lowpower/power_management/main/Kconfig.esp32c5.supported_freq @@ -0,0 +1,57 @@ +choice EXAMPLE_PM_MAX_FREQ_MHZ + prompt "Max CPU frequency (MHz)" + default EXAMPLE_PM_MAX_FREQ_MHZ_240 + config EXAMPLE_PM_MAX_FREQ_MHZ_12 + bool "12" + config EXAMPLE_PM_MAX_FREQ_MHZ_24 + bool "24" + config EXAMPLE_PM_MAX_FREQ_MHZ_40 + bool "40" + config EXAMPLE_PM_MAX_FREQ_MHZ_48 + bool "48" + config EXAMPLE_PM_MAX_FREQ_MHZ_80 + bool "80" + config EXAMPLE_PM_MAX_FREQ_MHZ_160 + bool "160" + config EXAMPLE_PM_MAX_FREQ_MHZ_240 + bool "240" +endchoice + +config EXAMPLE_PM_MAX_FREQ + int + default 12 if EXAMPLE_PM_MAX_FREQ_MHZ_12 + default 24 if EXAMPLE_PM_MAX_FREQ_MHZ_24 + default 40 if EXAMPLE_PM_MAX_FREQ_MHZ_40 + default 48 if EXAMPLE_PM_MAX_FREQ_MHZ_48 + default 80 if EXAMPLE_PM_MAX_FREQ_MHZ_80 + default 160 if EXAMPLE_PM_MAX_FREQ_MHZ_160 + default 240 if EXAMPLE_PM_MAX_FREQ_MHZ_240 + +choice EXAMPLE_PM_MIN_FREQ_MHZ + prompt "Min CPU frequency (MHz)" + default EXAMPLE_PM_MIN_FREQ_MHZ_48 + config EXAMPLE_PM_MIN_FREQ_MHZ_12 + bool "12" + config EXAMPLE_PM_MIN_FREQ_MHZ_24 + bool "24" + config EXAMPLE_PM_MIN_FREQ_MHZ_40 + bool "40 (use with 40MHz XTAL)" + config EXAMPLE_PM_MIN_FREQ_MHZ_48 + bool "48 (use with 48MHz XTAL)" + config EXAMPLE_PM_MIN_FREQ_MHZ_80 + bool "80" + config EXAMPLE_PM_MIN_FREQ_MHZ_160 + bool "160" + config EXAMPLE_PM_MIN_FREQ_MHZ_240 + bool "240" +endchoice + +config EXAMPLE_PM_MIN_FREQ + int + default 12 if EXAMPLE_PM_MIN_FREQ_MHZ_12 + default 24 if EXAMPLE_PM_MIN_FREQ_MHZ_24 + default 40 if EXAMPLE_PM_MIN_FREQ_MHZ_40 + default 48 if EXAMPLE_PM_MIN_FREQ_MHZ_48 + default 80 if EXAMPLE_PM_MIN_FREQ_MHZ_80 + default 160 if EXAMPLE_PM_MIN_FREQ_MHZ_160 + default 240 if EXAMPLE_PM_MIN_FREQ_MHZ_240 diff --git a/examples/lowpower/power_management/main/Kconfig.esp32c6.supported_freq b/examples/lowpower/power_management/main/Kconfig.esp32c6.supported_freq new file mode 100644 index 00000000000..8afb03bed4c --- /dev/null +++ b/examples/lowpower/power_management/main/Kconfig.esp32c6.supported_freq @@ -0,0 +1,51 @@ +choice EXAMPLE_PM_MAX_FREQ_MHZ + prompt "Max CPU frequency (MHz)" + default EXAMPLE_PM_MAX_FREQ_MHZ_160 + config EXAMPLE_PM_MAX_FREQ_MHZ_10 + bool "10" + config EXAMPLE_PM_MAX_FREQ_MHZ_20 + bool "20" + config EXAMPLE_PM_MAX_FREQ_MHZ_40 + bool "40" + config EXAMPLE_PM_MAX_FREQ_MHZ_80 + bool "80" + config EXAMPLE_PM_MAX_FREQ_MHZ_120 + bool "120" + config EXAMPLE_PM_MAX_FREQ_MHZ_160 + bool "160" +endchoice + +config EXAMPLE_PM_MAX_FREQ + int + default 10 if EXAMPLE_PM_MAX_FREQ_MHZ_10 + default 20 if EXAMPLE_PM_MAX_FREQ_MHZ_20 + default 40 if EXAMPLE_PM_MAX_FREQ_MHZ_40 + default 80 if EXAMPLE_PM_MAX_FREQ_MHZ_80 + default 120 if EXAMPLE_PM_MAX_FREQ_MHZ_120 + default 160 if EXAMPLE_PM_MAX_FREQ_MHZ_160 + +choice EXAMPLE_PM_MIN_FREQ_MHZ + prompt "Min CPU frequency (MHz)" + default EXAMPLE_PM_MIN_FREQ_MHZ_40 + config EXAMPLE_PM_MIN_FREQ_MHZ_10 + bool "10" + config EXAMPLE_PM_MIN_FREQ_MHZ_20 + bool "20" + config EXAMPLE_PM_MIN_FREQ_MHZ_40 + bool "40" + config EXAMPLE_PM_MIN_FREQ_MHZ_80 + bool "80" + config EXAMPLE_PM_MIN_FREQ_MHZ_120 + bool "120" + config EXAMPLE_PM_MIN_FREQ_MHZ_160 + bool "160" +endchoice + +config EXAMPLE_PM_MIN_FREQ + int + default 10 if EXAMPLE_PM_MIN_FREQ_MHZ_10 + default 20 if EXAMPLE_PM_MIN_FREQ_MHZ_20 + default 40 if EXAMPLE_PM_MIN_FREQ_MHZ_40 + default 80 if EXAMPLE_PM_MIN_FREQ_MHZ_80 + default 120 if EXAMPLE_PM_MIN_FREQ_MHZ_120 + default 160 if EXAMPLE_PM_MIN_FREQ_MHZ_160 diff --git a/examples/lowpower/power_management/main/Kconfig.esp32c61.supported_freq b/examples/lowpower/power_management/main/Kconfig.esp32c61.supported_freq new file mode 100644 index 00000000000..c4a4958fc3a --- /dev/null +++ b/examples/lowpower/power_management/main/Kconfig.esp32c61.supported_freq @@ -0,0 +1,45 @@ +choice EXAMPLE_PM_MAX_FREQ_MHZ + prompt "Max CPU frequency (MHz)" + default EXAMPLE_PM_MAX_FREQ_MHZ_160 + config EXAMPLE_PM_MAX_FREQ_MHZ_10 + bool "10" + config EXAMPLE_PM_MAX_FREQ_MHZ_20 + bool "20" + config EXAMPLE_PM_MAX_FREQ_MHZ_40 + bool "40" + config EXAMPLE_PM_MAX_FREQ_MHZ_80 + bool "80" + config EXAMPLE_PM_MAX_FREQ_MHZ_160 + bool "160" +endchoice + +config EXAMPLE_PM_MAX_FREQ + int + default 10 if EXAMPLE_PM_MAX_FREQ_MHZ_10 + default 20 if EXAMPLE_PM_MAX_FREQ_MHZ_20 + default 40 if EXAMPLE_PM_MAX_FREQ_MHZ_40 + default 80 if EXAMPLE_PM_MAX_FREQ_MHZ_80 + default 160 if EXAMPLE_PM_MAX_FREQ_MHZ_160 + +choice EXAMPLE_PM_MIN_FREQ_MHZ + prompt "Min CPU frequency (MHz)" + default EXAMPLE_PM_MIN_FREQ_MHZ_40 + config EXAMPLE_PM_MIN_FREQ_MHZ_10 + bool "10" + config EXAMPLE_PM_MIN_FREQ_MHZ_20 + bool "20" + config EXAMPLE_PM_MIN_FREQ_MHZ_40 + bool "40" + config EXAMPLE_PM_MIN_FREQ_MHZ_80 + bool "80" + config EXAMPLE_PM_MIN_FREQ_MHZ_160 + bool "160" +endchoice + +config EXAMPLE_PM_MIN_FREQ + int + default 10 if EXAMPLE_PM_MIN_FREQ_MHZ_10 + default 20 if EXAMPLE_PM_MIN_FREQ_MHZ_20 + default 40 if EXAMPLE_PM_MIN_FREQ_MHZ_40 + default 80 if EXAMPLE_PM_MIN_FREQ_MHZ_80 + default 160 if EXAMPLE_PM_MIN_FREQ_MHZ_160 diff --git a/examples/lowpower/power_management/main/Kconfig.esp32h2.supported_freq b/examples/lowpower/power_management/main/Kconfig.esp32h2.supported_freq new file mode 100644 index 00000000000..fefe8b87926 --- /dev/null +++ b/examples/lowpower/power_management/main/Kconfig.esp32h2.supported_freq @@ -0,0 +1,51 @@ +choice EXAMPLE_PM_MAX_FREQ_MHZ + prompt "Max CPU frequency (MHz)" + default EXAMPLE_PM_MAX_FREQ_MHZ_96 + config EXAMPLE_PM_MAX_FREQ_MHZ_8 + bool "8" + config EXAMPLE_PM_MAX_FREQ_MHZ_16 + bool "16" + config EXAMPLE_PM_MAX_FREQ_MHZ_32 + bool "32" + config EXAMPLE_PM_MAX_FREQ_MHZ_48 + bool "48" + config EXAMPLE_PM_MAX_FREQ_MHZ_64 + bool "64" + config EXAMPLE_PM_MAX_FREQ_MHZ_96 + bool "96" +endchoice + +config EXAMPLE_PM_MAX_FREQ + int + default 8 if EXAMPLE_PM_MAX_FREQ_MHZ_8 + default 16 if EXAMPLE_PM_MAX_FREQ_MHZ_16 + default 32 if EXAMPLE_PM_MAX_FREQ_MHZ_32 + default 48 if EXAMPLE_PM_MAX_FREQ_MHZ_48 + default 64 if EXAMPLE_PM_MAX_FREQ_MHZ_64 + default 96 if EXAMPLE_PM_MAX_FREQ_MHZ_96 + +choice EXAMPLE_PM_MIN_FREQ_MHZ + prompt "Min CPU frequency (MHz)" + default EXAMPLE_PM_MIN_FREQ_MHZ_32 + config EXAMPLE_PM_MIN_FREQ_MHZ_8 + bool "8" + config EXAMPLE_PM_MIN_FREQ_MHZ_16 + bool "16" + config EXAMPLE_PM_MIN_FREQ_MHZ_32 + bool "32" + config EXAMPLE_PM_MIN_FREQ_MHZ_48 + bool "48" + config EXAMPLE_PM_MIN_FREQ_MHZ_64 + bool "64" + config EXAMPLE_PM_MIN_FREQ_MHZ_96 + bool "96" +endchoice + +config EXAMPLE_PM_MIN_FREQ + int + default 8 if EXAMPLE_PM_MIN_FREQ_MHZ_8 + default 16 if EXAMPLE_PM_MIN_FREQ_MHZ_16 + default 32 if EXAMPLE_PM_MIN_FREQ_MHZ_32 + default 48 if EXAMPLE_PM_MIN_FREQ_MHZ_48 + default 64 if EXAMPLE_PM_MIN_FREQ_MHZ_64 + default 96 if EXAMPLE_PM_MIN_FREQ_MHZ_96 diff --git a/examples/lowpower/power_management/main/Kconfig.esp32h21.supported_freq b/examples/lowpower/power_management/main/Kconfig.esp32h21.supported_freq new file mode 100644 index 00000000000..7cc2e944bf9 --- /dev/null +++ b/examples/lowpower/power_management/main/Kconfig.esp32h21.supported_freq @@ -0,0 +1,45 @@ +choice EXAMPLE_PM_MAX_FREQ_MHZ + prompt "Max CPU frequency (MHz)" + default EXAMPLE_PM_MAX_FREQ_MHZ_96 + config EXAMPLE_PM_MAX_FREQ_MHZ_8 + bool "8" + config EXAMPLE_PM_MAX_FREQ_MHZ_16 + bool "16" + config EXAMPLE_PM_MAX_FREQ_MHZ_32 + bool "32" + config EXAMPLE_PM_MAX_FREQ_MHZ_48 + bool "48" + config EXAMPLE_PM_MAX_FREQ_MHZ_96 + bool "96" +endchoice + +config EXAMPLE_PM_MAX_FREQ + int + default 8 if EXAMPLE_PM_MAX_FREQ_MHZ_8 + default 16 if EXAMPLE_PM_MAX_FREQ_MHZ_16 + default 32 if EXAMPLE_PM_MAX_FREQ_MHZ_32 + default 48 if EXAMPLE_PM_MAX_FREQ_MHZ_48 + default 96 if EXAMPLE_PM_MAX_FREQ_MHZ_96 + +choice EXAMPLE_PM_MIN_FREQ_MHZ + prompt "Min CPU frequency (MHz)" + default EXAMPLE_PM_MIN_FREQ_MHZ_32 + config EXAMPLE_PM_MIN_FREQ_MHZ_8 + bool "8" + config EXAMPLE_PM_MIN_FREQ_MHZ_16 + bool "16" + config EXAMPLE_PM_MIN_FREQ_MHZ_32 + bool "32" + config EXAMPLE_PM_MIN_FREQ_MHZ_48 + bool "48" + config EXAMPLE_PM_MIN_FREQ_MHZ_96 + bool "96" +endchoice + +config EXAMPLE_PM_MIN_FREQ + int + default 8 if EXAMPLE_PM_MIN_FREQ_MHZ_8 + default 16 if EXAMPLE_PM_MIN_FREQ_MHZ_16 + default 32 if EXAMPLE_PM_MIN_FREQ_MHZ_32 + default 48 if EXAMPLE_PM_MIN_FREQ_MHZ_48 + default 96 if EXAMPLE_PM_MIN_FREQ_MHZ_96 diff --git a/examples/lowpower/power_management/main/Kconfig.esp32h4.supported_freq b/examples/lowpower/power_management/main/Kconfig.esp32h4.supported_freq new file mode 100644 index 00000000000..1390f7e4308 --- /dev/null +++ b/examples/lowpower/power_management/main/Kconfig.esp32h4.supported_freq @@ -0,0 +1,53 @@ +# ESP32-H4: 8, 16, 32, 48, 64, 96 + +choice EXAMPLE_PM_MAX_FREQ_MHZ + prompt "Max CPU frequency (MHz)" + default EXAMPLE_PM_MAX_FREQ_MHZ_96 + config EXAMPLE_PM_MAX_FREQ_MHZ_8 + bool "8" + config EXAMPLE_PM_MAX_FREQ_MHZ_16 + bool "16" + config EXAMPLE_PM_MAX_FREQ_MHZ_32 + bool "32" + config EXAMPLE_PM_MAX_FREQ_MHZ_48 + bool "48" + config EXAMPLE_PM_MAX_FREQ_MHZ_64 + bool "64" + config EXAMPLE_PM_MAX_FREQ_MHZ_96 + bool "96" +endchoice + +config EXAMPLE_PM_MAX_FREQ + int + default 8 if EXAMPLE_PM_MAX_FREQ_MHZ_8 + default 16 if EXAMPLE_PM_MAX_FREQ_MHZ_16 + default 32 if EXAMPLE_PM_MAX_FREQ_MHZ_32 + default 48 if EXAMPLE_PM_MAX_FREQ_MHZ_48 + default 64 if EXAMPLE_PM_MAX_FREQ_MHZ_64 + default 96 if EXAMPLE_PM_MAX_FREQ_MHZ_96 + +choice EXAMPLE_PM_MIN_FREQ_MHZ + prompt "Min CPU frequency (MHz)" + default EXAMPLE_PM_MIN_FREQ_MHZ_32 + config EXAMPLE_PM_MIN_FREQ_MHZ_8 + bool "8" + config EXAMPLE_PM_MIN_FREQ_MHZ_16 + bool "16" + config EXAMPLE_PM_MIN_FREQ_MHZ_32 + bool "32" + config EXAMPLE_PM_MIN_FREQ_MHZ_48 + bool "48" + config EXAMPLE_PM_MIN_FREQ_MHZ_64 + bool "64" + config EXAMPLE_PM_MIN_FREQ_MHZ_96 + bool "96" +endchoice + +config EXAMPLE_PM_MIN_FREQ + int + default 8 if EXAMPLE_PM_MIN_FREQ_MHZ_8 + default 16 if EXAMPLE_PM_MIN_FREQ_MHZ_16 + default 32 if EXAMPLE_PM_MIN_FREQ_MHZ_32 + default 48 if EXAMPLE_PM_MIN_FREQ_MHZ_48 + default 64 if EXAMPLE_PM_MIN_FREQ_MHZ_64 + default 96 if EXAMPLE_PM_MIN_FREQ_MHZ_96 diff --git a/examples/lowpower/power_management/main/Kconfig.esp32p4.supported_freq b/examples/lowpower/power_management/main/Kconfig.esp32p4.supported_freq new file mode 100644 index 00000000000..832edb9eb7f --- /dev/null +++ b/examples/lowpower/power_management/main/Kconfig.esp32p4.supported_freq @@ -0,0 +1,82 @@ +choice EXAMPLE_PM_MAX_FREQ_MHZ + prompt "Max CPU frequency (MHz)" + default EXAMPLE_PM_MAX_FREQ_MHZ_360 if ESP32P4_SELECTS_REV_LESS_V3 + default EXAMPLE_PM_MAX_FREQ_MHZ_400 if !ESP32P4_SELECTS_REV_LESS_V3 + config EXAMPLE_PM_MAX_FREQ_MHZ_10 + bool "10" + config EXAMPLE_PM_MAX_FREQ_MHZ_20 + bool "20" + config EXAMPLE_PM_MAX_FREQ_MHZ_40 + bool "40" + config EXAMPLE_PM_MAX_FREQ_MHZ_90 + bool "90" + depends on ESP32P4_SELECTS_REV_LESS_V3 + config EXAMPLE_PM_MAX_FREQ_MHZ_100 + bool "100" + depends on !ESP32P4_SELECTS_REV_LESS_V3 + config EXAMPLE_PM_MAX_FREQ_MHZ_180 + bool "180" + depends on ESP32P4_SELECTS_REV_LESS_V3 + config EXAMPLE_PM_MAX_FREQ_MHZ_200 + bool "200" + depends on !ESP32P4_SELECTS_REV_LESS_V3 + config EXAMPLE_PM_MAX_FREQ_MHZ_360 + bool "360" + depends on ESP32P4_SELECTS_REV_LESS_V3 + config EXAMPLE_PM_MAX_FREQ_MHZ_400 + bool "400" + depends on !ESP32P4_SELECTS_REV_LESS_V3 +endchoice + +config EXAMPLE_PM_MAX_FREQ + int + default 10 if EXAMPLE_PM_MAX_FREQ_MHZ_10 + default 20 if EXAMPLE_PM_MAX_FREQ_MHZ_20 + default 40 if EXAMPLE_PM_MAX_FREQ_MHZ_40 + default 90 if EXAMPLE_PM_MAX_FREQ_MHZ_90 + default 100 if EXAMPLE_PM_MAX_FREQ_MHZ_100 + default 180 if EXAMPLE_PM_MAX_FREQ_MHZ_180 + default 200 if EXAMPLE_PM_MAX_FREQ_MHZ_200 + default 360 if EXAMPLE_PM_MAX_FREQ_MHZ_360 + default 400 if EXAMPLE_PM_MAX_FREQ_MHZ_400 + +choice EXAMPLE_PM_MIN_FREQ_MHZ + prompt "Min CPU frequency (MHz)" + default EXAMPLE_PM_MIN_FREQ_MHZ_40 + config EXAMPLE_PM_MIN_FREQ_MHZ_10 + bool "10" + config EXAMPLE_PM_MIN_FREQ_MHZ_20 + bool "20" + config EXAMPLE_PM_MIN_FREQ_MHZ_40 + bool "40" + config EXAMPLE_PM_MIN_FREQ_MHZ_90 + bool "90" + depends on ESP32P4_SELECTS_REV_LESS_V3 + config EXAMPLE_PM_MIN_FREQ_MHZ_100 + bool "100" + depends on !ESP32P4_SELECTS_REV_LESS_V3 + config EXAMPLE_PM_MIN_FREQ_MHZ_180 + bool "180" + depends on ESP32P4_SELECTS_REV_LESS_V3 + config EXAMPLE_PM_MIN_FREQ_MHZ_200 + bool "200" + depends on !ESP32P4_SELECTS_REV_LESS_V3 + config EXAMPLE_PM_MIN_FREQ_MHZ_360 + bool "360" + depends on ESP32P4_SELECTS_REV_LESS_V3 + config EXAMPLE_PM_MIN_FREQ_MHZ_400 + bool "400" + depends on !ESP32P4_SELECTS_REV_LESS_V3 +endchoice + +config EXAMPLE_PM_MIN_FREQ + int + default 10 if EXAMPLE_PM_MIN_FREQ_MHZ_10 + default 20 if EXAMPLE_PM_MIN_FREQ_MHZ_20 + default 40 if EXAMPLE_PM_MIN_FREQ_MHZ_40 + default 90 if EXAMPLE_PM_MIN_FREQ_MHZ_90 + default 100 if EXAMPLE_PM_MIN_FREQ_MHZ_100 + default 180 if EXAMPLE_PM_MIN_FREQ_MHZ_180 + default 200 if EXAMPLE_PM_MIN_FREQ_MHZ_200 + default 360 if EXAMPLE_PM_MIN_FREQ_MHZ_360 + default 400 if EXAMPLE_PM_MIN_FREQ_MHZ_400 diff --git a/examples/lowpower/power_management/main/Kconfig.esp32s2.supported_freq b/examples/lowpower/power_management/main/Kconfig.esp32s2.supported_freq new file mode 100644 index 00000000000..dce3f21be62 --- /dev/null +++ b/examples/lowpower/power_management/main/Kconfig.esp32s2.supported_freq @@ -0,0 +1,51 @@ +choice EXAMPLE_PM_MAX_FREQ_MHZ + prompt "Max CPU frequency (MHz)" + default EXAMPLE_PM_MAX_FREQ_MHZ_240 + config EXAMPLE_PM_MAX_FREQ_MHZ_10 + bool "10" + config EXAMPLE_PM_MAX_FREQ_MHZ_20 + bool "20" + config EXAMPLE_PM_MAX_FREQ_MHZ_40 + bool "40" + config EXAMPLE_PM_MAX_FREQ_MHZ_80 + bool "80" + config EXAMPLE_PM_MAX_FREQ_MHZ_160 + bool "160" + config EXAMPLE_PM_MAX_FREQ_MHZ_240 + bool "240" +endchoice + +config EXAMPLE_PM_MAX_FREQ + int + default 10 if EXAMPLE_PM_MAX_FREQ_MHZ_10 + default 20 if EXAMPLE_PM_MAX_FREQ_MHZ_20 + default 40 if EXAMPLE_PM_MAX_FREQ_MHZ_40 + default 80 if EXAMPLE_PM_MAX_FREQ_MHZ_80 + default 160 if EXAMPLE_PM_MAX_FREQ_MHZ_160 + default 240 if EXAMPLE_PM_MAX_FREQ_MHZ_240 + +choice EXAMPLE_PM_MIN_FREQ_MHZ + prompt "Min CPU frequency (MHz)" + default EXAMPLE_PM_MIN_FREQ_MHZ_40 + config EXAMPLE_PM_MIN_FREQ_MHZ_10 + bool "10" + config EXAMPLE_PM_MIN_FREQ_MHZ_20 + bool "20" + config EXAMPLE_PM_MIN_FREQ_MHZ_40 + bool "40" + config EXAMPLE_PM_MIN_FREQ_MHZ_80 + bool "80" + config EXAMPLE_PM_MIN_FREQ_MHZ_160 + bool "160" + config EXAMPLE_PM_MIN_FREQ_MHZ_240 + bool "240" +endchoice + +config EXAMPLE_PM_MIN_FREQ + int + default 10 if EXAMPLE_PM_MIN_FREQ_MHZ_10 + default 20 if EXAMPLE_PM_MIN_FREQ_MHZ_20 + default 40 if EXAMPLE_PM_MIN_FREQ_MHZ_40 + default 80 if EXAMPLE_PM_MIN_FREQ_MHZ_80 + default 160 if EXAMPLE_PM_MIN_FREQ_MHZ_160 + default 240 if EXAMPLE_PM_MIN_FREQ_MHZ_240 diff --git a/examples/lowpower/power_management/main/Kconfig.esp32s3.supported_freq b/examples/lowpower/power_management/main/Kconfig.esp32s3.supported_freq new file mode 100644 index 00000000000..dce3f21be62 --- /dev/null +++ b/examples/lowpower/power_management/main/Kconfig.esp32s3.supported_freq @@ -0,0 +1,51 @@ +choice EXAMPLE_PM_MAX_FREQ_MHZ + prompt "Max CPU frequency (MHz)" + default EXAMPLE_PM_MAX_FREQ_MHZ_240 + config EXAMPLE_PM_MAX_FREQ_MHZ_10 + bool "10" + config EXAMPLE_PM_MAX_FREQ_MHZ_20 + bool "20" + config EXAMPLE_PM_MAX_FREQ_MHZ_40 + bool "40" + config EXAMPLE_PM_MAX_FREQ_MHZ_80 + bool "80" + config EXAMPLE_PM_MAX_FREQ_MHZ_160 + bool "160" + config EXAMPLE_PM_MAX_FREQ_MHZ_240 + bool "240" +endchoice + +config EXAMPLE_PM_MAX_FREQ + int + default 10 if EXAMPLE_PM_MAX_FREQ_MHZ_10 + default 20 if EXAMPLE_PM_MAX_FREQ_MHZ_20 + default 40 if EXAMPLE_PM_MAX_FREQ_MHZ_40 + default 80 if EXAMPLE_PM_MAX_FREQ_MHZ_80 + default 160 if EXAMPLE_PM_MAX_FREQ_MHZ_160 + default 240 if EXAMPLE_PM_MAX_FREQ_MHZ_240 + +choice EXAMPLE_PM_MIN_FREQ_MHZ + prompt "Min CPU frequency (MHz)" + default EXAMPLE_PM_MIN_FREQ_MHZ_40 + config EXAMPLE_PM_MIN_FREQ_MHZ_10 + bool "10" + config EXAMPLE_PM_MIN_FREQ_MHZ_20 + bool "20" + config EXAMPLE_PM_MIN_FREQ_MHZ_40 + bool "40" + config EXAMPLE_PM_MIN_FREQ_MHZ_80 + bool "80" + config EXAMPLE_PM_MIN_FREQ_MHZ_160 + bool "160" + config EXAMPLE_PM_MIN_FREQ_MHZ_240 + bool "240" +endchoice + +config EXAMPLE_PM_MIN_FREQ + int + default 10 if EXAMPLE_PM_MIN_FREQ_MHZ_10 + default 20 if EXAMPLE_PM_MIN_FREQ_MHZ_20 + default 40 if EXAMPLE_PM_MIN_FREQ_MHZ_40 + default 80 if EXAMPLE_PM_MIN_FREQ_MHZ_80 + default 160 if EXAMPLE_PM_MIN_FREQ_MHZ_160 + default 240 if EXAMPLE_PM_MIN_FREQ_MHZ_240 diff --git a/examples/lowpower/power_management/main/Kconfig.projbuild b/examples/lowpower/power_management/main/Kconfig.projbuild new file mode 100644 index 00000000000..f793187d9f1 --- /dev/null +++ b/examples/lowpower/power_management/main/Kconfig.projbuild @@ -0,0 +1,17 @@ +# PM frequency options: one file per target (see test_freqs[] in +# components/esp_pm/test_apps/esp_pm/main/test_pm.c) + +menu "Example Configuration" + + orsource "Kconfig.$IDF_TARGET.supported_freq" + + config EXAMPLE_PM_LIGHT_SLEEP_ENABLE + bool "Enable automatic light sleep when idle" + default y if FREERTOS_USE_TICKLESS_IDLE + default n + help + When enabled (and tickless idle is enabled), the chip may enter light + sleep when no PM lock prevents it. Effective only if Component config + -> FreeRTOS -> Tickless idle support is enabled. + +endmenu diff --git a/examples/lowpower/power_management/main/power_management_example_main.c b/examples/lowpower/power_management/main/power_management_example_main.c new file mode 100644 index 00000000000..5c595d2cf98 --- /dev/null +++ b/examples/lowpower/power_management/main/power_management_example_main.c @@ -0,0 +1,81 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: CC0-1.0 + */ + +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_pm.h" +#include "sdkconfig.h" + +#define DEMO_PERIOD_MS 1000 +#define NESTED_HOLD_MS 200 +#define NESTED_ACTIVE_MS (3 * NESTED_HOLD_MS) +#define NESTED_IDLE_MS (DEMO_PERIOD_MS - NESTED_ACTIVE_MS) +#define PM_DUMP_INTERVAL_MS 10000 + +static void task_demo_nested_locks(void *arg) +{ + (void)arg; + esp_pm_lock_handle_t lock_no_ls; + esp_pm_lock_handle_t lock_apb; + esp_pm_lock_handle_t lock_cpu; + + ESP_ERROR_CHECK(esp_pm_lock_create(ESP_PM_NO_LIGHT_SLEEP, 0, "demo_no_ls", &lock_no_ls)); + ESP_ERROR_CHECK(esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "demo_apb", &lock_apb)); + ESP_ERROR_CHECK(esp_pm_lock_create(ESP_PM_CPU_FREQ_MAX, 0, "demo_cpu", &lock_cpu)); + + while (1) { + ESP_ERROR_CHECK(esp_pm_lock_acquire(lock_no_ls)); + // CPU working at min_freq_mhz, but not enter Light-sleep mode to + // maintain the ability to respond to interruptions + vTaskDelay(pdMS_TO_TICKS(NESTED_HOLD_MS)); + ESP_ERROR_CHECK(esp_pm_lock_acquire(lock_apb)); + // CPU working at the frequency of the maximum APB frequency supported + // by the SOC, to keep peripherals working at a high frequency. + vTaskDelay(pdMS_TO_TICKS(NESTED_HOLD_MS)); + ESP_ERROR_CHECK(esp_pm_lock_acquire(lock_cpu)); + // CPU working at max_freq_mhz, to achieve best performance. + vTaskDelay(pdMS_TO_TICKS(NESTED_HOLD_MS)); + ESP_ERROR_CHECK(esp_pm_lock_release(lock_cpu)); + ESP_ERROR_CHECK(esp_pm_lock_release(lock_apb)); + ESP_ERROR_CHECK(esp_pm_lock_release(lock_no_ls)); + // If light_sleep_enable is true, the system will enter Light-sleep mode. + // Otherwise, the CPU stays at min_freq_mhz in IDLE. + vTaskDelay(pdMS_TO_TICKS(NESTED_IDLE_MS)); + } +} + +/* Print PM config and lock/mode stats every 10s */ +static void task_pm_dump(void *arg) +{ + (void)arg; + vTaskDelay(pdMS_TO_TICKS(PM_DUMP_INTERVAL_MS)); + while (1) { + esp_pm_config_t cfg; + if (esp_pm_get_configuration(&cfg) == ESP_OK) { + printf("\n--- PM: max_freq=%d min_freq=%d MHz, light_sleep=%d ---\n", + cfg.max_freq_mhz, cfg.min_freq_mhz, cfg.light_sleep_enable ? 1 : 0); + } + esp_pm_dump_locks(stdout); + vTaskDelay(pdMS_TO_TICKS(PM_DUMP_INTERVAL_MS)); + } +} + +void app_main(void) +{ + printf("\n=== Power Management Example (nested locks, single task) ===\n"); + esp_pm_config_t pm_config = { + .max_freq_mhz = CONFIG_EXAMPLE_PM_MAX_FREQ, + .min_freq_mhz = CONFIG_EXAMPLE_PM_MIN_FREQ, + .light_sleep_enable = CONFIG_EXAMPLE_PM_LIGHT_SLEEP_ENABLE, + }; + ESP_ERROR_CHECK(esp_pm_configure(&pm_config)); + printf("PM configured: max=%d min=%d MHz, light_sleep_enable=%d\n", + pm_config.max_freq_mhz, pm_config.min_freq_mhz, pm_config.light_sleep_enable ? 1 : 0); + + xTaskCreate(task_demo_nested_locks, "demo_pm", 2048, NULL, 3, NULL); + xTaskCreate(task_pm_dump, "pm_dump", 2048, NULL, 0, NULL); +} diff --git a/examples/lowpower/power_management/pytest_power_management.py b/examples/lowpower/power_management/pytest_power_management.py new file mode 100644 index 00000000000..d0ebfd221f5 --- /dev/null +++ b/examples/lowpower/power_management/pytest_power_management.py @@ -0,0 +1,58 @@ +# SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: CC0-1.0 + +import re + +import pytest +from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize + +LOCK_PCT_TOL = 5 + +LOCK_EXPECT_PCT = { + 'demo_no_ls': 60, + 'demo_apb': 40, + 'demo_cpu': 20, +} + + +def _parse_lock_stats(dut: Dut, timeout: int = 15) -> dict[str, int]: + dut.expect_exact('Lock stats:', timeout=timeout) + dut.expect(re.compile(rb'Name\s+Type\s+Arg\s+Active\s+Total_count\s+Time'), timeout=2) + lock_pct: dict[str, int] = {} + pattern = re.compile(rb'(demo_no_ls|demo_apb|demo_cpu)\s+\S+\s+\d+\s+\d+\s+\d+\s+\d+\s+(\d+)\s*%') + while len(lock_pct) < len(LOCK_EXPECT_PCT): + m = dut.expect(pattern, timeout=timeout) + lock_pct[m.group(1).decode()] = int(m.group(2)) + return lock_pct + + +def _run_pm_example_test(dut: Dut) -> None: + dut.expect_exact('=== Power Management Example (nested locks, single task) ===', timeout=10) + dut.expect(re.compile(rb'--- PM: max_freq=\d+ min_freq=\d+ MHz, light_sleep=\d+ ---'), timeout=15) + + lock_pct = _parse_lock_stats(dut, timeout=5) + for name, expected in LOCK_EXPECT_PCT.items(): + pct = lock_pct[name] + assert (expected - LOCK_PCT_TOL) <= pct <= (expected + LOCK_PCT_TOL) + + +@pytest.mark.generic +@idf_parametrize('target', ['supported_targets'], indirect=['target']) +def test_esp_pm_mode_stats(dut: Dut) -> None: + _run_pm_example_test(dut) + + +@pytest.mark.generic +@pytest.mark.parametrize('config', ['pd_top'], indirect=True) +@idf_parametrize('target', ['esp32c6', 'esp32c61', 'esp32h2', 'esp32p4'], indirect=['target']) +def test_esp_pm_mode_stats_pd_top(dut: Dut) -> None: + _run_pm_example_test(dut) + + +@pytest.mark.generic +@pytest.mark.esp32c5_eco3 +@pytest.mark.parametrize('config', ['pd_top'], indirect=True) +@idf_parametrize('target', ['esp32c5'], indirect=['target']) +def test_esp_pm_mode_stats_pd_top_esp32c5_eco3(dut: Dut) -> None: + _run_pm_example_test(dut) diff --git a/examples/lowpower/power_management/sdkconfig.ci.default b/examples/lowpower/power_management/sdkconfig.ci.default new file mode 100644 index 00000000000..e69de29bb2d diff --git a/examples/lowpower/power_management/sdkconfig.ci.pd_top b/examples/lowpower/power_management/sdkconfig.ci.pd_top new file mode 100644 index 00000000000..5658858b850 --- /dev/null +++ b/examples/lowpower/power_management/sdkconfig.ci.pd_top @@ -0,0 +1 @@ +CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP=y diff --git a/examples/lowpower/power_management/sdkconfig.defaults b/examples/lowpower/power_management/sdkconfig.defaults new file mode 100644 index 00000000000..9d127f18b3f --- /dev/null +++ b/examples/lowpower/power_management/sdkconfig.defaults @@ -0,0 +1,7 @@ +# Enable power management (required for esp_pm component) +CONFIG_PM_ENABLE=y +CONFIG_PM_PROFILING=y +CONFIG_FREERTOS_HZ=1000 + +# Enable tickless idle so that automatic light sleep can be used when light_sleep_enable is true +CONFIG_FREERTOS_USE_TICKLESS_IDLE=y