Merge branch 'feature/esp32c3_uart_add_wakeup_event' into 'master'

UART: add uart wakeup event for esp32c3 and esp32s3

Closes IDF-3416

See merge request espressif/esp-idf!14482
This commit is contained in:
Michael (XIAO Xufeng) 2022-02-04 17:23:29 +00:00
commit c1b30491dd
27 changed files with 413 additions and 159 deletions

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -58,6 +58,9 @@ typedef enum {
UART_PARITY_ERR, /*!< UART RX parity event*/
UART_DATA_BREAK, /*!< UART TX data and break event*/
UART_PATTERN_DET, /*!< UART pattern detected */
#if SOC_UART_SUPPORT_WAKEUP_INT
UART_WAKEUP, /*!< UART wakeup event */
#endif
UART_EVENT_MAX, /*!< UART event max index*/
} uart_event_type_t;

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -47,11 +47,20 @@ static const char *UART_TAG = "uart";
#define UART_PATTERN_DET_QLEN_DEFAULT (10)
#define UART_MIN_WAKEUP_THRESH (UART_LL_MIN_WAKEUP_THRESH)
#if SOC_UART_SUPPORT_WAKEUP_INT
#define UART_INTR_CONFIG_FLAG ((UART_INTR_RXFIFO_FULL) \
| (UART_INTR_RXFIFO_TOUT) \
| (UART_INTR_RXFIFO_OVF) \
| (UART_INTR_BRK_DET) \
| (UART_INTR_PARITY_ERR)) \
| (UART_INTR_WAKEUP)
#else
#define UART_INTR_CONFIG_FLAG ((UART_INTR_RXFIFO_FULL) \
| (UART_INTR_RXFIFO_TOUT) \
| (UART_INTR_RXFIFO_OVF) \
| (UART_INTR_BRK_DET) \
| (UART_INTR_PARITY_ERR))
#endif
#define UART_ENTER_CRITICAL_ISR(mux) portENTER_CRITICAL_ISR(mux)
#define UART_EXIT_CRITICAL_ISR(mux) portEXIT_CRITICAL_ISR(mux)
@ -1058,7 +1067,14 @@ static void UART_ISR_ATTR uart_rx_intr_handler_default(void *param)
uart_hal_clr_intsts_mask(&(uart_context[uart_num].hal), UART_INTR_TX_DONE);
xSemaphoreGiveFromISR(p_uart_obj[uart_num]->tx_done_sem, &HPTaskAwoken);
}
} else {
}
#if SOC_UART_SUPPORT_WAKEUP_INT
else if (uart_intr_status & UART_INTR_WAKEUP) {
uart_hal_clr_intsts_mask(&(uart_context[uart_num].hal), UART_INTR_WAKEUP);
uart_event.type = UART_WAKEUP;
}
#endif
else {
uart_hal_clr_intsts_mask(&(uart_context[uart_num].hal), uart_intr_status); /*simply clear all other intr status*/
uart_event.type = UART_EVENT_MAX;
}

View File

