diff --git a/components/esp_driver_uart/CMakeLists.txt b/components/esp_driver_uart/CMakeLists.txt index 3c564f0485..fbe98b24e1 100644 --- a/components/esp_driver_uart/CMakeLists.txt +++ b/components/esp_driver_uart/CMakeLists.txt @@ -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") diff --git a/components/esp_driver_uart/include/driver/uart_wakeup.h b/components/esp_driver_uart/include/driver/uart_wakeup.h new file mode 100644 index 0000000000..5697fbd699 --- /dev/null +++ b/components/esp_driver_uart/include/driver/uart_wakeup.h @@ -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 diff --git a/components/esp_driver_uart/src/uart.c b/components/esp_driver_uart/src/uart.c index 883104dbca..fec9052da1 100644 --- a/components/esp_driver_uart/src/uart.c +++ b/components/esp_driver_uart/src/uart.c @@ -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; } diff --git a/components/esp_driver_uart/src/uart_wakeup.c b/components/esp_driver_uart/src/uart_wakeup.c new file mode 100644 index 0000000000..deb8e2b89c --- /dev/null +++ b/components/esp_driver_uart/src/uart_wakeup.c @@ -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; +} diff --git a/components/hal/esp32/include/hal/uart_ll.h b/components/hal/esp32/include/hal/uart_ll.h index bb1d1006e3..1a4ade0f65 100644 --- a/components/hal/esp32/include/hal/uart_ll.h +++ b/components/hal/esp32/include/hal/uart_ll.h @@ -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); } /** diff --git a/components/hal/esp32c2/include/hal/uart_ll.h b/components/hal/esp32c2/include/hal/uart_ll.h index 2ef71b907f..2bbbe79c78 100644 --- a/components/hal/esp32c2/include/hal/uart_ll.h +++ b/components/hal/esp32c2/include/hal/uart_ll.h @@ -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; } /** diff --git a/components/hal/esp32c3/include/hal/uart_ll.h b/components/hal/esp32c3/include/hal/uart_ll.h index b2741137e9..33ebd6d4a0 100644 --- a/components/hal/esp32c3/include/hal/uart_ll.h +++ b/components/hal/esp32c3/include/hal/uart_ll.h @@ -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; } /** diff --git a/components/hal/esp32c5/include/hal/lp_core_ll.h b/components/hal/esp32c5/include/hal/lp_core_ll.h index 77937944ae..974c5391cd 100644 --- a/components/hal/esp32c5/include/hal/lp_core_ll.h +++ b/components/hal/esp32c5/include/hal/lp_core_ll.h @@ -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 * diff --git a/components/hal/esp32c5/include/hal/uart_ll.h b/components/hal/esp32c5/include/hal/uart_ll.h index 2b06e0fe47..0ecc3a878a 100644 --- a/components/hal/esp32c5/include/hal/uart_ll.h +++ b/components/hal/esp32c5/include/hal/uart_ll.h @@ -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; } /** diff --git a/components/hal/esp32c6/include/hal/lp_core_ll.h b/components/hal/esp32c6/include/hal/lp_core_ll.h index 8f3446d389..4b61d36563 100644 --- a/components/hal/esp32c6/include/hal/lp_core_ll.h +++ b/components/hal/esp32c6/include/hal/lp_core_ll.h @@ -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 * diff --git a/components/hal/esp32c6/include/hal/uart_ll.h b/components/hal/esp32c6/include/hal/uart_ll.h index f382ff6bb3..0763d62ab6 100644 --- a/components/hal/esp32c6/include/hal/uart_ll.h +++ b/components/hal/esp32c6/include/hal/uart_ll.h @@ -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; } /** diff --git a/components/hal/esp32c61/include/hal/uart_ll.h b/components/hal/esp32c61/include/hal/uart_ll.h index 5cff1d1f5e..9fc7cec73b 100644 --- a/components/hal/esp32c61/include/hal/uart_ll.h +++ b/components/hal/esp32c61/include/hal/uart_ll.h @@ -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; } /** diff --git a/components/hal/esp32h2/include/hal/uart_ll.h b/components/hal/esp32h2/include/hal/uart_ll.h index f9abd2c260..3a89955c94 100644 --- a/components/hal/esp32h2/include/hal/uart_ll.h +++ b/components/hal/esp32h2/include/hal/uart_ll.h @@ -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; } /** diff --git a/components/hal/esp32h21/include/hal/uart_ll.h b/components/hal/esp32h21/include/hal/uart_ll.h index 826d7c3f77..3b5e926454 100644 --- a/components/hal/esp32h21/include/hal/uart_ll.h +++ b/components/hal/esp32h21/include/hal/uart_ll.h @@ -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; } /** diff --git a/components/hal/esp32p4/include/hal/lp_core_ll.h b/components/hal/esp32p4/include/hal/lp_core_ll.h index eb2c57be31..f309dd9dfa 100644 --- a/components/hal/esp32p4/include/hal/lp_core_ll.h +++ b/components/hal/esp32p4/include/hal/lp_core_ll.h @@ -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 * diff --git a/components/hal/esp32p4/include/hal/uart_ll.h b/components/hal/esp32p4/include/hal/uart_ll.h index e50d181af6..4d43b6607d 100644 --- a/components/hal/esp32p4/include/hal/uart_ll.h +++ b/components/hal/esp32p4/include/hal/uart_ll.h @@ -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; } /** diff --git a/components/hal/esp32s2/include/hal/uart_ll.h b/components/hal/esp32s2/include/hal/uart_ll.h index a5aeeaa316..982659ec2e 100644 --- a/components/hal/esp32s2/include/hal/uart_ll.h +++ b/components/hal/esp32s2/include/hal/uart_ll.h @@ -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; } /** diff --git a/components/hal/esp32s3/include/hal/uart_ll.h b/components/hal/esp32s3/include/hal/uart_ll.h index 91cebea9a4..751a040bb7 100644 --- a/components/hal/esp32s3/include/hal/uart_ll.h +++ b/components/hal/esp32s3/include/hal/uart_ll.h @@ -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; } /** diff --git a/components/hal/include/hal/uart_hal.h b/components/hal/include/hal/uart_hal.h index 1ea84a7888..a42bda8eee 100644 --- a/components/hal/include/hal/uart_hal.h +++ b/components/hal/include/hal/uart_hal.h @@ -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 */ diff --git a/components/hal/include/hal/uart_types.h b/components/hal/include/hal/uart_types.h index b97944abea..16bfc44203 100644 --- a/components/hal/include/hal/uart_types.h +++ b/components/hal/include/hal/uart_types.h @@ -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 diff --git a/components/hal/uart_hal.c b/components/hal/uart_hal.c index 305bec872c..72d9cb4003 100644 --- a/components/hal/uart_hal.c +++ b/components/hal/uart_hal.c @@ -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) diff --git a/components/soc/esp32/include/soc/Kconfig.soc_caps.in b/components/soc/esp32/include/soc/Kconfig.soc_caps.in index ab709e39b5..ad1f3a641b 100644 --- a/components/soc/esp32/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32/include/soc/Kconfig.soc_caps.in @@ -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 diff --git a/components/soc/esp32/include/soc/soc_caps.h b/components/soc/esp32/include/soc/soc_caps.h index 3c82507ac2..2eb511a556 100644 --- a/components/soc/esp32/include/soc/soc_caps.h +++ b/components/soc/esp32/include/soc/soc_caps.h @@ -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 diff --git a/components/soc/esp32c2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c2/include/soc/Kconfig.soc_caps.in index 47ff2ad605..30d436d3d7 100644 --- a/components/soc/esp32c2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c2/include/soc/Kconfig.soc_caps.in @@ -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 diff --git a/components/soc/esp32c2/include/soc/soc_caps.h b/components/soc/esp32c2/include/soc/soc_caps.h index 3cd251ac81..11cd8e53bd 100644 --- a/components/soc/esp32c2/include/soc/soc_caps.h +++ b/components/soc/esp32c2/include/soc/soc_caps.h @@ -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) diff --git a/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in index 28014f98e0..750d3a5088 100644 --- a/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in @@ -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 diff --git a/components/soc/esp32c3/include/soc/soc_caps.h b/components/soc/esp32c3/include/soc/soc_caps.h index 822fbf2274..42d03da3de 100644 --- a/components/soc/esp32c3/include/soc/soc_caps.h +++ b/components/soc/esp32c3/include/soc/soc_caps.h @@ -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) diff --git a/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in index 4d7cfaf710..41d2f7524b 100644 --- a/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in @@ -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 diff --git a/components/soc/esp32c5/include/soc/soc_caps.h b/components/soc/esp32c5/include/soc/soc_caps.h index 911977a2ed..0d97a78c52 100644 --- a/components/soc/esp32c5/include/soc/soc_caps.h +++ b/components/soc/esp32c5/include/soc/soc_caps.h @@ -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) diff --git a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in index d74c870750..5ab77211fb 100644 --- a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in @@ -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 diff --git a/components/soc/esp32c6/include/soc/soc_caps.h b/components/soc/esp32c6/include/soc/soc_caps.h index 0fca54482c..afc4e6938b 100644 --- a/components/soc/esp32c6/include/soc/soc_caps.h +++ b/components/soc/esp32c6/include/soc/soc_caps.h @@ -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) diff --git a/components/soc/esp32c61/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c61/include/soc/Kconfig.soc_caps.in index d5a23d2cce..c69697d56b 100644 --- a/components/soc/esp32c61/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c61/include/soc/Kconfig.soc_caps.in @@ -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 diff --git a/components/soc/esp32c61/include/soc/soc_caps.h b/components/soc/esp32c61/include/soc/soc_caps.h index e9c42dafa7..487522db1d 100644 --- a/components/soc/esp32c61/include/soc/soc_caps.h +++ b/components/soc/esp32c61/include/soc/soc_caps.h @@ -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) diff --git a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in index d3aa4adaa4..e1c2b788c4 100644 --- a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in @@ -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 diff --git a/components/soc/esp32h2/include/soc/soc_caps.h b/components/soc/esp32h2/include/soc/soc_caps.h index 9127a6a1b2..6074728561 100644 --- a/components/soc/esp32h2/include/soc/soc_caps.h +++ b/components/soc/esp32h2/include/soc/soc_caps.h @@ -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) diff --git a/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in index 3ed6d1cb59..81357d8718 100644 --- a/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in @@ -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 diff --git a/components/soc/esp32h21/include/soc/soc_caps.h b/components/soc/esp32h21/include/soc/soc_caps.h index 40af70d1d8..99231f1918 100644 --- a/components/soc/esp32h21/include/soc/soc_caps.h +++ b/components/soc/esp32h21/include/soc/soc_caps.h @@ -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) diff --git a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in index c5b719d763..a5aabc99bc 100644 --- a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in @@ -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 diff --git a/components/soc/esp32p4/include/soc/soc_caps.h b/components/soc/esp32p4/include/soc/soc_caps.h index 3e4ed6d390..0dbaa89fd5 100644 --- a/components/soc/esp32p4/include/soc/soc_caps.h +++ b/components/soc/esp32p4/include/soc/soc_caps.h @@ -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) diff --git a/components/soc/esp32p4/register/soc/lpperi_struct.h b/components/soc/esp32p4/register/soc/lpperi_struct.h index 34cbda01df..30a5ddf1de 100644 --- a/components/soc/esp32p4/register/soc/lpperi_struct.h +++ b/components/soc/esp32p4/register/soc/lpperi_struct.h @@ -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 */ diff --git a/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in index 7b95cac118..c574221a3b 100644 --- a/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in @@ -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 diff --git a/components/soc/esp32s2/include/soc/soc_caps.h b/components/soc/esp32s2/include/soc/soc_caps.h index 7b5ed1b032..4b7f1a75af 100644 --- a/components/soc/esp32s2/include/soc/soc_caps.h +++ b/components/soc/esp32s2/include/soc/soc_caps.h @@ -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 diff --git a/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in b/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in index 0ac4830bf4..f84efefb2e 100644 --- a/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in @@ -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 diff --git a/components/soc/esp32s3/include/soc/soc_caps.h b/components/soc/esp32s3/include/soc/soc_caps.h index ae28654f8e..72b2d60da7 100644 --- a/components/soc/esp32s3/include/soc/soc_caps.h +++ b/components/soc/esp32s3/include/soc/soc_caps.h @@ -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) diff --git a/components/ulp/CMakeLists.txt b/components/ulp/CMakeLists.txt index dbe990e652..eea6ea5126 100644 --- a/components/ulp/CMakeLists.txt +++ b/components/ulp/CMakeLists.txt @@ -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) diff --git a/components/ulp/cmake/IDFULPProject.cmake b/components/ulp/cmake/IDFULPProject.cmake index 12d4a3aa53..a7fad364b8 100644 --- a/components/ulp/cmake/IDFULPProject.cmake +++ b/components/ulp/cmake/IDFULPProject.cmake @@ -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" diff --git a/components/ulp/lp_core/lp_core.c b/components/ulp/lp_core/lp_core.c index 0efa300ac0..a0b1669d11 100644 --- a/components/ulp/lp_core/lp_core.c +++ b/components/ulp/lp_core/lp_core.c @@ -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; } diff --git a/components/ulp/lp_core/lp_core/include/ulp_lp_core_utils.h b/components/ulp/lp_core/lp_core/include/ulp_lp_core_utils.h index 10fe3b525f..4b6065c6b1 100644 --- a/components/ulp/lp_core/lp_core/include/ulp_lp_core_utils.h +++ b/components/ulp/lp_core/lp_core/include/ulp_lp_core_utils.h @@ -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 #include #include +#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. diff --git a/components/ulp/lp_core/lp_core/lp_core_utils.c b/components/ulp/lp_core/lp_core/lp_core_utils.c index d3e8664907..4a9bdb8a54 100644 --- a/components/ulp/lp_core/lp_core/lp_core_utils.c +++ b/components/ulp/lp_core/lp_core/lp_core_utils.c @@ -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(); diff --git a/components/ulp/lp_core/shared/include/ulp_lp_core_lp_uart_shared.h b/components/ulp/lp_core/shared/include/ulp_lp_core_lp_uart_shared.h new file mode 100644 index 0000000000..2c8e59bd25 --- /dev/null +++ b/components/ulp/lp_core/shared/include/ulp_lp_core_lp_uart_shared.h @@ -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 diff --git a/components/ulp/lp_core/shared/ulp_lp_core_lp_uart_shared.c b/components/ulp/lp_core/shared/ulp_lp_core_lp_uart_shared.c new file mode 100644 index 0000000000..57faac9a7d --- /dev/null +++ b/components/ulp/lp_core/shared/ulp_lp_core_lp_uart_shared.c @@ -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); +} diff --git a/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/CMakeLists.txt b/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/CMakeLists.txt index 6c1a9d331d..b15fe5c4a5 100644 --- a/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/CMakeLists.txt +++ b/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/CMakeLists.txt @@ -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) diff --git a/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/lp_core/test_main_uart_wakeup.c b/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/lp_core/test_main_uart_wakeup.c new file mode 100644 index 0000000000..54e2f69188 --- /dev/null +++ b/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/lp_core/test_main_uart_wakeup.c @@ -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(); +} diff --git a/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/test_lp_core_uart_wakeup.c b/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/test_lp_core_uart_wakeup.c new file mode 100644 index 0000000000..ee54e80372 --- /dev/null +++ b/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/test_lp_core_uart_wakeup.c @@ -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); diff --git a/components/ulp/test_apps/lp_core/lp_core_basic_tests/pytest_lp_core_basic.py b/components/ulp/test_apps/lp_core/lp_core_basic_tests/pytest_lp_core_basic.py index 33e7b3c950..4d0c7f570e 100644 --- a/components/ulp/test_apps/lp_core/lp_core_basic_tests/pytest_lp_core_basic.py +++ b/components/ulp/test_apps/lp_core/lp_core_basic_tests/pytest_lp_core_basic.py @@ -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) diff --git a/components/ulp/test_apps/lp_core/lp_core_basic_tests/sdkconfig.ci.defaults b/components/ulp/test_apps/lp_core/lp_core_basic_tests/sdkconfig.ci.defaults new file mode 100644 index 0000000000..c7626f4733 --- /dev/null +++ b/components/ulp/test_apps/lp_core/lp_core_basic_tests/sdkconfig.ci.defaults @@ -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 diff --git a/docs/doxygen/Doxyfile b/docs/doxygen/Doxyfile index 3bc068d0cf..09f838afbe 100644 --- a/docs/doxygen/Doxyfile +++ b/docs/doxygen/Doxyfile @@ -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) diff --git a/docs/doxygen/Doxyfile_esp32c5 b/docs/doxygen/Doxyfile_esp32c5 index 853631e4ef..5560f252b7 100644 --- a/docs/doxygen/Doxyfile_esp32c5 +++ b/docs/doxygen/Doxyfile_esp32c5 @@ -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 \ diff --git a/docs/doxygen/Doxyfile_esp32c6 b/docs/doxygen/Doxyfile_esp32c6 index d0abf139ee..ecbd454182 100644 --- a/docs/doxygen/Doxyfile_esp32c6 +++ b/docs/doxygen/Doxyfile_esp32c6 @@ -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 \ diff --git a/docs/doxygen/Doxyfile_esp32p4 b/docs/doxygen/Doxyfile_esp32p4 index 58be5a5c3a..3d50cda7fa 100644 --- a/docs/doxygen/Doxyfile_esp32p4 +++ b/docs/doxygen/Doxyfile_esp32p4 @@ -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 \ diff --git a/docs/en/api-reference/peripherals/uart.rst b/docs/en/api-reference/peripherals/uart.rst index 346fc093a5..5fea3490cb 100644 --- a/docs/en/api-reference/peripherals/uart.rst +++ b/docs/en/api-reference/peripherals/uart.rst @@ -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 diff --git a/docs/en/api-reference/system/ulp-lp-core.rst b/docs/en/api-reference/system/ulp-lp-core.rst index 203e997acc..eebe9ac213 100644 --- a/docs/en/api-reference/system/ulp-lp-core.rst +++ b/docs/en/api-reference/system/ulp-lp-core.rst @@ -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 + diff --git a/docs/zh_CN/api-reference/peripherals/uart.rst b/docs/zh_CN/api-reference/peripherals/uart.rst index 2f2a1ae197..5b55cc1ca7 100644 --- a/docs/zh_CN/api-reference/peripherals/uart.rst +++ b/docs/zh_CN/api-reference/peripherals/uart.rst @@ -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 diff --git a/examples/system/.build-test-rules.yml b/examples/system/.build-test-rules.yml index 8354a17256..254cb891d4 100644 --- a/examples/system/.build-test-rules.yml +++ b/examples/system/.build-test-rules.yml @@ -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) diff --git a/examples/system/ulp/lp_core/lp_uart/lp_uart_char_seq_wakeup/CMakeLists.txt b/examples/system/ulp/lp_core/lp_uart/lp_uart_char_seq_wakeup/CMakeLists.txt new file mode 100644 index 0000000000..0249365348 --- /dev/null +++ b/examples/system/ulp/lp_core/lp_uart/lp_uart_char_seq_wakeup/CMakeLists.txt @@ -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) diff --git a/examples/system/ulp/lp_core/lp_uart/lp_uart_char_seq_wakeup/README.md b/examples/system/ulp/lp_core/lp_uart/lp_uart_char_seq_wakeup/README.md new file mode 100644 index 0000000000..b54710235e --- /dev/null +++ b/examples/system/ulp/lp_core/lp_uart/lp_uart_char_seq_wakeup/README.md @@ -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.) diff --git a/examples/system/ulp/lp_core/lp_uart/lp_uart_char_seq_wakeup/main/CMakeLists.txt b/examples/system/ulp/lp_core/lp_uart/lp_uart_char_seq_wakeup/main/CMakeLists.txt new file mode 100644 index 0000000000..2d86ebdb05 --- /dev/null +++ b/examples/system/ulp/lp_core/lp_uart/lp_uart_char_seq_wakeup/main/CMakeLists.txt @@ -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}") diff --git a/examples/system/ulp/lp_core/lp_uart/lp_uart_char_seq_wakeup/main/lp_core/main.c b/examples/system/ulp/lp_core/lp_uart/lp_uart_char_seq_wakeup/main/lp_core/main.c new file mode 100644 index 0000000000..0bc04ec231 --- /dev/null +++ b/examples/system/ulp/lp_core/lp_uart/lp_uart_char_seq_wakeup/main/lp_core/main.c @@ -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; +} diff --git a/examples/system/ulp/lp_core/lp_uart/lp_uart_char_seq_wakeup/main/lp_uart_main.c b/examples/system/ulp/lp_core/lp_uart/lp_uart_char_seq_wakeup/main/lp_uart_main.c new file mode 100644 index 0000000000..d490220c53 --- /dev/null +++ b/examples/system/ulp/lp_core/lp_uart/lp_uart_char_seq_wakeup/main/lp_uart_main.c @@ -0,0 +1,68 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#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"); + } + +} diff --git a/examples/system/ulp/lp_core/lp_uart/lp_uart_char_seq_wakeup/sdkconfig.defaults b/examples/system/ulp/lp_core/lp_uart/lp_uart_char_seq_wakeup/sdkconfig.defaults new file mode 100644 index 0000000000..f018081b4d --- /dev/null +++ b/examples/system/ulp/lp_core/lp_uart/lp_uart_char_seq_wakeup/sdkconfig.defaults @@ -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