soc: esp32: add light sleep sample code
Add light sleep sample code. Signed-off-by: Glauber Maroto Ferreira <glauber.ferreira@espressif.com>
This commit is contained in:
parent
9336a267f1
commit
2ad13a50a7
4 changed files with 174 additions and 0 deletions
7
samples/boards/esp32/light_sleep/CMakeLists.txt
Normal file
7
samples/boards/esp32/light_sleep/CMakeLists.txt
Normal file
|
@ -0,0 +1,7 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
cmake_minimum_required(VERSION 3.20.0)
|
||||
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
|
||||
project(esp32_light_sleep)
|
||||
|
||||
target_sources(app PRIVATE src/main.c)
|
70
samples/boards/esp32/light_sleep/README.rst
Normal file
70
samples/boards/esp32/light_sleep/README.rst
Normal file
|
@ -0,0 +1,70 @@
|
|||
.. _esp32-light-sleep-sample:
|
||||
|
||||
ESP32 Light Sleep demo
|
||||
######################
|
||||
|
||||
Overview
|
||||
********
|
||||
|
||||
This example illustrates usage of light sleep mode. Unlike deep sleep mode,
|
||||
light sleep preserves the state of the memory, CPU, and peripherals. Execution
|
||||
of code on both CPUs is stopped when esp_light_sleep_start() function is called.
|
||||
When the chip exits light sleep mode, execution continues at the point where it
|
||||
was stopped, and esp_light_sleep_start() function returns.
|
||||
|
||||
The example enables the following wakeup sources:
|
||||
|
||||
* ``Timer``: wake up the chip in 2 seconds.
|
||||
* ``EXT0``: wake up the chip if a button attached to GPIO0 is pressed (i.e. if
|
||||
GPIO0 goes low).
|
||||
|
||||
Requirements
|
||||
************
|
||||
|
||||
This example can be used with any ESP32 development board. Most boards have a
|
||||
button attached to GPIO0, often labelled BOOT. If the board does not have such
|
||||
button, an external button can be connected, along with a 10k pull-up resistor,
|
||||
and a 100nF capacitor to ground for debouncing.
|
||||
|
||||
Building, Flashing and Running
|
||||
******************************
|
||||
|
||||
.. zephyr-app-commands::
|
||||
:zephyr-app: samples/boards/esp32/light_sleep
|
||||
:board: esp32
|
||||
:goals: build flash
|
||||
:compact:
|
||||
|
||||
Sample Output
|
||||
=================
|
||||
ESP32 core output
|
||||
-----------------
|
||||
|
||||
In the scenario below, the button attached to GPIO0 was pressed and held for
|
||||
about 500 ms, after the second wakeup from light sleep. The program has
|
||||
indicated the wakeup reason after each sleep iteration.
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
*** Booting Zephyr OS build zephyr-v3.1.0-3667-gb42e2b225ecf ***
|
||||
|
||||
Entering light sleep
|
||||
Returned from light sleep, reason: timer, t=3344 ms, slept for 2001 ms
|
||||
Entering light sleep
|
||||
Returned from light sleep, reason: timer, t=5354 ms, slept for 2000 ms
|
||||
Entering light sleep
|
||||
Returned from light sleep, reason: pin, t=5885 ms, slept for 521 ms
|
||||
Waiting for GPIO0 to go high...
|
||||
Entering light sleep
|
||||
Returned from light sleep, reason: timer, t=8765 ms, slept for 2000 ms
|
||||
Entering light sleep
|
||||
Returned from light sleep, reason: timer, t=10776 ms, slept for 2001 ms
|
||||
Entering light sleep
|
||||
|
||||
Troubleshooting
|
||||
***************
|
||||
|
||||
If pressing the button attached to GPIO0 does not affect program behavior,
|
||||
check DTR/RTS configuration in the serial monitor. This is not necessary for
|
||||
IDF monitor, but for other tools it might be necessary to set DTR and RTS line
|
||||
state to "disabled" or "de-asserted".
|
3
samples/boards/esp32/light_sleep/prj.conf
Normal file
3
samples/boards/esp32/light_sleep/prj.conf
Normal file
|
@ -0,0 +1,3 @@
|
|||
CONFIG_PM=y
|
||||
# Required to disable default behavior of deep sleep on timeout
|
||||
CONFIG_PM_DEVICE=y
|
94
samples/boards/esp32/light_sleep/src/main.c
Normal file
94
samples/boards/esp32/light_sleep/src/main.c
Normal file
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* Copyright (c) 2022 Espressif Systems (Shanghai) Co., Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/pm/pm.h>
|
||||
#include <zephyr/pm/device.h>
|
||||
#include <zephyr/pm/policy.h>
|
||||
#include <zephyr/drivers/gpio.h>
|
||||
#include "esp_sleep.h"
|
||||
|
||||
/* Most development boards have "boot" button attached to GPIO0.
|
||||
* You can also change this to another pin.
|
||||
*/
|
||||
#define SW0_NODE DT_ALIAS(sw0)
|
||||
|
||||
#if !DT_NODE_HAS_STATUS(SW0_NODE, okay)
|
||||
#error "unsupported board: sw0 devicetree alias is not defined"
|
||||
#endif
|
||||
|
||||
/* Add an extra delay when sleeping to make sure that light sleep
|
||||
* is chosen.
|
||||
*/
|
||||
#define LIGHT_SLP_EXTRA_DELAY (50UL)
|
||||
|
||||
static const struct gpio_dt_spec button =
|
||||
GPIO_DT_SPEC_GET_OR(SW0_NODE, gpios, {0});
|
||||
|
||||
void main(void)
|
||||
{
|
||||
if (!device_is_ready(button.port)) {
|
||||
printk("Error: button device %s is not ready\n", button.port->name);
|
||||
return;
|
||||
}
|
||||
|
||||
const int wakeup_level = (button.dt_flags & GPIO_ACTIVE_LOW) ? 0 : 1;
|
||||
|
||||
esp_gpio_wakeup_enable(button.pin,
|
||||
wakeup_level == 0 ? GPIO_INTR_LOW_LEVEL : GPIO_INTR_HIGH_LEVEL);
|
||||
|
||||
while (true) {
|
||||
/* Wake up in 2 seconds, or when button is pressed */
|
||||
esp_sleep_enable_timer_wakeup(2000000);
|
||||
esp_sleep_enable_gpio_wakeup();
|
||||
|
||||
/* Wait until GPIO goes high */
|
||||
if (gpio_pin_get_dt(&button) == wakeup_level) {
|
||||
printk("Waiting for GPIO%d to go high...\n", button.pin);
|
||||
do {
|
||||
k_busy_wait(10000);
|
||||
} while (gpio_pin_get_dt(&button) == wakeup_level);
|
||||
}
|
||||
|
||||
printk("Entering light sleep\n");
|
||||
/* To make sure the complete line is printed before entering sleep mode,
|
||||
* need to wait until UART TX FIFO is empty
|
||||
*/
|
||||
k_busy_wait(10000);
|
||||
|
||||
/* Get timestamp before entering sleep */
|
||||
int64_t t_before_ms = k_uptime_get();
|
||||
|
||||
/* Sleep triggers the idle thread, which makes the pm subsystem select some
|
||||
* pre-defined power state. Light sleep is used here because there is enough
|
||||
* time to consider it, energy-wise, worthy.
|
||||
*/
|
||||
k_sleep(K_USEC(DT_PROP(DT_NODELABEL(light_sleep), min_residency_us) +
|
||||
LIGHT_SLP_EXTRA_DELAY));
|
||||
/* Execution continues here after wakeup */
|
||||
|
||||
/* Get timestamp after waking up from sleep */
|
||||
int64_t t_after_ms = k_uptime_get();
|
||||
|
||||
/* Determine wake up reason */
|
||||
const char *wakeup_reason;
|
||||
|
||||
switch (esp_sleep_get_wakeup_cause()) {
|
||||
case ESP_SLEEP_WAKEUP_TIMER:
|
||||
wakeup_reason = "timer";
|
||||
break;
|
||||
case ESP_SLEEP_WAKEUP_GPIO:
|
||||
wakeup_reason = "pin";
|
||||
break;
|
||||
default:
|
||||
wakeup_reason = "other";
|
||||
break;
|
||||
}
|
||||
|
||||
printk("Returned from light sleep, reason: %s, t=%lld ms, slept for %lld ms\n",
|
||||
wakeup_reason, t_after_ms, (t_after_ms - t_before_ms));
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue