From fb20e147d5bbd9247e46a668633eb65f00104f85 Mon Sep 17 00:00:00 2001 From: Song Ruo Jing Date: Mon, 14 Jul 2025 14:59:21 +0800 Subject: [PATCH] fix(console): release default console UART pins if console is switched in bootloader Also print out console UART pin number in app cpu_startup stage Closes https://github.com/espressif/esp-idf/issues/16764 Closes https://github.com/espressif/esp-idf/issues/17459 --- .../src/bootloader_console.c | 27 +++++++++++++++---- components/esp_system/port/cpu_start.c | 10 ++++++- 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/components/bootloader_support/src/bootloader_console.c b/components/bootloader_support/src/bootloader_console.c index eb83ae8b13..e5769d7120 100644 --- a/components/bootloader_support/src/bootloader_console.c +++ b/components/bootloader_support/src/bootloader_console.c @@ -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 */ @@ -10,7 +10,6 @@ #include "soc/uart_periph.h" #include "soc/uart_channel.h" #include "soc/io_mux_reg.h" -#include "soc/gpio_periph.h" #include "soc/gpio_sig_map.h" #include "soc/rtc.h" #include "hal/gpio_ll.h" @@ -26,9 +25,21 @@ #include "esp_rom_sys.h" #include "esp_rom_caps.h" +static void __attribute__((unused)) release_default_console_io(void) +{ + // Default console is UART0 with TX and RX on their IOMUX pins + gpio_ll_output_disable(&GPIO, UART_NUM_0_TXD_DIRECT_GPIO_NUM); + gpio_ll_func_sel(&GPIO, U0TXD_GPIO_NUM, PIN_FUNC_GPIO); // Set TX pin to GPIO function to truly disable output + esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ONE_INPUT, UART_PERIPH_SIGNAL(UART_NUM_0, SOC_UART_RX_PIN_IDX), 0); +} + #ifdef CONFIG_ESP_CONSOLE_NONE void bootloader_console_init(void) { + // Wait for UART FIFO to be empty. + esp_rom_output_tx_wait_idle(0); + release_default_console_io(); + esp_rom_install_channel_putc(1, NULL); esp_rom_install_channel_putc(2, NULL); } @@ -59,9 +70,7 @@ void bootloader_console_init(void) if (uart_num != 0 || uart_tx_gpio != UART_NUM_0_TXD_DIRECT_GPIO_NUM || uart_rx_gpio != UART_NUM_0_RXD_DIRECT_GPIO_NUM) { - // Change default UART pins back to GPIOs - gpio_ll_func_sel(&GPIO, UART_NUM_0_RXD_DIRECT_GPIO_NUM, PIN_FUNC_GPIO); - gpio_ll_func_sel(&GPIO, UART_NUM_0_TXD_DIRECT_GPIO_NUM, PIN_FUNC_GPIO); + release_default_console_io(); // Route GPIO signals to/from pins const uint32_t tx_idx = UART_PERIPH_SIGNAL(uart_num, SOC_UART_TX_PIN_IDX); const uint32_t rx_idx = UART_PERIPH_SIGNAL(uart_num, SOC_UART_RX_PIN_IDX); @@ -101,6 +110,10 @@ static char s_usb_cdc_buf[ESP_ROM_CDC_ACM_WORK_BUF_MIN]; void bootloader_console_init(void) { + // Wait for UART FIFO to be empty. + esp_rom_output_tx_wait_idle(0); + release_default_console_io(); + #ifdef CONFIG_IDF_TARGET_ESP32S2 /* ESP32-S2 specific patch to set the correct serial number in the descriptor. * Later chips don't need this. @@ -120,6 +133,10 @@ void bootloader_console_init(void) #ifdef CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG void bootloader_console_init(void) { + // Wait for UART FIFO to be empty. + esp_rom_output_tx_wait_idle(0); + release_default_console_io(); + esp_rom_output_switch_buffer(ESP_ROM_USB_SERIAL_DEVICE_NUM); /* Switch console channel to avoid output on UART and allow */ diff --git a/components/esp_system/port/cpu_start.c b/components/esp_system/port/cpu_start.c index ea59796c44..cbd5dafa3c 100644 --- a/components/esp_system/port/cpu_start.c +++ b/components/esp_system/port/cpu_start.c @@ -97,6 +97,7 @@ #include "hal/cache_hal.h" #include "hal/cache_ll.h" #include "hal/efuse_ll.h" +#include "soc/uart_pins.h" #include "hal/cpu_utility_ll.h" #include "soc/periph_defs.h" #include "esp_cpu.h" @@ -773,8 +774,15 @@ NOINLINE_ATTR static void system_early_init(const soc_reset_reason_t *rst_reas) // In a single thread mode, the freertos is not started yet. So don't have to use a critical section. int __DECLARE_RCC_ATOMIC_ENV __attribute__((unused)); // To avoid build errors about spinlock's __DECLARE_RCC_ATOMIC_ENV esp_rom_uart_set_clock_baudrate(CONFIG_ESP_CONSOLE_ROM_SERIAL_PORT_NUM, clock_hz, CONFIG_ESP_CONSOLE_UART_BAUDRATE); + int console_uart_tx_pin = U0TXD_GPIO_NUM; + int console_uart_rx_pin = U0RXD_GPIO_NUM; +#if CONFIG_ESP_CONSOLE_UART_CUSTOM + console_uart_tx_pin = (CONFIG_ESP_CONSOLE_UART_TX_GPIO >= 0) ? CONFIG_ESP_CONSOLE_UART_TX_GPIO : U0TXD_GPIO_NUM; + console_uart_rx_pin = (CONFIG_ESP_CONSOLE_UART_RX_GPIO >= 0) ? CONFIG_ESP_CONSOLE_UART_RX_GPIO : U0RXD_GPIO_NUM; #endif -#endif + ESP_EARLY_LOGI(TAG, "GPIO %d and %d are used as console UART I/O pins", console_uart_rx_pin, console_uart_tx_pin); +#endif // CONFIG_ESP_CONSOLE_UART +#endif // !CONFIG_IDF_ENV_FPGA #if SOC_DEEP_SLEEP_SUPPORTED // Need to unhold the IOs that were hold right before entering deep sleep, which are used as wakeup pins