add example deep sleep wake stub
This commit is contained in:
@@ -42,6 +42,12 @@ examples/system/deep_sleep:
|
||||
temporary: true
|
||||
reason: target(s) not supported yet
|
||||
|
||||
examples/system/deep_sleep_wake_stub:
|
||||
disable:
|
||||
- if: IDF_TARGET in ["esp32c2", "esp32c6", "esp32h2"]
|
||||
temporary: true
|
||||
reason: target(s) is not supported yet
|
||||
|
||||
examples/system/efuse:
|
||||
disable_test:
|
||||
- if: IDF_TARGET == "esp32s3"
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
# The following lines of boilerplate have to be in your project's CMakeLists
|
||||
# in this exact order for cmake to work correctly
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(deep_sleep_wake_stub)
|
||||
@@ -0,0 +1,75 @@
|
||||
| Supported Targets | ESP32 | ESP32-C3 | ESP32-S2 | ESP32-S3 |
|
||||
| ----------------- | ----- | -------- | -------- | -------- |
|
||||
|
||||
# Deep Sleep Wake Stub Example
|
||||
|
||||
(See the README.md file in the upper level 'examples' directory for more information about examples.)
|
||||
|
||||
The [Deep-sleep wake stub](https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/deep-sleep-stub.html) is used to RTC fast boot mode that avoid the SPI flash booting, thus speeding up the wakeup process. This example demonstrates how to implement the wake stub.
|
||||
|
||||
In this example, the `CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP` Kconfig option is used, which allows you to reduce the boot time of the bootloader during waking up from deep sleep. The bootloader stores in rtc memory the address of a running partition and uses it when it wakes up. This example allows you to skip all image checks and speed up the boot.
|
||||
|
||||
## How to use example
|
||||
|
||||
### Hardware Required
|
||||
|
||||
This example should be able to run on any commonly available ESP32/ESP32-S2/ESP32-S3/ESP32-C3 development board without any extra hardware if only **Timer** wake up sources are used.
|
||||
|
||||
### Configure the project
|
||||
|
||||
|
||||
```
|
||||
idf.py menuconfig
|
||||
```
|
||||
|
||||
* **Wake up time** can be configured via `Example configuration > Wake up interval in seconds`
|
||||
Wake up sources that are unused or unconnected should be disabled in configuration to prevent inadvertent triggering of wake up as a result of floating pins.
|
||||
|
||||
|
||||
### Build and Flash
|
||||
|
||||
Build the project and flash it to the board, then run monitor tool to view serial output:
|
||||
|
||||
```
|
||||
idf.py -p PORT flash monitor
|
||||
```
|
||||
|
||||
(Replace PORT with the name of the serial port to use.)
|
||||
|
||||
(To exit the serial monitor, type ``Ctrl-]``.)
|
||||
|
||||
See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects.
|
||||
|
||||
## Example Output
|
||||
|
||||
On initial startup, this example will detect that this is the first boot and output the following log:
|
||||
|
||||
```
|
||||
...
|
||||
I (309) cpu_start: Starting scheduler on PRO CPU.
|
||||
I (0) cpu_start: Starting scheduler on APP CPU.
|
||||
Not a deep sleep reset
|
||||
Enabling timer wakeup, 10s
|
||||
Entering deep sleep
|
||||
```
|
||||
|
||||
The ESP chips will then enter deep sleep. When a timer wake up occurs, if deep sleep wake stub enabled, the ESP chips will boot from RTC memory and execute stub code. The output log such as the following:
|
||||
|
||||
```
|
||||
...
|
||||
ESP-ROM:esp32s3-20210327
|
||||
Build:Mar 27 2021
|
||||
rst:0x5 (DSLEEP),boot:0x8 (SPI_FAST_FLASH_BOOT)
|
||||
wake stub: wakeup count is 1, wakeup cause is 8
|
||||
wake stub: going to deep sleep
|
||||
ESP-ROM:esp32s3-20210327
|
||||
Build:Mar 27 2021
|
||||
rst:0x5 (DSLEEP),boot:0x8 (SPI_FAST_FLASH_BOOT)
|
||||
wake stub: wakeup count is 2, wakeup cause is 8
|
||||
wake stub: going to deep sleep
|
||||
ESP-ROM:esp32s3-20210327
|
||||
Build:Mar 27 2021
|
||||
rst:0x5 (DSLEEP),boot:0x8 (SPI_FAST_FLASH_BOOT)
|
||||
wake stub: wakeup count is 3, wakeup cause is 8
|
||||
wake stub: going to deep sleep
|
||||
```
|
||||
@@ -0,0 +1,3 @@
|
||||
idf_component_register(SRCS "wake_stub_example_main.c"
|
||||
"rtc_wake_stub_example.c"
|
||||
INCLUDE_DIRS ".")
|
||||
@@ -0,0 +1,10 @@
|
||||
menu "Example Configuration"
|
||||
|
||||
config WAKE_UP_TIME
|
||||
int "Wake up interval in seconds"
|
||||
default 10
|
||||
range 1 60
|
||||
help
|
||||
Configurable wake up interval in seconds.
|
||||
|
||||
endmenu
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include "esp_sleep.h"
|
||||
#include "esp_wake_stub.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
/*
|
||||
* Deep sleep wake stub function is a piece of code that will be loaded into 'RTC Fast Memory'.
|
||||
* The first way is to use the RTC_IRAM_ATTR attribute to place a function into RTC memory,
|
||||
* The second way is to place the function into any source file whose name starts with rtc_wake_stub.
|
||||
* Files names rtc_wake_stub* have their contents automatically put into RTC memory by the linker.
|
||||
*
|
||||
* First, call esp_set_deep_sleep_wake_stub to set the wake stub function as the RTC stub entry,
|
||||
* The wake stub function runs immediately as soon as the chip wakes up - before any normal
|
||||
* initialisation, bootloader, or ESP-IDF code has run. After the wake stub runs, the SoC
|
||||
* can go back to sleep or continue to start ESP-IDF normally.
|
||||
*
|
||||
* Wake stub code must be carefully written, there are some rules for wake stub:
|
||||
* 1) The wake stub code can only access data loaded in RTC memory.
|
||||
* 2) The wake stub code can only call functions implemented in ROM or loaded into RTC Fast Memory.
|
||||
* 3) RTC memory must include any read-only data (.rodata) used by the wake stub.
|
||||
*/
|
||||
|
||||
// counter value, stored in RTC memory
|
||||
static uint32_t s_count = 0;
|
||||
static const uint32_t s_max_count = 20;
|
||||
|
||||
// wakeup_cause stored in RTC memory
|
||||
static uint32_t wakeup_cause;
|
||||
|
||||
// wake up stub function stored in RTC memory
|
||||
void wake_stub_example(void)
|
||||
{
|
||||
// Get wakeup cause.
|
||||
wakeup_cause = esp_wake_stub_get_wakeup_cause();
|
||||
// Increment the counter.
|
||||
s_count++;
|
||||
// Print the counter value and wakeup cause.
|
||||
ESP_RTC_LOGI("wake stub: wakeup count is %d, wakeup cause is %d", s_count, wakeup_cause);
|
||||
|
||||
if (s_count >= s_max_count) {
|
||||
// Reset s_count
|
||||
s_count = 0;
|
||||
|
||||
// Set the default wake stub.
|
||||
// There is a default version of this function provided in esp-idf.
|
||||
esp_default_wake_deep_sleep();
|
||||
|
||||
// Return from the wake stub function to continue
|
||||
// booting the firmware.
|
||||
return;
|
||||
}
|
||||
// s_count is < s_max_count, go back to deep sleep.
|
||||
|
||||
// Set wakeup time in stub, if need to check GPIOs or read some sensor periodically in the stub.
|
||||
esp_wake_stub_set_wakeup_time(CONFIG_WAKE_UP_TIME*1000000);
|
||||
|
||||
// Print status.
|
||||
ESP_RTC_LOGI("wake stub: going to deep sleep");
|
||||
|
||||
// Set stub entry, then going to deep sleep again.
|
||||
esp_wake_stub_sleep(&wake_stub_example);
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void wake_stub_example(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_sleep.h"
|
||||
#include "esp_wake_stub.h"
|
||||
#include "driver/rtc_io.h"
|
||||
#include "rtc_wake_stub_example.h"
|
||||
|
||||
// sleep_enter_time stored in RTC memory
|
||||
static RTC_DATA_ATTR struct timeval sleep_enter_time;
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
struct timeval now;
|
||||
gettimeofday(&now, NULL);
|
||||
int sleep_time_ms = (now.tv_sec - sleep_enter_time.tv_sec) * 1000 + (now.tv_usec - sleep_enter_time.tv_usec) / 1000;
|
||||
|
||||
if (esp_sleep_get_wakeup_cause() == ESP_SLEEP_WAKEUP_TIMER) {
|
||||
printf("Wake up from timer. Time spent in deep sleep: %dms\n", sleep_time_ms);
|
||||
}
|
||||
|
||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
|
||||
const int wakeup_time_sec = CONFIG_WAKE_UP_TIME;
|
||||
printf("Enabling timer wakeup, %ds\n", wakeup_time_sec);
|
||||
esp_sleep_enable_timer_wakeup(wakeup_time_sec * 1000000);
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
// Isolate GPIO12 pin from external circuits. This is needed for modules
|
||||
// which have an external pull-up resistor on GPIO12 (such as ESP32-WROVER)
|
||||
// to minimize current consumption.
|
||||
rtc_gpio_isolate(GPIO_NUM_12);
|
||||
#endif
|
||||
|
||||
// Set the wake stub function
|
||||
esp_set_deep_sleep_wake_stub(&wake_stub_example);
|
||||
|
||||
printf("Entering deep sleep\n");
|
||||
gettimeofday(&sleep_enter_time, NULL);
|
||||
|
||||
esp_deep_sleep_start();
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP=y
|
||||
Reference in New Issue
Block a user