refactor(uart): minor refactor to uart wakeup code

This commit is contained in:
Song Ruo Jing
2025-04-23 18:16:44 +08:00
parent 669e677ba3
commit 5bb83afac7
4 changed files with 49 additions and 63 deletions

View File

@ -74,8 +74,11 @@ esp_err_t uart_wakeup_setup(uart_port_t uart_num, const uart_wakeup_cfg_t *cfg);
* *
* @param uart_num The UART port to initialize for wakeup (e.g., UART_NUM_0, UART_NUM_1, etc.). * @param uart_num The UART port to initialize for wakeup (e.g., UART_NUM_0, UART_NUM_1, etc.).
* @param wakeup_mode The UART wakeup mode set in `uart_wakeup_setup`. * @param wakeup_mode The UART wakeup mode set in `uart_wakeup_setup`.
*
* @return
* - `ESP_OK` Clear wakeup configuration successfully.
*/ */
void uart_wakeup_clear(uart_port_t uart_num, uart_wakeup_mode_t wakeup_mode); esp_err_t uart_wakeup_clear(uart_port_t uart_num, uart_wakeup_mode_t wakeup_mode);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -11,6 +11,7 @@
* Updates to this file should be made carefully and should not include FreeRTOS APIs or other IDF-specific functionalities, such as the interrupt allocator. * 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 "esp_check.h"
#include "driver/uart_wakeup.h" #include "driver/uart_wakeup.h"
#include "hal/uart_hal.h" #include "hal/uart_hal.h"
#include "esp_private/esp_sleep_internal.h" #include "esp_private/esp_sleep_internal.h"
@ -54,29 +55,26 @@ static esp_err_t uart_char_seq_wk_configure(uart_dev_t *hw, const char* phrase)
esp_err_t uart_wakeup_setup(uart_port_t uart_num, const uart_wakeup_cfg_t *cfg) esp_err_t uart_wakeup_setup(uart_port_t uart_num, const uart_wakeup_cfg_t *cfg)
{ {
ESP_RETURN_ON_FALSE(cfg, ESP_ERR_INVALID_ARG, TAG, "cfg is NULL");
if (cfg == NULL) {
return ESP_ERR_INVALID_ARG;
}
uart_dev_t *hw = UART_LL_GET_HW(uart_num); uart_dev_t *hw = UART_LL_GET_HW(uart_num);
uart_hal_context_t hal = {
.dev = hw,
};
soc_module_clk_t src_clk;
uart_hal_get_sclk(&hal, &src_clk);
if (uart_num < SOC_UART_HP_NUM && cfg->wakeup_mode != UART_WK_MODE_ACTIVE_THRESH) {
// For wakeup modes except ACTIVE_THRESH, the function clock needs to be exist to trigger wakeup
ESP_RETURN_ON_FALSE(src_clk == SOC_MOD_CLK_XTAL, ESP_ERR_NOT_SUPPORTED, TAG, "failed to setup uart wakeup due to the clock source is not XTAL!");
}
esp_err_t ret = ESP_OK;
// This should be mocked at ll level if the selection of the UART wakeup mode is not supported by this SOC. // 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); uart_ll_set_wakeup_mode(hw, cfg->wakeup_mode);
#if SOC_PM_SUPPORT_PMU_CLK_ICG #if SOC_PM_SUPPORT_PMU_CLK_ICG
// When hp uarts are utilized, the main XTAL need to be PU and UARTx & IOMX ICG need to be ungate // When hp uarts are utilized, the main XTAL need to be PU and UARTx & IOMX ICG need to be ungate
bool __attribute__((unused)) is_hp_uart = (uart_num < SOC_UART_HP_NUM); if (uart_num < SOC_UART_HP_NUM && cfg->wakeup_mode != UART_WK_MODE_ACTIVE_THRESH) {
uart_hal_context_t hal = {
.dev = hw,
};
soc_module_clk_t src_clk;
uart_hal_get_sclk(&hal, &src_clk);
if (is_hp_uart && cfg->wakeup_mode != UART_WK_MODE_ACTIVE_THRESH) {
if (src_clk != SOC_MOD_CLK_XTAL) {
ESP_LOGE(TAG, "Failed to setup uart wakeup due to the clock source is not XTAL!");
return ESP_ERR_NOT_SUPPORTED;
}
esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL, ESP_PD_OPTION_ON); esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL, ESP_PD_OPTION_ON);
esp_sleep_clock_config(UART_LL_SLEEP_CLOCK(uart_num), ESP_SLEEP_CLOCK_OPTION_UNGATE); esp_sleep_clock_config(UART_LL_SLEEP_CLOCK(uart_num), ESP_SLEEP_CLOCK_OPTION_UNGATE);
esp_sleep_clock_config(ESP_SLEEP_CLOCK_IOMUX, ESP_SLEEP_CLOCK_OPTION_UNGATE); esp_sleep_clock_config(ESP_SLEEP_CLOCK_IOMUX, ESP_SLEEP_CLOCK_OPTION_UNGATE);
@ -86,45 +84,48 @@ esp_err_t uart_wakeup_setup(uart_port_t uart_num, const uart_wakeup_cfg_t *cfg)
switch (cfg->wakeup_mode) { switch (cfg->wakeup_mode) {
#if SOC_UART_WAKEUP_SUPPORT_ACTIVE_THRESH_MODE #if SOC_UART_WAKEUP_SUPPORT_ACTIVE_THRESH_MODE
case UART_WK_MODE_ACTIVE_THRESH: 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)) { 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; ret = ESP_ERR_INVALID_ARG;
} else {
uart_ll_set_wakeup_edge_thrd(hw, cfg->rx_edge_threshold);
} }
uart_ll_set_wakeup_edge_thrd(hw, cfg->rx_edge_threshold); break;
return ESP_OK;
#endif #endif
#if SOC_UART_WAKEUP_SUPPORT_FIFO_THRESH_MODE #if SOC_UART_WAKEUP_SUPPORT_FIFO_THRESH_MODE
case UART_WK_MODE_FIFO_THRESH: case UART_WK_MODE_FIFO_THRESH:
if (cfg->rx_fifo_threshold > UART_LL_WAKEUP_FIFO_THRED_MAX(hw)) { if (cfg->rx_fifo_threshold > UART_LL_WAKEUP_FIFO_THRED_MAX(hw)) {
return ESP_ERR_INVALID_ARG; ret = ESP_ERR_INVALID_ARG;
} else {
uart_ll_set_wakeup_fifo_thrd(hw, cfg->rx_fifo_threshold);
} }
uart_ll_set_wakeup_fifo_thrd(hw, cfg->rx_fifo_threshold); break;
return ESP_OK;
#endif #endif
#if SOC_UART_WAKEUP_SUPPORT_START_BIT_MODE #if SOC_UART_WAKEUP_SUPPORT_START_BIT_MODE
case UART_WK_MODE_START_BIT: case UART_WK_MODE_START_BIT:
return ESP_OK; break;
#endif #endif
#if SOC_UART_WAKEUP_SUPPORT_CHAR_SEQ_MODE #if SOC_UART_WAKEUP_SUPPORT_CHAR_SEQ_MODE
case UART_WK_MODE_CHAR_SEQ: case UART_WK_MODE_CHAR_SEQ:
return uart_char_seq_wk_configure(hw, cfg->wake_chars_seq); ret = uart_char_seq_wk_configure(hw, cfg->wake_chars_seq);
break;
#endif #endif
default:
ret = ESP_ERR_INVALID_ARG;
break;
} }
return ESP_ERR_INVALID_ARG; return ret;
} }
void uart_wakeup_clear(uart_port_t uart_num, uart_wakeup_mode_t wakeup_mode) esp_err_t uart_wakeup_clear(uart_port_t uart_num, uart_wakeup_mode_t wakeup_mode)
{ {
#if SOC_PM_SUPPORT_PMU_CLK_ICG #if SOC_PM_SUPPORT_PMU_CLK_ICG
// When hp uarts are utilized, the main XTAL need to be PU and UARTx & IOMX ICG need to be ungate // When hp uarts are utilized, the main XTAL need to be PU and UARTx & IOMX ICG need to be ungate
bool __attribute__((unused)) is_hp_uart = (uart_num < SOC_UART_HP_NUM); if (uart_num < SOC_UART_HP_NUM && wakeup_mode != UART_WK_MODE_ACTIVE_THRESH) {
if (is_hp_uart && wakeup_mode != UART_WK_MODE_ACTIVE_THRESH) {
esp_sleep_clock_config(UART_LL_SLEEP_CLOCK(uart_num), ESP_SLEEP_CLOCK_OPTION_GATE); esp_sleep_clock_config(UART_LL_SLEEP_CLOCK(uart_num), ESP_SLEEP_CLOCK_OPTION_GATE);
esp_sleep_clock_config(ESP_SLEEP_CLOCK_IOMUX, ESP_SLEEP_CLOCK_OPTION_GATE); esp_sleep_clock_config(ESP_SLEEP_CLOCK_IOMUX, ESP_SLEEP_CLOCK_OPTION_GATE);
esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL, ESP_PD_OPTION_OFF); esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL, ESP_PD_OPTION_OFF);
} }
#endif #endif
return ESP_OK;
} }

