feat: supports lp uart wakeup

This commit is contained in:
igor.udot 2024-07-08 17:37:08 +08:00
parent cc1819200d
commit f742a05b28
70 changed files with 1830 additions and 99 deletions

View File

@ -3,7 +3,7 @@ idf_build_get_property(target IDF_TARGET)
set(srcs)
set(public_include "include")
if(CONFIG_SOC_UART_SUPPORTED)
list(APPEND srcs "src/uart.c")
list(APPEND srcs "src/uart.c" "src/uart_wakeup.c")
endif()
if(${target} STREQUAL "linux")

View File

@ -0,0 +1,72 @@
/*
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "esp_err.h"
#include "soc/soc_caps.h"
#include "hal/uart_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Structure that holds configuration for UART wakeup.
*
* This structure is used to configure the wakeup behavior for a UART port. The wakeup mode can be
* selected from several options, such as active threshold, FIFO threshold, start bit detection, and
* character sequence detection. The availability of different wakeup modes depends on the SOC capabilities.
*/
typedef struct {
/** Wakeup mode selection */
uart_wakeup_mode_t wakeup_mode;
#if SOC_UART_WAKEUP_SUPPORT_ACTIVE_THRESH_MODE
/** Used in Active threshold wake-up;
related: UART_WK_MODE_ACTIVE_THRESH;
Configures the number of RXD edge changes to wake up the chip.*/
uint16_t rx_edge_threshold;
#endif
#if SOC_UART_WAKEUP_SUPPORT_FIFO_THRESH_MODE
/** Used in Bytes received in RX FIFO wake-up;
related: UART_WK_MODE_FIFO_THRESH;
Configures the number of received data bytes to wake up the chip.*/
uint16_t rx_fifo_threshold;
#endif
#if SOC_UART_WAKEUP_SUPPORT_CHAR_SEQ_MODE
/** Used in Character sequence detection(Trigger phrase) wake-up;
related: UART_WK_MODE_CHAR_SEQ;
'*' represents any symbol.
The end character cannot be '*'.
Example: "he**o" matches hello, heyyo. */
char wake_chars_seq[SOC_UART_WAKEUP_CHARS_SEQ_MAX_LEN];
#endif
} uart_wakeup_cfg_t;
/**
* @brief Initializes the UART wakeup functionality.
*
* This function configures the wakeup behavior for a specified UART port based on the provided configuration.
* The behavior depends on the selected wakeup mode and additional parameters such as active threshold or
* character sequence, if applicable. It is important that the provided configuration matches the capabilities
* of the SOC to ensure proper operation.
*
* @param uart_num The UART port to initialize for wakeup (e.g., UART_NUM_0, UART_NUM_1, etc.).
* @param cfg Pointer to the `uart_wakeup_cfg_t` structure that contains the wakeup configuration settings.
*
* @return
* - `ESP_OK` if the wakeup configuration was successfully applied.
* - `ESP_ERR_INVALID_ARG` if the provided configuration is invalid (e.g., threshold values out of range).
*/
esp_err_t uart_wakeup_setup(uart_port_t uart_num, const uart_wakeup_cfg_t *cfg);
#ifdef __cplusplus
}
#endif

View File

