警告

This document is not updated for ESP32C5 yet, so some of the content may not be correct.

This warning was automatically inserted due to the source file being in the add_warnings_pages list.

# 电源管理

[English]

## 概述

ESP-IDF 中集成的电源管理算法可以根据应用程序组件的需求，调整外围总线 (APB) 频率和 CPU 频率，并使芯片进入 Light-sleep 模式，尽可能减少运行应用程序的功耗。

应用程序组件可以通过创建和获取电源管理锁来控制功耗。

例如：

- 对于从 APB 获得时钟频率的外设，其驱动可以要求在使用该外设时，将 APB 频率设置为 80 MHz。

- RTOS 可以要求 CPU 在有任务准备开始运行时以最高配置频率工作。

- 一些外设可能需要中断才能启用，因此其驱动也会要求禁用 Light-sleep 模式。

请求较高的 APB 频率或 CPU 频率以及禁用 Light-sleep 模式会增加功耗，因此请将组件使用的电源管理锁降到最少。

## 电源管理配置

编译时可使用 CONFIG_PM_ENABLE 选项启用电源管理功能。

启用电源管理功能将会增加中断延迟。额外延迟与多个因素有关，例如：CPU 频率、单/双核模式、是否需要进行频率切换等。CPU 频率为 240 MHz 且未启用频率调节时，最小额外延迟为 0.2 us；如果启用频率调节，且在中断入口将频率由 40 MHz 调节至 80 MHz，则最大额外延迟为 40 us。

通过调用 `esp_pm_configure()` 函数可以在应用程序中启用动态调频 (DFS) 功能和自动 Light-sleep 模式。此函数的参数 `esp_pm_config_t` 定义了频率调节的相关设置。在此参数结构中，需要初始化以下三个字段：

> - `max_freq_mhz`：最大 CPU 频率 (MHz)，即获取 `ESP_PM_CPU_FREQ_MAX` 锁后所使用的频率。该字段通常设置为 CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ。

- `min_freq_mhz`：最小 CPU 频率 (MHz)，即未持有电源管理锁时所使用的频率。

  - `light_sleep_enable`：没有获取任何管理锁时，决定系统是否需要自动进入 Light-sleep 状态 (`true`/`false`)。

如果在 menuconfig 中启用了 CONFIG_PM_DFS_INIT_AUTO 选项，最大 CPU 频率将由 CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ 设置决定，最小 CPU 频率将锁定为 XTAL 频率。

备注

自动 Light-sleep 模式基于 FreeRTOS Tickless Idle 功能，因此如果在 menuconfig 中没有启用 CONFIG_FREERTOS_USE_TICKLESS_IDLE 选项，在请求自动 Light-sleep 时，`esp_pm_configure()` 将会返回 ESP_ERR_NOT_SUPPORTED 错误。

备注

Light-sleep 状态下，外设设有时钟门控，不会产生来自 GPIO 和内部外设的中断。睡眠模式 文档中所提到的唤醒源可用于从 Light-sleep 状态触发唤醒。

例如，EXT0 和 EXT1 唤醒源可以通过 GPIO 唤醒芯片。

## 电源管理锁

应用程序可以通过获取或释放管理锁来控制电源管理算法。应用程序获取电源管理锁后，电源管理算法的操作将受到下面的限制。释放电源管理锁后，限制解除。

电源管理锁设有获取/释放计数器，如果已多次获取电源管理锁，则需要将电源管理锁释放相同次数以解除限制。

ESP32-C5 支持下表中三种电源管理锁。

电源管理锁 | 描述
--- | ---
`ESP_PM_CPU_FREQ_MAX` | 请求使用 `esp_pm_configure()` 将 CPU 频率设置为最大值。ESP32-C5 可以将该值设置为 Not updated yet。
`ESP_PM_APB_FREQ_MAX` | 请求将 APB 频率设置为最大值，ESP32-C5 支持的最大频率为 80 MHz。
`ESP_PM_NO_LIGHT_SLEEP` | 禁止自动切换至 Light-sleep 模式。

## ESP32-C5 电源管理算法

下表列出了启用动态调频时如何切换 CPU 频率和 APB 频率。可以使用 `esp_pm_configure()` 或 CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ 指定 CPU 最大频率。

