Sleep Modes

Overview

ESP32-C3 is capable of light sleep and deep sleep power saving modes.

In light sleep mode, digital peripherals, most of the RAM, and CPUs are clock-gated, and supply voltage is reduced. Upon exit from light sleep, peripherals and CPUs resume operation, their internal state is preserved.

In deep sleep mode, CPUs, most of the RAM, and all the digital peripherals which are clocked from APB_CLK are powered off. The only parts of the chip which can still be powered on are:

  • RTC controller

  • RTC peripherals

  • RTC fast memory

Wakeup from deep and light sleep modes can be done using several sources. These sources can be combined, in this case the chip will wake up when any one of the sources is triggered. Wakeup sources can be enabled using esp_sleep_enable_X_wakeup APIs and can be disabled using esp_sleep_disable_wakeup_source() API. Next section describes these APIs in detail. Wakeup sources can be configured at any moment before entering light or deep sleep mode.

Additionally, the application can force specific powerdown modes for the RTC peripherals and RTC memories using esp_sleep_pd_config() API.

Once wakeup sources are configured, application can enter sleep mode using esp_light_sleep_start() or esp_deep_sleep_start() APIs. At this point the hardware will be configured according to the requested wakeup sources, and RTC controller will either power down or power off the CPUs and digital peripherals.

WiFi/BT and sleep modes

In Deep-sleep and Light-sleep modes, the wireless peripherals are powered down. Before entering Deep-sleep or Light-sleep modes, the application must disable Wi-Fi and Bluetooth using the appropriate calls (i.e., nimble_port_stop(), nimble_port_deinit(), esp_bluedroid_disable(), esp_bluedroid_deinit(), esp_bt_controller_disable(), esp_bt_controller_deinit(), esp_wifi_stop()). Wi-Fi and Bluetooth connections are not maintained in Deep-sleep or Light-sleep mode, even if these functions are not called.

If Wi-Fi/Bluetooth connections need to be maintained, enable Wi-Fi/Bluetooth Modem-sleep mode and automatic Light-sleep feature (see Power Management APIs). This will allow the system to wake up from sleep automatically when required by the Wi-Fi/Bluetooth driver, thereby maintaining the connection.

Wakeup sources

Timer

RTC controller has a built in timer which can be used to wake up the chip after a predefined amount of time. Time is specified at microsecond precision, but the actual resolution depends on the clock source selected for RTC SLOW_CLK.

This wakeup mode doesn’t require RTC peripherals or RTC memories to be powered on during sleep.

esp_sleep_enable_timer_wakeup() function can be used to enable deep sleep wakeup using a timer.

GPIO Wakeup

Any IO can be used as the external input to wakeup the chip from Light-sleep. Each pin can be individually configured to trigger wakeup on high or low level using gpio_wakeup_enable() function. Then esp_sleep_enable_gpio_wakeup() function should be called to enable this wakeup source.

Additionally, IOs that are powered by the VDD3P3_RTC power domain can be used to wakeup the chip from Deep-sleep. The wakeup pin and wakeup trigger level can be configured by calling esp_deep_sleep_enable_gpio_wakeup(). The function will enable the Deep-sleep wakeup for the selected pin.

UART wakeup (light sleep only)

When ESP32-C3 receives UART input from external devices, it is often required to wake up the chip when input data is available. UART peripheral contains a feature which allows waking up the chip from light sleep when a certain number of positive edges on RX pin are seen. This number of positive edges can be set using uart_set_wakeup_threshold() function. Note that the character which triggers wakeup (and any characters before it) will not be received by the UART after wakeup. This means that the external device typically needs to send an extra character to the ESP32-C3 to trigger wakeup, before sending the data.

esp_sleep_enable_uart_wakeup() function can be used to enable this wakeup source.

After waking-up from UART, you should send some extra data through the UART port in Active mode, so that the internal wakeup indication signal can be cleared. Otherwises, the next UART wake-up would trigger with two less rising edges than the configured threshold value.

Power-down of RTC peripherals and memories

