深度睡眠

概述

ESP32 具有深度睡眠节电功能。在这种模式下,CPU、大多数的 RAM 和所有的由时钟 APB_CLK 驱动的数字外设都会被断电。芯片中还继续处于供电状态的部分包括:RTC 控制器、RTC 外设(包括 ULP 协处理器)、RTC 内存(低速和快速)。

从深度睡眠中唤醒可以使用几种源。这些源可以组合在一起,此时,任何一种源都可以触发唤醒。可以通过 API esp_deep_sleep_enable_X_wakeup 来使能唤醒源。下一节将描述这些 API 的细节。你可以在系统进入深度睡眠前的任何时刻配置唤醒源。

此外,应用程序可以使用 API esp_deep_sleep_pd_config 让 RTC 外设和 RTC 内存强制断电。

唤醒源被配置后,应用程序可以使用 API esp_deep_sleep_start 进入深度睡眠。从这一点看,硬件将会根据所请求的唤醒源来配置,RTC 控制器将给 CPU 和数字外设断电。

唤醒源

定时器

RTC 控制器中有一个内置的定时器,可用于在预定义的时间到达后唤醒芯片。时间的精度是微秒,但是实际的分辨率依赖于为 RTC SLOW_CLK 所选择的时钟源。关于 RTC 时钟选项的更多细节请参考 ESP32 技术参考手册的 “Reset and Clock” 一章。

这种唤醒模式不需要 RTC 外设或内存在深度睡眠器件供电。

下面的函数可以用于使能使用定时器深度睡眠唤醒。

esp_err_t esp_deep_sleep_enable_timer_wakeup(uint64_t time_in_us)

Enable wakeup by timer.

Return
  • ESP_OK on success
  • ESP_ERR_INVALID_ARG if value is out of range (TBD)
Parameters
  • time_in_us: time before wakeup, in microseconds

触摸板

RTC IO 模块中包含这样一个逻辑:当发生触摸传感器中断时触发唤醒。你需要在芯片进入深度睡眠前配置触摸屏的中断。

ESP32 的修订版 0 和 1 仅在 RTC 外设没有被强制供电时支持该唤醒(即 ESP_PD_DOMAIN_RTC_PERIPH 被设置为 ESP_PD_OPTION_AUTO)。

esp_err_t esp_deep_sleep_enable_touchpad_wakeup()

Enable wakeup by touch sensor.

Note
In revisions 0 and 1 of the ESP32, touch wakeup source can not be used when RTC_PERIPH power domain is forced to be powered on (ESP_PD_OPTION_ON) or when ext0 wakeup source is used.
Return
  • ESP_OK on success
  • ESP_ERR_INVALID_STATE if wakeup triggers conflict

外部唤醒(ext0)

RTC IO 模块中包含这样一个逻辑,当某个 RTC GPIO 被设置为预定义的逻辑值时触发唤醒。RTC IO 是 RTC 外设电源域的一部分,因此如果该唤醒源被请求的话,RTC 外设将在深度睡眠期间保持供电。

因为 RTC IO 模块在这个模式被使能,因此也可以使用内部上拉或下拉电阻。它们需要应用程序在调用 esp_deep_sleep_start 前使用先调用函数 rtc_gpio_pullup_enrtc_gpio_pulldown_en

在 ESP32 的修订版 0 和 1 中,这个唤醒源与 ULP 和触摸唤醒源都不兼容。

警告

从深度睡眠中唤醒后,用于唤醒的 IO Pad 将被配置为 RTC IO,因此在将该 pad 用作数字 IO 前,需要使用函数 rtc_gpio_deinit(gpio_num) 对它进行重新配置。

esp_err_t esp_deep_sleep_enable_ext0_wakeup(gpio_num_t gpio_num, int level)

Enable wakeup using a pin.

This function uses external wakeup feature of RTC_IO peripheral. It will work only if RTC peripherals are kept on during deep sleep.

This feature can monitor any pin which is an RTC IO. Once the pin transitions into the state given by level argument, the chip will be woken up.

Note
This function does not modify pin configuration. The pin is configured in esp_deep_sleep_start, immediately before entering deep sleep.
Note
In revisions 0 and 1 of the ESP32, ext0 wakeup source can not be used together with touch or ULP wakeup sources.
Return
  • ESP_OK on success
  • ESP_ERR_INVALID_ARG if the selected GPIO is not an RTC GPIO, or the mode is invalid
  • ESP_ERR_INVALID_STATE if wakeup triggers conflict