CPU 最高频率 | 电源管理锁获取情况 | APB 频率和 CPU 频率

如果没有获取任何管理锁，调用 `esp_pm_configure()` 将启动 Light-sleep 模式。Light-sleep 模式持续时间由以下因素决定：

- 处于阻塞状态的 FreeRTOS 任务数（有限超时）

- 高分辨率定时器 API 注册的计数器数量

也可以设置 Light-sleep 模式在最近事件（任务解除阻塞，或计时器超时）之前的持续时间，在持续时间结束后再唤醒芯片。

为了跳过不必要的唤醒，可以将 `skip_unhandled_events` 选项设置为 `true` 来初始化 `esp_timer`。带有此标志的定时器不会唤醒系统，有助于减少功耗。

## 动态调频和外设驱动

启用动态调频后，APB 频率可在一个 RTOS 滴答周期内多次更改。有些外设不受 APB 频率变更的影响，但有些外设可能会出现问题。例如，Timer Group 外设定时器会继续计数，但定时器计数的速度将随 APB 频率的变更而变更。

时钟频率不受 APB 频率影响的外设时钟源通常有 `REF_TICK`, `XTAL`, `RC_FAST` (i.e., `RTC_8M`)。因此，为了保证外设在 DFS 期间的所有行为一致，建议在上述时钟中选择其一作为外设的时钟源。如果想要了解更多详情可以浏览每个外设 ”API 参考 > 外设 API“ 页面的 “电源管理” 章节。

目前以下外设驱动程序可感知动态调频，并在调频期间使用 `ESP_PM_APB_FREQ_MAX` 锁：

- SPI master

- I2C

- I2S（如果 APLL 锁在使用中，I2S 则会启用 `ESP_PM_NO_LIGHT_SLEEP` 锁）

- SDMMC

启用以下驱动程序时，将占用 `ESP_PM_APB_FREQ_MAX` 锁：

- SPI slave：从调用 `spi_slave_initialize()` 至 `spi_slave_free()` 期间。

- GPTimer：从调用 `gptimer_enable()` 至 `gptimer_disable()` 期间。

- Ethernet：从调用 `esp_eth_driver_install()` 至 `esp_eth_driver_uninstall()` 期间。

- WiFi：从调用 `esp_wifi_start()` 至 `esp_wifi_stop()` 期间。如果启用了调制解调器睡眠模式，广播关闭时将释放此管理锁。

- Bluetooth：从调用 `esp_bt_controller_enable()` 至 `esp_bt_controller_disable()` 期间。如果启用了蓝牙调制解调器，广播关闭时将释放此管理锁。但依然占用 `ESP_PM_NO_LIGHT_SLEEP` 锁。

- PCNT：从调用 `pcnt_unit_enable()` 至 `pcnt_unit_disable()` 期间。

- Sigma-delta：从调用 `sdm_channel_enable()` 至 `sdm_channel_disable()` 期间。

- MCPWM: 从调用 `mcpwm_timer_enable()` 至 `mcpwm_timer_disable()` 期间，以及调用 `mcpwm_capture_timer_enable()` 至 `mcpwm_capture_timer_disable()` 期间。

以下外设驱动程序无法感知动态调频，应用程序需自己获取/释放管理锁：

- 旧版 PCNT 驱动

- 旧版 Sigma-delta 驱动

- 旧版定时器驱动 (Timer Group)

- 旧版 MCPWM 驱动

## Light-sleep 外设下电

> ESP32-C5 支持在 Light-sleep 时掉电外设的电源域.

> 如果在 menuconfig 中启用了 CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP，在初始化外设时，驱动会将外设工作的寄存器上下文注册到休眠备份链表中，在进入休眠前，`REG_DMA` 外设会读取休眠备份链表中的配置，根据链表中的配置将外设的寄存器上下文备份至内存，`REG_DMA` 也会在唤醒时将上下文从内存恢复到外设寄存中。

> 目前 IDF 支持以下外设的 Light-sleep 上下文备份，它们的上下文会自动恢复，或者提供了相关的选项允许用户进入外设下电模式：