By default, esp_deep_sleep_start() and esp_light_sleep_start() functions will power down all RTC power domains which are not needed by the enabled wakeup sources. To override this behaviour, esp_sleep_pd_config() function is provided.

In ESP32-C3 there is only RTC fast memory, so if some variables in the program are marked by RTC_DATA_ATTR, RTC_SLOW_ATTR or RTC_FAST_ATTR attributes, all of them go to RTC fast memory. It will be kept powered on by default. This can be overridden using esp_sleep_pd_config() function, if desired.

Power-down of Flash

By default, to avoid potential issues, esp_light_sleep_start() function will not power down flash. To be more specific, it takes time to power down the flash and during this period the system may be woken up, which then actually powers up the flash before this flash could be powered down completely. As a result, there is a chance that the flash may not work properly.

So, in theory, it’s ok if you only wake up the system after the flash is completely powered down. However, in reality, the flash power-down period can be hard to predict (for example, this period can be much longer when you add filter capacitors to the flash’s power supply circuit) and uncontrollable (for example, the asynchronous wake-up signals make the actual sleep time uncontrollable).

Warning

If a filter capacitor is added to your flash power supply circuit, please do everything possible to avoid powering down flash.

Therefore, it’s recommended not to power down flash when using ESP-IDF. For power-sensitive applications, it’s recommended to use Kconfig option CONFIG_ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND to reduce the power consumption of the flash during light sleep, instead of powering down the flash.

However, for those who have fully understood the risk and are still willing to power down the flash to further reduce the power consumption, please check the following mechanisms:

  • Setting Kconfig option CONFIG_ESP_SLEEP_POWER_DOWN_FLASH only powers down the flash when the RTC timer is the only wake-up source and the sleep time is longer than the flash power-down period.

  • Calling esp_sleep_pd_config(ESP_PD_DOMAIN_VDDSDIO, ESP_PD_OPTION_OFF) powers down flash when the RTC timer is not enabled as a wakeup source or the sleep time is longer than the flash power-down period.

Note

  • ESP-IDF does not provide any mechanism that can power down the flash in all conditions when light sleep.

  • esp_deep_sleep_start() function will force power down flash regardless of user configuration.

Entering light sleep

esp_light_sleep_start() function can be used to enter light sleep once wakeup sources are configured. It is also possible to go into light sleep with no wakeup sources configured, in this case the chip will be in light sleep mode indefinitely, until external reset is applied.

Entering deep sleep

esp_deep_sleep_start() function can be used to enter deep sleep once wakeup sources are configured. It is also possible to go into deep sleep with no wakeup sources configured, in this case the chip will be in deep sleep mode indefinitely, until external reset is applied.

Configuring IOs

Some ESP32-C3 IOs have internal pullups or pulldowns, which are enabled by default. If an external circuit drives this pin in deep sleep mode, current consumption may increase due to current flowing through these pullups and pulldowns.

To isolate a pin, preventing extra current draw, call rtc_gpio_isolate() function.

For example, on ESP32-WROVER module, GPIO12 is pulled up externally. GPIO12 also has an internal pulldown in the ESP32 chip. This means that in deep sleep, some current will flow through these external and internal resistors, increasing deep sleep current above the minimal possible value. Add the following code before esp_deep_sleep_start() to remove this extra current:

rtc_gpio_isolate(GPIO_NUM_12);

UART output handling

Before entering sleep mode, esp_deep_sleep_start() will flush the contents of UART FIFOs.

When entering light sleep mode using esp_light_sleep_start(), UART FIFOs will not be flushed. Instead, UART output will be suspended, and remaining characters in the FIFO will be sent out after wakeup from light sleep.

Checking sleep wakeup cause

esp_sleep_get_wakeup_cause() function can be used to check which wakeup source has triggered wakeup from sleep mode.

Disable sleep wakeup source

Previously configured wakeup source can be disabled later using esp_sleep_disable_wakeup_source() API. This function deactivates trigger for the given wakeup source. Additionally it can disable all triggers if the argument is ESP_SLEEP_WAKEUP_ALL.

Application Example

Implementation of basic functionality of deep sleep is shown in protocols/sntp example, where ESP module is periodically waken up to retrieve time from NTP server.