@ -70,7 +70,7 @@ static const char *UART_TAG = "uart";
#define UART_CLKDIV_FRAG_BIT_WIDTH (3)
#define UART_TX_IDLE_NUM_DEFAULT (0)
#define UART_PATTERN_DET_QLEN_DEFAULT (10)
#define UART_MIN_WAKEUP_THRESH (UART_LL_MIN_WAKEUP_THRESH)
#define UART_MIN_WAKEUP_THRESH (UART_LL_WAKEUP_EDGE_THRED_MIN)
#if (SOC_UART_LP_NUM >= 1)
#define UART_THRESHOLD_NUM(uart_num, field_name) ((uart_num < SOC_UART_HP_NUM) ? field_name : LP_##field_name)
@ -1945,7 +1945,7 @@ esp_err_t uart_set_wakeup_threshold(uart_port_t uart_num, int wakeup_threshold)
ESP_RETURN_ON_FALSE((wakeup_threshold <= UART_THRESHOLD_NUM(uart_num, UART_ACTIVE_THRESHOLD_V) && wakeup_threshold >= UART_MIN_WAKEUP_THRESH), ESP_ERR_INVALID_ARG, UART_TAG,
"wakeup_threshold out of bounds");
UART_ENTER_CRITICAL(&(uart_context[uart_num].spinlock));
uart_hal_set_wakeup_thrd(&(uart_context[uart_num].hal), wakeup_threshold);
uart_hal_set_wakeup_edge_thrd(&(uart_context[uart_num].hal), wakeup_threshold);
HP_UART_PAD_CLK_ATOMIC() {
uart_ll_enable_pad_sleep_clock(uart_context[uart_num].hal.dev, true);
}
@ -1957,7 +1957,7 @@ esp_err_t uart_get_wakeup_threshold(uart_port_t uart_num, int *out_wakeup_thresh
{
ESP_RETURN_ON_FALSE((uart_num < UART_NUM_MAX), ESP_ERR_INVALID_ARG, UART_TAG, "uart_num error");
ESP_RETURN_ON_FALSE((out_wakeup_threshold != NULL), ESP_ERR_INVALID_ARG, UART_TAG, "argument is NULL");
uart_hal_get_wakeup_thrd(&(uart_context[uart_num].hal), (uint32_t *)out_wakeup_threshold);
uart_hal_get_wakeup_edge_thrd(&(uart_context[uart_num].hal), (uint32_t *)out_wakeup_threshold);
return ESP_OK;
}

View File

@ -0,0 +1,91 @@
/*
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/*
* WARNING:
*
* This file is shared between the HP and LP cores.
* Updates to this file should be made carefully and should not include FreeRTOS APIs or other IDF-specific functionalities, such as the interrupt allocator.
*/
#include "driver/uart_wakeup.h"
#include "hal/uart_hal.h"
#if SOC_UART_WAKEUP_SUPPORT_CHAR_SEQ_MODE
static esp_err_t uart_char_seq_wk_configure(uart_dev_t *hw, const char* phrase)
{
if (phrase == NULL || phrase[0] == '\0') {
return ESP_ERR_INVALID_ARG;
}
esp_err_t ret = ESP_OK;
uint32_t mask = 0;
uint32_t index = 0;
while (index < SOC_UART_WAKEUP_CHARS_SEQ_MAX_LEN && phrase[index] != '\0') {
if (phrase[index] == '*') {
mask |= 1 << index;
} else {
uart_ll_set_char_seq_wk_char(hw, index, phrase[index]);
}
index++;
}
if (
index == 0 ||
phrase[index - 1] == '*' ||
mask > 0xF
) {
return ESP_ERR_INVALID_ARG;
}
uart_ll_set_wakeup_char_seq_mask(hw, mask);
uart_ll_set_wakeup_char_seq_char_num(hw, index - 1);
return ret;
}
#endif
esp_err_t uart_wakeup_setup(uart_port_t uart_num, const uart_wakeup_cfg_t *cfg)
{
if (cfg == NULL) {
return ESP_ERR_INVALID_ARG;
}
uart_dev_t *hw = UART_LL_GET_HW(uart_num);
// This should be mocked at ll level if the selection of the UART wakeup mode is not supported by this SOC.
uart_ll_set_wakeup_mode(hw, cfg->wakeup_mode);
switch (cfg->wakeup_mode) {
#if SOC_UART_WAKEUP_SUPPORT_ACTIVE_THRESH_MODE
case UART_WK_MODE_ACTIVE_THRESH:
// UART_ACTIVE_THRESHOLD register has only 10 bits, and the min value is 3.
if (cfg->rx_edge_threshold < UART_LL_WAKEUP_EDGE_THRED_MIN || cfg->rx_edge_threshold > UART_LL_WAKEUP_EDGE_THRED_MAX(hw)) {
return ESP_ERR_INVALID_ARG;
}
uart_ll_set_wakeup_edge_thrd(hw, cfg->rx_edge_threshold);
return ESP_OK;
#endif
#if SOC_UART_WAKEUP_SUPPORT_FIFO_THRESH_MODE
case UART_WK_MODE_FIFO_THRESH:
if (cfg->rx_fifo_threshold > UART_LL_WAKEUP_FIFO_THRED_MAX(hw)) {
return ESP_ERR_INVALID_ARG;
}
uart_ll_set_wakeup_fifo_thrd(hw, cfg->rx_fifo_threshold);
return ESP_OK;
#endif
#if SOC_UART_WAKEUP_SUPPORT_START_BIT_MODE
case UART_WK_MODE_START_BIT:
return ESP_OK;
#endif
#if SOC_UART_WAKEUP_SUPPORT_CHAR_SEQ_MODE
case UART_WK_MODE_CHAR_SEQ:
return uart_char_seq_wk_configure(hw, cfg->wake_chars_seq);
#endif
}
return ESP_ERR_INVALID_ARG;
}

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -30,8 +30,10 @@ extern "C" {
// The timeout calibration factor when using ref_tick
#define UART_LL_TOUT_REF_FACTOR_DEFAULT (8)
#define UART_LL_MIN_WAKEUP_THRESH (3)
#define UART_LL_WAKEUP_EDGE_THRED_MIN (3)
#define UART_LL_INTR_MASK (0x7ffff) //All interrupt mask
#define UART_LL_WAKEUP_EDGE_THRED_MAX(hw) UART_ACTIVE_THRESHOLD_V
// Define UART interrupts
typedef enum {
@ -710,13 +712,19 @@ FORCE_INLINE_ATTR void uart_ll_set_dtr_active_level(uart_dev_t *hw, int level)
*
* @return None.
*/
FORCE_INLINE_ATTR void uart_ll_set_wakeup_thrd(uart_dev_t *hw, uint32_t wakeup_thrd)
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+2)
// Note: On ESP32, the minimum UART wakeup threshold is 2 + 1 = 3 (UART_ACTIVE_THRESHOLD set to 0 leads to consecutive triggering wakeup)
hw->sleep_conf.active_threshold = wakeup_thrd - (UART_LL_MIN_WAKEUP_THRESH - 1);
hw->sleep_conf.active_threshold = wakeup_thrd - (UART_LL_WAKEUP_EDGE_THRED_MIN - 1);
}
/**
* @brief Mocking the selection of the UART wakeup mode, as it is not supported by this SOC.
*/
FORCE_INLINE_ATTR void uart_ll_set_wakeup_mode(uart_dev_t *hw, uart_wakeup_mode_t mode)
{}
/**
* @brief Enable/disable the UART pad clock in sleep_state
*
@ -867,9 +875,9 @@ FORCE_INLINE_ATTR void uart_ll_get_at_cmd_char(uart_dev_t *hw, uint8_t *cmd_char
*
* @return The UART wakeup threshold value.
*/
FORCE_INLINE_ATTR uint32_t uart_ll_get_wakeup_thrd(uart_dev_t *hw)
FORCE_INLINE_ATTR uint32_t uart_ll_get_wakeup_edge_thrd(uart_dev_t *hw)
{
return hw->sleep_conf.active_threshold + (UART_LL_MIN_WAKEUP_THRESH - 1);
return hw->sleep_conf.active_threshold + (UART_LL_WAKEUP_EDGE_THRED_MIN - 1);
}
/**

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -29,8 +29,9 @@ extern "C" {
// Get UART hardware instance with giving uart num
#define UART_LL_GET_HW(num) (((num) == UART_NUM_0) ? (&UART0) : (&UART1))
#define UART_LL_MIN_WAKEUP_THRESH (3)
#define UART_LL_WAKEUP_EDGE_THRED_MIN (3)
#define UART_LL_INTR_MASK (0x7ffff) //All interrupt mask
#define UART_LL_WAKEUP_EDGE_THRED_MAX(hw) UART_ACTIVE_THRESHOLD_V
#define UART_LL_FSM_IDLE (0x0)
#define UART_LL_FSM_TX_WAIT_SEND (0xf)
@ -673,12 +674,18 @@ FORCE_INLINE_ATTR void uart_ll_set_dtr_active_level(uart_dev_t *hw, int level)
*
* @return None.
*/
FORCE_INLINE_ATTR void uart_ll_set_wakeup_thrd(uart_dev_t *hw, uint32_t wakeup_thrd)
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_conf.active_threshold = wakeup_thrd - UART_LL_MIN_WAKEUP_THRESH;
hw->sleep_conf.active_threshold = wakeup_thrd - UART_LL_WAKEUP_EDGE_THRED_MIN;
}
/**
* @brief Mocking the selection of the UART wakeup mode, as it is not supported by this SOC.
*/
FORCE_INLINE_ATTR void uart_ll_set_wakeup_mode(uart_dev_t *hw, uart_wakeup_mode_t mode)
{}
/**
* @brief Enable/disable the UART pad clock in sleep_state
*
@ -836,9 +843,9 @@ FORCE_INLINE_ATTR void uart_ll_get_at_cmd_char(uart_dev_t *hw, uint8_t *cmd_char
*
* @return The UART wakeup threshold value.
*/
FORCE_INLINE_ATTR uint32_t uart_ll_get_wakeup_thrd(uart_dev_t *hw)
FORCE_INLINE_ATTR uint32_t uart_ll_get_wakeup_edge_thrd(uart_dev_t *hw)
{
return hw->sleep_conf.active_threshold + UART_LL_MIN_WAKEUP_THRESH;
return hw->sleep_conf.active_threshold + UART_LL_WAKEUP_EDGE_THRED_MIN;
}
/**

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -29,8 +29,9 @@ extern "C" {
// Get UART hardware instance with giving uart num
#define UART_LL_GET_HW(num) (((num) == UART_NUM_0) ? (&UART0) : (&UART1))
#define UART_LL_MIN_WAKEUP_THRESH (3)
#define UART_LL_WAKEUP_EDGE_THRED_MIN (3)
#define UART_LL_INTR_MASK (0x7ffff) //All interrupt mask
#define UART_LL_WAKEUP_EDGE_THRED_MAX(hw) UART_ACTIVE_THRESHOLD_V
#define UART_LL_FSM_IDLE (0x0)
#define UART_LL_FSM_TX_WAIT_SEND (0xf)
@ -676,12 +677,18 @@ FORCE_INLINE_ATTR void uart_ll_set_dtr_active_level(uart_dev_t *hw, int level)
*
* @return None.
*/
FORCE_INLINE_ATTR void uart_ll_set_wakeup_thrd(uart_dev_t *hw, uint32_t wakeup_thrd)
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_conf.active_threshold = wakeup_thrd - UART_LL_MIN_WAKEUP_THRESH;
hw->sleep_conf.active_threshold = wakeup_thrd - UART_LL_WAKEUP_EDGE_THRED_MIN;
}
/**
* @brief Mocking the selection of the UART wakeup mode, as it is not supported by this SOC.
*/
FORCE_INLINE_ATTR void uart_ll_set_wakeup_mode(uart_dev_t *hw, uart_wakeup_mode_t mode)
{}
/**
* @brief Enable/disable the UART pad clock in sleep_state
*
@ -839,9 +846,9 @@ FORCE_INLINE_ATTR void uart_ll_get_at_cmd_char(uart_dev_t *hw, uint8_t *cmd_char
*
* @return The UART wakeup threshold value.
*/
FORCE_INLINE_ATTR uint32_t uart_ll_get_wakeup_thrd(uart_dev_t *hw)
FORCE_INLINE_ATTR uint32_t uart_ll_get_wakeup_edge_thrd(uart_dev_t *hw)
{
return hw->sleep_conf.active_threshold + UART_LL_MIN_WAKEUP_THRESH;
return hw->sleep_conf.active_threshold + UART_LL_WAKEUP_EDGE_THRED_MIN;
}
/**

View File

@ -131,6 +131,14 @@ static inline uint8_t lp_core_ll_get_triggered_interrupt_srcs(void)
return LPPERI.interrupt_source.lp_interrupt_source;
}
/**
* @brief Enable wakeup from LP UART.
*/
static inline void lp_core_ll_enable_lp_uart_wakeup(bool enable)
{
LPPERI.mem_ctrl.uart_wakeup_en = enable;
}
/**
* @brief Get the flag that marks whether LP CPU is awakened by ETM
*

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -32,8 +32,10 @@ extern "C" {
#define UART_LL_GET_HW(num) (((num) == UART_NUM_0) ? (&UART0) : (((num) == UART_NUM_1) ? (&UART1) : (&LP_UART)))
#define UART_LL_REG_FIELD_BIT_SHIFT(hw) (((hw) == &LP_UART) ? 3 : 0)
#define UART_LL_WAKEUP_EDGE_THRED_MAX(hw) (((hw) == &LP_UART) ? LP_UART_ACTIVE_THRESHOLD_V : UART_ACTIVE_THRESHOLD_V )
#define UART_LL_WAKEUP_FIFO_THRED_MAX(hw) (((hw) == &LP_UART) ? LP_UART_RX_WAKE_UP_THRHD_V : UART_RX_WAKE_UP_THRHD_V )
#define UART_LL_MIN_WAKEUP_THRESH (3)
#define UART_LL_WAKEUP_EDGE_THRED_MIN (3)
#define UART_LL_INTR_MASK (0x7ffff) //All interrupt mask
#define UART_LL_FSM_IDLE (0x0)
@ -908,10 +910,114 @@ FORCE_INLINE_ATTR void uart_ll_set_dtr_active_level(uart_dev_t *hw, int level)
*
* @return None.
*/
FORCE_INLINE_ATTR void uart_ll_set_wakeup_thrd(uart_dev_t *hw, uint32_t wakeup_thrd)
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_MIN_WAKEUP_THRESH;
hw->sleep_conf2.active_threshold = wakeup_thrd - UART_LL_WAKEUP_EDGE_THRED_MIN;
}
/**
* @brief Set the number of received data bytes for the RX FIFO threshold wake-up mode.
*
* @param hw Beginning address of the peripheral registers.
* @param wakeup_thrd The wakeup threshold value in bytes to be set.
*
* @return None.
*/
FORCE_INLINE_ATTR void uart_ll_set_wakeup_fifo_thrd(uart_dev_t *hw, uint32_t wakeup_thrd)
{
// System would wakeup when reach the number of the received data number threshold.
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->sleep_conf2, rx_wake_up_thrhd, wakeup_thrd << UART_LL_REG_FIELD_BIT_SHIFT(hw));
}
/**
* @brief Set the UART wakeup mode.
*
* @param hw Beginning address of the peripheral registers.
* @param mode UART wakeup mode to be set.
*
* @return None.
*/
FORCE_INLINE_ATTR void uart_ll_set_wakeup_mode(uart_dev_t *hw, uart_wakeup_mode_t mode)
{
switch(mode){
case UART_WK_MODE_ACTIVE_THRESH:
hw->sleep_conf2.wk_mode_sel = 0;
break;
case UART_WK_MODE_FIFO_THRESH:
hw->sleep_conf2.wk_mode_sel = 1;
break;
case UART_WK_MODE_START_BIT:
hw->sleep_conf2.wk_mode_sel = 2;
break;
case UART_WK_MODE_CHAR_SEQ:
hw->sleep_conf2.wk_mode_sel = 3;
break;
default:
abort();
break;
}
}
/**
* @brief Set the UART specific character sequence wakeup mode mask.
*
* @param hw Beginning address of the peripheral registers.
* @param mask UART wakeup char seq mask to be set.
*
* @return None.
*/
FORCE_INLINE_ATTR void uart_ll_set_wakeup_char_seq_mask(uart_dev_t *hw, uint32_t mask)
{
hw->sleep_conf2.wk_char_mask = mask;
}
/**
* @brief Set the UART specific character sequence wakeup phrase size.
*
* @param hw Beginning address of the peripheral registers.
* @param char_num UART wakeup char seq phrase size to be set.
*
* @return None.
*/
FORCE_INLINE_ATTR void uart_ll_set_wakeup_char_seq_char_num(uart_dev_t *hw, uint32_t char_num)
{
hw->sleep_conf2.wk_char_num = char_num;
}
/**
* @brief Set the UART specific character sequence wakeup mode char.
*
* @param hw Beginning address of the peripheral registers.
* @param char_position UART wakeup char seq char position to be set.
* @param value UART wakeup char seq char value to be set.
*
* @return None.
*/
FORCE_INLINE_ATTR void uart_ll_set_char_seq_wk_char(uart_dev_t *hw, uint32_t char_position, char value)
{
switch (char_position) {
case 0:
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->sleep_conf1, wk_char0, value);
break;
case 1:
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->sleep_conf0, wk_char1, value);
break;
case 2:
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->sleep_conf0, wk_char2, value);
break;
case 3:
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->sleep_conf0, wk_char3, value);
break;
case 4:
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->sleep_conf0, wk_char4, value);
break;
default:
abort();
break;
}
}
/**
@ -1098,9 +1204,9 @@ FORCE_INLINE_ATTR void uart_ll_get_at_cmd_char(uart_dev_t *hw, uint8_t *cmd_char
*
* @return The UART wakeup threshold value.
*/
FORCE_INLINE_ATTR uint32_t uart_ll_get_wakeup_thrd(uart_dev_t *hw)
FORCE_INLINE_ATTR uint32_t uart_ll_get_wakeup_edge_thrd(uart_dev_t *hw)
{
return hw->sleep_conf2.active_threshold + UART_LL_MIN_WAKEUP_THRESH;
return hw->sleep_conf2.active_threshold + UART_LL_WAKEUP_EDGE_THRED_MIN;
}
/**

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -136,6 +136,14 @@ static inline uint8_t lp_core_ll_get_triggered_interrupt_srcs(void)
return LPPERI.interrupt_source.lp_interrupt_source;
}
/**
* @brief Enable wakeup from LP UART.
*/
static inline void lp_core_ll_enable_lp_uart_wakeup(bool enable)
{
LPPERI.mem_ctrl.uart_wakeup_en = enable;
}
/**
* @brief Get the flag that marks whether LP CPU is awakened by ETM
*

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -32,8 +32,10 @@ extern "C" {
#define UART_LL_GET_HW(num) (((num) == UART_NUM_0) ? (&UART0) : (((num) == UART_NUM_1) ? (&UART1) : (&LP_UART)))
#define UART_LL_REG_FIELD_BIT_SHIFT(hw) (((hw) == &LP_UART) ? 3 : 0)
#define UART_LL_WAKEUP_EDGE_THRED_MAX(hw) (((hw) == &LP_UART) ? LP_UART_ACTIVE_THRESHOLD_V : UART_ACTIVE_THRESHOLD_V )
#define UART_LL_WAKEUP_FIFO_THRED_MAX(hw) (((hw) == &LP_UART) ? LP_UART_RX_WAKE_UP_THRHD_V : UART_RX_WAKE_UP_THRHD_V )
#define UART_LL_MIN_WAKEUP_THRESH (3)
#define UART_LL_WAKEUP_EDGE_THRED_MIN (3)
#define UART_LL_INTR_MASK (0x7ffff) //All interrupt mask
#define UART_LL_FSM_IDLE (0x0)
@ -889,10 +891,114 @@ FORCE_INLINE_ATTR void uart_ll_set_dtr_active_level(uart_dev_t *hw, int level)
*
* @return None.
*/
FORCE_INLINE_ATTR void uart_ll_set_wakeup_thrd(uart_dev_t *hw, uint32_t wakeup_thrd)
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_MIN_WAKEUP_THRESH;
hw->sleep_conf2.active_threshold = wakeup_thrd - UART_LL_WAKEUP_EDGE_THRED_MIN;
}
/**
* @brief Set the number of received data bytes for the RX FIFO threshold wake-up mode.
*
* @param hw Beginning address of the peripheral registers.
* @param wakeup_thrd The wakeup threshold value in bytes to be set.
*
* @return None.
*/
FORCE_INLINE_ATTR void uart_ll_set_wakeup_fifo_thrd(uart_dev_t *hw, uint32_t wakeup_thrd)
{
// System would wakeup when reach the number of the received data number threshold.
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->sleep_conf2, rx_wake_up_thrhd, wakeup_thrd << UART_LL_REG_FIELD_BIT_SHIFT(hw));
}
/**
* @brief Set the UART wakeup mode.
*
* @param hw Beginning address of the peripheral registers.
* @param mode UART wakeup mode to be set.
*
* @return None.
*/
FORCE_INLINE_ATTR void uart_ll_set_wakeup_mode(uart_dev_t *hw, uart_wakeup_mode_t mode)
{
switch(mode){
case UART_WK_MODE_ACTIVE_THRESH:
hw->sleep_conf2.wk_mode_sel = 0;
break;
case UART_WK_MODE_FIFO_THRESH:
hw->sleep_conf2.wk_mode_sel = 1;
break;
case UART_WK_MODE_START_BIT:
hw->sleep_conf2.wk_mode_sel = 2;
break;
case UART_WK_MODE_CHAR_SEQ:
hw->sleep_conf2.wk_mode_sel = 3;
break;
default:
abort();
break;
}
}
/**
* @brief Set the UART specific character sequence wakeup mode mask.
*
* @param hw Beginning address of the peripheral registers.
* @param mask UART wakeup char seq mask to be set.
*
* @return None.
*/
FORCE_INLINE_ATTR void uart_ll_set_wakeup_char_seq_mask(uart_dev_t *hw, uint32_t mask)
{
hw->sleep_conf2.wk_char_mask = mask;
}
/**
* @brief Set the UART specific character sequence wakeup phrase size.
*
* @param hw Beginning address of the peripheral registers.
* @param char_num UART wakeup char seq phrase size to be set.
*
* @return None.
*/
FORCE_INLINE_ATTR void uart_ll_set_wakeup_char_seq_char_num(uart_dev_t *hw, uint32_t char_num)
{
hw->sleep_conf2.wk_char_num = char_num;
}
/**
* @brief Set the UART specific character sequence wakeup mode char.
*
* @param hw Beginning address of the peripheral registers.
* @param char_position UART wakeup char seq char position to be set.
* @param value UART wakeup char seq char value to be set.
*
* @return None.
*/
FORCE_INLINE_ATTR void uart_ll_set_char_seq_wk_char(uart_dev_t *hw, uint32_t char_position, char value)
{
switch (char_position) {
case 0:
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->sleep_conf1, wk_char0, value);
break;
case 1:
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->sleep_conf0, wk_char1, value);
break;
case 2:
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->sleep_conf0, wk_char2, value);
break;
case 3:
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->sleep_conf0, wk_char3, value);
break;
case 4:
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->sleep_conf0, wk_char4, value);
break;
default:
abort();
break;
}
}
/**
@ -1079,9 +1185,9 @@ FORCE_INLINE_ATTR void uart_ll_get_at_cmd_char(uart_dev_t *hw, uint8_t *cmd_char
*
* @return The UART wakeup threshold value.
*/
FORCE_INLINE_ATTR uint32_t uart_ll_get_wakeup_thrd(uart_dev_t *hw)
FORCE_INLINE_ATTR uint32_t uart_ll_get_wakeup_edge_thrd(uart_dev_t *hw)
{
return hw->sleep_conf2.active_threshold + UART_LL_MIN_WAKEUP_THRESH;
return hw->sleep_conf2.active_threshold + UART_LL_WAKEUP_EDGE_THRED_MIN;
}
/**

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -30,7 +30,7 @@ extern "C" {
// Get UART hardware instance with giving uart num
#define UART_LL_GET_HW(num) (((num) == UART_NUM_0) ? (&UART0) : (((num) == UART_NUM_1) ? (&UART1) : (&UART2)))
#define UART_LL_MIN_WAKEUP_THRESH (3)
#define UART_LL_WAKEUP_EDGE_THRED_MIN (3)
#define UART_LL_INTR_MASK (0x7ffff) //All interrupt mask
#define UART_LL_FSM_IDLE (0x0)
@ -64,6 +64,9 @@ extern "C" {
((hw) == &UART1) ? PCR.uart1_##reg_suffix.uart1_##field_suffix : \
PCR.uart2_##reg_suffix.uart2_##field_suffix)
#define UART_LL_WAKEUP_EDGE_THRED_MAX(hw) UART_ACTIVE_THRESHOLD_V
#define UART_LL_WAKEUP_FIFO_THRED_MAX(hw) UART_RX_WAKE_UP_THRHD_V
// Define UART interrupts
typedef enum {
UART_INTR_RXFIFO_FULL = (0x1 << 0),
@ -736,9 +739,112 @@ FORCE_INLINE_ATTR void uart_ll_set_dtr_active_level(uart_dev_t *hw, int level)
*
* @return None.
*/
FORCE_INLINE_ATTR void uart_ll_set_wakeup_thrd(uart_dev_t *hw, uint32_t wakeup_thrd)
FORCE_INLINE_ATTR void uart_ll_set_wakeup_edge_thrd(uart_dev_t *hw, uint32_t wakeup_thrd)
{
hw->sleep_conf2.active_threshold = wakeup_thrd - UART_LL_MIN_WAKEUP_THRESH;
hw->sleep_conf2.active_threshold = wakeup_thrd - UART_LL_WAKEUP_EDGE_THRED_MIN;
}
/**
* @brief Set the number of received data bytes for the RX FIFO threshold wake-up mode.
*
* @param hw Beginning address of the peripheral registers.
* @param wakeup_thrd The wakeup threshold value in bytes to be set.
*
* @return None.
*/
FORCE_INLINE_ATTR void uart_ll_set_wakeup_fifo_thrd(uart_dev_t *hw, uint32_t wakeup_thrd)
{
// System would wakeup when reach the number of the received data number threshold.
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->sleep_conf2, rx_wake_up_thrhd, wakeup_thrd);
}
/**
* @brief Set the UART wakeup mode.
*
* @param hw Beginning address of the peripheral registers.
* @param mode UART wakeup mode to be set.
*
* @return None.
*/
FORCE_INLINE_ATTR void uart_ll_set_wakeup_mode(uart_dev_t *hw, uart_wakeup_mode_t mode)
{
switch(mode){
case UART_WK_MODE_ACTIVE_THRESH:
hw->sleep_conf2.wk_mode_sel = 0;
break;
case UART_WK_MODE_FIFO_THRESH:
hw->sleep_conf2.wk_mode_sel = 1;
break;
case UART_WK_MODE_START_BIT:
hw->sleep_conf2.wk_mode_sel = 2;
break;
case UART_WK_MODE_CHAR_SEQ:
hw->sleep_conf2.wk_mode_sel = 3;
break;
default:
abort();
break;
}
}
/**
* @brief Set the UART specific character sequence wakeup mode mask.
*
* @param hw Beginning address of the peripheral registers.
* @param mask UART wakeup char seq mask to be set.
*
* @return None.
*/
FORCE_INLINE_ATTR void uart_ll_set_wakeup_char_seq_mask(uart_dev_t *hw, uint32_t mask)
{
hw->sleep_conf2.wk_char_mask = mask;
}
/**
* @brief Set the UART specific character sequence wakeup phrase size.
*
* @param hw Beginning address of the peripheral registers.
* @param char_num UART wakeup char seq phrase size to be set.
*
* @return None.
*/
FORCE_INLINE_ATTR void uart_ll_set_wakeup_char_seq_char_num(uart_dev_t *hw, uint32_t char_num)
{
hw->sleep_conf2.wk_char_num = char_num;
}
/**
* @brief Set the UART specific character sequence wakeup mode char.
*
* @param hw Beginning address of the peripheral registers.
* @param char_position UART wakeup char seq char position to be set.
* @param value UART wakeup char seq char value to be set.
*
* @return None.
*/
FORCE_INLINE_ATTR void uart_ll_set_char_seq_wk_char(uart_dev_t *hw, uint32_t char_position, char value)
{
switch (char_position) {
case 0:
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->sleep_conf1, wk_char0, value);
break;
case 1:
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->sleep_conf0, wk_char1, value);
break;
case 2:
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->sleep_conf0, wk_char2, value);
break;
case 3:
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->sleep_conf0, wk_char3, value);
break;
case 4:
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->sleep_conf0, wk_char4, value);
break;
default:
abort();
break;
}
}
/**
@ -901,9 +1007,9 @@ FORCE_INLINE_ATTR void uart_ll_get_at_cmd_char(uart_dev_t *hw, uint8_t *cmd_char
*
* @return The UART wakeup threshold value.
*/
FORCE_INLINE_ATTR uint32_t uart_ll_get_wakeup_thrd(uart_dev_t *hw)
FORCE_INLINE_ATTR uint32_t uart_ll_get_wakeup_edge_thrd(uart_dev_t *hw)
{
return hw->sleep_conf2.active_threshold + UART_LL_MIN_WAKEUP_THRESH;
return hw->sleep_conf2.active_threshold + UART_LL_WAKEUP_EDGE_THRED_MIN;
}
/**

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -29,7 +29,7 @@ extern "C" {
// Get UART hardware instance with giving uart num
#define UART_LL_GET_HW(num) (((num) == UART_NUM_0) ? (&UART0) : (&UART1))
#define UART_LL_MIN_WAKEUP_THRESH (3)
#define UART_LL_WAKEUP_EDGE_THRED_MIN (3)
#define UART_LL_INTR_MASK (0x7ffff) //All interrupt mask
#define UART_LL_FSM_IDLE (0x0)
@ -57,6 +57,10 @@ extern "C" {
#define UART_LL_PCR_REG_GET(hw, reg_suffix, field_suffix) \
(((hw) == &UART0) ? PCR.uart0_##reg_suffix.uart0_##field_suffix : PCR.uart1_##reg_suffix.uart1_##field_suffix)
#define UART_LL_WAKEUP_EDGE_THRED_MAX(hw) UART_ACTIVE_THRESHOLD_V
#define UART_LL_WAKEUP_FIFO_THRED_MAX(hw) UART_RX_WAKE_UP_THRHD_V
// Define UART interrupts
typedef enum {
UART_INTR_RXFIFO_FULL = (0x1 << 0),
@ -717,12 +721,116 @@ FORCE_INLINE_ATTR void uart_ll_set_dtr_active_level(uart_dev_t *hw, int level)
*
* @return None.
*/
FORCE_INLINE_ATTR void uart_ll_set_wakeup_thrd(uart_dev_t *hw, uint32_t wakeup_thrd)
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_MIN_WAKEUP_THRESH;
hw->sleep_conf2.active_threshold = wakeup_thrd - UART_LL_WAKEUP_EDGE_THRED_MIN;
}
/**
* @brief Set the number of received data bytes for the RX FIFO threshold wake-up mode.
*
* @param hw Beginning address of the peripheral registers.
* @param wakeup_thrd The wakeup threshold value in bytes to be set.
*
* @return None.
*/
FORCE_INLINE_ATTR void uart_ll_set_wakeup_fifo_thrd(uart_dev_t *hw, uint32_t wakeup_thrd)
{
// System would wakeup when reach the number of the received data number threshold.
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->sleep_conf2, rx_wake_up_thrhd, wakeup_thrd);
}
/**
* @brief Set the UART wakeup mode.
*
* @param hw Beginning address of the peripheral registers.
* @param mode UART wakeup mode to be set.
*
* @return None.
*/
FORCE_INLINE_ATTR void uart_ll_set_wakeup_mode(uart_dev_t *hw, uart_wakeup_mode_t mode)
{
switch(mode){
case UART_WK_MODE_ACTIVE_THRESH:
hw->sleep_conf2.wk_mode_sel = 0;
break;
case UART_WK_MODE_FIFO_THRESH:
hw->sleep_conf2.wk_mode_sel = 1;
break;
case UART_WK_MODE_START_BIT:
hw->sleep_conf2.wk_mode_sel = 2;
break;
case UART_WK_MODE_CHAR_SEQ:
hw->sleep_conf2.wk_mode_sel = 3;
break;
default:
abort();
break;
}
}
/**
* @brief Set the UART specific character sequence wakeup mode mask.
*
* @param hw Beginning address of the peripheral registers.
* @param mask UART wakeup char seq mask to be set.
*
* @return None.
*/
FORCE_INLINE_ATTR void uart_ll_set_wakeup_char_seq_mask(uart_dev_t *hw, uint32_t mask)
{
hw->sleep_conf2.wk_char_mask = mask;
}
/**
* @brief Set the UART specific character sequence wakeup phrase size.
*
* @param hw Beginning address of the peripheral registers.
* @param char_num UART wakeup char seq phrase size to be set.
*
* @return None.
*/
FORCE_INLINE_ATTR void uart_ll_set_wakeup_char_seq_char_num(uart_dev_t *hw, uint32_t char_num)
{
hw->sleep_conf2.wk_char_num = char_num;
}
/**
* @brief Set the UART specific character sequence wakeup mode char.
*
* @param hw Beginning address of the peripheral registers.
* @param char_position UART wakeup char seq char position to be set.
* @param value UART wakeup char seq char value to be set.
*
* @return None.
*/
FORCE_INLINE_ATTR void uart_ll_set_char_seq_wk_char(uart_dev_t *hw, uint32_t char_position, char value)
{
switch (char_position) {
case 0:
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->sleep_conf1, wk_char0, value);
break;
case 1:
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->sleep_conf0, wk_char1, value);
break;
case 2:
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->sleep_conf0, wk_char2, value);
break;
case 3:
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->sleep_conf0, wk_char3, value);
break;
case 4:
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->sleep_conf0, wk_char4, value);
break;
default:
abort();
break;
}
}
/**
* @brief Enable/disable the UART pad clock in sleep_state
*
@ -883,9 +991,9 @@ FORCE_INLINE_ATTR void uart_ll_get_at_cmd_char(uart_dev_t *hw, uint8_t *cmd_char
*
* @return The UART wakeup threshold value.
*/
FORCE_INLINE_ATTR uint32_t uart_ll_get_wakeup_thrd(uart_dev_t *hw)
FORCE_INLINE_ATTR uint32_t uart_ll_get_wakeup_edge_thrd(uart_dev_t *hw)
{
return hw->sleep_conf2.active_threshold + UART_LL_MIN_WAKEUP_THRESH;
return hw->sleep_conf2.active_threshold + UART_LL_WAKEUP_EDGE_THRED_MIN;
}
/**

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -31,7 +31,7 @@ extern "C" {
// Get UART hardware instance with giving uart num
#define UART_LL_GET_HW(num) (((num) == UART_NUM_0) ? (&UART0) : (&UART1))
#define UART_LL_MIN_WAKEUP_THRESH (3)
#define UART_LL_WAKEUP_EDGE_THRED_MIN (3)
#define UART_LL_INTR_MASK (0x7ffff) //All interrupt mask
#define UART_LL_FSM_IDLE (0x0)
@ -63,6 +63,9 @@ extern "C" {
#define UART_LL_SLEEP_RETENTION_MODULE_ID(uart_num) ((uart_num == UART_NUM_0) ? SLEEP_RETENTION_MODULE_UART0 : \
(uart_num == UART_NUM_1) ? SLEEP_RETENTION_MODULE_UART1 : -1)
#define UART_LL_WAKEUP_EDGE_THRED_MAX(hw) UART_ACTIVE_THRESHOLD_V
#define UART_LL_WAKEUP_FIFO_THRED_MAX(hw) UART_RX_WAKE_UP_THRHD_V
// Define UART interrupts
typedef enum {
UART_INTR_RXFIFO_FULL = (0x1 << 0),
@ -721,12 +724,116 @@ FORCE_INLINE_ATTR void uart_ll_set_dtr_active_level(uart_dev_t *hw, int level)
*
* @return None.
*/
FORCE_INLINE_ATTR void uart_ll_set_wakeup_thrd(uart_dev_t *hw, uint32_t wakeup_thrd)
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_MIN_WAKEUP_THRESH;
hw->sleep_conf2.active_threshold = wakeup_thrd - UART_LL_WAKEUP_EDGE_THRED_MIN;
}
/**
* @brief Set the number of received data bytes for the RX FIFO threshold wake-up mode.
*
* @param hw Beginning address of the peripheral registers.
* @param wakeup_thrd The wakeup threshold value in bytes to be set.
*
* @return None.
*/
FORCE_INLINE_ATTR void uart_ll_set_wakeup_fifo_thrd(uart_dev_t *hw, uint32_t wakeup_thrd)
{
// System would wakeup when reach the number of the received data number threshold.
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->sleep_conf2, rx_wake_up_thrhd, wakeup_thrd);
}
/**
* @brief Set the UART wakeup mode.
*
* @param hw Beginning address of the peripheral registers.
* @param mode UART wakeup mode to be set.
*
* @return None.
*/
FORCE_INLINE_ATTR void uart_ll_set_wakeup_mode(uart_dev_t *hw, uart_wakeup_mode_t mode)
{
switch(mode){
case UART_WK_MODE_ACTIVE_THRESH:
hw->sleep_conf2.wk_mode_sel = 0;
break;
case UART_WK_MODE_FIFO_THRESH:
hw->sleep_conf2.wk_mode_sel = 1;
break;
case UART_WK_MODE_START_BIT:
hw->sleep_conf2.wk_mode_sel = 2;
break;
case UART_WK_MODE_CHAR_SEQ:
hw->sleep_conf2.wk_mode_sel = 3;
break;
default:
abort();
break;
}
}
/**
* @brief Set the UART specific character sequence wakeup mode mask.
*
* @param hw Beginning address of the peripheral registers.
* @param mask UART wakeup char seq mask to be set.
*
* @return None.
*/
FORCE_INLINE_ATTR void uart_ll_set_wakeup_char_seq_mask(uart_dev_t *hw, uint32_t mask)
{
hw->sleep_conf2.wk_char_mask = mask;
}
/**
* @brief Set the UART specific character sequence wakeup phrase size.
*
* @param hw Beginning address of the peripheral registers.
* @param char_num UART wakeup char seq phrase size to be set.
*
* @return None.
*/
FORCE_INLINE_ATTR void uart_ll_set_wakeup_char_seq_char_num(uart_dev_t *hw, uint32_t char_num)
{
hw->sleep_conf2.wk_char_num = char_num;
}
/**
* @brief Set the UART specific character sequence wakeup mode char.
*
* @param hw Beginning address of the peripheral registers.
* @param char_position UART wakeup char seq char position to be set.
* @param value UART wakeup char seq char value to be set.
*
* @return None.
*/
FORCE_INLINE_ATTR void uart_ll_set_char_seq_wk_char(uart_dev_t *hw, uint32_t char_position, char value)
{
switch (char_position) {
case 0:
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->sleep_conf1, wk_char0, value);
break;
case 1:
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->sleep_conf0, wk_char1, value);
break;
case 2:
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->sleep_conf0, wk_char2, value);
break;
case 3:
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->sleep_conf0, wk_char3, value);
break;
case 4:
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->sleep_conf0, wk_char4, value);
break;
default:
abort();
break;
}
}
/**
* @brief Enable/disable the UART pad clock in sleep_state
*
@ -887,9 +994,9 @@ FORCE_INLINE_ATTR void uart_ll_get_at_cmd_char(uart_dev_t *hw, uint8_t *cmd_char
*
* @return The UART wakeup threshold value.
*/
FORCE_INLINE_ATTR uint32_t uart_ll_get_wakeup_thrd(uart_dev_t *hw)
FORCE_INLINE_ATTR uint32_t uart_ll_get_wakeup_edge_thrd(uart_dev_t *hw)
{
return hw->sleep_conf2.active_threshold + UART_LL_MIN_WAKEUP_THRESH;
return hw->sleep_conf2.active_threshold + UART_LL_WAKEUP_EDGE_THRED_MIN;
}
/**

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -158,6 +158,14 @@ static inline void lp_core_ll_clear_etm_wakeup_status(void)
LP_SYS.sys_ctrl.lp_core_etm_wakeup_flag_clr = 1;
}
/**
* @brief Enable wakeup from LP UART.
*/
static inline void lp_core_ll_enable_lp_uart_wakeup(bool enable)
{
LPPERI.mem_ctrl.lp_uart_wakeup_en = enable;
}
/**
* @brief Get the flag that marks whether LP CPU is awakened by ETM
*

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -38,8 +38,10 @@ extern "C" {
(num) == 4 ? (&UART4) : (&LP_UART))
#define UART_LL_REG_FIELD_BIT_SHIFT(hw) (((hw) == &LP_UART) ? 3 : 0)
#define UART_LL_WAKEUP_EDGE_THRED_MAX(hw) (((hw) == &LP_UART) ? LP_UART_ACTIVE_THRESHOLD_V : UART_ACTIVE_THRESHOLD_V )
#define UART_LL_WAKEUP_FIFO_THRED_MAX(hw) (((hw) == &LP_UART) ? LP_UART_RX_WAKE_UP_THRHD_V : UART_RX_WAKE_UP_THRHD_V )
#define UART_LL_MIN_WAKEUP_THRESH (3)
#define UART_LL_WAKEUP_EDGE_THRED_MIN (3)
#define UART_LL_INTR_MASK (0x7ffff) //All interrupt mask
#define UART_LL_FSM_IDLE (0x0)
@ -1006,10 +1008,114 @@ FORCE_INLINE_ATTR void uart_ll_set_dtr_active_level(uart_dev_t *hw, int level)
*
* @return None.
*/
FORCE_INLINE_ATTR void uart_ll_set_wakeup_thrd(uart_dev_t *hw, uint32_t wakeup_thrd)
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_MIN_WAKEUP_THRESH;
hw->sleep_conf2.active_threshold = wakeup_thrd - UART_LL_WAKEUP_EDGE_THRED_MIN;
}
/**
* @brief Set the number of received data bytes for the RX FIFO threshold wake-up mode.
*
* @param hw Beginning address of the peripheral registers.
* @param wakeup_thrd The wakeup threshold value in bytes to be set.
*
* @return None.
*/
FORCE_INLINE_ATTR void uart_ll_set_wakeup_fifo_thrd(uart_dev_t *hw, uint32_t wakeup_thrd)
{
// System would wakeup when reach the number of the received data number threshold.
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->sleep_conf2, rx_wake_up_thrhd, wakeup_thrd << UART_LL_REG_FIELD_BIT_SHIFT(hw));
}
/**
* @brief Set the UART wakeup mode.
*
* @param hw Beginning address of the peripheral registers.
* @param mode UART wakeup mode to be set.
*
* @return None.
*/
FORCE_INLINE_ATTR void uart_ll_set_wakeup_mode(uart_dev_t *hw, uart_wakeup_mode_t mode)
{
switch(mode){
case UART_WK_MODE_ACTIVE_THRESH:
hw->sleep_conf2.wk_mode_sel = 0;
break;
case UART_WK_MODE_FIFO_THRESH:
hw->sleep_conf2.wk_mode_sel = 1;
break;
case UART_WK_MODE_START_BIT:
hw->sleep_conf2.wk_mode_sel = 2;
break;
case UART_WK_MODE_CHAR_SEQ:
hw->sleep_conf2.wk_mode_sel = 3;
break;
default:
abort();
break;
}
}
/**
* @brief Set the UART specific character sequence wakeup mode mask.
*
* @param hw Beginning address of the peripheral registers.
* @param mask UART wakeup char seq mask to be set.
*
* @return None.
*/
FORCE_INLINE_ATTR void uart_ll_set_wakeup_char_seq_mask(uart_dev_t *hw, uint32_t mask)
{
hw->sleep_conf2.wk_char_mask = mask;
}
/**
* @brief Set the UART specific character sequence wakeup phrase size.
*
* @param hw Beginning address of the peripheral registers.
* @param char_num UART wakeup char seq phrase size to be set.
*
* @return None.
*/
FORCE_INLINE_ATTR void uart_ll_set_wakeup_char_seq_char_num(uart_dev_t *hw, uint32_t char_num)
{
hw->sleep_conf2.wk_char_num = char_num;
}
/**
* @brief Set the UART specific character sequence wakeup mode char.
*
* @param hw Beginning address of the peripheral registers.
* @param char_position UART wakeup char seq char position to be set.
* @param value UART wakeup char seq char value to be set.
*
* @return None.
*/
FORCE_INLINE_ATTR void uart_ll_set_char_seq_wk_char(uart_dev_t *hw, uint32_t char_position, char value)
{
switch (char_position) {
case 0:
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->sleep_conf1, wk_char0, value);
break;
case 1:
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->sleep_conf0, wk_char1, value);
break;
case 2:
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->sleep_conf0, wk_char2, value);
break;
case 3:
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->sleep_conf0, wk_char3, value);
break;
case 4:
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->sleep_conf0, wk_char4, value);
break;
default:
abort();
break;
}
}
/**
@ -1209,9 +1315,9 @@ FORCE_INLINE_ATTR void uart_ll_get_at_cmd_char(uart_dev_t *hw, uint8_t *cmd_char
*
* @return The UART wakeup threshold value.
*/
FORCE_INLINE_ATTR uint32_t uart_ll_get_wakeup_thrd(uart_dev_t *hw)
FORCE_INLINE_ATTR uint32_t uart_ll_get_wakeup_edge_thrd(uart_dev_t *hw)
{
return hw->sleep_conf2.active_threshold + UART_LL_MIN_WAKEUP_THRESH;
return hw->sleep_conf2.active_threshold + UART_LL_WAKEUP_EDGE_THRED_MIN;
}
/**

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -28,8 +28,9 @@ extern "C" {
// Get UART hardware instance with giving uart num
#define UART_LL_GET_HW(num) (((num) == UART_NUM_0) ? (&UART0) : (&UART1))
#define UART_LL_MIN_WAKEUP_THRESH (3)
#define UART_LL_WAKEUP_EDGE_THRED_MIN (3)
#define UART_LL_INTR_MASK (0x7ffff) //All interrupt mask
#define UART_LL_WAKEUP_EDGE_THRED_MAX(hw) UART_ACTIVE_THRESHOLD_V
// Define UART interrupts
typedef enum {
@ -651,12 +652,18 @@ FORCE_INLINE_ATTR void uart_ll_set_dtr_active_level(uart_dev_t *hw, int level)
*
* @return None.
*/
FORCE_INLINE_ATTR void uart_ll_set_wakeup_thrd(uart_dev_t *hw, uint32_t wakeup_thrd)
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_conf.active_threshold = wakeup_thrd - UART_LL_MIN_WAKEUP_THRESH;
hw->sleep_conf.active_threshold = wakeup_thrd - UART_LL_WAKEUP_EDGE_THRED_MIN;
}
/**
* @brief Mocking the selection of the UART wakeup mode, as it is not supported by this SOC.
*/
FORCE_INLINE_ATTR void uart_ll_set_wakeup_mode(uart_dev_t *hw, uart_wakeup_mode_t mode)
{}
/**
* @brief Enable/disable the UART pad clock in sleep_state
*
@ -807,9 +814,9 @@ FORCE_INLINE_ATTR void uart_ll_get_at_cmd_char(uart_dev_t *hw, uint8_t *cmd_char
*
* @return The UART wakeup threshold value.
*/
FORCE_INLINE_ATTR uint32_t uart_ll_get_wakeup_thrd(uart_dev_t *hw)
FORCE_INLINE_ATTR uint32_t uart_ll_get_wakeup_edge_thrd(uart_dev_t *hw)
{
return hw->sleep_conf.active_threshold + UART_LL_MIN_WAKEUP_THRESH;
return hw->sleep_conf.active_threshold + UART_LL_WAKEUP_EDGE_THRED_MIN;
}
/**

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -29,8 +29,9 @@ extern "C" {
// Get UART hardware instance with giving uart num
#define UART_LL_GET_HW(num) (((num) == UART_NUM_0) ? (&UART0) : (((num) == UART_NUM_1) ? (&UART1) : (&UART2)))
#define UART_LL_MIN_WAKEUP_THRESH (3)
#define UART_LL_WAKEUP_EDGE_THRED_MIN (3)
#define UART_LL_INTR_MASK (0x7ffff) //All interrupt mask
#define UART_LL_WAKEUP_EDGE_THRED_MAX(hw) UART_ACTIVE_THRESHOLD_V
#define UART_LL_FSM_IDLE (0x0)
#define UART_LL_FSM_TX_WAIT_SEND (0xf)
@ -679,12 +680,18 @@ FORCE_INLINE_ATTR void uart_ll_set_dtr_active_level(uart_dev_t *hw, int level)
*
* @return None.
*/
FORCE_INLINE_ATTR void uart_ll_set_wakeup_thrd(uart_dev_t *hw, uint32_t wakeup_thrd)
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_conf.active_threshold = wakeup_thrd - UART_LL_MIN_WAKEUP_THRESH;
hw->sleep_conf.active_threshold = wakeup_thrd - UART_LL_WAKEUP_EDGE_THRED_MIN;
}
/**
* @brief Mocking the selection of the UART wakeup mode, as it is not supported by this SOC.
*/
FORCE_INLINE_ATTR void uart_ll_set_wakeup_mode(uart_dev_t *hw, uart_wakeup_mode_t mode)
{}
/**
* @brief Enable/disable the UART pad clock in sleep_state
*
@ -835,9 +842,9 @@ FORCE_INLINE_ATTR void uart_ll_get_at_cmd_char(uart_dev_t *hw, uint8_t *cmd_char
*
* @return The UART wakeup threshold value.
*/
FORCE_INLINE_ATTR uint32_t uart_ll_get_wakeup_thrd(uart_dev_t *hw)
FORCE_INLINE_ATTR uint32_t uart_ll_get_wakeup_edge_thrd(uart_dev_t *hw)
{
return hw->sleep_conf.active_threshold + UART_LL_MIN_WAKEUP_THRESH;
return hw->sleep_conf.active_threshold + UART_LL_WAKEUP_EDGE_THRED_MIN;
}
/**

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -202,7 +202,7 @@ void uart_hal_init(uart_hal_context_t *hal, uart_port_t uart_num);
* @brief Get the UART source clock type
*
* @param hal Context of the HAL layer
* @param sclk The poiter to accept the UART source clock type
* @param sclk The pointer to accept the UART source clock type
*
* @return None
*/
@ -341,7 +341,7 @@ void uart_hal_tx_break(uart_hal_context_t *hal, uint32_t break_num);
*
* @return None
*/
void uart_hal_set_wakeup_thrd(uart_hal_context_t *hal, uint32_t wakeup_thrd);
void uart_hal_set_wakeup_edge_thrd(uart_hal_context_t *hal, uint32_t wakeup_thrd);
/**
* @brief Configure the UART mode
@ -357,7 +357,7 @@ void uart_hal_set_mode(uart_hal_context_t *hal, uart_mode_t mode);
* @brief Configure the UART hardware to inverse the signals
*
* @param hal Context of the HAL layer
* @param inv_mask The sigal mask needs to be inversed. Use the ORred mask of type `uart_signal_inv_t`
* @param inv_mask The signal mask needs to be inversed. Use the ORred mask of type `uart_signal_inv_t`
*
* @return None
*/
@ -371,7 +371,7 @@ void uart_hal_inverse_signal(uart_hal_context_t *hal, uint32_t inv_mask);
*
* @return None
*/
void uart_hal_get_wakeup_thrd(uart_hal_context_t *hal, uint32_t *wakeup_thrd);
void uart_hal_get_wakeup_edge_thrd(uart_hal_context_t *hal, uint32_t *wakeup_thrd);
/**
* @brief Get the UART data bit configuration
@ -437,7 +437,7 @@ bool uart_hal_is_hw_rts_en(uart_hal_context_t *hal);
* @brief Configure TX signal loop back to RX module, just for the testing purposes
*
* @param hal Context of the HAL layer
* @param loop_back_en Set ture to enable the loop back function, else set it false.
* @param loop_back_en Set true to enable the loop back function, else set it false.
*
* @return None
*/

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -140,6 +140,26 @@ typedef struct {
uint8_t xoff_thrd; /*!< If the software flow control is enabled and the data amount in rxfifo is more than xoff_thrd, an xoff_char will be sent*/
} uart_sw_flowctrl_t;
/**
* @brief Enumeration of UART wake-up modes.
*/
typedef enum {
#if SOC_UART_WAKEUP_SUPPORT_ACTIVE_THRESH_MODE
UART_WK_MODE_ACTIVE_THRESH = 0, /*!< Wake-up triggered by active edge threshold */
#endif
#if SOC_UART_WAKEUP_SUPPORT_FIFO_THRESH_MODE
UART_WK_MODE_FIFO_THRESH = 1, /*!< Wake-up triggered by the number of bytes received in the RX FIFO */
#endif
#if SOC_UART_WAKEUP_SUPPORT_START_BIT_MODE
UART_WK_MODE_START_BIT = 2, /*!< Wake-up triggered by the detection of a start bit */
#endif
#if SOC_UART_WAKEUP_SUPPORT_CHAR_SEQ_MODE
UART_WK_MODE_CHAR_SEQ = 3 /*!< Wake-up triggered by detecting a specific character sequence */
#endif
} uart_wakeup_mode_t;
#ifdef __cplusplus
}
#endif

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -88,14 +88,14 @@ void uart_hal_set_txfifo_empty_thr(uart_hal_context_t *hal, uint32_t empty_thrhd
uart_ll_set_txfifo_empty_thr(hal->dev, empty_thrhd);
}
void uart_hal_set_wakeup_thrd(uart_hal_context_t *hal, uint32_t wakeup_thrd)
void uart_hal_set_wakeup_edge_thrd(uart_hal_context_t *hal, uint32_t wakeup_thrd)
{
uart_ll_set_wakeup_thrd(hal->dev, wakeup_thrd);
uart_ll_set_wakeup_edge_thrd(hal->dev, wakeup_thrd);
}
void uart_hal_get_wakeup_thrd(uart_hal_context_t *hal, uint32_t *wakeup_thrd)
void uart_hal_get_wakeup_edge_thrd(uart_hal_context_t *hal, uint32_t *wakeup_thrd)
{
*wakeup_thrd = uart_ll_get_wakeup_thrd(hal->dev);
*wakeup_thrd = uart_ll_get_wakeup_edge_thrd(hal->dev);
}
void uart_hal_set_mode(uart_hal_context_t *hal, uart_mode_t mode)