Parameters
  • gpio_num: GPIO number used as wakeup source. Only GPIOs which are have RTC functionality can be used: 0,2,4,12-15,25-27,32-39.
  • level: input level which will trigger wakeup (0=low, 1=high)

外部唤醒(ext1)

RTC 控制器包含使用多个 RTC GPIO 触发唤醒的逻辑。下面其中一个逻辑功能可以用于触发唤醒:

  • 当任意一个所选引脚为高电平时唤醒 (ESP_EXT1_WAKEUP_ANY_HIGH)
  • 当所有所选引脚为低电平时唤醒 (ESP_EXT1_WAKEUP_ALL_LOW)

这个唤醒源由 RTC 控制器实现。这种模式下的 RTC 外设和 RTC 内存可以被断电。不过,如果 RTC 外设被断电,内部上拉和下拉电阻将被禁止。为了使用内部上拉和下拉电阻,需要 RTC 外设电源域在睡眠期间保持开启,并在进入深度睡眠前使用函数 rtc_gpio_ 配置上拉/下拉电阻

esp_deep_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
gpio_pullup_dis(gpio_num);
gpio_pulldown_en(gpio_num);

警告

从深度睡眠中唤醒后,用于唤醒的 IO Pad 将被配置为 RTC IO,因此在将该 pad 用作数字 IO 前,需要使用函数 rtc_gpio_deinit(gpio_num) 对它进行重新配置。

下列函数可以用于使能这个唤醒模式:

esp_err_t esp_deep_sleep_enable_ext1_wakeup(uint64_t mask, esp_ext1_wakeup_mode_t mode)

Enable wakeup using multiple pins.

This function uses external wakeup feature of RTC controller. It will work even if RTC peripherals are shut down during deep sleep.

This feature can monitor any number of pins which are in RTC IOs. Once any of the selected pins goes into the state given by mode argument, the chip will be woken up.

Note
This function does not modify pin configuration. The pins are configured in esp_deep_sleep_start, immediately before entering deep sleep.
Note
internal pullups and pulldowns don’t work when RTC peripherals are shut down. In this case, external resistors need to be added. Alternatively, RTC peripherals (and pullups/pulldowns) may be kept enabled using esp_deep_sleep_pd_config function.
Return
  • ESP_OK on success
  • ESP_ERR_INVALID_ARG if any of the selected GPIOs is not an RTC GPIO, or mode is invalid
Parameters
  • mask: bit mask of GPIO numbers which will cause wakeup. Only GPIOs which are have RTC functionality can be used in this bit map: 0,2,4,12-15,25-27,32-39.
  • mode: select logic function used to determine wakeup condition:
    • ESP_EXT1_WAKEUP_ALL_LOW: wake up when all selected GPIOs are low
    • ESP_EXT1_WAKEUP_ANY_HIGH: wake up when any of the selected GPIOs is high

enum esp_ext1_wakeup_mode_t

Logic function used for EXT1 wakeup mode.

Values:

ESP_EXT1_WAKEUP_ALL_LOW = 0

Wake the chip when all selected GPIOs go low.

ESP_EXT1_WAKEUP_ANY_HIGH = 1

Wake the chip when any of the selected GPIOs go high.

ULP 协处理器唤醒

当芯片处于深度睡眠时,ULP 协处理器能够运行,可以用于轮询传感器、监视器 ADC 或者触摸板传感器的值,并在检查到某个特殊事件时唤醒芯片。ULP 协处理器是 RTC 外设电源域的一部分,它运行存储在 RTC 低速内存中的程序。如果请求了这种唤醒模式,则 RTC 低速内存将会在深度睡眠期间保持供电状态。RTC 外设会在 ULP 协处理器开始运行程序前自动上电;一旦程序停止运行,RTC 外设会再次自动断电。

ESP32 的修订版 0 和 1 仅在 RTC 外设没有被强制供电时支持该唤醒(即 ESP_PD_DOMAIN_RTC_PERIPH 被设置为 ESP_PD_OPTION_AUTO)。

下列函数可以用于使能这个唤醒模式:

esp_err_t esp_deep_sleep_enable_ulp_wakeup()

Enable wakeup by ULP coprocessor.

Note
In revisions 0 and 1 of the ESP32, ULP wakeup source can not be used when RTC_PERIPH power domain is forced to be powered on (ESP_PD_OPTION_ON) or when ext0 wakeup source is used.
Return
  • ESP_OK on success
  • ESP_ERR_INVALID_STATE if ULP co-processor is not enabled or if wakeup triggers conflict

