diff --git a/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in index 124c29af58e..caf04771c42 100644 --- a/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in @@ -1682,3 +1682,7 @@ config SOC_LP_CORE_SUPPORT_ETM config SOC_LP_CORE_SUPPORT_STORE_LOAD_EXCEPTIONS bool default y + +config SOC_LP_CORE_LP_UART_WAKEUP_KEEP_TRIGGERED + bool + default y diff --git a/components/soc/esp32c5/include/soc/soc_caps.h b/components/soc/esp32c5/include/soc/soc_caps.h index e48b06940fc..c29faf2c3fa 100644 --- a/components/soc/esp32c5/include/soc/soc_caps.h +++ b/components/soc/esp32c5/include/soc/soc_caps.h @@ -673,3 +673,4 @@ #define SOC_LP_CORE_SINGLE_INTERRUPT_VECTOR (1) /*!< LP Core interrupts all map to a single entry in vector table */ #define SOC_LP_CORE_SUPPORT_ETM (1) /*!< LP Core supports ETM */ #define SOC_LP_CORE_SUPPORT_STORE_LOAD_EXCEPTIONS (1) /*!< LP Core will raise exceptions if accessing invalid addresses */ +#define SOC_LP_CORE_LP_UART_WAKEUP_KEEP_TRIGGERED (1) /*!< LP UART wakeup source is kept triggered */ diff --git a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in index 0ff6514c5ca..d45fc08eda1 100644 --- a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in @@ -1431,6 +1431,10 @@ config SOC_LP_CORE_SUPPORT_ETM bool default y +config SOC_LP_CORE_LP_UART_WAKEUP_KEEP_TRIGGERED + bool + default y + config SOC_DEBUG_HAVE_OCD_STUB_BINS bool default y diff --git a/components/soc/esp32c6/include/soc/soc_caps.h b/components/soc/esp32c6/include/soc/soc_caps.h index c0289d7c42b..9f7c074d50d 100644 --- a/components/soc/esp32c6/include/soc/soc_caps.h +++ b/components/soc/esp32c6/include/soc/soc_caps.h @@ -588,6 +588,7 @@ /*------------------------------------- ULP CAPS -------------------------------------*/ #define SOC_LP_CORE_SINGLE_INTERRUPT_VECTOR (1) /*!< LP Core interrupts all map to a single entry in vector table */ #define SOC_LP_CORE_SUPPORT_ETM (1) /*!< LP Core supports ETM */ +#define SOC_LP_CORE_LP_UART_WAKEUP_KEEP_TRIGGERED (1) /*!< LP UART wakeup source is kept triggered */ /*------------------------------------- DEBUG CAPS -------------------------------------*/ #define SOC_DEBUG_HAVE_OCD_STUB_BINS (1) diff --git a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in index 5b79c33908a..314c8116688 100644 --- a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in @@ -1986,3 +1986,7 @@ config SOC_LP_CORE_SUPPORT_LP_ADC config SOC_LP_CORE_SUPPORT_STORE_LOAD_EXCEPTIONS bool default y + +config SOC_LP_CORE_LP_UART_WAKEUP_KEEP_TRIGGERED + bool + default y diff --git a/components/soc/esp32p4/include/soc/soc_caps.h b/components/soc/esp32p4/include/soc/soc_caps.h index 1695ac50a2a..37ac6beee79 100644 --- a/components/soc/esp32p4/include/soc/soc_caps.h +++ b/components/soc/esp32p4/include/soc/soc_caps.h @@ -769,3 +769,4 @@ #define SOC_LP_CORE_SUPPORT_ETM (1) /*!< LP Core supports ETM */ #define SOC_LP_CORE_SUPPORT_LP_ADC (1) /*!< LP ADC can be accessed from the LP-Core */ #define SOC_LP_CORE_SUPPORT_STORE_LOAD_EXCEPTIONS (1) /*!< LP Core will raise exceptions if accessing invalid addresses */ +#define SOC_LP_CORE_LP_UART_WAKEUP_KEEP_TRIGGERED (1) /*!< LP UART wakeup source is kept triggered */ diff --git a/components/ulp/lp_core/lp_core/lp_core_utils.c b/components/ulp/lp_core/lp_core/lp_core_utils.c index c936956fca5..f332ebe9cc4 100644 --- a/components/ulp/lp_core/lp_core/lp_core_utils.c +++ b/components/ulp/lp_core/lp_core/lp_core_utils.c @@ -25,9 +25,19 @@ #include "esp_cpu.h" #include "ulp_lp_core_cpu_freq_shared.h" +#include "ulp_lp_core_lp_uart_shared.h" +#include "ulp_lp_core_uart.h" static uint32_t lp_wakeup_cause = 0; +#if SOC_ULP_LP_UART_SUPPORTED +void ulp_lp_core_lp_uart_reset_wakeup_en(void) +{ + lp_core_ll_enable_lp_uart_wakeup(false); + lp_core_ll_enable_lp_uart_wakeup(true); +} +#endif + void ulp_lp_core_update_wakeup_cause(void) { lp_wakeup_cause = 0; @@ -42,6 +52,13 @@ void ulp_lp_core_update_wakeup_cause(void) && (uart_ll_get_intraw_mask(&LP_UART) & LP_UART_WAKEUP_INT_RAW)) { lp_wakeup_cause |= LP_CORE_LL_WAKEUP_SOURCE_LP_UART; uart_ll_clr_intsts_mask(&LP_UART, LP_UART_WAKEUP_INT_CLR); +#if SOC_LP_CORE_LP_UART_WAKEUP_KEEP_TRIGGERED + // In these chips, the LP UART wakeup source is kept triggered, so we need to + // reset the wakeup register and flush the UART buffer manually after waking up. + lp_core_uart_tx_flush(LP_UART_NUM_0); + lp_core_uart_clear_buf(); + ulp_lp_core_lp_uart_reset_wakeup_en(); +#endif } #endif @@ -133,15 +150,6 @@ void ulp_lp_core_delay_cycles(uint32_t cycles) } } -#if SOC_ULP_LP_UART_SUPPORTED - -void ulp_lp_core_lp_uart_reset_wakeup_en(void) -{ - lp_core_ll_enable_lp_uart_wakeup(false); - lp_core_ll_enable_lp_uart_wakeup(true); -} -#endif - void ulp_lp_core_halt(void) { lp_core_ll_request_sleep(); diff --git a/components/ulp/lp_core/shared/include/ulp_lp_core_lp_uart_shared.h b/components/ulp/lp_core/shared/include/ulp_lp_core_lp_uart_shared.h index 2c8e59bd255..a962c327c84 100644 --- a/components/ulp/lp_core/shared/include/ulp_lp_core_lp_uart_shared.h +++ b/components/ulp/lp_core/shared/include/ulp_lp_core_lp_uart_shared.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -18,9 +18,10 @@ extern "C" { * * @note This function configures the LP UART wakeup mode. Ensure that the UART has already been initialized * with the lp_core_uart_init() call. - * Once the LP Core wakes up due to the LP UART, the wakeup feature is disabled. - * To re-enable the wakeup from the LP UART, you must call - * ulp_lp_core_lp_uart_reset_wakeup_en() again before the LP core goes to sleep. + * Once the LP Core wakes up due to the LP UART, the wakeup will be kept triggered in the chips with + * SOC_LP_CORE_LP_UART_WAKEUP_KEEP_TRIGGERED. You need to call ulp_lp_core_lp_uart_reset_wakeup_en() + * to reset the wakeup signal and the UART buffer manually after waking up, which is done in ulp + * startup phase. * Also be aware of limitations in different modes mentioned in the uart_wakeup_cfg_t struct. * * diff --git a/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/lp_core/test_main_uart_wakeup.c b/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/lp_core/test_main_uart_wakeup.c index 54e2f691881..aecb478f326 100644 --- a/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/lp_core/test_main_uart_wakeup.c +++ b/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/lp_core/test_main_uart_wakeup.c @@ -1,19 +1,17 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #include "ulp_lp_core_utils.h" #include "ulp_lp_core_print.h" -#include "ulp_lp_core_lp_uart_shared.h" -#include "lp_core_uart.h" #include "ulp_lp_core_uart.h" int main(void) { lp_core_printf("Hello world\r\n"); - ulp_lp_core_delay_us(5000); - lp_core_uart_clear_buf(); - ulp_lp_core_lp_uart_reset_wakeup_en(); + lp_core_uart_tx_flush(LP_UART_NUM_0); + + return 0; } diff --git a/docs/en/api-reference/system/sleep_modes.rst b/docs/en/api-reference/system/sleep_modes.rst index ec0637c93c8..4fb0567ca12 100644 --- a/docs/en/api-reference/system/sleep_modes.rst +++ b/docs/en/api-reference/system/sleep_modes.rst @@ -365,6 +365,24 @@ 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. + + .. only:: SOC_LP_CORE_LP_UART_WAKEUP_KEEP_TRIGGERED + + .. note:: + + On chips with ``SOC_LP_CORE_LP_UART_WAKEUP_KEEP_TRIGGERED``, the LP UART wakeup signal remains triggered after a wakeup event. The LP core startup flow (:cpp:func:`ulp_lp_core_update_wakeup_cause`) automatically calls :cpp:func:`ulp_lp_core_lp_uart_reset_wakeup_en` and :cpp:func:`lp_core_uart_clear_buf` to clear this state. If the standard startup flow is not used, you must handle this manually; otherwise, repeated wakeups will occur. + + 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 diff --git a/docs/zh_CN/api-reference/system/sleep_modes.rst b/docs/zh_CN/api-reference/system/sleep_modes.rst index d12de5aafd0..6dfbfea8128 100644 --- a/docs/zh_CN/api-reference/system/sleep_modes.rst +++ b/docs/zh_CN/api-reference/system/sleep_modes.rst @@ -365,6 +365,24 @@ 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 相同。 + + .. only:: SOC_LP_CORE_LP_UART_WAKEUP_KEEP_TRIGGERED + + .. note:: + + 在支持 ``SOC_LP_CORE_LP_UART_WAKEUP_KEEP_TRIGGERED`` 的芯片上,LP UART 唤醒后唤醒信号会保持触发状态。LP 核启动流程(:cpp:func:`ulp_lp_core_update_wakeup_cause`)会自动调用 :cpp:func:`ulp_lp_core_lp_uart_reset_wakeup_en` 和 :cpp:func:`lp_core_uart_clear_buf` 清除该状态。若未走标准启动流程,则需手动处理,否则会被重复唤醒。 + + 有关 LP_UART 唤醒的示例代码,请参考 :example:`system/ulp/lp_core/lp_uart/lp_uart_char_seq_wakeup`。 + .. _disable_sleep_wakeup_source: 禁用睡眠模式唤醒源 diff --git a/examples/system/ulp/lp_core/lp_uart/lp_uart_char_seq_wakeup/main/lp_core/main.c b/examples/system/ulp/lp_core/lp_uart/lp_uart_char_seq_wakeup/main/lp_core/main.c index 0bc04ec231b..237842c54c1 100644 --- a/examples/system/ulp/lp_core/lp_uart/lp_uart_char_seq_wakeup/main/lp_core/main.c +++ b/examples/system/ulp/lp_core/lp_uart/lp_uart_char_seq_wakeup/main/lp_core/main.c @@ -1,20 +1,17 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #include "ulp_lp_core_utils.h" #include "ulp_lp_core_print.h" -#include "ulp_lp_core_lp_uart_shared.h" +#include "ulp_lp_core_uart.h" int main (void) { lp_core_printf("Hello world\r\n"); + lp_core_uart_tx_flush(LP_UART_NUM_0); - // If you want to make it possible to wake up from UART after sleep, - // you have to reset the wakeup register and the UART buffer manually. - // ulp_lp_core_lp_uart_reset_wakeup_en(); - // lp_core_uart_clear_buf(); return 0; }