> - INT_MTX

> - TEE/APM

> - IO_MUX / GPIO

> - MSPI (SPI0/1)

> - SYSTIMER

> - GPTimer

> - RMT

> - LEDC

> - I2C

> - I2S

> - ETM

> - MCPWM

> - All UARTs

> - Temperature Sensor

> - PARL_IO

> - All GPSPIs

> 一些外设尚未支持睡眠上下文恢复，或者寄存器丢失后根本无法恢复。即使外设下电功能被启用，它们也会阻止外设下电的发生：

> 以下外设（以及一些未在本章节任意一组中列出的外设）尚未支持外设下电功能。如果您的应用使用了这些外设，它们可能无法在从睡眠中醒来后仍然正常工作：

> - ASSIST_DEBUG

> - Trace

> - Crypto: AES/ECC/HMAC/RSA/SHA/DS/XTA_AES/ECDSA

> - PCNT

> - USB-Serial-JTAG

> - SARADC

> 备注

> 当外设电源域在睡眠期间断电时，IO_MUX 和 GPIO 模块都处于下电状态，这意味着芯片引脚的状态不会受这些模块控制。要在休眠期间保持 IO 的状态，需要在配置 GPIO 状态前后调用 `gpio_hold_dis()` 和 `gpio_hold_en()`。此操作可确保 IO 配置被锁存，防止 IO 在睡眠期间浮空。

## API 参考

### Header File

- components/esp_pm/include/esp_pm.h

- This header file can be included with:

  >     #include "esp_pm.h"

- This header file is a part of the API provided by the `esp_pm` component. To declare that your component depends on `esp_pm`, add the following to your CMakeLists.txt:

  >     REQUIRES esp_pm

  > or

  >     PRIV_REQUIRES esp_pm

### Functions

esp_err_t esp_pm_configure(const void *config)

  Set implementation-specific power management configuration.

  参数

    config -- pointer to implementation-specific configuration structure (e.g. esp_pm_config_esp32)

  返回

    - ESP_OK on success

    - ESP_ERR_INVALID_ARG if the configuration values are not correct

    - ESP_ERR_NOT_SUPPORTED if certain combination of values is not supported, or if CONFIG_PM_ENABLE is not enabled in sdkconfig

esp_err_t esp_pm_get_configuration(void *config)

  Get implementation-specific power management configuration.

  参数

    config -- pointer to implementation-specific configuration structure (e.g. esp_pm_config_esp32)

  返回

    - ESP_OK on success

    - ESP_ERR_INVALID_ARG if the pointer is null

esp_err_t esp_pm_lock_create(esp_pm_lock_type_t lock_type, int arg, const char *name, esp_pm_lock_handle_t *out_handle)

  Initialize a lock handle for certain power management parameter.

  When lock is created, initially it is not taken. Call esp_pm_lock_acquire to take the lock.

  This function must not be called from an ISR.

  备注

  If the lock_type argument is not valid, it will cause an abort.

  参数

    - lock_type -- Power management constraint which the lock should control

    - arg -- argument, value depends on lock_type, see esp_pm_lock_type_t

    - name -- arbitrary string identifying the lock (e.g. "wifi" or "spi"). Used by the esp_pm_dump_locks function to list existing locks. May be set to NULL. If not set to NULL, must point to a string which is valid for the lifetime of the lock.

    - out_handle -- [out] handle returned from this function. Use this handle when calling esp_pm_lock_delete, esp_pm_lock_acquire, esp_pm_lock_release. Must not be NULL.

  返回

    - ESP_OK on success

    - ESP_ERR_NO_MEM if the lock structure can not be allocated

    - ESP_ERR_INVALID_ARG if out_handle is NULL

    - ESP_ERR_NOT_SUPPORTED if CONFIG_PM_ENABLE is not enabled in sdkconfig

