uart: support light sleep on esp32s3

This commit is contained in:
laokaiyao 2022-01-12 11:03:38 +08:00
parent 35941de800
commit c4cfb654d2
27 changed files with 405 additions and 221 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 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -58,7 +58,7 @@ typedef enum {
UART_PARITY_ERR, /*!< UART RX parity event*/ UART_PARITY_ERR, /*!< UART RX parity event*/
UART_DATA_BREAK, /*!< UART TX data and break event*/ UART_DATA_BREAK, /*!< UART TX data and break event*/
UART_PATTERN_DET, /*!< UART pattern detected */ UART_PATTERN_DET, /*!< UART pattern detected */
#if SOC_UART_SUPPORT_WAKEUP #if SOC_UART_SUPPORT_WAKEUP_INT
UART_WAKEUP, /*!< UART wakeup event */ UART_WAKEUP, /*!< UART wakeup event */
#endif #endif
UART_EVENT_MAX, /*!< UART event max index*/ UART_EVENT_MAX, /*!< UART event max index*/

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 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -47,7 +47,7 @@ static const char *UART_TAG = "uart";
#define UART_PATTERN_DET_QLEN_DEFAULT (10) #define UART_PATTERN_DET_QLEN_DEFAULT (10)
#define UART_MIN_WAKEUP_THRESH (UART_LL_MIN_WAKEUP_THRESH) #define UART_MIN_WAKEUP_THRESH (UART_LL_MIN_WAKEUP_THRESH)
#if SOC_UART_SUPPORT_WAKEUP #if SOC_UART_SUPPORT_WAKEUP_INT
#define UART_INTR_CONFIG_FLAG ((UART_INTR_RXFIFO_FULL) \ #define UART_INTR_CONFIG_FLAG ((UART_INTR_RXFIFO_FULL) \
| (UART_INTR_RXFIFO_TOUT) \ | (UART_INTR_RXFIFO_TOUT) \
| (UART_INTR_RXFIFO_OVF) \ | (UART_INTR_RXFIFO_OVF) \
@ -1091,7 +1091,7 @@ static void UART_ISR_ATTR uart_rx_intr_handler_default(void *param)
xSemaphoreGiveFromISR(p_uart_obj[uart_num]->tx_done_sem, &HPTaskAwoken); xSemaphoreGiveFromISR(p_uart_obj[uart_num]->tx_done_sem, &HPTaskAwoken);
} }
} }
#if SOC_UART_SUPPORT_WAKEUP #if SOC_UART_SUPPORT_WAKEUP_INT
else if (uart_intr_status & UART_INTR_WAKEUP) { else if (uart_intr_status & UART_INTR_WAKEUP) {
uart_hal_clr_intsts_mask(&(uart_context[uart_num].hal), UART_INTR_WAKEUP); uart_hal_clr_intsts_mask(&(uart_context[uart_num].hal), UART_INTR_WAKEUP);
uart_event.type = UART_WAKEUP; uart_event.type = UART_WAKEUP;

View File

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

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 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -51,6 +51,7 @@ typedef enum {
UART_INTR_RS485_FRM_ERR = (0x1 << 16), UART_INTR_RS485_FRM_ERR = (0x1 << 16),
UART_INTR_RS485_CLASH = (0x1 << 17), UART_INTR_RS485_CLASH = (0x1 << 17),
UART_INTR_CMD_CHAR_DET = (0x1 << 18), UART_INTR_CMD_CHAR_DET = (0x1 << 18),
UART_INTR_WAKEUP = (0x1 << 19),
} uart_intr_t; } uart_intr_t;
static inline void uart_ll_set_reset_core(uart_dev_t *hw, bool core_rst_en) { 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 /*
// * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
// Licensed under the Apache License, Version 2.0 (the "License"); *
// you may not use this file except in compliance with the License. * SPDX-License-Identifier: Apache-2.0
// 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.
// The LL layer for UART register operations. // The LL layer for UART register operations.
// Note that most of the register operations in this layer are non-atomic 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_FRM_ERR = (0x1<<16),
UART_INTR_RS485_CLASH = (0x1<<17), UART_INTR_RS485_CLASH = (0x1<<17),
UART_INTR_CMD_CHAR_DET = (0x1<<18), UART_INTR_CMD_CHAR_DET = (0x1<<18),
UART_INTR_WAKEUP = (0x1 << 19),
} uart_intr_t; } uart_intr_t;
/** /**

View File

@ -1,16 +1,8 @@
// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD /*
// * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
// Licensed under the Apache License, Version 2.0 (the "License"); *
// you may not use this file except in compliance with the License. * SPDX-License-Identifier: Apache-2.0
// 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.
// The LL layer for UART register operations. // The LL layer for UART register operations.
// Note that most of the register operations in this layer are non-atomic 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_FRM_ERR = (0x1 << 16),
UART_INTR_RS485_CLASH = (0x1 << 17), UART_INTR_RS485_CLASH = (0x1 << 17),
UART_INTR_CMD_CHAR_DET = (0x1 << 18), UART_INTR_CMD_CHAR_DET = (0x1 << 18),
UART_INTR_WAKEUP = (0x1 << 19),
} uart_intr_t; } uart_intr_t;

View File

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

View File

@ -247,7 +247,7 @@
#define SOC_UART_NUM (2) #define SOC_UART_NUM (2)
#define SOC_UART_FIFO_LEN (128) /*!< The UART hardware FIFO length */ #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_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_RTC_CLK (1)
#define SOC_UART_SUPPORT_XTAL_CLK (1) #define SOC_UART_SUPPORT_XTAL_CLK (1)

View File

@ -583,7 +583,7 @@ config SOC_UART_SUPPORT_XTAL_CLK
bool bool
default y default y
config SOC_UART_SUPPORT_WAKEUP config SOC_UART_SUPPORT_WAKEUP_INT
bool bool
default y default y

View File

@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -288,7 +288,7 @@
#define SOC_UART_SUPPORT_RTC_CLK (1) #define SOC_UART_SUPPORT_RTC_CLK (1)
#define SOC_UART_SUPPORT_XTAL_CLK (1) #define SOC_UART_SUPPORT_XTAL_CLK (1)
#define SOC_UART_SUPPORT_WAKEUP (1) #define SOC_UART_SUPPORT_WAKEUP_INT (1) /*!< Support UART wakeup interrupt */
#define SOC_UART_REQUIRE_CORE_RESET (1) #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 // UART has an extra TX_WAIT_SEND state when the FIFO is not empty and XOFF is enabled

View File

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

View File

@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -279,7 +279,7 @@
#define SOC_UART_NUM (2) #define SOC_UART_NUM (2)
#define SOC_UART_FIFO_LEN (128) /*!< The UART hardware FIFO length */ #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_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_RTC_CLK (1)
#define SOC_UART_SUPPORT_XTAL_CLK (1) #define SOC_UART_SUPPORT_XTAL_CLK (1)

View File

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

View File

@ -275,6 +275,7 @@
/*-------------------------- UART CAPS ---------------------------------------*/ /*-------------------------- UART CAPS ---------------------------------------*/
// ESP32-S2 has 2 UART. // ESP32-S2 has 2 UART.
#define SOC_UART_NUM (2) #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_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_FIFO_LEN (128) /*!< The UART hardware FIFO length */
#define SOC_UART_BITRATE_MAX (5000000) /*!< Max bit rate supported by UART */ #define SOC_UART_BITRATE_MAX (5000000) /*!< Max bit rate supported by UART */

View File

@ -659,6 +659,26 @@ config SOC_TOUCH_PAD_MEASURE_WAIT_MAX
hex hex
default 0xFF 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 config SOC_UART_SUPPORT_RTC_CLK
bool bool
default y default y
@ -838,19 +858,3 @@ config SOC_TWAI_BRP_MAX
config SOC_TWAI_SUPPORTS_RX_STATUS config SOC_TWAI_SUPPORTS_RX_STATUS
bool bool
default y 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

@ -252,8 +252,13 @@
#include "twai_caps.h" #include "twai_caps.h"
/*-------------------------- UART CAPS ---------------------------------------*/ /*-------------------------- 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_RTC_CLK (1) /*!< Support RTC clock as the clock source */
#define SOC_UART_SUPPORT_XTAL_CLK (1) /*!< Support XTAL 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

@ -1,5 +1,3 @@
| Supported Targets | ESP32-C3 |
| ----------------- | -------- |
# Light Sleep Example # Light Sleep Example
(See the README.md file in the upper level 'examples' directory for more information about examples.) (See the README.md file in the upper level 'examples' directory for more information about examples.)
@ -10,6 +8,7 @@ The example enables the following wakeup sources:
- Timer: wake up the chip in 2 seconds - 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) - 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. The example also prints time spent in light sleep mode to illustrate that timekeeping continues while the chip is in light sleep.
@ -41,19 +40,47 @@ See the Getting Started Guide for full steps to configure and use ESP-IDF to bui
## Example Output ## 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 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 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 Entering light sleep
Returned from light sleep, reason: pin, t=5297 ms, slept for 1266 ms Returned from light sleep, reason: uart, t=5148 ms, slept for 418 ms
Waiting for GPIO0 to go high...
Entering light sleep 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 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 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. 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 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): def test_examples_system_light_sleep(env, extra_data):
dut = env.get_dut('light_sleep_example', 'examples/system/light_sleep') dut = env.get_dut('light_sleep_example', 'examples/system/light_sleep')
dut.start_app() dut.start_app()
@ -32,7 +32,7 @@ def test_examples_system_light_sleep(env, extra_data):
groups = dut.expect(EXIT_SLEEP_REGEX) groups = dut.expect(EXIT_SLEEP_REGEX)
print('Got second sleep period, wakeup from {}, slept for {}'.format(groups[0], groups[2])) print('Got second sleep period, wakeup from {}, slept for {}'.format(groups[0], groups[2]))
# sleep time error should be less than 1ms # 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 # this time we'll test gpio wakeup
dut.expect(ENTERING_SLEEP_STR) dut.expect(ENTERING_SLEEP_STR)
@ -49,8 +49,17 @@ def test_examples_system_light_sleep(env, extra_data):
dut.port_inst.setDTR(False) dut.port_inst.setDTR(False)
dut.expect(ENTERING_SLEEP_STR) dut.expect(ENTERING_SLEEP_STR)
print('Went to sleep again') 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) 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') print('Woke up from timer again')