API Reference

Functions

esp_err_t esp_sleep_disable_wakeup_source(esp_sleep_source_t source)

Disable wakeup source.

This function is used to deactivate wake up trigger for source defined as parameter of the function.

See docs/sleep-modes.rst for details.

Note

This function does not modify wake up configuration in RTC. It will be performed in esp_sleep_start function.

Parameters

source – - number of source to disable of type esp_sleep_source_t

Returns

  • ESP_OK on success

  • ESP_ERR_INVALID_STATE if trigger was not active

esp_err_t esp_sleep_enable_timer_wakeup(uint64_t time_in_us)

Enable wakeup by timer.

Parameters

time_in_us – time before wakeup, in microseconds

Returns

  • ESP_OK on success

  • ESP_ERR_INVALID_ARG if value is out of range (TBD)

bool esp_sleep_is_valid_wakeup_gpio(gpio_num_t gpio_num)

Returns true if a GPIO number is valid for use as wakeup source.

Note

For SoCs with RTC IO capability, this can be any valid RTC IO input pin.

Parameters

gpio_num – Number of the GPIO to test for wakeup source capability

Returns

True if this GPIO number will be accepted as a sleep wakeup source.

esp_err_t esp_deep_sleep_enable_gpio_wakeup(uint64_t gpio_pin_mask, esp_deepsleep_gpio_wake_up_mode_t mode)

Enable wakeup using specific gpio pins.

This function enables an IO pin to wake the chip from deep sleep

Note

This function does not modify pin configuration. The pins are configured inside esp_deep_sleep_start, immediately before entering sleep mode.

Note

You don’t need to worry about pull-up or pull-down resistors before using this function because the ESP_SLEEP_GPIO_ENABLE_INTERNAL_RESISTORS option is enabled by default. It will automatically set pull-up or pull-down resistors internally in esp_deep_sleep_start based on the wakeup mode. However, when using external pull-up or pull-down resistors, please be sure to disable the ESP_SLEEP_GPIO_ENABLE_INTERNAL_RESISTORS option, as the combination of internal and external resistors may cause interference. BTW, when you use low level to wake up the chip, we strongly recommend you to add external resistors (pull-up).

Parameters
  • gpio_pin_mask – Bit mask of GPIO numbers which will cause wakeup. Only GPIOs which have RTC functionality (pads that powered by VDD3P3_RTC) can be used in this bit map.

  • mode – Select logic function used to determine wakeup condition:

    • ESP_GPIO_WAKEUP_GPIO_LOW: wake up when the gpio turn to low.

    • ESP_GPIO_WAKEUP_GPIO_HIGH: wake up when the gpio turn to high.

Returns

  • ESP_OK on success

  • ESP_ERR_INVALID_ARG if the mask contains any invalid deep sleep wakeup pin or wakeup mode is invalid

esp_err_t esp_sleep_enable_gpio_wakeup(void)

Enable wakeup from light sleep using GPIOs.

Each GPIO supports wakeup function, which can be triggered on either low level or high level. Unlike EXT0 and EXT1 wakeup sources, this method can be used both for all IOs: RTC IOs and digital IOs. It can only be used to wakeup from light sleep though.

To enable wakeup, first call gpio_wakeup_enable, specifying gpio number and wakeup level, for each GPIO which is used for wakeup. Then call this function to enable wakeup feature.

Note

On ESP32, GPIO wakeup source can not be used together with touch or ULP wakeup sources.

Returns

  • ESP_OK on success

  • ESP_ERR_INVALID_STATE if wakeup triggers conflict

esp_err_t esp_sleep_enable_uart_wakeup(int uart_num)

Enable wakeup from light sleep using UART.

Use uart_set_wakeup_threshold function to configure UART wakeup threshold.

Wakeup from light sleep takes some time, so not every character sent to the UART can be received by the application.

Note

ESP32 does not support wakeup from UART2.

Parameters

uart_num – UART port to wake up from

Returns

  • ESP_OK on success

  • ESP_ERR_INVALID_ARG if wakeup from given UART is not supported