esp_err_t esp_pm_lock_acquire(esp_pm_lock_handle_t handle)

  Take a power management lock.

  Once the lock is taken, power management algorithm will not switch to the mode specified in a call to esp_pm_lock_create, or any of the lower power modes (higher numeric values of 'mode').

  The lock is recursive, in the sense that if esp_pm_lock_acquire is called a number of times, esp_pm_lock_release has to be called the same number of times in order to release the lock.

  This function may be called from an ISR.

  This function is not thread-safe w.r.t. calls to other esp_pm_lock_* functions for the same handle.

  参数

    handle -- handle obtained from esp_pm_lock_create function

  返回

    - ESP_OK on success

    - ESP_ERR_INVALID_ARG if the handle is invalid

    - ESP_ERR_NOT_SUPPORTED if CONFIG_PM_ENABLE is not enabled in sdkconfig

esp_err_t esp_pm_lock_release(esp_pm_lock_handle_t handle)

  Release the lock taken using esp_pm_lock_acquire.

  Call to this functions removes power management restrictions placed when taking the lock.

  Locks are recursive, so if esp_pm_lock_acquire is called a number of times, esp_pm_lock_release has to be called the same number of times in order to actually release the lock.

  This function may be called from an ISR.

  This function is not thread-safe w.r.t. calls to other esp_pm_lock_* functions for the same handle.

  参数

    handle -- handle obtained from esp_pm_lock_create function

  返回

    - ESP_OK on success

    - ESP_ERR_INVALID_ARG if the handle is invalid

    - ESP_ERR_INVALID_STATE if lock is not acquired

    - ESP_ERR_NOT_SUPPORTED if CONFIG_PM_ENABLE is not enabled in sdkconfig

esp_err_t esp_pm_lock_delete(esp_pm_lock_handle_t handle)

  Delete a lock created using esp_pm_lock.

  The lock must be released before calling this function.

  This function must not be called from an ISR.

  参数

    handle -- handle obtained from esp_pm_lock_create function

  返回

    - ESP_OK on success

    - ESP_ERR_INVALID_ARG if the handle argument is NULL

    - ESP_ERR_INVALID_STATE if the lock is still acquired

    - ESP_ERR_NOT_SUPPORTED if CONFIG_PM_ENABLE is not enabled in sdkconfig

esp_err_t esp_pm_dump_locks(FILE *stream)

  Dump the list of all locks to stderr

  This function dumps debugging information about locks created using esp_pm_lock_create to an output stream.

  This function must not be called from an ISR. If esp_pm_lock_acquire/release are called while this function is running, inconsistent results may be reported.

  参数

    stream -- stream to print information to; use stdout or stderr to print to the console; use fmemopen/open_memstream to print to a string buffer.

  返回

    - ESP_OK on success

    - ESP_ERR_NOT_SUPPORTED if CONFIG_PM_ENABLE is not enabled in sdkconfig

### Structures

struct esp_pm_config_t

  Power management config.

  Pass a pointer to this structure as an argument to esp_pm_configure function.

  Public Members

  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

### Type Definitions

typedef esp_pm_config_t esp_pm_config_esp32_t

  backward compatibility newer chips no longer require this typedef

typedef esp_pm_config_t esp_pm_config_esp32s2_t

typedef esp_pm_config_t esp_pm_config_esp32s3_t

typedef esp_pm_config_t esp_pm_config_esp32c3_t

typedef esp_pm_config_t esp_pm_config_esp32c2_t

typedef esp_pm_config_t esp_pm_config_esp32c6_t

typedef struct esp_pm_lock *esp_pm_lock_handle_t

  Opaque handle to the power management lock.

### Enumerations

enum esp_pm_lock_type_t

  Power management constraints.

  Values:

  enumerator ESP_PM_CPU_FREQ_MAX

    Require CPU frequency to be at the maximum value set via esp_pm_configure. Argument is unused and should be set to 0.

  enumerator ESP_PM_APB_FREQ_MAX

    Require APB frequency to be at the maximum value supported by the chip. Argument is unused and should be set to 0.

  enumerator ESP_PM_NO_LIGHT_SLEEP

    Prevent the system from going into light sleep. Argument is unused and should be set to 0.

  enumerator ESP_PM_LOCK_MAX

此文档对您有帮助吗？

- 反馈已收到，谢谢！
- 如果您有其他意见，欢迎填写乐鑫文档反馈表。

- 我们重视您的反馈。
- 您可以填写乐鑫文档反馈表告诉我们如何改进该文档。