View File

@ -1,2 +1,7 @@
idf_component_register(SRCS "light_sleep_example_main.c" set(srcs "light_sleep_example_main.c"
INCLUDE_DIRS ".") "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

@ -4,8 +4,6 @@
* SPDX-License-Identifier: Unlicense OR CC0-1.0 * SPDX-License-Identifier: Unlicense OR CC0-1.0
*/ */
/* Light sleep example */
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
@ -13,112 +11,53 @@
#include <sys/time.h> #include <sys/time.h>
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "freertos/task.h" #include "freertos/task.h"
#include "driver/uart.h"
#include "esp_sleep.h" #include "esp_sleep.h"
#include "esp_log.h" #include "esp_log.h"
#include "driver/uart.h" #include "light_sleep_example.h"
#include "driver/gpio.h"
#include "esp_timer.h"
#include "soc/uart_struct.h"
#include "soc/rtc.h"
#include "esp_pm.h"
#include "esp32c3/pm.h"
#define TAG "UART" static void light_sleep_task(void *args)
#define TEST_UART_NUM 1
#define TEST_BUF_SIZE 1024
static QueueHandle_t uart0_queue;
void light_sleep_wakeup_config(void)
{ {
ESP_ERROR_CHECK(gpio_sleep_set_direction(6, GPIO_MODE_INPUT)); while (true) {
ESP_ERROR_CHECK(gpio_sleep_set_pull_mode(6, GPIO_PULLUP_ONLY)); 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:
*/
uart_wait_tx_idle_polling(CONFIG_ESP_CONSOLE_UART_NUM);
if (uart_set_wakeup_threshold(TEST_UART_NUM, 3) != ESP_OK) { /* Get timestamp before entering sleep */
ESP_LOGE(TAG, "set uart1 wakeup threshold failed"); int64_t t_before_us = esp_timer_get_time();
}
if (esp_sleep_enable_uart_wakeup(TEST_UART_NUM) != ESP_OK) {
ESP_LOGE(TAG, "set uart1 wakeup failed");
}
ESP_LOGI(TAG, "set_light_sleep_wakeup ok");
}
void light_sleep_setup(void) /* Enter sleep mode */
{ esp_light_sleep_start();
light_sleep_wakeup_config();
esp_pm_config_esp32c3_t pm_config = { /* Get timestamp after waking up from sleep */
.max_freq_mhz = CONFIG_ESP32C3_DEFAULT_CPU_FREQ_MHZ, int64_t t_after_us = esp_timer_get_time();
.min_freq_mhz = (int) rtc_clk_xtal_freq_get(),
.light_sleep_enable = true
};
ESP_ERROR_CHECK(esp_pm_configure(&pm_config));
}
#define RD_BUF_SIZE 1024 /* Determine wake up reason */
const char* wakeup_reason;
static void uart_wakeup_task(void *arg) switch (esp_sleep_get_wakeup_cause()) {
{ case ESP_SLEEP_WAKEUP_TIMER:
uart_event_t event; wakeup_reason = "timer";
// esp_light_sleep_start(); break;
case ESP_SLEEP_WAKEUP_GPIO:
esp_pm_lock_handle_t lock = ((struct { esp_pm_lock_handle_t lock; } *)arg)->lock; wakeup_reason = "pin";
light_sleep_setup(); break;
case ESP_SLEEP_WAKEUP_UART:
uint8_t* dtmp = (uint8_t*) malloc(RD_BUF_SIZE); wakeup_reason = "uart";
/* Hang-up for a while to switch and execuse the uart task
for(;;) { * Otherwise the chip may fall sleep again before running uart task */
//Waiting for UART event. vTaskDelay(1);
if(xQueueReceive(uart0_queue, (void * )&event, (portTickType)portMAX_DELAY)) { break;
default:
esp_pm_lock_acquire(lock); wakeup_reason = "other";
break;
ESP_LOGI(TAG, "uar%d recved event:%d (wk:%d)", TEST_UART_NUM, event.type, UART_WAKEUP); }
switch(event.type) { printf("Returned from light sleep, reason: %s, t=%lld ms, slept for %lld ms\n",
case UART_DATA: wakeup_reason, t_after_us / 1000, (t_after_us - t_before_us) / 1000);
ESP_LOGI(TAG, "[UART DATA]: %d", event.size); if (esp_sleep_get_wakeup_cause() == ESP_SLEEP_WAKEUP_GPIO) {
uart_read_bytes(TEST_UART_NUM, dtmp, event.size, portMAX_DELAY); /* Waiting for the gpio inactive, or the chip will continously trigger wakeup*/
ESP_LOGI(TAG, "[DATA EVT]:"); example_wait_gpio_inactive();
uart_write_bytes(TEST_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(TEST_UART_NUM);
xQueueReset(uart0_queue);
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(TEST_UART_NUM);
xQueueReset(uart0_queue);
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;
case UART_WAKEUP:
ESP_LOGI(TAG, "uart uart wakeup");
break;
default:
ESP_LOGI(TAG, "uart event type: %d", event.type);
break;
}
ESP_LOGI(TAG, "uart[%d] esp_pm_lock_release()", TEST_UART_NUM);
esp_pm_lock_release(lock);
} }
} }
vTaskDelete(NULL); vTaskDelete(NULL);
@ -126,22 +65,12 @@ static void uart_wakeup_task(void *arg)
void app_main(void) void app_main(void)
{ {
uart_config_t uart_config = { /* Enable wakeup from light sleep by gpio */
.baud_rate = 115200, example_register_gpio_wakeup();
.data_bits = UART_DATA_8_BITS, /* Enable wakeup from light sleep by timer */
.parity = UART_PARITY_DISABLE, example_register_timer_wakeup();
.stop_bits = UART_STOP_BITS_1, /* Enable wakeup from light sleep by uart */
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE, example_register_uart_wakeup();
.source_clk = UART_SCLK_XTAL,
};
//Install UART driver, and get the queue.
uart_driver_install(TEST_UART_NUM, TEST_BUF_SIZE * 2, TEST_BUF_SIZE * 2, 20, &uart0_queue, 0);
uart_param_config(TEST_UART_NUM, &uart_config);
uart_set_pin(TEST_UART_NUM, 7, 6, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
light_sleep_wakeup_config();
static esp_pm_lock_handle_t uart_event_lock; xTaskCreate(light_sleep_task, "light_sleep_task", 4096, NULL, 6, NULL);
ESP_ERROR_CHECK(esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "uart_evt", &uart_event_lock));
struct { esp_pm_lock_handle_t lock; } args = { .lock = uart_event_lock };
xTaskCreate(uart_wakeup_task, "uart_wakeup_task", 2048, &args, 12, 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

@ -1,2 +1 @@
CONFIG_PM_ENABLE=y CONFIG_ESP32_DEFAULT_CPU_FREQ_80=y
CONFIG_FREERTOS_USE_TICKLESS_IDLE=y

View File

@ -1061,7 +1061,6 @@ components/hal/esp32s2/include/hal/touch_sensor_hal.h
components/hal/esp32s2/include/hal/touch_sensor_ll.h components/hal/esp32s2/include/hal/touch_sensor_ll.h
components/hal/esp32s2/include/hal/trace_ll.h components/hal/esp32s2/include/hal/trace_ll.h
components/hal/esp32s2/include/hal/twai_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/include/hal/usb_ll.h
components/hal/esp32s2/interrupt_descriptor_table.c components/hal/esp32s2/interrupt_descriptor_table.c
components/hal/esp32s2/touch_sensor_hal.c components/hal/esp32s2/touch_sensor_hal.c
@ -1085,7 +1084,6 @@ components/hal/esp32s3/include/hal/spi_flash_ll.h
components/hal/esp32s3/include/hal/spimem_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/systimer_ll.h
components/hal/esp32s3/include/hal/twai_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/uhci_ll.h
components/hal/esp32s3/include/hal/usb_ll.h components/hal/esp32s3/include/hal/usb_ll.h
components/hal/esp32s3/include/hal/usb_serial_jtag_ll.h components/hal/esp32s3/include/hal/usb_serial_jtag_ll.h