View File

@ -775,6 +775,10 @@ config SOC_UART_BITRATE_MAX
int
default 5000000
config SOC_UART_WAKEUP_SUPPORT_ACTIVE_THRESH_MODE
bool
default y
config SOC_SPIRAM_SUPPORTED
bool
default y

View File

@ -356,6 +356,8 @@
#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_WAKEUP_SUPPORT_ACTIVE_THRESH_MODE (1)
/*-------------------------- SPIRAM CAPS -------------------------------------*/
#define SOC_SPIRAM_SUPPORTED 1

View File

@ -699,6 +699,10 @@ config SOC_UART_SUPPORT_FSM_TX_WAIT_SEND
bool
default y
config SOC_UART_WAKEUP_SUPPORT_ACTIVE_THRESH_MODE
bool
default y
config SOC_SUPPORT_COEXISTENCE
bool
default y

View File

@ -307,6 +307,8 @@
// 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_WAKEUP_SUPPORT_ACTIVE_THRESH_MODE (1)
/*-------------------------- COEXISTENCE CAPS -------------------------------*/
#define SOC_SUPPORT_COEXISTENCE (1)

View File

@ -1003,6 +1003,10 @@ config SOC_UART_SUPPORT_FSM_TX_WAIT_SEND
bool
default y
config SOC_UART_WAKEUP_SUPPORT_ACTIVE_THRESH_MODE
bool
default y
config SOC_COEX_HW_PTI
bool
default y