esp_err_t esp_sleep_enable_wifi_wakeup(void)

Enable wakeup by WiFi MAC.

Returns

  • ESP_OK on success

esp_err_t esp_sleep_disable_wifi_wakeup(void)

Disable wakeup by WiFi MAC.

Returns

  • ESP_OK on success

uint64_t esp_sleep_get_ext1_wakeup_status(void)

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

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

Returns

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

uint64_t esp_sleep_get_gpio_wakeup_status(void)

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

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

Returns

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

esp_err_t esp_sleep_pd_config(esp_sleep_pd_domain_t domain, esp_sleep_pd_option_t option)

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

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

Parameters
  • domain – power domain to configure

  • option – power down option (ESP_PD_OPTION_OFF, ESP_PD_OPTION_ON, or ESP_PD_OPTION_AUTO)

Returns

  • ESP_OK on success

  • ESP_ERR_INVALID_ARG if either of the arguments is out of range

void esp_deep_sleep_start(void)

Enter deep sleep with the configured wakeup options.

This function does not return.

esp_err_t esp_light_sleep_start(void)

Enter light sleep with the configured wakeup options.

Returns

  • ESP_OK on success (returned after wakeup)

  • ESP_ERR_SLEEP_REJECT sleep request is rejected(wakeup source set before the sleep request)

  • ESP_ERR_SLEEP_TOO_SHORT_SLEEP_DURATION after deducting the sleep flow overhead, the final sleep duration is too short to cover the minimum sleep duration of the chip, when rtc timer wakeup source enabled

void esp_deep_sleep(uint64_t time_in_us)

Enter deep-sleep mode.

The device will automatically wake up after the deep-sleep time Upon waking up, the device calls deep sleep wake stub, and then proceeds to load application.

Call to this function is equivalent to a call to esp_deep_sleep_enable_timer_wakeup followed by a call to esp_deep_sleep_start.

esp_deep_sleep does not shut down WiFi, BT, and higher level protocol connections gracefully. Make sure relevant WiFi and BT stack functions are called to close any connections and deinitialize the peripherals. These include:

  • esp_bluedroid_disable

  • esp_bt_controller_disable

  • esp_wifi_stop

This function does not return.

Note

The device will wake up immediately if the deep-sleep time is set to 0

Parameters

time_in_us – deep-sleep time, unit: microsecond

esp_sleep_wakeup_cause_t esp_sleep_get_wakeup_cause(void)

Get the wakeup source which caused wakeup from sleep.

Returns

cause of wake up from last sleep (deep sleep or light sleep)

void esp_wake_deep_sleep(void)

Default stub to run on wake from deep sleep.

Allows for executing code immediately on wake from sleep, before the software bootloader or ESP-IDF app has started up.

This function is weak-linked, so you can implement your own version to run code immediately when the chip wakes from sleep.

See docs/deep-sleep-stub.rst for details.

void esp_set_deep_sleep_wake_stub(esp_deep_sleep_wake_stub_fn_t new_stub)

Install a new stub at runtime to run on wake from deep sleep.

If implementing esp_wake_deep_sleep() then it is not necessary to call this function.

However, it is possible to call this function to substitute a different deep sleep stub. Any function used as a deep sleep stub must be marked RTC_IRAM_ATTR, and must obey the same rules given for esp_wake_deep_sleep().

esp_deep_sleep_wake_stub_fn_t esp_get_deep_sleep_wake_stub(void)

Get current wake from deep sleep stub.

Returns

Return current wake from deep sleep stub, or NULL if no stub is installed.

void esp_default_wake_deep_sleep(void)

The default esp-idf-provided esp_wake_deep_sleep() stub.

See docs/deep-sleep-stub.rst for details.

void esp_deep_sleep_disable_rom_logging(void)

Disable logging from the ROM code after deep sleep.

Using LSB of RTC_STORE4.

esp_err_t esp_sleep_cpu_pd_low_init(bool enable)

CPU Power down low-level initialize.

Parameters

enable – enable or disable CPU power down during light sleep

