fix(ulp): fix lp uart keep wakeup triggered

This commit is contained in:
hebinglin
2026-06-05 20:01:15 +08:00
parent ddf8cc3626
commit 46ff88717c
14 changed files with 57 additions and 29 deletions

View File

@@ -1606,3 +1606,7 @@ config SOC_LP_CORE_SUPPORT_I2C
config SOC_LP_CORE_HW_AUTO_CLRWAKEUPCAUSE
bool
default y
config SOC_LP_CORE_LP_UART_WAKEUP_KEEP_TRIGGERED
bool
default y

View File

@@ -639,3 +639,4 @@
#define SOC_LP_CORE_SUPPORT_STORE_LOAD_EXCEPTIONS (1) /*!< LP Core will raise exceptions if accessing invalid addresses */
#define SOC_LP_CORE_SUPPORT_I2C (1) /*!< LP Core supports I2C */
#define SOC_LP_CORE_HW_AUTO_CLRWAKEUPCAUSE (1) /*!< LP core requests sleep, PMU clears both HP and LP wakeup causes */
#define SOC_LP_CORE_LP_UART_WAKEUP_KEEP_TRIGGERED (1) /*!< LP UART wakeup source is kept triggered */

View File

@@ -1343,6 +1343,10 @@ config SOC_LP_CORE_HW_AUTO_CLRWAKEUPCAUSE
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

View File

@@ -544,6 +544,7 @@
#define SOC_LP_CORE_SUPPORT_ETM (1) /*!< LP Core supports ETM */
#define SOC_LP_CORE_SUPPORT_I2C (1) /*!< LP Core supports I2C */
#define SOC_LP_CORE_HW_AUTO_CLRWAKEUPCAUSE (1) /*!< LP core requests sleep, PMU clears both HP and LP wakeup causes */
#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)

View File

@@ -1922,3 +1922,7 @@ config SOC_LP_CORE_SUPPORT_I2C
config SOC_LP_CORE_HW_AUTO_CLRWAKEUPCAUSE
bool
default y
config SOC_LP_CORE_LP_UART_WAKEUP_KEEP_TRIGGERED
bool
default y

View File

@@ -735,3 +735,4 @@
#define SOC_LP_CORE_SUPPORT_STORE_LOAD_EXCEPTIONS (1) /*!< LP Core will raise exceptions if accessing invalid addresses */
#define SOC_LP_CORE_SUPPORT_I2C (1) /*!< LP Core supports I2C */
#define SOC_LP_CORE_HW_AUTO_CLRWAKEUPCAUSE (1) /*!< LP core requests sleep, PMU clears both HP and LP wakeup causes */
#define SOC_LP_CORE_LP_UART_WAKEUP_KEEP_TRIGGERED (1) /*!< LP UART wakeup source is kept triggered */

View File

@@ -1547,6 +1547,10 @@ config SOC_LP_CORE_HAS_PMP
bool
default y
config SOC_LP_CORE_LP_UART_WAKEUP_KEEP_TRIGGERED
bool
default y
config SOC_LP_TIMER_BIT_WIDTH_LO
int
default 32

View File

@@ -576,6 +576,7 @@
#define SOC_LP_CORE_SUPPORT_I2C (1) /*!< LP Core supports I2C */
#define SOC_LP_CORE_HW_AUTO_CLRWAKEUPCAUSE (1) /*!< LP core requests sleep, PMU clears both HP and LP wakeup causes */
#define SOC_LP_CORE_HAS_PMP (1) /*!< LP Core RISC-V has 16 PMP entries (128-byte granularity, RISC-V v1.10) */
#define SOC_LP_CORE_LP_UART_WAKEUP_KEEP_TRIGGERED (1) /*!< LP UART wakeup source is kept triggered */
/*-------------------------- LP_TIMER CAPS ----------------------------------*/
#define SOC_LP_TIMER_BIT_WIDTH_LO 32 // Bit width of lp_timer low part

View File

@@ -25,6 +25,8 @@
#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"
#if SOC_LP_CORE_HW_AUTO_CLRWAKEUPCAUSE
#include "hal/lp_aon_hal.h"
#include "rom/rtc.h"
@@ -32,6 +34,14 @@
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;
@@ -46,6 +56,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
@@ -141,15 +158,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_sleep_start_lp_core(void)
{
#if SOC_LP_CORE_HW_AUTO_CLRWAKEUPCAUSE

View File

@@ -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
*/
@@ -19,9 +19,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.
*
*

View File

@@ -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;
}

View File

@@ -454,9 +454,11 @@ The UART wakeup supports the following modes:
#. 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::
.. only:: SOC_LP_CORE_LP_UART_WAKEUP_KEEP_TRIGGERED
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.
.. 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`.

View File

@@ -454,9 +454,11 @@ 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::
.. only:: SOC_LP_CORE_LP_UART_WAKEUP_KEEP_TRIGGERED
当 LP 核因 LP_UART 唤醒后,必须在 LP 核进入睡眠前调用 :cpp:func:`ulp_lp_core_lp_uart_reset_wakeup_en` 函数或是复位整个 LP UART 模块以清除唤醒信号,否则会被重复唤醒。
.. 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`

View File

@@ -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;
}