From 1218210404111e915f3669b41d7488a4bb65309f Mon Sep 17 00:00:00 2001 From: Song Ruo Jing Date: Mon, 6 Jul 2026 19:28:56 +0800 Subject: [PATCH] fix(uart): reduce current consumption in sleep mode --- components/esp_driver_uart/src/uart.c | 10 ++++++---- components/esp_hw_support/sleep_gpio.c | 27 ++++++++++++++------------ 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/components/esp_driver_uart/src/uart.c b/components/esp_driver_uart/src/uart.c index 5fa812a96ee..56660ab6258 100644 --- a/components/esp_driver_uart/src/uart.c +++ b/components/esp_driver_uart/src/uart.c @@ -870,8 +870,8 @@ esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int r #if CONFIG_ESP_SLEEP_GPIO_RESET_WORKAROUND || CONFIG_PM_SLP_DISABLE_GPIO // In such case, IOs are going to switch to sleep configuration (isolate) when entering sleep for power saving reason // But TX IO in isolate state could write garbled data to the other end - // Therefore, we should disable the switch of the TX pin to sleep configuration - gpio_sleep_sel_dis(tx_io_num); + // Therefore, we should enable internal pull-up of the TX pin in sleep configuration + gpio_sleep_set_pull_mode(tx_io_num, GPIO_PULLUP_ONLY); #endif if (tx_rx_same_io || !uart_try_set_iomux_pin(uart_num, tx_io_num, SOC_UART_TX_PIN_IDX)) { if (uart_num < SOC_UART_HP_NUM) { @@ -895,8 +895,10 @@ esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int r #if CONFIG_ESP_SLEEP_GPIO_RESET_WORKAROUND || CONFIG_PM_SLP_DISABLE_GPIO // In such case, IOs are going to switch to sleep configuration (isolate) when entering sleep for power saving reason // But RX IO in isolate state could receive garbled data into FIFO, which is not desired - // Therefore, we should disable the switch of the RX pin to sleep configuration - gpio_sleep_sel_dis(rx_io_num); + // Therefore, we should enable internal pull-up of the RX pin in sleep configuration + // Meanwhile, RX pin may be used for wakeup, so configure RX pin as input + gpio_sleep_set_pull_mode(rx_io_num, GPIO_PULLUP_ONLY); + gpio_sleep_set_direction(rx_io_num, GPIO_MODE_INPUT); #endif if (tx_rx_same_io || !uart_try_set_iomux_pin(uart_num, rx_io_num, SOC_UART_RX_PIN_IDX)) { io_reserve_mask &= ~BIT64(rx_io_num); // input IO via GPIO matrix does not need to be reserved diff --git a/components/esp_hw_support/sleep_gpio.c b/components/esp_hw_support/sleep_gpio.c index 94720466a61..c2b4f209880 100644 --- a/components/esp_hw_support/sleep_gpio.c +++ b/components/esp_hw_support/sleep_gpio.c @@ -64,6 +64,21 @@ void esp_sleep_config_gpio_isolate(void) } } +#if CONFIG_ESP_CONSOLE_UART +#if CONFIG_ESP_CONSOLE_UART_CUSTOM + const gpio_num_t uart_tx_gpio = (CONFIG_ESP_CONSOLE_UART_TX_GPIO >= 0) ? CONFIG_ESP_CONSOLE_UART_TX_GPIO : U0TXD_GPIO_NUM; + const gpio_num_t uart_rx_gpio = (CONFIG_ESP_CONSOLE_UART_RX_GPIO >= 0) ? CONFIG_ESP_CONSOLE_UART_RX_GPIO : U0RXD_GPIO_NUM; +#else + const gpio_num_t uart_tx_gpio = U0TXD_GPIO_NUM; + const gpio_num_t uart_rx_gpio = U0RXD_GPIO_NUM; +#endif + // Pull up TX and RX lines to avoid garbled data during sleep + gpio_sleep_set_pull_mode(uart_tx_gpio, GPIO_PULLUP_ONLY); + gpio_sleep_set_pull_mode(uart_rx_gpio, GPIO_PULLUP_ONLY); + // TX pin can be isolated, but RX pin may be used for wakeup, so configure RX pin as input + gpio_sleep_set_direction(uart_rx_gpio, GPIO_MODE_INPUT); +#endif + #if CONFIG_ESP_SLEEP_MSPI_NEED_ALL_IO_PU && !SOC_MSPI_HAS_INDEPENT_IOMUX gpio_sleep_set_pull_mode(esp_mspi_get_io(ESP_MSPI_IO_CLK), GPIO_PULLUP_ONLY); gpio_sleep_set_pull_mode(esp_mspi_get_io(ESP_MSPI_IO_Q), GPIO_PULLUP_ONLY); @@ -91,18 +106,6 @@ void esp_sleep_enable_gpio_switch(bool enable) ESP_EARLY_LOGI(TAG, "%s automatic switching of GPIO sleep configuration", enable ? "Enable" : "Disable"); for (gpio_num_t gpio_num = GPIO_NUM_0; gpio_num < GPIO_NUM_MAX; gpio_num++) { if (GPIO_IS_VALID_GPIO(gpio_num)) { -#if CONFIG_ESP_CONSOLE_UART -#if CONFIG_ESP_CONSOLE_UART_CUSTOM - const int uart_tx_gpio = (CONFIG_ESP_CONSOLE_UART_TX_GPIO >= 0) ? CONFIG_ESP_CONSOLE_UART_TX_GPIO : UART_NUM_0_TXD_DIRECT_GPIO_NUM; - const int uart_rx_gpio = (CONFIG_ESP_CONSOLE_UART_RX_GPIO >= 0) ? CONFIG_ESP_CONSOLE_UART_RX_GPIO : UART_NUM_0_RXD_DIRECT_GPIO_NUM; - if ((gpio_num == uart_tx_gpio) || (gpio_num == uart_rx_gpio)) { -#else - if ((gpio_num == UART_NUM_0_TXD_DIRECT_GPIO_NUM) || (gpio_num == UART_NUM_0_RXD_DIRECT_GPIO_NUM)) { -#endif - gpio_sleep_sel_dis(gpio_num); - continue; - } -#endif /* If the PSRAM is disable in ESP32xx chips equipped with PSRAM, there will be a large current leakage. */ #if CONFIG_ESP_SLEEP_PSRAM_LEAKAGE_WORKAROUND && CONFIG_SPIRAM & !SOC_MSPI_HAS_INDEPENT_IOMUX if (gpio_num == esp_mspi_get_io(ESP_MSPI_IO_CS1)) {