View File

@ -5,26 +5,14 @@
*/ */
#include <stdio.h> #include <stdio.h>
#include <unistd.h> #include <unistd.h>
#include <string.h>
#include <sys/param.h>
#include "unity.h" #include "unity.h"
#include "test_utils.h" #include "test_utils.h"
#include "driver/uart.h" #include "driver/uart.h"
#include "driver/uart_wakeup.h" #include "driver/uart_wakeup.h"
#include "esp_log.h"
#include "esp_rom_gpio.h"
#include "esp_private/gpio.h"
#include "esp_sleep.h" #include "esp_sleep.h"
#include "esp_timer.h" #include "esp_timer.h"
#if SOC_LP_GPIO_MATRIX_SUPPORTED
#include "driver/lp_io.h"
#include "driver/rtc_io.h"
#include "hal/rtc_io_ll.h"
#endif
#include "soc/uart_periph.h"
#include "soc/uart_pins.h" #include "soc/uart_pins.h"
#include "soc/soc_caps.h" #include "soc/soc_caps.h"
#include "soc/clk_tree_defs.h"
#include "test_common.h" #include "test_common.h"
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32P4 #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32P4
@ -84,9 +72,9 @@ static esp_err_t uart_initialization(uart_port_param_t *port_param)
}; };
const int uart_tx = port_param->tx_pin_num; const int uart_tx = port_param->tx_pin_num;
const int uart_rx = port_param->rx_pin_num; const int uart_rx = port_param->rx_pin_num;
TEST_ESP_OK(uart_driver_install(uart_num, BUF_SIZE * 2, BUF_SIZE * 2, 20, NULL, 0));
TEST_ESP_OK(uart_param_config(uart_num, &uart_config)); TEST_ESP_OK(uart_param_config(uart_num, &uart_config));
TEST_ESP_OK(uart_set_pin(uart_num, uart_tx, uart_rx, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE)); TEST_ESP_OK(uart_set_pin(uart_num, uart_tx, uart_rx, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE));
TEST_ESP_OK(uart_driver_install(uart_num, BUF_SIZE * 2, BUF_SIZE * 2, 20, NULL, 0));
return ESP_OK; return ESP_OK;
} }
@ -100,9 +88,6 @@ static esp_err_t uart_wakeup_config(uart_port_param_t *port_param, uart_wakeup_c
* of the SOC to ensure proper operation. Besides, the Rx pin need extra configuration to enable it can work during light sleep */ * of the SOC to ensure proper operation. Besides, the Rx pin need extra configuration to enable it can work during light sleep */
uart_port_t uart_num = port_param->port_num; uart_port_t uart_num = port_param->port_num;
int rx_io_num = port_param->rx_pin_num;
// Keep configure of rx_io
TEST_ESP_OK(gpio_sleep_sel_dis(rx_io_num));
// Initializes the UART wakeup functionality. // Initializes the UART wakeup functionality.
TEST_ESP_OK(uart_wakeup_setup(uart_num, uart_wakeup_cfg)); TEST_ESP_OK(uart_wakeup_setup(uart_num, uart_wakeup_cfg));
TEST_ESP_OK(esp_sleep_enable_uart_wakeup(uart_num)); TEST_ESP_OK(esp_sleep_enable_uart_wakeup(uart_num));

View File

@ -12,7 +12,6 @@
#include "soc/uart_pins.h" #include "soc/uart_pins.h"
#include "driver/uart.h" #include "driver/uart.h"
#include "driver/uart_wakeup.h" #include "driver/uart_wakeup.h"
#include "driver/gpio.h"
#include "sdkconfig.h" #include "sdkconfig.h"
#define EXAMPLE_UART_NUM 0 #define EXAMPLE_UART_NUM 0
@ -42,6 +41,7 @@ static void uart_wakeup_task(void *arg)
} }
uint8_t* dtmp = (uint8_t*) malloc(EXAMPLE_READ_BUF_SIZE); uint8_t* dtmp = (uint8_t*) malloc(EXAMPLE_READ_BUF_SIZE);
assert(dtmp);
while(1) { while(1) {
// Waiting for UART event. // Waiting for UART event.
@ -100,7 +100,7 @@ static void uart_wakeup_task(void *arg)
vTaskDelete(NULL); vTaskDelete(NULL);
} }
static esp_err_t uart_initialization(void) static void uart_initialization(void)
{ {
uart_config_t uart_cfg = { uart_config_t uart_cfg = {
.baud_rate = CONFIG_ESP_CONSOLE_UART_BAUDRATE, .baud_rate = CONFIG_ESP_CONSOLE_UART_BAUDRATE,
@ -115,19 +115,16 @@ static esp_err_t uart_initialization(void)
#endif #endif
}; };
//Install UART driver, and get the queue. //Install UART driver, and get the queue.
ESP_RETURN_ON_ERROR(uart_driver_install(EXAMPLE_UART_NUM, EXAMPLE_UART_BUF_SIZE, EXAMPLE_UART_BUF_SIZE, 20, &uart_evt_que, 0), ESP_ERROR_CHECK(uart_driver_install(EXAMPLE_UART_NUM, EXAMPLE_UART_BUF_SIZE, EXAMPLE_UART_BUF_SIZE, 20, &uart_evt_que, 0));
TAG, "Install uart failed");
if (EXAMPLE_UART_NUM == CONFIG_ESP_CONSOLE_UART_NUM) { if (EXAMPLE_UART_NUM == CONFIG_ESP_CONSOLE_UART_NUM) {
/* temp fix for uart garbled output, can be removed when IDF-5683 done */ /* temp fix for uart garbled output, can be removed when IDF-5683 done */
ESP_RETURN_ON_ERROR(uart_wait_tx_idle_polling(EXAMPLE_UART_NUM), TAG, "Wait uart tx done failed"); ESP_ERROR_CHECK(uart_wait_tx_idle_polling(EXAMPLE_UART_NUM));
} }
ESP_RETURN_ON_ERROR(uart_param_config(EXAMPLE_UART_NUM, &uart_cfg), TAG, "Configure uart param failed"); ESP_ERROR_CHECK(uart_param_config(EXAMPLE_UART_NUM, &uart_cfg));
ESP_RETURN_ON_ERROR(uart_set_pin(EXAMPLE_UART_NUM, EXAMPLE_UART_TX_IO_NUM, EXAMPLE_UART_RX_IO_NUM, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE), ESP_ERROR_CHECK(uart_set_pin(EXAMPLE_UART_NUM, EXAMPLE_UART_TX_IO_NUM, EXAMPLE_UART_RX_IO_NUM, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE));
TAG, "Configure uart gpio pins failed");
return ESP_OK;
} }
static esp_err_t uart_wakeup_config(void) static void uart_wakeup_config(void)
{ {
uart_wakeup_cfg_t uart_wakeup_cfg = {}; uart_wakeup_cfg_t uart_wakeup_cfg = {};
uint8_t wakeup_mode = CONFIG_EXAMPLE_UART_WAKEUP_MODE_SELCTED; uint8_t wakeup_mode = CONFIG_EXAMPLE_UART_WAKEUP_MODE_SELCTED;
@ -162,23 +159,23 @@ static esp_err_t uart_wakeup_config(void)
#endif #endif
default: default:
ESP_LOGE(TAG, "Unknown UART wakeup mode"); ESP_LOGE(TAG, "Unknown UART wakeup mode");
return ESP_FAIL; ESP_ERROR_CHECK(ESP_FAIL);
break; break;
} }
ESP_ERROR_CHECK(uart_wakeup_setup(EXAMPLE_UART_NUM, &uart_wakeup_cfg)); ESP_ERROR_CHECK(uart_wakeup_setup(EXAMPLE_UART_NUM, &uart_wakeup_cfg));
ESP_ERROR_CHECK(esp_sleep_enable_uart_wakeup(EXAMPLE_UART_NUM)); ESP_ERROR_CHECK(esp_sleep_enable_uart_wakeup(EXAMPLE_UART_NUM));
return ESP_OK;
} }
esp_err_t example_register_uart_wakeup(void) esp_err_t example_register_uart_wakeup(void)
{ {
/* Initialize uart1 */ /* Initialize console uart */
ESP_RETURN_ON_ERROR(uart_initialization(), TAG, "Initialize uart%d failed", EXAMPLE_UART_NUM); uart_initialization();
/* Enable wakeup from uart */ /* Enable wakeup from uart */
ESP_RETURN_ON_ERROR(uart_wakeup_config(), TAG, "Configure uart as wakeup source failed"); uart_wakeup_config();
xTaskCreate(uart_wakeup_task, "uart_wakeup_task", 4096, NULL, 5, NULL); xTaskCreate(uart_wakeup_task, "uart_wakeup_task", 4096, NULL, 5, NULL);
ESP_LOGI(TAG, "uart wakeup source is ready"); ESP_LOGI(TAG, "uart wakeup source is ready");
return ESP_OK; return ESP_OK;
} }