View File

@ -418,6 +418,8 @@
// 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_WAKEUP_SUPPORT_ACTIVE_THRESH_MODE (1)
/*-------------------------- COEXISTENCE HARDWARE PTI CAPS -------------------------------*/
#define SOC_COEX_HW_PTI (1)

View File

@ -1399,6 +1399,26 @@ config SOC_UART_SUPPORT_FSM_TX_WAIT_SEND
bool
default y
config SOC_UART_WAKEUP_CHARS_SEQ_MAX_LEN
int
default 5
config SOC_UART_WAKEUP_SUPPORT_ACTIVE_THRESH_MODE
bool
default y
config SOC_UART_WAKEUP_SUPPORT_FIFO_THRESH_MODE
bool
default y
config SOC_UART_WAKEUP_SUPPORT_START_BIT_MODE
bool
default y
config SOC_UART_WAKEUP_SUPPORT_CHAR_SEQ_MODE
bool
default y
config SOC_COEX_HW_PTI
bool
default y

View File

@ -562,6 +562,12 @@
// 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_WAKEUP_CHARS_SEQ_MAX_LEN 5
#define SOC_UART_WAKEUP_SUPPORT_ACTIVE_THRESH_MODE (1)
#define SOC_UART_WAKEUP_SUPPORT_FIFO_THRESH_MODE (1)
#define SOC_UART_WAKEUP_SUPPORT_START_BIT_MODE (1)
#define SOC_UART_WAKEUP_SUPPORT_CHAR_SEQ_MODE (1)
/*-------------------------- COEXISTENCE HARDWARE PTI CAPS -------------------------------*/
#define SOC_COEX_HW_PTI (1)

