Skip to content

电源管理

ESP-IDF的集成电源管理可以根据程序组件的需求, 调节总线的频率, CPU的频率

CONFIG_PM_ENABLE 选项启用电源管理功能。

使用这一个进行调节CPU的频率会使得中断的响应时间增加

启用动态调频和自动 Light-sleep

c
esp_err_t esp_pm_configure(const void *config)

这一个里面需要设置三个函数

  • max_freq_mhz:最大 CPU 频率 (MHz),即获取 ESP_PM_CPU_FREQ_MAX 锁后所使用的频率。该字段通常设置为 CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ
  • min_freq_mhz:最小 CPU 频率 (MHz),即仅获取 ESP_PM_APB_FREQ_MAX 锁后所使用的频率。该字段可设置为晶振 (XTAL) 频率值,或者 XTAL 频率值除以整数。注意,10 MHz 是生成 1 MHz 的 REF_TICK 默认时钟所需的最小频率。
  • light_sleep_enable:没有获取任何管理锁时,决定系统是否需要自动进入 Light-sleep 状态 (true/false)。

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

ESP32的电源管理中,管理锁用于保护系统在深度睡眠模式下不被意外唤醒。当ESP32进入深度睡眠模式后,所有的外设和时钟都被关闭,只有管理模块处于工作状态。如果在此期间,外部信号或中断触发了某个外设,可能会导致系统被唤醒,从而影响功耗。因此,ESP32引入了管理锁的概念,当管理锁被锁定时,即使有外部触发,系统也不会被唤醒。只有当管理锁被解锁时,才会允许外部信号触发系统唤醒。这样可以有效地防止系统被意外唤醒,延长电池寿命。

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

If power management support is enabled, FreeRTOS will be able to put the system into light sleep mode when no tasks need to run for a number of ticks. This number can be set using FREERTOS_IDLE_TIME_BEFORE_SLEEP option. This feature is also known as "automatic light sleep".

可以使用这一个选项设置自动睡眠

CPU 最高频率电源管理锁获取情况APB 频率和 CPU 频率
240获取 ESP_PM_CPU_FREQ_MAXESP_PM_APB_FREQ_MAXCPU: 240 MHzAPB: 80 MHz
使用 esp_pm_configure() 为二者设置最小值
160获取 ESP_PM_CPU_FREQ_MAXCPU: 160 MHzAPB: 80 MHz
获取 ESP_PM_APB_FREQ_MAX,未获得 ESP_PM_CPU_FREQ_MAXCPU: 80 MHzAPB: 80 MHz
使用 esp_pm_configure() 为二者设置最小值
80获取 ESP_PM_CPU_FREQ_MAXESP_PM_APB_FREQ_MAXCPU: 80 MHzAPB: 80 MHz
使用 esp_pm_configure() 为二者设置最小值

动态调频和外设驱动

使用动态调频的时候, APB的频率可以在一个RTOS的周期里面多次改变, 有的外设不受APB的频率影响, 有的可能会出现问题

Timer Group 外设定时器会继续计数,但定时器计数的速度将随 APB 频率的变更而变更。

时钟频率不受 APB 频率影响的外设时钟源通常有 REF_TICK, XTAL, RC_FAST (i.e., RTC_8M)。

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

  • SPI master
  • I2C
  • I2S(如果 APLL 锁在使用中,I2S 则会启用 ESP_PM_NO_LIGHT_SLEEP 锁)
  • SDMMC

启用以下驱动程序时,将占用 ESP_PM_APB_FREQ_MAX 锁:

API

c
#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

    PRIV_REQUIRES esp_pm

c
esp_err_t esp_pm_configure(const void *config)

配置函数, 使用这一个函数进行配置

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

初始化句柄, 初始化的时候这一个句柄是没有获取的

  • 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.
c
esp_err_t esp_pm_lock_acquire(esp_pm_lock_handle_t handle)

这一个锁被获取的时候会使用对应的电池管理算法, 这一个锁是一个递归的锁, 可以在中断里面使用

handle -- handle obtained from esp_pm_lock_create function

c
esp_err_t esp_pm_lock_release(esp_pm_lock_handle_t handle)

释放这一个锁

重启

c
void esp_restart(void)

重启

c
esp_err_t esp_register_shutdown_handler(shutdown_handler_t handle)

注册一个回调函数, 会在esp_restart函数执行的时候进行调用