Returns

  • ESP_OK on success

  • ESP_ERR_NO_MEM not enough retention memory

void esp_sleep_config_gpio_isolate(void)

Configure to isolate all GPIO pins in sleep state.

void esp_sleep_enable_gpio_switch(bool enable)

Enable or disable GPIO pins status switching between slept status and waked status.

Parameters

enable – decide whether to switch status or not

Type Definitions

typedef esp_sleep_source_t esp_sleep_wakeup_cause_t
typedef void (*esp_deep_sleep_wake_stub_fn_t)(void)

Function type for stub to run on wake from sleep.

Enumerations

enum esp_sleep_ext1_wakeup_mode_t

Logic function used for EXT1 wakeup mode.

Values:

enumerator ESP_EXT1_WAKEUP_ANY_LOW

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

enumerator ESP_EXT1_WAKEUP_ANY_HIGH

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

enumerator ESP_EXT1_WAKEUP_ALL_LOW
enum esp_deepsleep_gpio_wake_up_mode_t

Values:

enumerator ESP_GPIO_WAKEUP_GPIO_LOW
enumerator ESP_GPIO_WAKEUP_GPIO_HIGH
enum esp_sleep_pd_domain_t

Power domains which can be powered down in sleep mode.

Values:

enumerator ESP_PD_DOMAIN_RTC_PERIPH

RTC IO, sensors and ULP co-processor.

enumerator ESP_PD_DOMAIN_RTC_SLOW_MEM

RTC slow memory.

enumerator ESP_PD_DOMAIN_RTC_FAST_MEM

RTC fast memory.

enumerator ESP_PD_DOMAIN_XTAL

XTAL oscillator.

enumerator ESP_PD_DOMAIN_CPU

CPU core.

enumerator ESP_PD_DOMAIN_RTC8M

Internal 8M oscillator.

enumerator ESP_PD_DOMAIN_VDDSDIO

VDD_SDIO.

enumerator ESP_PD_DOMAIN_MAX

Number of domains.

enum esp_sleep_pd_option_t

Power down options.

Values:

enumerator ESP_PD_OPTION_OFF

Power down the power domain in sleep mode.

enumerator ESP_PD_OPTION_ON

Keep power domain enabled during sleep mode.

enumerator ESP_PD_OPTION_AUTO

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

enum esp_sleep_source_t

Sleep wakeup cause.

Values:

enumerator ESP_SLEEP_WAKEUP_UNDEFINED

In case of deep sleep, reset was not caused by exit from deep sleep.

enumerator ESP_SLEEP_WAKEUP_ALL

Not a wakeup cause, used to disable all wakeup sources with esp_sleep_disable_wakeup_source.

enumerator ESP_SLEEP_WAKEUP_EXT0

Wakeup caused by external signal using RTC_IO.

enumerator ESP_SLEEP_WAKEUP_EXT1

Wakeup caused by external signal using RTC_CNTL.

enumerator ESP_SLEEP_WAKEUP_TIMER

Wakeup caused by timer.

enumerator ESP_SLEEP_WAKEUP_TOUCHPAD

Wakeup caused by touchpad.

enumerator ESP_SLEEP_WAKEUP_ULP

Wakeup caused by ULP program.

enumerator ESP_SLEEP_WAKEUP_GPIO

Wakeup caused by GPIO (light sleep only on ESP32, S2 and S3)

enumerator ESP_SLEEP_WAKEUP_UART

Wakeup caused by UART (light sleep only)

enumerator ESP_SLEEP_WAKEUP_WIFI

Wakeup caused by WIFI (light sleep only)

enumerator ESP_SLEEP_WAKEUP_COCPU

Wakeup caused by COCPU int.

enumerator ESP_SLEEP_WAKEUP_COCPU_TRAP_TRIG

Wakeup caused by COCPU crash.

enumerator ESP_SLEEP_WAKEUP_BT

Wakeup caused by BT (light sleep only)

enum [anonymous]

Values:

enumerator ESP_ERR_SLEEP_REJECT
enumerator ESP_ERR_SLEEP_TOO_SHORT_SLEEP_DURATION