View File

@ -1343,6 +1343,26 @@ config SOC_UART_SUPPORT_FSM_TX_WAIT_SEND
bool
default y
config SOC_UART_WAKEUP_CHARS_SEQ_MAX_LEN
int
default 5
config SOC_UART_WAKEUP_SUPPORT_ACTIVE_THRESH_MODE
bool
default y
config SOC_UART_WAKEUP_SUPPORT_FIFO_THRESH_MODE
bool
default y
config SOC_UART_WAKEUP_SUPPORT_START_BIT_MODE
bool
default y
config SOC_UART_WAKEUP_SUPPORT_CHAR_SEQ_MODE
bool
default y
config SOC_COEX_HW_PTI
bool
default y

View File

@ -519,7 +519,14 @@
// 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_WAKEUP_CHARS_SEQ_MAX_LEN 5
#define SOC_UART_WAKEUP_SUPPORT_ACTIVE_THRESH_MODE (1)
#define SOC_UART_WAKEUP_SUPPORT_FIFO_THRESH_MODE (1)
#define SOC_UART_WAKEUP_SUPPORT_START_BIT_MODE (1)
#define SOC_UART_WAKEUP_SUPPORT_CHAR_SEQ_MODE (1)
// TODO: IDF-5679 (Copy from esp32c3, need check)
/*-------------------------- COEXISTENCE HARDWARE PTI CAPS -------------------------------*/
#define SOC_COEX_HW_PTI (1)