@ -48,6 +48,7 @@ typedef enum {
UART_INTR_RS485_FRM_ERR = (0x1 << 16),
UART_INTR_RS485_CLASH = (0x1 << 17),
UART_INTR_CMD_CHAR_DET = (0x1 << 18),
UART_INTR_WAKEUP = (0x1 << 19),
} uart_intr_t;
static inline void uart_ll_reset_core(uart_dev_t *hw) {

View File

@ -1,16 +1,8 @@
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
// The LL layer for UART register operations.
// Note that most of the register operations in this layer are non-atomic operations.
@ -59,6 +51,7 @@ typedef enum {
UART_INTR_RS485_FRM_ERR = (0x1 << 16),
UART_INTR_RS485_CLASH = (0x1 << 17),
UART_INTR_CMD_CHAR_DET = (0x1 << 18),
UART_INTR_WAKEUP = (0x1 << 19),
} uart_intr_t;
static inline void uart_ll_set_reset_core(uart_dev_t *hw, bool core_rst_en) {

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -51,6 +51,7 @@ typedef enum {
UART_INTR_RS485_FRM_ERR = (0x1 << 16),
UART_INTR_RS485_CLASH = (0x1 << 17),
UART_INTR_CMD_CHAR_DET = (0x1 << 18),
UART_INTR_WAKEUP = (0x1 << 19),
} uart_intr_t;
static inline void uart_ll_set_reset_core(uart_dev_t *hw, bool core_rst_en) {

View File

@ -1,16 +1,8 @@
// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/*
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
// The LL layer for UART register operations.
// Note that most of the register operations in this layer are non-atomic operations.
@ -57,6 +49,7 @@ typedef enum {
UART_INTR_RS485_FRM_ERR = (0x1<<16),
UART_INTR_RS485_CLASH = (0x1<<17),
UART_INTR_CMD_CHAR_DET = (0x1<<18),
UART_INTR_WAKEUP = (0x1 << 19),
} uart_intr_t;
/**

View File

@ -1,16 +1,8 @@
// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/*
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
// The LL layer for UART register operations.
// Note that most of the register operations in this layer are non-atomic operations.
@ -60,6 +52,7 @@ typedef enum {
UART_INTR_RS485_FRM_ERR = (0x1 << 16),
UART_INTR_RS485_CLASH = (0x1 << 17),
UART_INTR_CMD_CHAR_DET = (0x1 << 18),
UART_INTR_WAKEUP = (0x1 << 19),
} uart_intr_t;

View File

@ -467,6 +467,10 @@ config SOC_UART_BITRATE_MAX
int
default 5000000
config SOC_UART_SUPPORT_WAKEUP_INT
bool
default y
config SOC_UART_SUPPORT_RTC_CLK
bool
default y

View File

@ -250,7 +250,7 @@
#define SOC_UART_NUM (2)
#define SOC_UART_FIFO_LEN (128) /*!< The UART hardware FIFO length */
#define SOC_UART_BITRATE_MAX (5000000) /*!< Max bit rate supported by UART */
#define SOC_UART_SUPPORT_WAKEUP_INT (1) /*!< Support UART wakeup interrupt */
#define SOC_UART_SUPPORT_RTC_CLK (1)
#define SOC_UART_SUPPORT_XTAL_CLK (1)

View File

@ -591,6 +591,10 @@ config SOC_UART_SUPPORT_XTAL_CLK
bool
default y
config SOC_UART_SUPPORT_WAKEUP_INT
bool
default y
config SOC_UART_REQUIRE_CORE_RESET
bool
default y

View File

@ -290,6 +290,7 @@
#define SOC_UART_SUPPORT_RTC_CLK (1)
#define SOC_UART_SUPPORT_XTAL_CLK (1)
#define SOC_UART_SUPPORT_WAKEUP_INT (1) /*!< Support UART wakeup interrupt */
#define SOC_UART_REQUIRE_CORE_RESET (1)
// UART has an extra TX_WAIT_SEND state when the FIFO is not empty and XOFF is enabled

View File

@ -563,6 +563,10 @@ config SOC_UART_BITRATE_MAX
int
default 5000000
config SOC_UART_SUPPORT_WAKEUP_INT
bool
default y
config SOC_UART_SUPPORT_RTC_CLK
bool
default y

View File

@ -281,7 +281,7 @@
#define SOC_UART_NUM (2)
#define SOC_UART_FIFO_LEN (128) /*!< The UART hardware FIFO length */
#define SOC_UART_BITRATE_MAX (5000000) /*!< Max bit rate supported by UART */
#define SOC_UART_SUPPORT_WAKEUP_INT (1) /*!< Support UART wakeup interrupt */
#define SOC_UART_SUPPORT_RTC_CLK (1)
#define SOC_UART_SUPPORT_XTAL_CLK (1)

View File

@ -583,6 +583,10 @@ config SOC_UART_NUM
int
default 2
config SOC_UART_SUPPORT_WAKEUP_INT
bool
default y
config SOC_UART_SUPPORT_REF_TICK
bool
default y

View File

@ -277,6 +277,7 @@
/*-------------------------- UART CAPS ---------------------------------------*/
// ESP32-S2 has 2 UART.
#define SOC_UART_NUM (2)
#define SOC_UART_SUPPORT_WAKEUP_INT (1) /*!< Support UART wakeup interrupt */
#define SOC_UART_SUPPORT_REF_TICK (1) /*!< Support REF_TICK as the clock source */
#define SOC_UART_FIFO_LEN (128) /*!< The UART hardware FIFO length */
#define SOC_UART_BITRATE_MAX (5000000) /*!< Max bit rate supported by UART */

View File

@ -667,6 +667,26 @@ config SOC_TOUCH_PAD_MEASURE_WAIT_MAX
hex
default 0xFF
config SOC_UART_NUM
int
default 3
config SOC_UART_FIFO_LEN
int
default 128
config SOC_UART_BITRATE_MAX
int
default 5000000
config SOC_UART_SUPPORT_FSM_TX_WAIT_SEND
bool
default y
config SOC_UART_SUPPORT_WAKEUP_INT
bool
default y
config SOC_UART_SUPPORT_RTC_CLK
bool
default y
@ -846,19 +866,3 @@ config SOC_TWAI_BRP_MAX
config SOC_TWAI_SUPPORTS_RX_STATUS
bool
default y
config SOC_UART_FIFO_LEN
int
default 128
config SOC_UART_BITRATE_MAX
int
default 5000000
config SOC_UART_NUM
int
default 3
config SOC_UART_SUPPORT_FSM_TX_WAIT_SEND
bool
default y

View File

@ -264,8 +264,13 @@
#include "twai_caps.h"
/*-------------------------- UART CAPS ---------------------------------------*/
#include "uart_caps.h"
// ESP32-S3 has 3 UARTs
#define SOC_UART_NUM (3)
#define SOC_UART_FIFO_LEN (128) /*!< The UART hardware FIFO length */
#define SOC_UART_BITRATE_MAX (5000000) /*!< Max bit rate supported by UART */
// UART has an extra TX_WAIT_SEND state when the FIFO is not empty and XOFF is enabled
#define SOC_UART_SUPPORT_FSM_TX_WAIT_SEND (1)
#define SOC_UART_SUPPORT_WAKEUP_INT (1) /*!< Support UART wakeup interrupt */
#define SOC_UART_SUPPORT_RTC_CLK (1) /*!< Support RTC clock as the clock source */
#define SOC_UART_SUPPORT_XTAL_CLK (1) /*!< Support XTAL clock as the clock source */

View File

@ -1,31 +0,0 @@
// Copyright 2010-2020 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#define SOC_UART_FIFO_LEN (128) /*!< The UART hardware FIFO length */
#define SOC_UART_BITRATE_MAX (5000000) /*!< Max bit rate supported by UART */
#define SOC_UART_NUM (3)
// UART has an extra TX_WAIT_SEND state when the FIFO is not empty and XOFF is enabled
#define SOC_UART_SUPPORT_FSM_TX_WAIT_SEND (1)
#ifdef __cplusplus
}
#endif

View File

@ -8,6 +8,7 @@ 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)
- UART0: wake up the chip when the uart rx pin (default GPIO6) receive more than 3 edges.
The example also prints time spent in light sleep mode to illustrate that timekeeping continues while the chip is in light sleep.
@ -39,19 +40,47 @@ See the Getting Started Guide for full steps to configure and use ESP-IDF to bui
## Example Output
### Wake-up by Timer
If do nothing to the example, the chip will wake-up every 2000 ms by timer, and fall into light sleep again after print some logs. We can see the wake-up reason is `timer` in this case.
### Wake-up by GPIO
For this example, the wake-up GPIO is bound to the 'BOOT' button on the board, we can wake-up the chip from light sleep by pressing the 'BOOT' button, the chip will wake-up immediately after we pressed the button. We can see the wake-up reason is `pin` in this case and the chip will fall into light sleep again if we release the button.
### Wake-up by UART
For this example, the wake-up UART is bound to the default console port (UART_NUM_0), we can wake-up the chip from light sleep by inputting some keys on the key board. We can see the wake-up reason is `uart` in this case.
Note #1: the UART wake-up threshould is set to 3 in this example, which means the ascii code of the input character should has at least 3 edges, for example, the ascii code of character `0` is `0011 0000` in binary, which only contains 2 edges, so the character `0` is not enough to wakeup the chip.
Note #2: only UART0 and UART1 (if has) are supported to be configured as wake up source. And for ESP32, we have to use iomux pin for RX signal (i.e. GPIO3 for UART0 & GPIO9 for UART1), otherwise it won't success.
Note #3: due to limitation of the HW, the bytes that received during light sleep is only used for waking up, and it will not be received by UART peripheral or passed to the driver.
```
Entering light sleep
Returned from light sleep, reason: timer, t=2014 ms, slept for 2000 ms
Returned from light sleep, reason: timer, t=2713 ms, slept for 1999 ms
Entering light sleep
Returned from light sleep, reason: timer, t=4023 ms, slept for 2000 ms
Returned from light sleep, reason: timer, t=4722 ms, slept for 2000 ms
Entering light sleep
Returned from light sleep, reason: pin, t=5297 ms, slept for 1266 ms
Waiting for GPIO0 to go high...
Returned from light sleep, reason: uart, t=5148 ms, slept for 418 ms
Entering light sleep
Returned from light sleep, reason: timer, t=10072 ms, slept for 2000 ms
Returned from light sleep, reason: uart, t=6178 ms, slept for 1022 ms
Entering light sleep
Returned from light sleep, reason: timer, t=12080 ms, slept for 2000 ms
Returned from light sleep, reason: timer, t=8187 ms, slept for 2000 ms
Entering light sleep
Returned from light sleep, reason: timer, t=10195 ms, slept for 2000 ms
Entering light sleep
Returned from light sleep, reason: timer, t=12203 ms, slept for 2000 ms
Entering light sleep
Returned from light sleep, reason: pin, t=12555 ms, slept for 342 ms
Waiting for GPIO9 to go high...
Entering light sleep
Returned from light sleep, reason: pin, t=12564 ms, slept for 1 ms
Waiting for GPIO9 to go high...
Entering light sleep
...
```
In the scenario above, the button attached to GPIO0 was pressed and held for about 3 seconds, after the 2nd wakeup from light sleep. The program has indicated the wakeup reason after each sleep iteration.

View File

@ -12,7 +12,7 @@ WAITING_FOR_GPIO_STR = re.compile(r'Waiting for GPIO\d to go high...')
WAKEUP_INTERVAL_MS = 2000
@ttfw_idf.idf_example_test(env_tag='Example_GENERIC', target=['esp32', 'esp32c3'])
@ttfw_idf.idf_example_test(env_tag='Example_GENERIC', target=['esp32', 'esp32s2', 'esp32c3', 'esp32s3'])
def test_examples_system_light_sleep(env, extra_data):
dut = env.get_dut('light_sleep_example', 'examples/system/light_sleep')
dut.start_app()
@ -32,7 +32,7 @@ def test_examples_system_light_sleep(env, extra_data):
groups = dut.expect(EXIT_SLEEP_REGEX)
print('Got second sleep period, wakeup from {}, slept for {}'.format(groups[0], groups[2]))
# sleep time error should be less than 1ms
assert(groups[0] == 'timer' and int(groups[2]) == WAKEUP_INTERVAL_MS)
assert(groups[0] == 'timer' and int(groups[2]) >= WAKEUP_INTERVAL_MS - 1 and int(groups[2]) <= WAKEUP_INTERVAL_MS + 1)
# this time we'll test gpio wakeup
dut.expect(ENTERING_SLEEP_STR)
@ -49,8 +49,17 @@ def test_examples_system_light_sleep(env, extra_data):
dut.port_inst.setDTR(False)
dut.expect(ENTERING_SLEEP_STR)
print('Went to sleep again')
# Write 'U' to uart, 'U' in ascii is 0x55 which contains 8 edges in total
dut.write('U')
time.sleep(1)
groups = dut.expect(EXIT_SLEEP_REGEX)
assert(groups[0] == 'timer' and int(groups[2]) == WAKEUP_INTERVAL_MS)
print('Got third sleep period, wakeup from {}, slept for {}'.format(groups[0], groups[2]))
assert(groups[0] == 'uart' and int(groups[2]) < WAKEUP_INTERVAL_MS)
print('Went to sleep again')
groups = dut.expect(EXIT_SLEEP_REGEX)
assert(groups[0] == 'timer' and int(groups[2]) >= WAKEUP_INTERVAL_MS - 1 and int(groups[2]) <= WAKEUP_INTERVAL_MS + 1)
print('Woke up from timer again')

View File

@ -1,2 +1,7 @@
idf_component_register(SRCS "light_sleep_example_main.c"
INCLUDE_DIRS ".")
set(srcs "light_sleep_example_main.c"
"gpio_wakeup.c"
"timer_wakeup.c"
"uart_wakeup.c")
idf_component_register(SRCS ${srcs}
INCLUDE_DIRS ".")

View File

@ -0,0 +1,58 @@
/*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_check.h"
#include "esp_sleep.h"
#include "driver/gpio.h"
/* Most development boards have "boot" button attached to GPIO0.
* You can also change this to another pin.
*/
#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32H2
#define BOOT_BUTTON_NUM 9
#else
#define BOOT_BUTTON_NUM 0
#endif
/* Use boot button as gpio input */
#define GPIO_WAKEUP_NUM BOOT_BUTTON_NUM
/* "Boot" button is active low */
#define GPIO_WAKEUP_LEVEL 0
static const char *TAG = "gpio_wakeup";
void example_wait_gpio_inactive(void)
{
printf("Waiting for GPIO%d to go high...\n", GPIO_WAKEUP_NUM);
while (gpio_get_level(GPIO_WAKEUP_NUM) == GPIO_WAKEUP_LEVEL) {
vTaskDelay(pdMS_TO_TICKS(10));
}
}
esp_err_t example_register_gpio_wakeup(void)
{
/* Initialize GPIO */
gpio_config_t config = {
.pin_bit_mask = BIT64(GPIO_WAKEUP_NUM),
.mode = GPIO_MODE_INPUT,
.pull_down_en = false,
.pull_up_en = false,
.intr_type = GPIO_INTR_DISABLE
};
ESP_RETURN_ON_ERROR(gpio_config(&config), TAG, "Initialize GPIO%d failed", GPIO_WAKEUP_NUM);
/* Enable wake up from GPIO */
ESP_RETURN_ON_ERROR(gpio_wakeup_enable(GPIO_WAKEUP_NUM, GPIO_WAKEUP_LEVEL == 0 ? GPIO_INTR_LOW_LEVEL : GPIO_INTR_HIGH_LEVEL),
TAG, "Enable gpio wakeup failed");
ESP_RETURN_ON_ERROR(esp_sleep_enable_gpio_wakeup(), TAG, "Configure gpio as wakeup source failed");
/* Make sure the GPIO is inactive and it won't trigger wakeup immediately */
example_wait_gpio_inactive();
ESP_LOGI(TAG, "gpio wakeup source is ready");
return ESP_OK;
}

View File

@ -0,0 +1,23 @@
/*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
void example_wait_gpio_inactive(void);
esp_err_t example_register_gpio_wakeup(void);
esp_err_t example_register_timer_wakeup(void);
esp_err_t example_register_uart_wakeup(void);
#ifdef __cplusplus
}
#endif

View File

@ -1,11 +1,8 @@
/* Light sleep example
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
/*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
#include <stdio.h>
#include <string.h>
@ -14,50 +11,14 @@
#include <sys/time.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/uart.h"
#include "esp_sleep.h"
#include "esp_log.h"
#include "driver/uart.h"
#include "driver/gpio.h"
#include "esp_timer.h"
#include "light_sleep_example.h"
/* Most development boards have "boot" button attached to GPIO0.
* You can also change this to another pin.
*/
#if CONFIG_IDF_TARGET_ESP32C3
#define BUTTON_GPIO_NUM_DEFAULT 9
#else
#define BUTTON_GPIO_NUM_DEFAULT 0
#endif
/* "Boot" button is active low */
#define BUTTON_WAKEUP_LEVEL_DEFAULT 0
void app_main(void)
static void light_sleep_task(void *args)
{
/* Configure the button GPIO as input, enable wakeup */
const int button_gpio_num = BUTTON_GPIO_NUM_DEFAULT;
const int wakeup_level = BUTTON_WAKEUP_LEVEL_DEFAULT;
gpio_config_t config = {
.pin_bit_mask = BIT64(button_gpio_num),
.mode = GPIO_MODE_INPUT
};
ESP_ERROR_CHECK(gpio_config(&config));
gpio_wakeup_enable(button_gpio_num,
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_get_level(button_gpio_num) == wakeup_level) {
printf("Waiting for GPIO%d to go high...\n", button_gpio_num);
do {
vTaskDelay(pdMS_TO_TICKS(10));
} while (gpio_get_level(button_gpio_num) == wakeup_level);
}
printf("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:
@ -69,7 +30,6 @@ void app_main(void)
/* Enter sleep mode */
esp_light_sleep_start();
/* Execution continues here after wakeup */
/* Get timestamp after waking up from sleep */
int64_t t_after_us = esp_timer_get_time();
@ -83,13 +43,34 @@ void app_main(void)
case ESP_SLEEP_WAKEUP_GPIO:
wakeup_reason = "pin";
break;
case ESP_SLEEP_WAKEUP_UART:
wakeup_reason = "uart";
/* Hang-up for a while to switch and execuse the uart task
* Otherwise the chip may fall sleep again before running uart task */
vTaskDelay(1);
break;
default:
wakeup_reason = "other";
break;
}
printf("Returned from light sleep, reason: %s, t=%lld ms, slept for %lld ms\n",
wakeup_reason, t_after_us / 1000, (t_after_us - t_before_us) / 1000);
if (esp_sleep_get_wakeup_cause() == ESP_SLEEP_WAKEUP_GPIO) {
/* Waiting for the gpio inactive, or the chip will continously trigger wakeup*/
example_wait_gpio_inactive();
}
}
vTaskDelete(NULL);
}
void app_main(void)
{
/* Enable wakeup from light sleep by gpio */
example_register_gpio_wakeup();
/* Enable wakeup from light sleep by timer */
example_register_timer_wakeup();
/* Enable wakeup from light sleep by uart */
example_register_uart_wakeup();
xTaskCreate(light_sleep_task, "light_sleep_task", 4096, NULL, 6, NULL);
}

