Merge branch 'change/esp_idf_uart_wakeup_refactor' into 'master'

Change: derecate uart wakeup old config apis and add modes descriptions in docs

Closes PM-408 and PM-669

See merge request espressif/esp-idf!45862
This commit is contained in:
He Binglin
2026-03-06 17:33:44 +08:00
18 changed files with 305 additions and 38 deletions
@@ -833,7 +833,8 @@ esp_err_t uart_get_collision_flag(uart_port_t uart_num, bool* collision_flag);
* - ESP_ERR_INVALID_ARG if uart_num is incorrect or wakeup_threshold is
* outside of [3, 0x3ff] range.
*/
esp_err_t uart_set_wakeup_threshold(uart_port_t uart_num, int wakeup_threshold);
esp_err_t uart_set_wakeup_threshold(uart_port_t uart_num, int wakeup_threshold)
__attribute__((deprecated("use uart_wakeup_setup instead")));
/**
* @brief Get the number of RX pin signal edges for light sleep wakeup.
@@ -848,7 +849,8 @@ esp_err_t uart_set_wakeup_threshold(uart_port_t uart_num, int wakeup_threshold);
* - ESP_OK on success
* - ESP_ERR_INVALID_ARG if out_wakeup_threshold is NULL
*/
esp_err_t uart_get_wakeup_threshold(uart_port_t uart_num, int* out_wakeup_threshold);
esp_err_t uart_get_wakeup_threshold(uart_port_t uart_num, int* out_wakeup_threshold)
__attribute__((deprecated));
/**
* @brief Wait until UART tx memory empty and the last char send ok (polling mode).
+3
View File
@@ -2278,6 +2278,9 @@ esp_err_t uart_set_wakeup_threshold(uart_port_t uart_num, int wakeup_threshold)
"wakeup_threshold out of bounds");
UART_ENTER_CRITICAL(&(uart_context[uart_num].spinlock));
uart_hal_set_wakeup_edge_thrd(&(uart_context[uart_num].hal), wakeup_threshold);
PERIPH_RCC_ATOMIC() {
uart_ll_enable_pad_sleep_clock(uart_context[uart_num].hal.dev, true);
}
UART_EXIT_CRITICAL(&(uart_context[uart_num].spinlock));
return ESP_OK;
}
@@ -9,6 +9,7 @@
#include "test_utils.h"
#include "unity_test_utils.h"
#include "driver/uart.h"
#include "driver/uart_wakeup.h"
#include "esp_log.h"
#include "esp_rom_gpio.h"
#include "esp_private/gpio.h"
@@ -272,19 +273,6 @@ static void uart_hw_flow_set_get_test(int uart_num)
}
}
static void uart_wakeup_set_get_test(int uart_num)
{
printf("uart wake up set and get test\n");
int wake_up_set = 0;
int wake_up_get = 0;
for (int i = 3; i < 0x3ff; i++) {
wake_up_set = i;
TEST_ESP_OK(uart_set_wakeup_threshold(uart_num, wake_up_set));
TEST_ESP_OK(uart_get_wakeup_threshold(uart_num, &wake_up_get));
TEST_ASSERT_EQUAL(wake_up_set, wake_up_get);
}
}
TEST_CASE("uart general API test", "[uart]")
{
uart_port_param_t port_param = {};
@@ -304,7 +292,6 @@ TEST_CASE("uart general API test", "[uart]")
uart_stop_bit_set_get_test(uart_num);
uart_parity_set_get_test(uart_num);
uart_hw_flow_set_get_test(uart_num);
uart_wakeup_set_get_test(uart_num);
}
typedef struct {
@@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: CC0-1.0
import pytest
from pytest_embedded_idf import CaseTester
@@ -79,13 +79,14 @@ def test_uart_single_dev_psram(case_tester) -> None: # type: ignore
# ESP32 only supports uart wakeup if signal routes through IOMUX
# ESP32S3 multi device runner has no psram IDF-12837,
# ESP32P4 not yet supported IDF-12839.
@pytest.mark.temp_skip_ci(targets=['esp32', 'esp32s3', 'esp32p4'], reason='no multi-dev runner')
@pytest.mark.temp_skip_ci(targets=['esp32', 'esp32s3'], reason='no multi-dev runner')
@pytest.mark.generic_multi_device
@idf_parametrize('target', ['supported_targets'], indirect=['target'])
@pytest.mark.parametrize(
'config',
[
'iram_safe',
# Note: Software clock ICG (Idle Clock Gating) feature in ESP32-P4 won't work in release test.
'release',
],
indirect=True,
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -1112,8 +1112,10 @@ FORCE_INLINE_ATTR void uart_ll_set_dtr_active_level(uart_dev_t *hw, int level)
*/
FORCE_INLINE_ATTR void uart_ll_set_wakeup_edge_thrd(uart_dev_t *hw, uint32_t wakeup_thrd)
{
// System would wakeup when the number of positive edges of RxD signal is larger than or equal to (UART_ACTIVE_THRESHOLD+3)
hw->sleep_conf2.active_threshold = wakeup_thrd - UART_LL_WAKEUP_EDGE_THRED_MIN;
// System would wakeup when the number of positive edges of RxD signal is larger than or equal to (UART_ACTIVE_THRESHOLD+offset)
// HP UART: offset is 6, LP UART: offset is 3
uint32_t offset = (hw == &LP_UART) ? UART_LL_WAKEUP_EDGE_THRED_MIN : UART_LL_WAKEUP_EDGE_THRED_MIN + 3;
hw->sleep_conf2.active_threshold = wakeup_thrd - offset;
}
/**
@@ -1421,7 +1423,9 @@ FORCE_INLINE_ATTR void uart_ll_get_at_cmd_char(uart_dev_t *hw, uint8_t *cmd_char
*/
FORCE_INLINE_ATTR uint32_t uart_ll_get_wakeup_edge_thrd(uart_dev_t *hw)
{
return hw->sleep_conf2.active_threshold + UART_LL_WAKEUP_EDGE_THRED_MIN;
// HP UART: offset is 6, LP UART: offset is 3
uint32_t offset = (hw == &LP_UART) ? UART_LL_WAKEUP_EDGE_THRED_MIN : UART_LL_WAKEUP_EDGE_THRED_MIN + 3;
return hw->sleep_conf2.active_threshold + offset;
}
/**
@@ -522,13 +522,14 @@ esp_err_t esp_sleep_enable_gpio_wakeup(void);
/**
* @brief Enable wakeup from light sleep using UART
*
* Use uart_set_wakeup_threshold function to configure UART wakeup threshold.
* Use uart_wakeup_setup function to configure UART wakeup mode and parameters.
*
* Wakeup from light sleep takes some time, so not every character sent
* to the UART can be received by the application.
*
* @note 1. ESP32 does not support wakeup from UART2.
* 2. If PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP is enabled (if target supported),
* 2. Wakeup mode 0(Active threshold) don't need source clock, but other modes need.
* 3. If PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP is enabled (if target supported),
* this API is unavailable since the UART module is powered down during sleep.
*
* @param uart_num UART port to wake up from
+48 -2
View File
@@ -367,14 +367,44 @@ RTC peripherals or RTC memories do not need to be powered on during sleep in thi
Any IO can be used as the external input to wake up the chip from Light-sleep. Each pin can be individually configured to trigger wakeup on high or low level using the :cpp:func:`gpio_wakeup_enable` function. Then the :cpp:func:`esp_sleep_enable_gpio_wakeup` function should be called to enable this wakeup source.
.. _uart_wakeup_light_sleep:
UART Wakeup (Light-sleep Only)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
When {IDF_TARGET_NAME} receives UART input from external devices, it is often necessary to wake up the chip when input data is available. The 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 :cpp:func:`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 {IDF_TARGET_NAME} to trigger wakeup before sending the data.
When {IDF_TARGET_NAME} receives UART input from external devices, it is often necessary to wake up the chip when input data is available. The UART peripheral supports multiple wakeup modes that can wake up the chip from Light-sleep. The wakeup mode and its parameters can be configured using :cpp:func:`uart_wakeup_setup` function.
The UART wakeup supports the following modes:
.. only:: SOC_UART_WAKEUP_SUPPORT_ACTIVE_THRESH_MODE
**Mode 0 (UART_WK_MODE_ACTIVE_THRESH) - Active Edge Threshold Wakeup**
When all clocks are powered down, the chip can be woken up by toggling the RXD pin for a certain number of cycles. The chip wakes up when the number of rising edges is greater than or equal to threshold value. The threshold value can be configured using the ``rx_edge_threshold`` field in :cpp:type:`uart_wakeup_cfg_t` structure.
.. only:: SOC_UART_WAKEUP_SUPPORT_FIFO_THRESH_MODE
**Mode 1 (UART_WK_MODE_FIFO_THRESH) - RX FIFO Threshold Wakeup**
Since the UART Core clock remains active, the UART RX can still receive data and store it in the RX FIFO. The chip can be woken up from Light-sleep when the number of bytes in the RX FIFO exceeds the configured threshold. The threshold value can be configured using the ``rx_fifo_threshold`` field in :cpp:type:`uart_wakeup_cfg_t` structure.
.. only:: SOC_UART_WAKEUP_SUPPORT_START_BIT_MODE
**Mode 2 (UART_WK_MODE_START_BIT) - Start Bit Detection Wakeup**
The chip wakes up when the UART RX detects a start bit.
.. only:: SOC_UART_WAKEUP_SUPPORT_CHAR_SEQ_MODE
**Mode 3 (UART_WK_MODE_CHAR_SEQ) - Character Sequence Detection Wakeup**
The chip wakes up when the UART RX receives a specific character sequence. The character sequence can be configured using the ``wake_chars_seq`` field in :cpp:type:`uart_wakeup_cfg_t` structure. The character sequence supports wildcard matching using '*' to represent any symbol.
:cpp:func:`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.
.. only:: SOC_UART_WAKEUP_SUPPORT_ACTIVE_THRESH_MODE
After waking-up from UART wakeup mode 0, you should send some extra data through the UART port or reset the UART module in Active mode, otherwise, the next UART wake-up would trigger with two less rising edges than the configured threshold value.
.. only:: SOC_PM_SUPPORT_TOP_PD
@@ -382,6 +412,22 @@ After waking-up from UART, you should send some extra data through the UART port
In Light-sleep mode, setting Kconfig option :ref:`CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP` will invalidate UART wakeup.
.. only:: SOC_ULP_LP_UART_SUPPORTED
LP_UART can wake up the ULP LP core coprocessor. LP_UART supports the same wakeup modes as the HP UART described above, including active edge threshold wakeup, RX FIFO threshold wakeup, start bit detection wakeup, and character sequence detection wakeup.
To use LP_UART to wake up the ULP LP core, follow these steps:
#. Set the :c:macro:`ULP_LP_CORE_WAKEUP_SOURCE_LP_UART` flag in the ``wakeup_source`` field of the :cpp:type:`ulp_lp_core_cfg_t` structure.
#. Initialize the LP UART (call :cpp:func:`lp_core_uart_init`).
#. Configure the LP_UART wakeup mode using the :cpp:func:`lp_core_uart_wakeup_setup` function with a :cpp:type:`uart_wakeup_cfg_t` structure, using the same configuration method as HP UART.
.. note::
Once the LP core wakes up due to LP_UART, you must call :cpp:func:`ulp_lp_core_lp_uart_reset_wakeup_en` or reset the LP UART module to clear the wakeup signal before the LP core goes to sleep, otherwise, it will be repeated wakeup.
For example code on LP_UART wakeup, refer to :example:`system/ulp/lp_core/lp_uart/lp_uart_char_seq_wakeup`.
.. _disable_sleep_wakeup_source:
Disable Sleep Wakeup Source
+1
View File
@@ -23,3 +23,4 @@ ESP-IDF 6.x Migration Guide
:maxdepth: 1
release-6.x/6.0/index
release-6.x/6.1/index
@@ -0,0 +1,9 @@
Migration from 6.0 to 6.1
--------------------------
:link_to_translation:`zh_CN:[中文]`
.. toctree::
:maxdepth: 1
peripherals
@@ -0,0 +1,76 @@
Peripherals
===============
:link_to_translation:`zh_CN:[中文]`
UART
-----
UART Wakeup API Update
~~~~~~~~~~~~~~~~~~~~~~~~
In ESP-IDF v6.1, the legacy UART wakeup APIs :cpp:func:`uart_set_wakeup_threshold` and :cpp:func:`uart_get_wakeup_threshold` have been marked as deprecated and will be removed in future versions. These APIs only support the RXD edge threshold wakeup mode (Mode 0).
The new unified API :cpp:func:`uart_wakeup_setup` provides a more flexible configuration approach and supports multiple wakeup modes:
- **Mode 0 (UART_WK_MODE_ACTIVE_THRESH)** - Active edge threshold wakeup (corresponds to the legacy API functionality)
- **Mode 1 (UART_WK_MODE_FIFO_THRESH)** - RX FIFO threshold wakeup
- **Mode 2 (UART_WK_MODE_START_BIT)** - Start bit detection wakeup
- **Mode 3 (UART_WK_MODE_CHAR_SEQ)** - Character sequence detection wakeup
**Migration Example:**
Old code:
.. code-block:: c
// Set wakeup threshold
ESP_ERROR_CHECK(uart_set_wakeup_threshold(UART_NUM_0, 3));
ESP_ERROR_CHECK(esp_sleep_enable_uart_wakeup(UART_NUM_0));
// Get wakeup threshold
int threshold;
ESP_ERROR_CHECK(uart_get_wakeup_threshold(UART_NUM_0, &threshold));
New code:
.. code-block:: c
#include "driver/uart_wakeup.h"
// Configure active edge threshold wakeup mode (corresponds to legacy API functionality)
uart_wakeup_cfg_t wakeup_cfg = {
.wakeup_mode = UART_WK_MODE_ACTIVE_THRESH,
.rx_edge_threshold = 3, // Corresponds to the wakeup_threshold parameter of the legacy API
};
ESP_ERROR_CHECK(uart_wakeup_setup(UART_NUM_0, &wakeup_cfg));
ESP_ERROR_CHECK(esp_sleep_enable_uart_wakeup(UART_NUM_0));
// Note: The new API does not have a direct corresponding get function
// If you need to get the current configuration, you should save the configuration value yourself
Major Changes
^^^^^^^^^^^^^^^^^^^
1. **API Replacement**:
- :cpp:func:`uart_set_wakeup_threshold`:cpp:func:`uart_wakeup_setup`
- :cpp:func:`uart_get_wakeup_threshold` → Removed
2. **Configuration Method**:
- Legacy API uses a simple integer parameter
- New API uses :cpp:type:`uart_wakeup_cfg_t` structure, supporting multiple wakeup modes
3. **Header File**:
- New API requires including the ``driver/uart_wakeup.h`` header file
4. **Feature Extension**:
- New API supports multiple wakeup modes, which can be selected based on chip capabilities
- The availability of different wakeup modes depends on the chip's SOC capabilities (determined by ``SOC_UART_WAKEUP_SUPPORT_XXX_MODE`` macros)
Notes
^^^^^^^^^^
- Legacy API only supports Mode 0 (active edge threshold wakeup). When migrating, simply set ``wakeup_mode = UART_WK_MODE_ACTIVE_THRESH``
- The ``rx_edge_threshold`` parameter of the new API has the same meaning as the ``wakeup_threshold`` parameter of the legacy API
- If you need to get the current wakeup configuration at runtime, it is recommended to save the configuration value when calling :cpp:func:`uart_wakeup_setup`
- Different chips may support different wakeup modes. Please refer to the :ref:`UART Wakeup (Light-sleep Only) <uart_wakeup_light_sleep>` section.
@@ -367,14 +367,44 @@ RTC 控制器中内嵌定时器,可用于在预定义的时间到达后唤醒
任何一个 IO 都可以用作外部输入管脚,将芯片从 Light-sleep 状态唤醒。调用 :cpp:func:`gpio_wakeup_enable` 函数可以将任意管脚单独配置为在高电平或低电平触发唤醒。此后,应调用 :cpp:func:`esp_sleep_enable_gpio_wakeup` 函数来启用此唤醒源。
.. _uart_wakeup_light_sleep:
UART 唤醒(仅适用于 Light-sleep 模式)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
当 {IDF_TARGET_NAME} 从外部设备接收 UART 输入时,通常需要在输入数据可用时唤醒芯片。UART 外设支持在 RX 管脚上观测到一定数量的上升沿时,将芯片从 Light-sleep 模式中唤醒。调用 :cpp:func:`uart_set_wakeup_threshold` 函数可设置被观测上升沿的数量。请注意,触发唤醒的字符(及该字符前的所有字符)在唤醒后不会被 UART 接收,因此在发送数据之前,外部设备通常需要首先向 {IDF_TARGET_NAME} 额外发送一个字符以触发唤醒
当 {IDF_TARGET_NAME} 从外部设备接收 UART 输入时,通常需要在输入数据可用时唤醒芯片。UART 外设支持多种唤醒模式,可以将芯片从 Light-sleep 模式中唤醒。唤醒模式及其参数可以通过调用 :cpp:func:`uart_wakeup_setup` 函数进行配置
UART 唤醒支持以下模式:
.. only:: SOC_UART_WAKEUP_SUPPORT_ACTIVE_THRESH_MODE
**模式 0 (UART_WK_MODE_ACTIVE_THRESH) - 边沿阈值唤醒**
当所有时钟都关闭时,此时可以通过使 RXD 翻转若干周期,当上升沿个数大于等于设定阈值时唤醒芯片。阈值可以通过 :cpp:type:`uart_wakeup_cfg_t` 结构体中的 ``rx_edge_threshold`` 字段进行配置。
.. only:: SOC_UART_WAKEUP_SUPPORT_FIFO_THRESH_MODE
**模式 1 (UART_WK_MODE_FIFO_THRESH) - RX FIFO 阈值唤醒**
由于 UART Core 时钟保持工作,因此 UART RX 仍然可以接收数据并将数据暂存在 Rx FIFO 中。当 Rx FIFO 中的数据量超过配置的阈值时,可以将芯片从 Light-sleep 中唤醒。阈值可以通过 :cpp:type:`uart_wakeup_cfg_t` 结构体中的 ``rx_fifo_threshold`` 字段进行配置。
.. only:: SOC_UART_WAKEUP_SUPPORT_START_BIT_MODE
**模式 2 (UART_WK_MODE_START_BIT) - 起始位检测唤醒**
当 UART RX 监测到起始位后,唤醒芯片。
.. only:: SOC_UART_WAKEUP_SUPPORT_CHAR_SEQ_MODE
**模式 3 (UART_WK_MODE_CHAR_SEQ) - 字符序列检测唤醒**
当 UART RX 接收到特定字符序列后,唤醒芯片。字符序列可以通过 :cpp:type:`uart_wakeup_cfg_t` 结构体中的 ``wake_chars_seq`` 字段进行配置。字符序列支持使用 '*' 作为通配符来匹配任意字符。
可调用 :cpp:func:`esp_sleep_enable_uart_wakeup` 函数来启用此唤醒源。
使用 UART 唤醒之后,在芯片 Active 模式下需要让 UART 接受一些数据用来清零内部的唤醒指示信号。不然的话,下一次 UART 唤醒的触发将只需要比配置的阈值少两个上升沿的数量。
.. only:: SOC_UART_WAKEUP_SUPPORT_ACTIVE_THRESH_MODE
使用 UART 唤醒模式 0 之后,需要通过在 Active 模式下向 UART 传输数据或是复位整个 UART 模块,否则下一次唤醒所需的上升沿个数将减少。
.. only:: SOC_PM_SUPPORT_TOP_PD
@@ -382,6 +412,22 @@ UART 唤醒(仅适用于 Light-sleep 模式)
在 Light-sleep 模式下,设置 Kconfig 选项 :ref:`CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP` 将使 UART 唤醒失效。
.. only:: SOC_ULP_LP_UART_SUPPORTED
LP_UART 可以将 ULP LP 内核协处理器唤醒。LP_UART 支持的唤醒模式与上述 HP UART 唤醒模式相同,包括边沿阈值唤醒、RX FIFO 阈值唤醒、起始位检测唤醒和字符序列检测唤醒。
要使用 LP_UART 唤醒 ULP LP 内核,需要执行以下步骤:
#. 在 :cpp:type:`ulp_lp_core_cfg_t` 结构体的 ``wakeup_source`` 字段中设置 :c:macro:`ULP_LP_CORE_WAKEUP_SOURCE_LP_UART` 标志位。
#. 初始化 LP UART(调用 :cpp:func:`lp_core_uart_init`)。
#. 使用 :cpp:func:`lp_core_uart_wakeup_setup` 函数配置 LP_UART 的唤醒模式,参数使用 :cpp:type:`uart_wakeup_cfg_t` 结构体,配置方式与 HP UART 相同。
.. note::
当 LP 核因 LP_UART 唤醒后,必须在 LP 核进入睡眠前调用 :cpp:func:`ulp_lp_core_lp_uart_reset_wakeup_en` 函数或是复位整个 LP UART 模块以清除唤醒信号,否则会被重复唤醒。
有关 LP_UART 唤醒的示例代码,请参考 :example:`system/ulp/lp_core/lp_uart/lp_uart_char_seq_wakeup`
.. _disable_sleep_wakeup_source:
禁用睡眠模式唤醒源
+1
View File
@@ -23,3 +23,4 @@
:maxdepth: 1
release-6.x/6.0/index
release-6.x/6.1/index
@@ -0,0 +1,9 @@
从 6.0 迁移到 6.1
------------------
:link_to_translation:`en:[English]`
.. toctree::
:maxdepth: 1
peripherals
@@ -0,0 +1,76 @@
外设驱动
=========
:link_to_translation:`en:[English]`
UART
------
UART 唤醒 API 更新
~~~~~~~~~~~~~~~~~~~~~
在 ESP-IDF v6.1 中,旧的 UART 唤醒 API :cpp:func:`uart_set_wakeup_threshold`:cpp:func:`uart_get_wakeup_threshold` 已被标记为废弃,并将在未来版本中移除。这些 API 仅支持基于 RXD 边沿阈值的唤醒模式(Mode 0)。
新的统一 API :cpp:func:`uart_wakeup_setup` 提供了更灵活的配置方式,支持多种唤醒模式:
- **Mode 0 (UART_WK_MODE_ACTIVE_THRESH)** - 边沿阈值唤醒(对应旧 API 的功能)
- **Mode 1 (UART_WK_MODE_FIFO_THRESH)** - RX FIFO 阈值唤醒
- **Mode 2 (UART_WK_MODE_START_BIT)** - 起始位检测唤醒
- **Mode 3 (UART_WK_MODE_CHAR_SEQ)** - 字符序列检测唤醒
**迁移示例:**
旧代码:
.. code-block:: c
// 设置唤醒阈值
ESP_ERROR_CHECK(uart_set_wakeup_threshold(UART_NUM_0, 3));
ESP_ERROR_CHECK(esp_sleep_enable_uart_wakeup(UART_NUM_0));
// 获取唤醒阈值
int threshold;
ESP_ERROR_CHECK(uart_get_wakeup_threshold(UART_NUM_0, &threshold));
新代码:
.. code-block:: c
#include "driver/uart_wakeup.h"
// 配置边沿阈值唤醒模式(对应旧 API 的功能)
uart_wakeup_cfg_t wakeup_cfg = {
.wakeup_mode = UART_WK_MODE_ACTIVE_THRESH,
.rx_edge_threshold = 3, // 对应旧 API 的 wakeup_threshold 参数
};
ESP_ERROR_CHECK(uart_wakeup_setup(UART_NUM_0, &wakeup_cfg));
ESP_ERROR_CHECK(esp_sleep_enable_uart_wakeup(UART_NUM_0));
// 注意:新 API 没有直接对应的获取函数
// 如果需要获取当前配置,需要自行保存配置值
主要变化
^^^^^^^^^^^
1. **API 替换**
- :cpp:func:`uart_set_wakeup_threshold`:cpp:func:`uart_wakeup_setup`
- :cpp:func:`uart_get_wakeup_threshold` → 已移除
2. **配置方式**
- 旧 API 使用简单的整数参数
- 新 API 使用 :cpp:type:`uart_wakeup_cfg_t` 结构体,支持多种唤醒模式
3. **头文件**
- 新 API 需要包含 ``driver/uart_wakeup.h`` 头文件
4. **功能扩展**
- 新 API 支持多种唤醒模式,可根据芯片能力选择使用
- 不同唤醒模式的可用性取决于芯片的 SOC 能力(通过 ``SOC_UART_WAKEUP_SUPPORT_XXX_MODE`` 宏判断)
注意事项
^^^^^^^^^^^
- 旧 API 仅支持 Mode 0(边沿阈值唤醒),迁移时只需设置 ``wakeup_mode = UART_WK_MODE_ACTIVE_THRESH``
- 新 API 的 ``rx_edge_threshold`` 参数与旧 API 的 ``wakeup_threshold`` 参数含义相同
- 如果需要在运行时获取当前唤醒配置,建议在调用 :cpp:func:`uart_wakeup_setup` 时保存配置值
- 不同芯片支持的唤醒模式可能不同,请参考 :ref:`UART 唤醒(仅适用于 Light-sleep 模式) <uart_wakeup_light_sleep>` 部分。
@@ -15,6 +15,7 @@
#include "driver/rtc_io.h"
#include "driver/gpio.h"
#include "driver/uart.h"
#include "driver/uart_wakeup.h"
#include "argtable3/argtable3.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
@@ -319,7 +320,8 @@ static int light_sleep(int argc, char **argv)
}
if (CONFIG_ESP_CONSOLE_UART_NUM <= UART_NUM_1) {
ESP_LOGI(TAG, "Enabling UART wakeup (press ENTER to exit light sleep)");
ESP_ERROR_CHECK( uart_set_wakeup_threshold(CONFIG_ESP_CONSOLE_UART_NUM, 3) );
uart_wakeup_cfg_t uart_wakeup_cfg = {.wakeup_mode = UART_WK_MODE_ACTIVE_THRESH, .rx_edge_threshold = 3};
ESP_ERROR_CHECK( uart_wakeup_setup(CONFIG_ESP_CONSOLE_UART_NUM, &uart_wakeup_cfg) );
ESP_ERROR_CHECK( esp_sleep_enable_uart_wakeup(CONFIG_ESP_CONSOLE_UART_NUM) );
}
fflush(stdout);
@@ -24,6 +24,7 @@
#include "driver/rtc_io.h"
#include "driver/gpio.h"
#include "driver/uart.h"
#include "driver/uart_wakeup.h"
#include "argtable3/argtable3.h"
#include "cmd_system.h"
#include "sdkconfig.h"
@@ -161,7 +162,8 @@ static int light_sleep(int argc, char **argv)
}
if (CONFIG_ESP_CONSOLE_UART_NUM >= 0 && CONFIG_ESP_CONSOLE_UART_NUM <= UART_NUM_1) {
ESP_LOGI(TAG, "Enabling UART wakeup (press ENTER to exit light sleep)");
ESP_ERROR_CHECK( uart_set_wakeup_threshold(CONFIG_ESP_CONSOLE_UART_NUM, 3) );
uart_wakeup_cfg_t uart_wakeup_cfg = {.wakeup_mode = UART_WK_MODE_ACTIVE_THRESH, .rx_edge_threshold = 3};
ESP_ERROR_CHECK( uart_wakeup_setup(CONFIG_ESP_CONSOLE_UART_NUM, &uart_wakeup_cfg) );
ESP_ERROR_CHECK( esp_sleep_enable_uart_wakeup(CONFIG_ESP_CONSOLE_UART_NUM) );
}
fflush(stdout);
@@ -26,7 +26,8 @@
#define EXAMPLE_UART_BAUDRATE 115200
#endif
#define EXAMPLE_UART_WAKEUP_EDGE_THRESHOLD 3
/* In ESP32, the min wakeup threshold is 2; in ESP32P4, the min wakeup threshold is 6; in other targets, the min wakeup threshold is 3.*/
#define EXAMPLE_UART_WAKEUP_EDGE_THRESHOLD 6
#define EXAMPLE_UART_WAKEUP_FIFO_THRESHOLD 8
#define EXAMPLE_UART_WAKEUP_CHARS_SEQ "ok"
#define EXAMPLE_UART_WAKEUP_CHARS_SEQ_LEN SOC_UART_WAKEUP_CHARS_SEQ_MAX_LEN
@@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: CC0-1.0
import logging
import time
@@ -32,7 +32,7 @@ def test_light_sleep(dut: Dut) -> None:
# enter sleep second time
dut.expect_exact(ENTERING_SLEEP_STR)
match = dut.expect(EXIT_SLEEP_REGEX)
logging.info('Got second sleep period, wakeup from {}, slept for {}'.format(match.group(1), match.group(3)))
logging.info(f'Got second sleep period, wakeup from {match.group(1)}, slept for {match.group(3)}')
# sleep time error should be less than 1ms
# TODO: Need to update sleep overhead_out time for esp32c5 (PM-209)
assert (
@@ -47,7 +47,7 @@ def test_light_sleep(dut: Dut) -> None:
dut.serial.proc.setDTR(True)
time.sleep(1)
match = dut.expect(EXIT_SLEEP_PIN_REGEX)
logging.info('Got third sleep period, wakeup from {}, slept for {}'.format(match.group(1), match.group(3)))
logging.info(f'Got third sleep period, wakeup from {match.group(1)}, slept for {match.group(3)}')
assert int(match.group(3)) < WAKEUP_INTERVAL_MS
dut.expect(WAITING_FOR_GPIO_STR)
@@ -57,11 +57,11 @@ def test_light_sleep(dut: Dut) -> None:
dut.expect_exact(ENTERING_SLEEP_STR)
logging.info('Went to sleep again')
# Write 'a' to uart, 'a' in ascii is 0x61 which contains 3 rising edges in total (including the stop bit)
dut.write('a')
# Write 'tt' to uart, 'tt' in ascii is 0x74 0x74 which contains 6 rising edges in total (including the stop bit)
dut.serial.proc.write(b'tt')
time.sleep(1)
match = dut.expect(EXIT_SLEEP_UART_REGEX)
logging.info('Got third sleep period, wakeup from {}, slept for {}'.format(match.group(1), match.group(3)))
logging.info(f'Got third sleep period, wakeup from {match.group(1)}, slept for {match.group(3)}')
assert int(match.group(3)) < WAKEUP_INTERVAL_MS
logging.info('Went to sleep again')