View File

@ -1023,6 +1023,26 @@ config SOC_UART_SUPPORT_FSM_TX_WAIT_SEND
bool
default y
config SOC_UART_WAKEUP_CHARS_SEQ_MAX_LEN
int
default 5
config SOC_UART_WAKEUP_SUPPORT_ACTIVE_THRESH_MODE
bool
default y
config SOC_UART_WAKEUP_SUPPORT_FIFO_THRESH_MODE
bool
default y
config SOC_UART_WAKEUP_SUPPORT_START_BIT_MODE
bool
default y
config SOC_UART_WAKEUP_SUPPORT_CHAR_SEQ_MODE
bool
default y
config SOC_COEX_HW_PTI
bool
default y

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -421,6 +421,12 @@
// 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_WAKEUP_CHARS_SEQ_MAX_LEN 5
#define SOC_UART_WAKEUP_SUPPORT_ACTIVE_THRESH_MODE (1)
#define SOC_UART_WAKEUP_SUPPORT_FIFO_THRESH_MODE (1)
#define SOC_UART_WAKEUP_SUPPORT_START_BIT_MODE (1)
#define SOC_UART_WAKEUP_SUPPORT_CHAR_SEQ_MODE (1)
// TODO: IDF-5679 (Copy from esp32c3, need check)
/*-------------------------- COEXISTENCE HARDWARE PTI CAPS -------------------------------*/
#define SOC_COEX_HW_PTI (1)

View File

@ -1347,6 +1347,26 @@ config SOC_UART_SUPPORT_SLEEP_RETENTION
bool
default y
config SOC_UART_WAKEUP_CHARS_SEQ_MAX_LEN
int
default 5
config SOC_UART_WAKEUP_SUPPORT_ACTIVE_THRESH_MODE
bool
default y
config SOC_UART_WAKEUP_SUPPORT_FIFO_THRESH_MODE
bool
default y
config SOC_UART_WAKEUP_SUPPORT_START_BIT_MODE
bool
default y
config SOC_UART_WAKEUP_SUPPORT_CHAR_SEQ_MODE
bool
default y
config SOC_COEX_HW_PTI
bool
default y

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -540,6 +540,12 @@
#define SOC_UART_SUPPORT_SLEEP_RETENTION (1) /*!< Support back up registers before sleep */
#define SOC_UART_WAKEUP_CHARS_SEQ_MAX_LEN 5
#define SOC_UART_WAKEUP_SUPPORT_ACTIVE_THRESH_MODE (1)
#define SOC_UART_WAKEUP_SUPPORT_FIFO_THRESH_MODE (1)
#define SOC_UART_WAKEUP_SUPPORT_START_BIT_MODE (1)
#define SOC_UART_WAKEUP_SUPPORT_CHAR_SEQ_MODE (1)
// TODO: IDF-5679 (Copy from esp32c6, need check)
/*-------------------------- COEXISTENCE HARDWARE PTI CAPS -------------------------------*/
#define SOC_COEX_HW_PTI (1)

View File

@ -591,6 +591,26 @@ config SOC_UART_SUPPORT_FSM_TX_WAIT_SEND
bool
default y
config SOC_UART_WAKEUP_CHARS_SEQ_MAX_LEN
int
default 5
config SOC_UART_WAKEUP_SUPPORT_ACTIVE_THRESH_MODE
bool
default y
config SOC_UART_WAKEUP_SUPPORT_FIFO_THRESH_MODE
bool
default y
config SOC_UART_WAKEUP_SUPPORT_START_BIT_MODE
bool
default y
config SOC_UART_WAKEUP_SUPPORT_CHAR_SEQ_MODE
bool
default y
config SOC_COEX_HW_PTI
bool
default y

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -501,6 +501,12 @@
// #define SOC_UART_SUPPORT_SLEEP_RETENTION (1) /*!< Support back up registers before sleep */
#define SOC_UART_WAKEUP_CHARS_SEQ_MAX_LEN 5
#define SOC_UART_WAKEUP_SUPPORT_ACTIVE_THRESH_MODE (1)
#define SOC_UART_WAKEUP_SUPPORT_FIFO_THRESH_MODE (1)
#define SOC_UART_WAKEUP_SUPPORT_START_BIT_MODE (1)
#define SOC_UART_WAKEUP_SUPPORT_CHAR_SEQ_MODE (1)
/*-------------------------- COEXISTENCE HARDWARE PTI CAPS -------------------------------*/
#define SOC_COEX_HW_PTI (1)

View File

@ -1899,6 +1899,26 @@ config SOC_UART_SUPPORT_FSM_TX_WAIT_SEND
bool
default y
config SOC_UART_WAKEUP_CHARS_SEQ_MAX_LEN
int
default 5
config SOC_UART_WAKEUP_SUPPORT_ACTIVE_THRESH_MODE
bool
default y
config SOC_UART_WAKEUP_SUPPORT_FIFO_THRESH_MODE
bool
default y
config SOC_UART_WAKEUP_SUPPORT_START_BIT_MODE
bool
default y
config SOC_UART_WAKEUP_SUPPORT_CHAR_SEQ_MODE
bool
default y
config SOC_LP_I2S_SUPPORT_VAD
bool
default y

View File

@ -698,6 +698,12 @@
// 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_WAKEUP_CHARS_SEQ_MAX_LEN 5
#define SOC_UART_WAKEUP_SUPPORT_ACTIVE_THRESH_MODE (1)
#define SOC_UART_WAKEUP_SUPPORT_FIFO_THRESH_MODE (1)
#define SOC_UART_WAKEUP_SUPPORT_START_BIT_MODE (1)
#define SOC_UART_WAKEUP_SUPPORT_CHAR_SEQ_MODE (1)
/*-------------------------- LP_VAD CAPS -------------------------------------*/
#define SOC_LP_I2S_SUPPORT_VAD (1)

View File

@ -1,5 +1,5 @@
/**
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/

View File

@ -895,6 +895,10 @@ config SOC_UART_BITRATE_MAX
int
default 5000000
config SOC_UART_WAKEUP_SUPPORT_ACTIVE_THRESH_MODE
bool
default y
config SOC_SPIRAM_SUPPORTED
bool
default y

View File

@ -369,6 +369,8 @@
#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_WAKEUP_SUPPORT_ACTIVE_THRESH_MODE (1)
/*-------------------------- SPIRAM CAPS -------------------------------------*/
#define SOC_SPIRAM_SUPPORTED 1
#define SOC_SPIRAM_XIP_SUPPORTED 1

View File

@ -1103,6 +1103,10 @@ config SOC_UART_SUPPORT_XTAL_CLK
bool
default y
config SOC_UART_WAKEUP_SUPPORT_ACTIVE_THRESH_MODE
bool
default y
config SOC_USB_OTG_PERIPH_NUM
int
default 1

View File

@ -423,6 +423,8 @@
#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_WAKEUP_SUPPORT_ACTIVE_THRESH_MODE (1)
/*-------------------------- USB CAPS ----------------------------------------*/
#define SOC_USB_OTG_PERIPH_NUM (1U)

View File

@ -56,7 +56,9 @@ if(CONFIG_ULP_COPROC_TYPE_LP_CORE)
"lp_core/shared/ulp_lp_core_critical_section_shared.c")
if(CONFIG_SOC_ULP_LP_UART_SUPPORTED)
list(APPEND srcs "lp_core/lp_core_uart.c")
list(APPEND srcs
"lp_core/lp_core_uart.c"
"lp_core/shared/ulp_lp_core_lp_uart_shared.c")
endif()
if(CONFIG_SOC_LP_I2C_SUPPORTED)

View File