View File

@ -0,0 +1,18 @@
/*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
#include "esp_check.h"
#include "esp_sleep.h"
#define TIMER_WAKEUP_TIME_US (2 * 1000 * 1000)
static const char *TAG = "timer_wakeup";
esp_err_t example_register_timer_wakeup(void)
{
ESP_RETURN_ON_ERROR(esp_sleep_enable_timer_wakeup(TIMER_WAKEUP_TIME_US), TAG, "Configure timer as wakeup source failed");
ESP_LOGI(TAG, "timer wakeup source is ready");
return ESP_OK;
}

View File

@ -0,0 +1,139 @@
/*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_check.h"
#include "esp_sleep.h"
#include "soc/uart_pins.h"
#include "driver/uart.h"
#include "driver/gpio.h"
#define EXAMPLE_UART_NUM 0
/* Notice that ESP32 has to use the iomux input to configure uart as wakeup source
* Please use 'UxRXD_GPIO_NUM' as uart rx pin. No limitation to the other target */
#define EXAMPLE_UART_TX_IO_NUM U0TXD_GPIO_NUM
#define EXAMPLE_UART_RX_IO_NUM U0RXD_GPIO_NUM
#define EXAMPLE_UART_WAKEUP_THRESHOLD 3
#define EXAMPLE_READ_BUF_SIZE 1024
#define EXAMPLE_UART_BUF_SIZE (EXAMPLE_READ_BUF_SIZE * 2)
static const char *TAG = "uart_wakeup";
static QueueHandle_t uart_evt_que = NULL;
static void uart_wakeup_task(void *arg)
{
uart_event_t event;
if (uart_evt_que == NULL) {
ESP_LOGE(TAG, "uart_evt_que is NULL");
abort();
}
uint8_t* dtmp = (uint8_t*) malloc(EXAMPLE_READ_BUF_SIZE);
while(1) {
// Waiting for UART event.
if(xQueueReceive(uart_evt_que, (void * )&event, (portTickType)portMAX_DELAY)) {
ESP_LOGI(TAG, "uart%d recved event:%d", EXAMPLE_UART_NUM, event.type);
switch(event.type) {
case UART_DATA:
ESP_LOGI(TAG, "[UART DATA]: %d", event.size);
uart_read_bytes(EXAMPLE_UART_NUM, dtmp, event.size, portMAX_DELAY);
ESP_LOGI(TAG, "[DATA EVT]:");
uart_write_bytes(EXAMPLE_UART_NUM, (const char *)dtmp, event.size);
break;
// Event of HW FIFO overflow detected
case UART_FIFO_OVF:
ESP_LOGI(TAG, "hw fifo overflow");
// If fifo overflow happened, you should consider adding flow control for your application.
// The ISR has already reset the rx FIFO,
// As an example, we directly flush the rx buffer here in order to read more data.
uart_flush_input(EXAMPLE_UART_NUM);
xQueueReset(uart_evt_que);
break;
// Event of UART ring buffer full
case UART_BUFFER_FULL:
ESP_LOGI(TAG, "ring buffer full");
// If buffer full happened, you should consider encreasing your buffer size
// As an example, we directly flush the rx buffer here in order to read more data.
uart_flush_input(EXAMPLE_UART_NUM);
xQueueReset(uart_evt_que);
break;
// Event of UART RX break detected
case UART_BREAK:
ESP_LOGI(TAG, "uart rx break");
break;
// Event of UART parity check error
case UART_PARITY_ERR:
ESP_LOGI(TAG, "uart parity error");
break;
// Event of UART frame error
case UART_FRAME_ERR:
ESP_LOGI(TAG, "uart frame error");
break;
// ESP32 can wakeup by uart but there is no wake up interrupt
#if SOC_UART_SUPPORT_WAKEUP_INT
// Event of waking up by UART
case UART_WAKEUP:
ESP_LOGI(TAG, "uart wakeup");
break;
#endif
default:
ESP_LOGI(TAG, "uart event type: %d", event.type);
break;
}
}
}
free(dtmp);
vTaskDelete(NULL);
}
static esp_err_t uart_initialization(void)
{
uart_config_t uart_cfg = {
.baud_rate = 115200,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
.source_clk = UART_SCLK_APB,
};
//Install UART driver, and get the queue.
ESP_RETURN_ON_ERROR(uart_driver_install(EXAMPLE_UART_NUM, EXAMPLE_UART_BUF_SIZE, EXAMPLE_UART_BUF_SIZE, 20, &uart_evt_que, 0),
TAG, "Install uart failed");
ESP_RETURN_ON_ERROR(uart_param_config(EXAMPLE_UART_NUM, &uart_cfg), TAG, "Configure uart param failed");
ESP_RETURN_ON_ERROR(uart_set_pin(EXAMPLE_UART_NUM, EXAMPLE_UART_TX_IO_NUM, EXAMPLE_UART_RX_IO_NUM, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE),
TAG, "Configure uart gpio pins failed");
return ESP_OK;
}
static esp_err_t uart_wakeup_config(void)
{
/* UART will wakeup the chip up from light sleep if the edges that RX pin received has reached the threshold
* Besides, the Rx pin need extra configuration to enable it can work during light sleep */
ESP_RETURN_ON_ERROR(gpio_sleep_set_direction(EXAMPLE_UART_RX_IO_NUM, GPIO_MODE_INPUT), TAG, "Set uart sleep gpio failed");
ESP_RETURN_ON_ERROR(gpio_sleep_set_pull_mode(EXAMPLE_UART_RX_IO_NUM, GPIO_PULLUP_ONLY), TAG, "Set uart sleep gpio failed");
ESP_RETURN_ON_ERROR(uart_set_wakeup_threshold(EXAMPLE_UART_NUM, EXAMPLE_UART_WAKEUP_THRESHOLD),
TAG, "Set uart wakeup threshold failed");
/* Only uart0 and uart1 (if has) support to be configured as wakeup source */
ESP_RETURN_ON_ERROR(esp_sleep_enable_uart_wakeup(EXAMPLE_UART_NUM),
TAG, "Configure uart as wakeup source failed");
return ESP_OK;
}
esp_err_t example_register_uart_wakeup(void)
{
/* Initialize uart1 */
ESP_RETURN_ON_ERROR(uart_initialization(), TAG, "Initialize uart%d failed", EXAMPLE_UART_NUM);
/* Enable wakeup from uart */
ESP_RETURN_ON_ERROR(uart_wakeup_config(), TAG, "Configure uart as wakeup source failed");
xTaskCreate(uart_wakeup_task, "uart_wakeup_task", 4096, NULL, 5, NULL);
ESP_LOGI(TAG, "uart wakeup source is ready");
return ESP_OK;
}

