From 54f6c44118bf92fbc6e24a2d720f8b65e560ded7 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sat, 21 Feb 2026 18:22:57 -0600 Subject: [PATCH] [uart] Restore gpio_func_sel for RX pins removed in ESP-IDF 5.5+ ESP-IDF 5.5 removed the gpio_func_sel(PIN_FUNC_GPIO) call for RX pins in uart_set_pin() (espressif/esp-idf@1d6bcb86ba), considering it unnecessary for GPIO matrix input routing. However, without this call, pins remain in their default IOMUX function after cold boot (e.g. GPIO4 on ESP32-C3 defaults to MTMS/JTAG function), which prevents UART RX from working via the GPIO matrix. This was masked until ESPHome 2025.11.0 because pin->setup() (which calls gpio_config() -> gpio_func_sel()) was always called. When #11914 made pin->setup() conditional to fix #11823, both paths that set PIN_FUNC_GPIO were eliminated simultaneously. Fixes #13310 --- esphome/components/uart/uart_component_esp_idf.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/esphome/components/uart/uart_component_esp_idf.cpp b/esphome/components/uart/uart_component_esp_idf.cpp index ea7a09fee6..c82ded7577 100644 --- a/esphome/components/uart/uart_component_esp_idf.cpp +++ b/esphome/components/uart/uart_component_esp_idf.cpp @@ -8,6 +8,7 @@ #include "esphome/core/log.h" #include "esphome/core/gpio.h" #include "driver/gpio.h" +#include "esp_private/gpio.h" #include "soc/gpio_num.h" #include "soc/uart_pins.h" @@ -201,6 +202,14 @@ void IDFUARTComponent::load_settings(bool dump_config) { return; } + // Workaround for ESP-IDF 5.5+ removing gpio_func_sel() from uart_set_pin() for RX pins + // (https://github.com/espressif/esp-idf/commit/1d6bcb86ba474990f5e9b7c62913ee15fbca0212). + // Without this, pins like GPIO4 on ESP32-C3 remain in their default IOMUX function + // (e.g. MTMS/JTAG) after cold boot, preventing UART RX from working via GPIO matrix. + if (rx >= 0) { + gpio_func_sel(static_cast(rx), PIN_FUNC_GPIO); + } + err = uart_set_pin(this->uart_num_, tx, rx, flow_control, UART_PIN_NO_CHANGE); if (err != ESP_OK) { ESP_LOGW(TAG, "uart_set_pin failed: %s", esp_err_to_name(err));