@ -113,6 +113,8 @@ function(ulp_apply_default_sources ulp_app_name)
"${IDF_PATH}/components/ulp/lp_core/lp_core/vector.S"
"${IDF_PATH}/components/ulp/lp_core/lp_core/port/${IDF_TARGET}/vector_table.S"
"${IDF_PATH}/components/ulp/lp_core/shared/ulp_lp_core_memory_shared.c"
"${IDF_PATH}/components/ulp/lp_core/shared/ulp_lp_core_lp_uart_shared.c"
"${IDF_PATH}/components/esp_driver_uart/src/uart_wakeup.c"
"${IDF_PATH}/components/ulp/lp_core/shared/ulp_lp_core_lp_timer_shared.c"
"${IDF_PATH}/components/ulp/lp_core/lp_core/lp_core_startup.c"
"${IDF_PATH}/components/ulp/lp_core/lp_core/lp_core_utils.c"

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -118,6 +118,12 @@ esp_err_t ulp_lp_core_run(ulp_lp_core_cfg_t* cfg)
lp_core_ll_hp_wake_lp();
}
#if SOC_ULP_LP_UART_SUPPORTED
if (cfg->wakeup_source & ULP_LP_CORE_WAKEUP_SOURCE_LP_UART) {
lp_core_ll_enable_lp_uart_wakeup(true);
}
#endif
#if SOC_LP_TIMER_SUPPORTED
ulp_lp_core_memory_shared_cfg_t* shared_mem = ulp_lp_core_memory_shared_cfg_get();
@ -133,11 +139,6 @@ esp_err_t ulp_lp_core_run(ulp_lp_core_cfg_t* cfg)
}
#endif
if (cfg->wakeup_source & (ULP_LP_CORE_WAKEUP_SOURCE_LP_UART)) {
ESP_LOGE(TAG, "Wake-up source not yet supported");
return ESP_ERR_INVALID_ARG;
}
return ESP_OK;
}

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -13,6 +13,7 @@ extern "C" {
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>
#include "soc/soc_caps.h"
/**
* @brief Traverse all possible wake-up sources and update the wake-up cause so that
@ -52,6 +53,13 @@ void ulp_lp_core_delay_us(uint32_t us);
*/
void ulp_lp_core_delay_cycles(uint32_t cycles);
#if SOC_ULP_LP_UART_SUPPORTED
/**
* @brief Reset LP CORE uart wakeup enable.
*/
void ulp_lp_core_lp_uart_reset_wakeup_en(void);
#endif
/**
* @brief Finishes the ULP program and powers down the ULP
* until next wakeup.

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -48,11 +48,13 @@ void ulp_lp_core_update_wakeup_cause(void)
pmu_ll_lp_clear_intsts_mask(&PMU, PMU_HP_SW_TRIGGER_INT_CLR);
}
#if SOC_ULP_LP_UART_SUPPORTED
if ((lp_core_ll_get_wakeup_source() & LP_CORE_LL_WAKEUP_SOURCE_LP_UART) \
&& (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);
}
#endif
if ((lp_core_ll_get_wakeup_source() & LP_CORE_LL_WAKEUP_SOURCE_LP_IO) \
&& rtcio_ll_get_interrupt_status()) {
@ -137,6 +139,15 @@ 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();

View File

@ -0,0 +1,41 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "esp_err.h"
#include "soc/soc_caps.h"
#include "driver/uart_wakeup.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Initialize and configure the LP UART wakeup mode.
*
* @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.
* Also be aware of limitations in different modes mentioned in the uart_wakeup_cfg_t struct.
*
*
* @param cfg Configuration for LP UART wakeup mode.
* @return esp_err_t ESP_OK when successful
*/
esp_err_t lp_core_uart_wakeup_setup(const uart_wakeup_cfg_t *cfg);
/**
* @brief Clear LP UART rx tx buffer.
*
* @note Clear LP UART rx tx buffer.
*/
void lp_core_uart_clear_buf(void);
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,24 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "ulp_lp_core_lp_uart_shared.h"
#include "hal/uart_hal.h"
/* LP UART HAL Context */
static uart_hal_context_t hal = {
.dev = (uart_dev_t *)UART_LL_GET_HW(LP_UART_NUM_0),
};
esp_err_t lp_core_uart_wakeup_setup(const uart_wakeup_cfg_t *cfg)
{
return uart_wakeup_setup(LP_UART_NUM_0, cfg);
}
void lp_core_uart_clear_buf(void)
{
/* Reset Tx/Rx FIFOs */
uart_ll_rxfifo_rst(hal.dev);
uart_ll_txfifo_rst(hal.dev);
}

View File

@ -6,6 +6,7 @@ endif()
if(CONFIG_SOC_ULP_LP_UART_SUPPORTED)
list(APPEND app_sources "test_lp_core_uart.c")
list(APPEND app_sources "test_lp_core_uart_wakeup.c")
endif()
if(CONFIG_SOC_LP_SPI_SUPPORTED)
@ -41,6 +42,7 @@ endif()
if(CONFIG_SOC_ULP_LP_UART_SUPPORTED)
set(lp_core_sources_uart "lp_core/test_main_uart.c")
set(lp_core_sources_uart_wakeup "lp_core/test_main_uart_wakeup.c")
endif()
if(CONFIG_SOC_LP_SPI_SUPPORTED)
@ -80,6 +82,7 @@ endif()
if(CONFIG_SOC_ULP_LP_UART_SUPPORTED)
ulp_embed_binary(lp_core_test_app_uart "${lp_core_sources_uart}" "${lp_core_exp_dep_srcs}")
ulp_embed_binary(lp_core_test_app_uart_wakeup "${lp_core_sources_uart_wakeup}" "${lp_core_exp_dep_srcs}")
endif()
if(CONFIG_SOC_LP_SPI_SUPPORTED)

View File

@ -0,0 +1,19 @@
/*
* SPDX-FileCopyrightText: 2024 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();
}

View File

@ -0,0 +1,311 @@
/*
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "esp_err.h"
#include "ulp_lp_core_lp_uart_shared.h"
#include "lp_core_uart.h"
#include "ulp_lp_core.h"
#include "esp_log.h"
#include "driver/uart.h"
#include "soc/uart_pins.h"
#include "test_utils.h"
#define ECHO_UART_PORT_NUM 1
#define ECHO_UART_BAUD_RATE 115200
#define BUF_SIZE (1024)
#define ECHO_TEST_TXD LP_U0RXD_GPIO_NUM
#define ECHO_TEST_RXD LP_U0TXD_GPIO_NUM
#define ECHO_TEST_RTS (UART_PIN_NO_CHANGE)
#define ECHO_TEST_CTS (UART_PIN_NO_CHANGE)
void init_host(void)
{
uart_config_t uart_config = {
.baud_rate = ECHO_UART_BAUD_RATE,
.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_DEFAULT,
};
int intr_alloc_flags = 0;
TEST_ESP_OK(uart_driver_install(ECHO_UART_PORT_NUM, BUF_SIZE * 2, 0, 0, NULL, intr_alloc_flags));
TEST_ESP_OK(uart_param_config(ECHO_UART_PORT_NUM, &uart_config));
TEST_ESP_OK(uart_set_pin(ECHO_UART_PORT_NUM, ECHO_TEST_TXD, ECHO_TEST_RXD, ECHO_TEST_RTS, ECHO_TEST_CTS));
unity_send_signal("Host Ready");
}
void deinit_host(void)
{
uart_driver_delete(ECHO_UART_PORT_NUM);
}
void send_and_verify_recived_data(const char* message, uint8_t length, bool should_wake_up)
{
unity_wait_for_signal("Slave Ready");
uart_flush_input(ECHO_UART_PORT_NUM);
uart_write_bytes(ECHO_UART_PORT_NUM, message, length);
uint8_t *data = (uint8_t *) malloc(BUF_SIZE);
int len = uart_read_bytes(ECHO_UART_PORT_NUM, data, (BUF_SIZE - 1), 1000 / portTICK_PERIOD_MS);
bool wake_up_detected = false;
const char *target = "Hello world";
int target_len = 11;
if (len > 0) {
if (len >= target_len) {
for (int i = 0; i <= len - target_len; i++) {
bool match = true;
for (int j = 0; j < target_len; j++) {
if (data[i + j] != target[j]) {
match = false;
break;
}
}
if (match) {
wake_up_detected = true;
break;
}
}
}
data[len] = '\0'; // Null-terminate the received data
}
free(data);
TEST_ESP_OK(should_wake_up != wake_up_detected);
}
extern const uint8_t lp_core_main_bin_start[] asm("_binary_lp_core_test_app_uart_wakeup_bin_start");
extern const uint8_t lp_core_main_bin_end[] asm("_binary_lp_core_test_app_uart_wakeup_bin_end");
static void lp_uart_init(void)
{
lp_core_uart_cfg_t cfg = LP_CORE_UART_DEFAULT_CONFIG();
TEST_ESP_OK(lp_core_uart_init(&cfg));
printf("LP UART initialized successfully\n");
}
static void lp_core_init(void)
{
ulp_lp_core_cfg_t cfg = {
.wakeup_source = ULP_LP_CORE_WAKEUP_SOURCE_LP_UART,
};
TEST_ESP_OK(ulp_lp_core_load_binary(lp_core_main_bin_start, (lp_core_main_bin_end - lp_core_main_bin_start)));
TEST_ESP_OK(ulp_lp_core_run(&cfg));
printf("LP core loaded with firmware and running successfully\n");
}
static void init_slave(uart_wakeup_cfg_t *wake_up_cfg)
{
unity_wait_for_signal("Host Ready");
lp_uart_init();
lp_core_init();
lp_core_uart_clear_buf();
TEST_ESP_OK(lp_core_uart_wakeup_setup(wake_up_cfg));
unity_send_signal("Slave Ready");
}
static void test_uart_wakeup_hello_sequence(void)
{
uart_wakeup_cfg_t wake_up_cfg = {
.wakeup_mode = UART_WK_MODE_CHAR_SEQ,
.wake_chars_seq = "he**o"
};
init_slave(&wake_up_cfg);
}
static void test_uart_wakeup_qwerty_sequence(void)
{
uart_wakeup_cfg_t wake_up_cfg = {
.wakeup_mode = UART_WK_MODE_CHAR_SEQ,
.wake_chars_seq = "qwert"
};
init_slave(&wake_up_cfg);
}
static void test_uart_wakeup_start_bit(void)
{
uart_wakeup_cfg_t wake_up_cfg = {
.wakeup_mode = UART_WK_MODE_START_BIT,
};
init_slave(&wake_up_cfg);
}
static void test_uart_wakeup_rx_fifo_8_bytes(void)
{
uart_wakeup_cfg_t wake_up_cfg = {
.wakeup_mode = UART_WK_MODE_FIFO_THRESH,
.rx_fifo_threshold = 8
};
init_slave(&wake_up_cfg);
}
static void test_uart_wakeup_rx_fifo_10_bytes(void)
{
uart_wakeup_cfg_t wake_up_cfg = {
.wakeup_mode = UART_WK_MODE_FIFO_THRESH,
.rx_fifo_threshold = 10
};
init_slave(&wake_up_cfg);
}
static void test_uart_wakeup_active_threshold_8(void)
{
uart_wakeup_cfg_t wake_up_cfg = {
.wakeup_mode = UART_WK_MODE_ACTIVE_THRESH,
.rx_edge_threshold = 8
};
init_slave(&wake_up_cfg);
}
// Host
static void send_uart_wakeup_positive_hello_sequence(void)
{
init_host();
send_and_verify_recived_data("hello", 5, true);
deinit_host();
}
static void send_uart_wakeup_negative_hello_sequence(void)
{
init_host();
send_and_verify_recived_data("hwllo", 5, false);
deinit_host();
}
static void send_uart_wakeup_positive_qwerty_sequence(void)
{
init_host();
send_and_verify_recived_data("qwert", 5, true);
deinit_host();
}
static void send_uart_wakeup_negative_qwerty_sequence(void)
{
init_host();
send_and_verify_recived_data("Qwert", 5, false);
deinit_host();
}
static void send_uart_wakeup_start_bit(void)
{
init_host();
send_and_verify_recived_data("@", 1, true);
deinit_host();
}
static void send_uart_wakeup_no_data(void)
{
init_host();
send_and_verify_recived_data("", 0, false);
deinit_host();
}
static void send_uart_wakeup_rx_fifo_9_bytes(void)
{
init_host();
send_and_verify_recived_data("123456789", 9, true);
deinit_host();
}
static void send_uart_wakeup_rx_fifo_8_bytes(void)
{
init_host();
send_and_verify_recived_data("12345678", 8, false);
deinit_host();
}
static void send_uart_wakeup_rx_fifo_11_bytes(void)
{
init_host();
send_and_verify_recived_data("12345678901", 11, true);
deinit_host();
}
static void send_uart_wakeup_rx_fifo_10_bytes(void)
{
init_host();
send_and_verify_recived_data("1234567890", 10, false);
deinit_host();
}
static void send_uart_wakeup_active_threshold_8(void)
{
/*
* This is only true in 8N1 mode (8 data bits, no parity, 1 stop bit).
* Sending "TT" corresponds to:
* +-------+--------------+------+--------+
* | Start | Data Bits | Stop | Raises |
* +-------+--------------+------+--------+
* | 0 | 00101010(T) | 1 | 4 |
* | 0 | 00101010(T) | 1 | 4 |
* +-------+--------------+------+--------+
*/
init_host();
send_and_verify_recived_data("TT", 2, true);
deinit_host();
}
static void send_uart_wakeup_active_threshold_7(void)
{
/*
* This is only true in 8N1 mode (8 data bits, no parity, 1 stop bit).
* Sending "Ta" corresponds to:
* +-------+--------------+------+--------+
* | Start | Data Bits | Stop | Raises |
* +-------+--------------+------+--------+
* | 0 | 00101010(T) | 1 | 4 |
* | 0 | 10000110(a) | 1 | 3 |
* +-------+--------------+------+--------+
*/
init_host();
send_and_verify_recived_data("Ta", 2, false);
deinit_host();
}
TEST_CASE_MULTIPLE_DEVICES("Hello sequence - positive hello", "[uart][wakeup][seq][timeout=5]",
test_uart_wakeup_hello_sequence, send_uart_wakeup_positive_hello_sequence);
TEST_CASE_MULTIPLE_DEVICES("Hello sequence - negative hello", "[uart][wakeup][seq][timeout=5]",
test_uart_wakeup_hello_sequence, send_uart_wakeup_negative_hello_sequence);
TEST_CASE_MULTIPLE_DEVICES("QWERTY sequence - positive", "[uart][wakeup][seq][timeout=5]",
test_uart_wakeup_qwerty_sequence, send_uart_wakeup_positive_qwerty_sequence);
TEST_CASE_MULTIPLE_DEVICES("QWERTY sequence - negative", "[uart][wakeup][seq][timeout=5]",
test_uart_wakeup_qwerty_sequence, send_uart_wakeup_negative_qwerty_sequence);
TEST_CASE_MULTIPLE_DEVICES("Start bit sequence - valid data", "[uart][wakeup][start_bit][timeout=5]",
test_uart_wakeup_start_bit, send_uart_wakeup_start_bit);
TEST_CASE_MULTIPLE_DEVICES("Start bit sequence - no data", "[uart][wakeup][start_bit][timeout=5]",
test_uart_wakeup_start_bit, send_uart_wakeup_no_data);
TEST_CASE_MULTIPLE_DEVICES("RX FIFO - 8 bytes", "[uart][wakeup][rx_fifo][timeout=5]",
test_uart_wakeup_rx_fifo_8_bytes, send_uart_wakeup_rx_fifo_8_bytes);
TEST_CASE_MULTIPLE_DEVICES("RX FIFO - 9 bytes", "[uart][wakeup][rx_fifo][timeout=5]",
test_uart_wakeup_rx_fifo_8_bytes, send_uart_wakeup_rx_fifo_9_bytes);
TEST_CASE_MULTIPLE_DEVICES("RX FIFO - 10 bytes", "[uart][wakeup][rx_fifo][timeout=5]",
test_uart_wakeup_rx_fifo_10_bytes, send_uart_wakeup_rx_fifo_10_bytes);
TEST_CASE_MULTIPLE_DEVICES("RX FIFO - 11 bytes", "[uart][wakeup][rx_fifo][timeout=5]",
test_uart_wakeup_rx_fifo_10_bytes, send_uart_wakeup_rx_fifo_11_bytes);
TEST_CASE_MULTIPLE_DEVICES("Active threshold - 8", "[uart][wakeup][edge][timeout=5]",
test_uart_wakeup_active_threshold_8, send_uart_wakeup_active_threshold_8);
TEST_CASE_MULTIPLE_DEVICES("Active threshold - 7", "[uart][wakeup][edge][timeout=5]",
test_uart_wakeup_active_threshold_8, send_uart_wakeup_active_threshold_7);

View File