View File

@ -925,7 +925,6 @@ components/hal/esp32c3/include/hal/spi_flash_ll.h
components/hal/esp32c3/include/hal/spimem_flash_ll.h
components/hal/esp32c3/include/hal/systimer_ll.h
components/hal/esp32c3/include/hal/twai_ll.h
components/hal/esp32c3/include/hal/uart_ll.h
components/hal/esp32c3/include/hal/uhci_ll.h
components/hal/esp32c3/include/hal/usb_serial_jtag_ll.h
components/hal/esp32c3/rtc_cntl_hal.c
@ -988,7 +987,6 @@ components/hal/esp32s2/include/hal/touch_sensor_hal.h
components/hal/esp32s2/include/hal/touch_sensor_ll.h
components/hal/esp32s2/include/hal/trace_ll.h
components/hal/esp32s2/include/hal/twai_ll.h
components/hal/esp32s2/include/hal/uart_ll.h
components/hal/esp32s2/include/hal/usb_ll.h
components/hal/esp32s2/interrupt_descriptor_table.c
components/hal/esp32s2/touch_sensor_hal.c
@ -1012,7 +1010,6 @@ components/hal/esp32s3/include/hal/spi_flash_ll.h
components/hal/esp32s3/include/hal/spimem_flash_ll.h
components/hal/esp32s3/include/hal/systimer_ll.h
components/hal/esp32s3/include/hal/twai_ll.h
components/hal/esp32s3/include/hal/uart_ll.h
components/hal/esp32s3/include/hal/uhci_ll.h
components/hal/esp32s3/include/hal/usb_ll.h
components/hal/esp32s3/include/hal/usb_serial_jtag_ll.h
@ -2704,7 +2701,6 @@ examples/system/himem/main/himem_example_main.c
examples/system/ipc/ipc_isr/example_test.py
examples/system/ipc/ipc_isr/main/main.c
examples/system/light_sleep/example_test.py
examples/system/light_sleep/main/light_sleep_example_main.c
examples/system/ota/advanced_https_ota/example_test.py
examples/system/ota/advanced_https_ota/main/advanced_https_ota_example.c
examples/system/ota/advanced_https_ota/main/ble_helper/ble_api.c