RTC 外设和内存断电

默认情况下,函数 esp_deep_sleep_start 将会关掉被使能的唤醒源不需要的所有 RTC 电源域。如果向修改这个默认行为,可以使用下面的函数:

Note: 在 ESP32 的修订版 1 中,RTC 快速内存在深度睡眠期间将总是保持使能,因此深度睡眠桩(stub)可以在复位后运行。如果应用程序在深度睡眠后不需要清除复位行为,也可以对其进行修改。

如果程序中的某些值被if昂懂啊 RTC 低速内存中(例如,使用 RTC_DATA_ATTR 属性),RTC 低速内存将默认保持供电。如果有需要,也可以使用函数 esp_deep_sleep_pd_config 对其进行修改。

esp_err_t esp_deep_sleep_pd_config(esp_deep_sleep_pd_domain_t domain, esp_deep_sleep_pd_option_t option)

Set power down mode for an RTC power domain in deep sleep.

If not set set using this API, all power domains default to ESP_PD_OPTION_AUTO.

Return
  • ESP_OK on success
  • ESP_ERR_INVALID_ARG if either of the arguments is out of range
Parameters
  • domain: power domain to configure
  • option: power down option (ESP_PD_OPTION_OFF, ESP_PD_OPTION_ON, or ESP_PD_OPTION_AUTO)

enum esp_deep_sleep_pd_domain_t

Power domains which can be powered down in deep sleep.

Values:

ESP_PD_DOMAIN_RTC_PERIPH

RTC IO, sensors and ULP co-processor.

ESP_PD_DOMAIN_RTC_SLOW_MEM

RTC slow memory.

ESP_PD_DOMAIN_RTC_FAST_MEM

RTC fast memory.

ESP_PD_DOMAIN_MAX

Number of domains.

enum esp_deep_sleep_pd_option_t

Power down options.

Values:

ESP_PD_OPTION_OFF

Power down the power domain in deep sleep.

ESP_PD_OPTION_ON

Keep power domain enabled during deep sleep.

ESP_PD_OPTION_AUTO

Keep power domain enabled in deep sleep, if it is needed by one of the wakeup options. Otherwise power it down.

进入深度睡眠

唤醒源配置后,下面函数可以用于进入深度睡眠。在没有配置唤醒源时也可以进入深度睡眠,在这种情形下,芯片将确切地处于深度睡眠模式,知道接收到外部复位。

void esp_deep_sleep_start()

Enter deep sleep with the configured wakeup options.

This function does not return.

检查深度睡眠唤醒原因

下面的函数可用于检测是何种唤醒源在深度睡眠期间被触发了。对于触摸板和 ext1 唤醒源,可以确定造成唤醒的引脚或触摸 pad。

esp_deep_sleep_wakeup_cause_t esp_deep_sleep_get_wakeup_cause()

Get the source which caused deep sleep wakeup.

Return
wakeup cause, or ESP_DEEP_SLEEP_WAKEUP_UNDEFINED if reset reason is other than deep sleep reset.

enum esp_deep_sleep_wakeup_cause_t

Deep sleep wakeup cause.

Values:

ESP_DEEP_SLEEP_WAKEUP_UNDEFINED
ESP_DEEP_SLEEP_WAKEUP_EXT0

Wakeup was not caused by deep sleep.

ESP_DEEP_SLEEP_WAKEUP_EXT1

Wakeup caused by external signal using RTC_IO.

ESP_DEEP_SLEEP_WAKEUP_TIMER

Wakeup caused by external signal using RTC_CNTL.

ESP_DEEP_SLEEP_WAKEUP_TOUCHPAD

Wakeup caused by timer.

ESP_DEEP_SLEEP_WAKEUP_ULP

Wakeup caused by touchpad.

touch_pad_t esp_deep_sleep_get_touchpad_wakeup_status()

Get the touch pad which caused wakeup.

If wakeup was caused by another source, this function will return TOUCH_PAD_MAX;

Return
touch pad which caused wakeup

uint64_t esp_deep_sleep_get_ext1_wakeup_status()

Get the bit mask of GPIOs which caused wakeup (ext1)

If wakeup was caused by another source, this function will return 0.

Return
bit mask, if GPIOn caused wakeup, BIT(n) will be set

应用程序示例

深度睡眠的基本示例程序是 protocols/sntp,它会让 ESP 模块周期性地唤醒,以从 NTP 服务器获取时间。

更多扩展示例请参考 system/deep_sleep,它描述了各种深度睡眠触发器和 ULP 协处理器编程的方法。