@ -1,7 +1,8 @@
# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: CC0-1.0
import pytest
from pytest_embedded import Dut
from pytest_embedded_idf import CaseTester
@pytest.mark.esp32c5
@ -52,7 +53,41 @@ def test_lp_vad(dut: Dut) -> None:
@pytest.mark.parametrize(
'count', [2], indirect=True
)
@pytest.mark.parametrize(
'config',
[
'defaults',
],
indirect=True,
)
def test_lp_core_multi_device(case_tester) -> None: # type: ignore
for case in case_tester.test_menu:
if case.attributes.get('test_env', 'generic_multi_device') == 'generic_multi_device':
case_tester.run_multi_dev_case(case=case, reset=True)
@pytest.mark.generic_multi_device
@pytest.mark.parametrize('target', [
'esp32c5',
'esp32c6',
'esp32p4',
], indirect=True)
@pytest.mark.parametrize(
'config',
[
'defaults',
],
indirect=True,
)
@pytest.mark.parametrize('count', [2], indirect=True)
def test_lp_uart_wakeup_modes(case_tester: CaseTester) -> None:
relevant_cases = [
case for case in case_tester.test_menu
if {'wakeup', 'uart'}.issubset(case.groups)
]
assert len(relevant_cases) == 12, (
f"Expected 12 test cases with groups 'wakeup' and 'uart', but found {len(relevant_cases)}."
)
for case in relevant_cases:
case_tester.run_multi_dev_case(case=case, reset=True)

View File

@ -0,0 +1,6 @@
CONFIG_ESP_TASK_WDT_INIT=n
CONFIG_ULP_COPROC_ENABLED=y
CONFIG_ULP_COPROC_TYPE_LP_CORE=y
CONFIG_ULP_COPROC_RESERVE_MEM=12000
CONFIG_ULP_PANIC_OUTPUT_ENABLE=y

View File

@ -329,6 +329,7 @@ INPUT = \
$(PROJECT_PATH)/components/wifi_provisioning/include/wifi_provisioning/wifi_scan.h \
$(PROJECT_PATH)/components/wpa_supplicant/esp_supplicant/include/esp_dpp.h \
$(PROJECT_PATH)/components/wpa_supplicant/esp_supplicant/include/esp_supplicant_utils.h \
$(PROJECT_PATH)/components/esp_driver_uart/include/driver/uart_wakeup.h \
## Target specific headers are in separate Doxyfile files
@INCLUDE = $(PROJECT_PATH)/docs/doxygen/Doxyfile_$(IDF_TARGET)

View File

@ -11,3 +11,4 @@ INPUT += \
$(PROJECT_PATH)/components/ulp/lp_core/lp_core/include/ulp_lp_core_interrupts.h \
$(PROJECT_PATH)/components/ulp/ulp_common/include/ulp_common.h \
$(PROJECT_PATH)/components/bt/include/esp32c5/include/esp_bt.h \
$(PROJECT_PATH)/components/ulp/lp_core/shared/include/ulp_lp_core_lp_uart_shared.h \

View File

@ -19,3 +19,4 @@ INPUT += \
$(PROJECT_PATH)/components/esp_tee/subproject/components/tee_sec_storage/include/esp_tee_sec_storage.h \
$(PROJECT_PATH)/components/esp_tee/subproject/components/tee_attestation/esp_tee_attestation.h \
$(PROJECT_PATH)/components/esp_tee/subproject/components/tee_ota_ops/include/esp_tee_ota_ops.h \
$(PROJECT_PATH)/components/ulp/lp_core/shared/include/ulp_lp_core_lp_uart_shared.h \

View File

@ -56,3 +56,4 @@ INPUT += \
$(PROJECT_PATH)/components/soc/$(IDF_TARGET)/include/soc/bitscrambler_peri_select.h \
$(PROJECT_PATH)/components/sdmmc/include/sd_pwr_ctrl.h \
$(PROJECT_PATH)/components/sdmmc/include/sd_pwr_ctrl_by_on_chip_ldo.h \
$(PROJECT_PATH)/components/ulp/lp_core/shared/include/ulp_lp_core_lp_uart_shared.h \

View File

@ -428,6 +428,7 @@ API Reference
-------------
.. include-build-file:: inc/uart.inc
.. include-build-file:: inc/uart_wakeup.inc
.. include-build-file:: inc/uart_types.inc

View File

@ -212,7 +212,7 @@ The ULP has the following wake-up sources:
* :c:macro:`ULP_LP_CORE_WAKEUP_SOURCE_LP_TIMER` - LP core can be woken up by the LP timer.
* :c:macro:`ULP_LP_CORE_WAKEUP_SOURCE_ETM` - LP core can be woken up by a ETM event. (Not yet supported)
* :c:macro:`ULP_LP_CORE_WAKEUP_SOURCE_LP_IO` - LP core can be woken up when LP IO level changes. (Not yet supported)
* :c:macro:`ULP_LP_CORE_WAKEUP_SOURCE_LP_UART` - LP core can be woken up after receiving a certain number of UART RX pulses. (Not yet supported)
* :c:macro:`ULP_LP_CORE_WAKEUP_SOURCE_LP_UART` - LP core can be woken up when LP_UART receives wakeup data based on different modes.
When the ULP is woken up, it will go through the following steps:
@ -390,6 +390,7 @@ Application Examples
:esp32c6: - :example:`system/ulp/lp_core/lp_i2c` reads external I2C ambient light sensor (BH1750) while the main CPU is in Deep-sleep and wakes up the main CPU once a threshold is met.
- :example:`system/ulp/lp_core/lp_uart/lp_uart_echo` reads data written to a serial console and echoes it back. This example demonstrates the usage of the LP UART driver running on the LP core.
- :example:`system/ulp/lp_core/lp_uart/lp_uart_print` shows how to print various statements from a program running on the LP core.
- :example:`system/ulp/lp_core/lp_uart/lp_uart_char_seq_wakeup` shows how to trigger a wakeup using the LP UART specific character sequence wakeup mode.
- :example:`system/ulp/lp_core/interrupt` shows how to register an interrupt handler on the LP core to receive an interrupt triggered by the main CPU.
- :example:`system/ulp/lp_core/gpio_intr_pulse_counter` shows how to use GPIO interrupts to count pulses while the main CPU is in Deep-sleep mode.
- :example:`system/ulp/lp_core/build_system/` demonstrates how to include custom ``CMakeLists.txt`` file for the ULP app.
@ -430,3 +431,8 @@ LP Core API Reference
.. include-build-file:: inc/ulp_lp_core_spi.inc
.. _esp-idf-monitor: https://github.com/espressif/esp-idf-monitor
.. only:: SOC_UART_HAS_LP_UART
.. include-build-file:: inc/ulp_lp_core_lp_uart_shared.inc

View File

@ -428,6 +428,7 @@ API 参考
---------------
.. include-build-file:: inc/uart.inc
.. include-build-file:: inc/uart_wakeup.inc
.. include-build-file:: inc/uart_types.inc

View File

@ -334,6 +334,12 @@ examples/system/ulp/lp_core/lp_spi:
depends_components:
- ulp
examples/system/ulp/lp_core/lp_uart/lp_uart_char_seq_wakeup:
disable:
- if: (SOC_ULP_LP_UART_SUPPORTED != 1)
depends_components:
- ulp
examples/system/ulp/lp_core/lp_uart/lp_uart_echo:
disable:
- if: (SOC_ULP_LP_UART_SUPPORTED != 1) or (SOC_DEEP_SLEEP_SUPPORTED != 1)

View File

@ -0,0 +1,7 @@
# This is the project CMakeLists.txt file for the test subproject
cmake_minimum_required(VERSION 3.16)
list(APPEND SDKCONFIG_DEFAULTS "sdkconfig.defaults")
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(lp_uart_echo_example)

View File

@ -0,0 +1,57 @@
| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-P4 |
| ----------------- | -------- | -------- | -------- |
# LP UART specific character sequence wakeup mode Example
(See the README.md file in the upper level 'examples' directory for more information about examples.)
## Overview
This example demonstrates how to use LP UART in specific character sequence wakeup mode.
## How to use example
### Hardware Required
To run this example, you should have an ESP based development board which supports LP UART wakeup such as the ESP32-C6 and a host machine with a serial input connection.
#### Pin Assignment:
**Note:** The following pin assignments are used by default.
| | Rx | Tx |
| ----------------------- | -------| -------|
| ESP32-C6 | GPIO4 | GPIO5 |
| ESP32-C5 | GPIO4 | GPIO5 |
| ESP32-P4 | GPIO15 | GPIO14 |
| Host machine | Tx | Rx |
### Build and Flash
Enter `idf.py -p PORT flash monitor` to build, flash and monitor the project.
(To exit the serial monitor, type ``Ctrl-]``.)
See the [Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html) for full steps to configure and use ESP-IDF to build projects.
Use another serial monitor program/instance such as idf.py monitor, minicom or miniterm to send and receive data from the LP core. Send "hello" or "he**o" to wake up the LP core.
The default baudrate used for the example is 115200. Care must be taken that the configuration matches on both the device and the serial terminal.
## Example Output
The log output from the serial monitor connected to the main core should indicate that the LP core and the LP UART peripheral have been successfully initialized.
```bash
Initializing...
LP UART initialized successfully
LP core loaded with firmware and running successfully
```
The log output from the serial monitor connected to the LP core after inputting "hello" will be:
```bash
Hello world
```
## Troubleshooting
(For any technical queries, please open an [issue](https://github.com/espressif/esp-idf/issues) on GitHub. We will get back to you as soon as possible.)

View File

@ -0,0 +1,25 @@
# Register the component
idf_component_register(SRCS "lp_uart_main.c"
INCLUDE_DIRS ""
REQUIRES ulp)
#
# ULP support additions to component CMakeLists.txt.
#
# 1. The LP Core app name must be unique (if multiple components use LP Core).
set(ulp_app_name lp_core_${COMPONENT_NAME})
#
# 2. Specify all C files.
# Files should be placed into a separate directory (in this case, lp_core/),
# which should not be added to COMPONENT_SRCS.
set(ulp_lp_core_sources "lp_core/main.c")
#
# 3. List all the component source files which include automatically
# generated LP Core export file, ${ulp_app_name}.h:
set(ulp_exp_dep_srcs "lp_uart_main.c")
#
# 4. Call function to build ULP binary and embed in project using the argument
# values above.
ulp_embed_binary(${ulp_app_name} "${ulp_lp_core_sources}" "${ulp_exp_dep_srcs}")

View File

@ -0,0 +1,20 @@
/*
* SPDX-FileCopyrightText: 2024 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"
int main (void)
{
lp_core_printf("Hello world\r\n");
// 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;
}

View File

@ -0,0 +1,68 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdio.h>
#include "esp_sleep.h"
#include "esp_err.h"
#include "lp_core_main.h"
#include "ulp_lp_core.h"
#include "lp_core_uart.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "ulp_lp_core_lp_uart_shared.h"
extern const uint8_t lp_core_main_bin_start[] asm("_binary_lp_core_main_bin_start");
extern const uint8_t lp_core_main_bin_end[] asm("_binary_lp_core_main_bin_end");
static void lp_uart_init(void)
{
lp_core_uart_cfg_t cfg = LP_CORE_UART_DEFAULT_CONFIG();
ESP_ERROR_CHECK(lp_core_uart_init(&cfg));
uart_wakeup_cfg_t wake_up_cfg = {
.wakeup_mode = UART_WK_MODE_CHAR_SEQ,
.wake_chars_seq = "he**o"
};
ESP_ERROR_CHECK(lp_core_uart_wakeup_setup(&wake_up_cfg));
printf("LP UART initialized successfully\n");
}
static void lp_core_init(void)
{
/* Set LP core wakeup source as the HP CPU */
ulp_lp_core_cfg_t cfg = {
.wakeup_source = ULP_LP_CORE_WAKEUP_SOURCE_LP_UART,
};
/* Load LP core firmware */
ESP_ERROR_CHECK(ulp_lp_core_load_binary(lp_core_main_bin_start, (lp_core_main_bin_end - lp_core_main_bin_start)));
/* Run LP core */
ESP_ERROR_CHECK(ulp_lp_core_run(&cfg));
printf("LP core loaded with firmware and running successfully\n");
}
void app_main(void)
{
printf("Initializing...\n");
/* Initialize LP_UART */
lp_uart_init();
/* Load LP Core binary and start the coprocessor */
lp_core_init();
while(1){
vTaskDelay(pdMS_TO_TICKS(5000));
printf("Main processor running\r\n");
}
}

View File

@ -0,0 +1,4 @@
# Enable LP Core
CONFIG_ULP_COPROC_ENABLED=y
CONFIG_ULP_COPROC_TYPE_LP_CORE=y
CONFIG_ULP_COPROC_RESERVE_MEM=8192