From 96372d209182f8dd42c6563503b1988a9027f14a Mon Sep 17 00:00:00 2001 From: Song Ruo Jing Date: Wed, 5 Feb 2025 16:06:33 +0800 Subject: [PATCH 01/10] fix(uart): fixed coverity ininitialized scalar variable in uart_tcgetattr --- components/esp_driver_uart/src/uart_vfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/esp_driver_uart/src/uart_vfs.c b/components/esp_driver_uart/src/uart_vfs.c index 8d00ab4338..8fa4b0c63f 100644 --- a/components/esp_driver_uart/src/uart_vfs.c +++ b/components/esp_driver_uart/src/uart_vfs.c @@ -880,7 +880,7 @@ static int uart_tcgetattr(int fd, struct termios *p) } { - uint32_t baudrate; + uint32_t baudrate = 0; if (uart_get_baudrate(fd, &baudrate) != ESP_OK) { errno = EINVAL; return -1; From 3de0b669e7de181f132f5d0bf4c96ade168403ad Mon Sep 17 00:00:00 2001 From: Song Ruo Jing Date: Thu, 6 Mar 2025 18:47:41 +0800 Subject: [PATCH 02/10] docs(uart): improve set/get baud rate API docs Closes https://github.com/espressif/esp-idf/issues/15449 --- components/esp_driver_uart/include/driver/uart.h | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/components/esp_driver_uart/include/driver/uart.h b/components/esp_driver_uart/include/driver/uart.h index ff3138ca7c..5ffb7dd269 100644 --- a/components/esp_driver_uart/include/driver/uart.h +++ b/components/esp_driver_uart/include/driver/uart.h @@ -34,7 +34,8 @@ extern "C" { * @brief UART configuration parameters for uart_param_config function */ typedef struct { - int baud_rate; /*!< UART baud rate*/ + int baud_rate; /*!< UART baud rate + Note that the actual baud rate set could have a slight deviation from the user-configured value due to rounding error*/ uart_word_length_t data_bits; /*!< UART byte size*/ uart_parity_t parity; /*!< UART parity mode*/ uart_stop_bits_t stop_bits; /*!< UART stop bits*/ @@ -225,7 +226,9 @@ esp_err_t uart_get_parity(uart_port_t uart_num, uart_parity_t* parity_mode); esp_err_t uart_get_sclk_freq(uart_sclk_t sclk, uint32_t* out_freq_hz); /** - * @brief Set UART baud rate. + * @brief Set desired UART baud rate. + * + * Note that the actual baud rate set could have a slight deviation from the user-configured value due to rounding error. * * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). * @param baudrate UART baud rate. @@ -237,7 +240,9 @@ esp_err_t uart_get_sclk_freq(uart_sclk_t sclk, uint32_t* out_freq_hz); esp_err_t uart_set_baudrate(uart_port_t uart_num, uint32_t baudrate); /** - * @brief Get the UART baud rate configuration. + * @brief Get the actual UART baud rate. + * + * It returns the real UART rate set in the hardware. It could have a slight deviation from the user-configured baud rate. * * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). * @param baudrate Pointer to accept value of UART baud rate From 52cd954e417908a2528d9c5665b5d70f3ee19f88 Mon Sep 17 00:00:00 2001 From: Song Ruo Jing Date: Thu, 13 Mar 2025 19:10:21 +0800 Subject: [PATCH 03/10] fix(sleep): uart suspend/flush should also check if port is enabled on esp32 --- components/esp_hw_support/sleep_modes.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index 42e2b0f1e5..f511d67f4f 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -543,13 +543,9 @@ static void IRAM_ATTR resume_timers(uint32_t pd_flags) { static void IRAM_ATTR flush_uarts(void) { for (int i = 0; i < SOC_UART_HP_NUM; ++i) { -#ifdef CONFIG_IDF_TARGET_ESP32 - esp_rom_output_tx_wait_idle(i); -#else if (uart_ll_is_enabled(i)) { esp_rom_output_tx_wait_idle(i); } -#endif } } @@ -563,11 +559,9 @@ FORCE_INLINE_ATTR void suspend_uarts(void) { s_suspended_uarts_bmap = 0; for (int i = 0; i < SOC_UART_HP_NUM; ++i) { -#ifndef CONFIG_IDF_TARGET_ESP32 if (!uart_ll_is_enabled(i)) { continue; } -#endif uart_ll_force_xoff(i); s_suspended_uarts_bmap |= BIT(i); #if SOC_UART_SUPPORT_FSM_TX_WAIT_SEND From 7c4a6bf9d686fd9e8fdd383f5e76245d493e2989 Mon Sep 17 00:00:00 2001 From: Song Ruo Jing Date: Wed, 19 Mar 2025 22:00:09 +0800 Subject: [PATCH 04/10] fix(uart): correct C3/S3 module enable porcedure to avoid undesired line noise --- components/hal/esp32c3/include/hal/uart_ll.h | 2 ++ components/hal/esp32s3/include/hal/uart_ll.h | 3 +++ 2 files changed, 5 insertions(+) diff --git a/components/hal/esp32c3/include/hal/uart_ll.h b/components/hal/esp32c3/include/hal/uart_ll.h index f9f00ad85a..85d6e430ba 100644 --- a/components/hal/esp32c3/include/hal/uart_ll.h +++ b/components/hal/esp32c3/include/hal/uart_ll.h @@ -107,12 +107,14 @@ static inline void uart_ll_reset_register(uart_port_t uart_num) // ESP32C3 requires a workaround: enable core reset before enabling uart module clock to prevent uart output garbage value switch (uart_num) { case 0: + SYSTEM.perip_rst_en0.reg_uart_rst = 0; UART0.clk_conf.rst_core = 1; SYSTEM.perip_rst_en0.reg_uart_rst = 1; SYSTEM.perip_rst_en0.reg_uart_rst = 0; UART0.clk_conf.rst_core = 0; break; case 1: + SYSTEM.perip_rst_en0.reg_uart1_rst = 0; UART1.clk_conf.rst_core = 1; SYSTEM.perip_rst_en0.reg_uart1_rst = 1; SYSTEM.perip_rst_en0.reg_uart1_rst = 0; diff --git a/components/hal/esp32s3/include/hal/uart_ll.h b/components/hal/esp32s3/include/hal/uart_ll.h index 3dd538ec50..3a1e41fa88 100644 --- a/components/hal/esp32s3/include/hal/uart_ll.h +++ b/components/hal/esp32s3/include/hal/uart_ll.h @@ -112,18 +112,21 @@ static inline void uart_ll_reset_register(uart_port_t uart_num) // ESP32S3 requires a workaround: enable core reset before enabling uart module clock to prevent uart output garbage value switch (uart_num) { case 0: + SYSTEM.perip_rst_en0.uart_rst = 0; UART0.clk_conf.rst_core = 1; SYSTEM.perip_rst_en0.uart_rst = 1; SYSTEM.perip_rst_en0.uart_rst = 0; UART0.clk_conf.rst_core = 0; break; case 1: + SYSTEM.perip_rst_en0.uart1_rst = 0; UART1.clk_conf.rst_core = 1; SYSTEM.perip_rst_en0.uart1_rst = 1; SYSTEM.perip_rst_en0.uart1_rst = 0; UART1.clk_conf.rst_core = 0; break; case 2: + SYSTEM.perip_rst_en1.uart2_rst = 0; UART2.clk_conf.rst_core = 1; SYSTEM.perip_rst_en1.uart2_rst = 1; SYSTEM.perip_rst_en1.uart2_rst = 0; From 5383558bb99471c9369047773fb5dca0b2b5f9d0 Mon Sep 17 00:00:00 2001 From: Song Ruo Jing Date: Thu, 3 Apr 2025 22:16:28 +0800 Subject: [PATCH 05/10] fix(uart): fix nmea0183 example wrong knots to m/s unit conversion Closes https://github.com/espressif/esp-idf/issues/15695 --- .../peripherals/uart/nmea0183_parser/main/nmea_parser.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/peripherals/uart/nmea0183_parser/main/nmea_parser.c b/examples/peripherals/uart/nmea0183_parser/main/nmea_parser.c index 0dbd6ab9d9..3502dca847 100644 --- a/examples/peripherals/uart/nmea0183_parser/main/nmea_parser.c +++ b/examples/peripherals/uart/nmea0183_parser/main/nmea_parser.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -264,7 +264,7 @@ static void parse_rmc(esp_gps_t *esp_gps) } break; case 7: /* Process ground speed in unit m/s */ - esp_gps->parent.speed = strtof(esp_gps->item_str, NULL) * 1.852; + esp_gps->parent.speed = strtof(esp_gps->item_str, NULL) * 0.514444; break; case 8: /* Process true course over ground */ esp_gps->parent.cog = strtof(esp_gps->item_str, NULL); @@ -338,7 +338,7 @@ static void parse_vtg(esp_gps_t *esp_gps) esp_gps->parent.variation = strtof(esp_gps->item_str, NULL); break; case 5:/* Process ground speed in unit m/s */ - esp_gps->parent.speed = strtof(esp_gps->item_str, NULL) * 1.852;//knots to m/s + esp_gps->parent.speed = strtof(esp_gps->item_str, NULL) * 0.514444;//knots to m/s break; case 7:/* Process ground speed in unit m/s */ esp_gps->parent.speed = strtof(esp_gps->item_str, NULL) / 3.6;//km/h to m/s @@ -702,7 +702,7 @@ nmea_parser_handle_t nmea_parser_init(const nmea_parser_config_t *config) .task_name = NULL }; if (esp_event_loop_create(&loop_args, &esp_gps->event_loop_hdl) != ESP_OK) { - ESP_LOGE(GPS_TAG, "create event loop faild"); + ESP_LOGE(GPS_TAG, "create event loop failed"); goto err_eloop; } /* Create NMEA Parser task */ From 74a496e3d0bc707055644b8c1be1cbed3ccad61e Mon Sep 17 00:00:00 2001 From: Song Ruo Jing Date: Mon, 19 May 2025 22:18:24 +0800 Subject: [PATCH 06/10] fix(dedic_gpio): fix calloc to heap_caps_calloc --- components/esp_driver_gpio/src/dedic_gpio.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/components/esp_driver_gpio/src/dedic_gpio.c b/components/esp_driver_gpio/src/dedic_gpio.c index 9c60cfe7e2..a5f80b50a7 100644 --- a/components/esp_driver_gpio/src/dedic_gpio.c +++ b/components/esp_driver_gpio/src/dedic_gpio.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 */ @@ -33,6 +33,8 @@ #include "hal/dedic_gpio_ll.h" #endif +#define DEDIC_GPIO_MEM_ALLOC_CAPS MALLOC_CAP_DEFAULT + static const char *TAG = "dedic_gpio"; typedef struct dedic_gpio_platform_t dedic_gpio_platform_t; @@ -75,7 +77,7 @@ static esp_err_t dedic_gpio_build_platform(int core_id) // prevent building platform concurrently _lock_acquire(&s_platform_mutexlock[core_id]); if (!s_platform[core_id]) { - s_platform[core_id] = calloc(1, sizeof(dedic_gpio_platform_t)); + s_platform[core_id] = (dedic_gpio_platform_t *)heap_caps_calloc(1, sizeof(dedic_gpio_platform_t), DEDIC_GPIO_MEM_ALLOC_CAPS); if (s_platform[core_id]) { // initialize platform members s_platform[core_id]->spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED; @@ -213,7 +215,7 @@ esp_err_t dedic_gpio_new_bundle(const dedic_gpio_bundle_config_t *config, dedic_ ESP_GOTO_ON_ERROR(dedic_gpio_build_platform(core_id), err, TAG, "build platform %d failed", core_id); size_t bundle_size = sizeof(dedic_gpio_bundle_t) + config->array_size * sizeof(config->gpio_array[0]); - bundle = calloc(1, bundle_size); + bundle = (dedic_gpio_bundle_t *)heap_caps_calloc(1, bundle_size, DEDIC_GPIO_MEM_ALLOC_CAPS); ESP_GOTO_ON_FALSE(bundle, ESP_ERR_NO_MEM, err, TAG, "no mem for bundle"); // for performance reasons, we only search for continuous channels From 752df66332e73a9ae9d66a8e5cd1cc54be470dfc Mon Sep 17 00:00:00 2001 From: Song Ruo Jing Date: Wed, 23 Apr 2025 15:28:41 +0800 Subject: [PATCH 07/10] feat(uart): add pin release process to uart driver --- components/esp_driver_uart/src/uart.c | 149 +++++++++++++++++++------- 1 file changed, 113 insertions(+), 36 deletions(-) diff --git a/components/esp_driver_uart/src/uart.c b/components/esp_driver_uart/src/uart.c index 6e0506a419..4dbde19bc5 100644 --- a/components/esp_driver_uart/src/uart.c +++ b/components/esp_driver_uart/src/uart.c @@ -33,6 +33,9 @@ #include "driver/rtc_io.h" #include "hal/rtc_io_ll.h" #include "driver/lp_io.h" +#if SOC_LP_GPIO_MATRIX_SUPPORTED +#include "soc/lp_gpio_pins.h" +#endif #endif #include "clk_ctrl_os.h" #include "esp_pm.h" @@ -105,6 +108,10 @@ static const char *UART_TAG = "uart"; .hal.dev = UART_LL_GET_HW(uart_num), \ INIT_CRIT_SECTION_LOCK_IN_STRUCT(spinlock) \ .hw_enabled = false, \ + .tx_io_num = -1, \ + .rx_io_num = -1, \ + .rts_io_num = -1, \ + .cts_io_num = -1, \ } typedef struct { @@ -170,6 +177,10 @@ typedef struct { bool retention_link_inited; /*!< Mark whether the retention link is inited */ bool retention_link_created; /*!< Mark whether the retention link is created */ #endif + int tx_io_num; + int rx_io_num; + int rts_io_num; + int cts_io_num; } uart_context_t; static uart_obj_t *p_uart_obj[UART_NUM_MAX] = {0}; @@ -703,8 +714,63 @@ static bool uart_try_set_iomux_pin(uart_port_t uart_num, int io_num, uint32_t id return true; } -//internal signal can be output to multiple GPIO pads -//only one GPIO pad can connect with input signal +static void uart_release_pin(uart_port_t uart_num) +{ + if (uart_num >= UART_NUM_MAX) { + return; + } + if (uart_context[uart_num].tx_io_num >= 0) { + gpio_ll_output_disable(&GPIO, uart_context[uart_num].tx_io_num); +#if (SOC_UART_LP_NUM >= 1) + if (!(uart_num < SOC_UART_HP_NUM)) { + rtc_gpio_deinit(uart_context[uart_num].tx_io_num); + } +#endif + } + + if (uart_context[uart_num].rx_io_num >= 0) { + if (uart_num < SOC_UART_HP_NUM) { + esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ONE_INPUT, UART_PERIPH_SIGNAL(uart_num, SOC_UART_RX_PIN_IDX), false); + } +#if (SOC_UART_LP_NUM >= 1) + else { +#if SOC_LP_GPIO_MATRIX_SUPPORTED + lp_gpio_connect_in_signal(LP_GPIO_MATRIX_CONST_ONE_INPUT, UART_PERIPH_SIGNAL(uart_num, SOC_UART_RX_PIN_IDX), false); +#endif + rtc_gpio_deinit(uart_context[uart_num].rx_io_num); + } +#endif + } + + if (uart_context[uart_num].rts_io_num >= 0) { + gpio_ll_output_disable(&GPIO, uart_context[uart_num].rts_io_num); +#if (SOC_UART_LP_NUM >= 1) + if (!(uart_num < SOC_UART_HP_NUM)) { + rtc_gpio_deinit(uart_context[uart_num].rts_io_num); + } +#endif + } + + if (uart_context[uart_num].cts_io_num >= 0) { + if (uart_num < SOC_UART_HP_NUM) { + esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ZERO_INPUT, UART_PERIPH_SIGNAL(uart_num, SOC_UART_CTS_PIN_IDX), false); + } +#if (SOC_UART_LP_NUM >= 1) + else { +#if SOC_LP_GPIO_MATRIX_SUPPORTED + lp_gpio_connect_in_signal(LP_GPIO_MATRIX_CONST_ZERO_INPUT, UART_PERIPH_SIGNAL(uart_num, SOC_UART_CTS_PIN_IDX), false); +#endif + rtc_gpio_deinit(uart_context[uart_num].cts_io_num); + } +#endif + } + + uart_context[uart_num].tx_io_num = -1; + uart_context[uart_num].rx_io_num = -1; + uart_context[uart_num].rts_io_num = -1; + uart_context[uart_num].cts_io_num = -1; +} + esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int rts_io_num, int cts_io_num) { ESP_RETURN_ON_FALSE((uart_num >= 0), ESP_FAIL, UART_TAG, "uart_num error"); @@ -736,48 +802,56 @@ esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int r } #endif + // First, release previously configured IOs if there is + uart_release_pin(uart_num); + // Since an IO cannot route peripheral signals via IOMUX and GPIO matrix at the same time, // if tx and rx share the same IO, both signals need to be route to IOs through GPIO matrix bool tx_rx_same_io = (tx_io_num == rx_io_num); /* In the following statements, if the io_num is negative, no need to configure anything. */ - if (tx_io_num >= 0 && (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) { - gpio_func_sel(tx_io_num, PIN_FUNC_GPIO); - esp_rom_gpio_connect_out_signal(tx_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_TX_PIN_IDX), 0, 0); - // output enable is set inside esp_rom_gpio_connect_out_signal func after the signal is connected - // (output enabled too early may cause unnecessary level change at the pad) - } -#if SOC_LP_GPIO_MATRIX_SUPPORTED - else { - rtc_gpio_init(tx_io_num); // set as a LP_GPIO pin - - lp_gpio_connect_out_signal(tx_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_TX_PIN_IDX), 0, 0); - // output enable is set inside lp_gpio_connect_out_signal func after the signal is connected - } -#endif - } - - if (rx_io_num >= 0 && (tx_rx_same_io || !uart_try_set_iomux_pin(uart_num, rx_io_num, SOC_UART_RX_PIN_IDX))) { - if (uart_num < SOC_UART_HP_NUM) { - gpio_func_sel(rx_io_num, PIN_FUNC_GPIO); - gpio_ll_input_enable(&GPIO, rx_io_num); - esp_rom_gpio_connect_in_signal(rx_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_RX_PIN_IDX), 0); - } -#if SOC_LP_GPIO_MATRIX_SUPPORTED - else { - rtc_gpio_mode_t mode = (tx_rx_same_io ? RTC_GPIO_MODE_INPUT_OUTPUT : RTC_GPIO_MODE_INPUT_ONLY); - rtc_gpio_set_direction(rx_io_num, mode); - if (!tx_rx_same_io) { // set the same pin again as a LP_GPIO will overwrite connected out_signal, not desired, so skip - rtc_gpio_init(rx_io_num); // set as a LP_GPIO pin + if (tx_io_num >= 0) { + uart_context[uart_num].tx_io_num = tx_io_num; + 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) { + gpio_func_sel(tx_io_num, PIN_FUNC_GPIO); + esp_rom_gpio_connect_out_signal(tx_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_TX_PIN_IDX), 0, 0); + // output enable is set inside esp_rom_gpio_connect_out_signal func after the signal is connected + // (output enabled too early may cause unnecessary level change at the pad) + } +#if SOC_LP_GPIO_MATRIX_SUPPORTED + else { + rtc_gpio_init(tx_io_num); // set as a LP_GPIO pin + lp_gpio_connect_out_signal(tx_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_TX_PIN_IDX), 0, 0); + // output enable is set inside lp_gpio_connect_out_signal func after the signal is connected } - - lp_gpio_connect_in_signal(rx_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_RX_PIN_IDX), 0); - } #endif + } } - if (rts_io_num >= 0 && !uart_try_set_iomux_pin(uart_num, rts_io_num, SOC_UART_RTS_PIN_IDX)) { + if (rx_io_num >= 0) { + uart_context[uart_num].rx_io_num = rx_io_num; + if (tx_rx_same_io || !uart_try_set_iomux_pin(uart_num, rx_io_num, SOC_UART_RX_PIN_IDX)) { + if (uart_num < SOC_UART_HP_NUM) { + gpio_func_sel(rx_io_num, PIN_FUNC_GPIO); + gpio_ll_input_enable(&GPIO, rx_io_num); + esp_rom_gpio_connect_in_signal(rx_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_RX_PIN_IDX), 0); + } +#if SOC_LP_GPIO_MATRIX_SUPPORTED + else { + rtc_gpio_mode_t mode = (tx_rx_same_io ? RTC_GPIO_MODE_INPUT_OUTPUT : RTC_GPIO_MODE_INPUT_ONLY); + rtc_gpio_set_direction(rx_io_num, mode); + if (!tx_rx_same_io) { // set the same pin again as a LP_GPIO will overwrite connected out_signal, not desired, so skip + rtc_gpio_init(rx_io_num); // set as a LP_GPIO pin + } + + lp_gpio_connect_in_signal(rx_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_RX_PIN_IDX), 0); + } +#endif + } + } + + if (rts_io_num >= 0 && (uart_context[uart_num].rts_io_num = rts_io_num, !uart_try_set_iomux_pin(uart_num, rts_io_num, SOC_UART_RTS_PIN_IDX))) { if (uart_num < SOC_UART_HP_NUM) { gpio_func_sel(rts_io_num, PIN_FUNC_GPIO); esp_rom_gpio_connect_out_signal(rts_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_RTS_PIN_IDX), 0, 0); @@ -792,7 +866,7 @@ esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int r #endif } - if (cts_io_num >= 0 && !uart_try_set_iomux_pin(uart_num, cts_io_num, SOC_UART_CTS_PIN_IDX)) { + if (cts_io_num >= 0 && (uart_context[uart_num].cts_io_num = cts_io_num, !uart_try_set_iomux_pin(uart_num, cts_io_num, SOC_UART_CTS_PIN_IDX))) { if (uart_num < SOC_UART_HP_NUM) { gpio_func_sel(cts_io_num, PIN_FUNC_GPIO); gpio_set_pull_mode(cts_io_num, GPIO_PULLUP_ONLY); @@ -1780,6 +1854,9 @@ esp_err_t uart_driver_delete(uart_port_t uart_num) ESP_LOGI(UART_TAG, "ALREADY NULL"); return ESP_OK; } + + uart_release_pin(uart_num); + esp_intr_free(p_uart_obj[uart_num]->intr_handle); uart_disable_rx_intr(uart_num); uart_disable_tx_intr(uart_num); From 501fb2fab27e483889adea159e8b109ff5915a1e Mon Sep 17 00:00:00 2001 From: Song Ruo Jing Date: Wed, 23 Apr 2025 16:13:09 +0800 Subject: [PATCH 08/10] fix(uart): eliminate garbled data on UART TX/RX line in sleep --- components/esp_driver_uart/src/uart.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/components/esp_driver_uart/src/uart.c b/components/esp_driver_uart/src/uart.c index 4dbde19bc5..920f982c05 100644 --- a/components/esp_driver_uart/src/uart.c +++ b/components/esp_driver_uart/src/uart.c @@ -725,6 +725,9 @@ static void uart_release_pin(uart_port_t uart_num) if (!(uart_num < SOC_UART_HP_NUM)) { rtc_gpio_deinit(uart_context[uart_num].tx_io_num); } +#endif +#if CONFIG_ESP_SLEEP_GPIO_RESET_WORKAROUND || CONFIG_PM_SLP_DISABLE_GPIO + gpio_sleep_sel_en(uart_context[uart_num].tx_io_num); // re-enable the switch to the sleep configuration to save power consumption #endif } @@ -739,6 +742,9 @@ static void uart_release_pin(uart_port_t uart_num) #endif rtc_gpio_deinit(uart_context[uart_num].rx_io_num); } +#endif +#if CONFIG_ESP_SLEEP_GPIO_RESET_WORKAROUND || CONFIG_PM_SLP_DISABLE_GPIO + gpio_sleep_sel_en(uart_context[uart_num].rx_io_num); // re-enable the switch to the sleep configuration to save power consumption #endif } @@ -812,6 +818,12 @@ esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int r /* In the following statements, if the io_num is negative, no need to configure anything. */ if (tx_io_num >= 0) { uart_context[uart_num].tx_io_num = tx_io_num; +#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); +#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) { gpio_func_sel(tx_io_num, PIN_FUNC_GPIO); @@ -831,6 +843,12 @@ esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int r if (rx_io_num >= 0) { uart_context[uart_num].rx_io_num = rx_io_num; +#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); +#endif if (tx_rx_same_io || !uart_try_set_iomux_pin(uart_num, rx_io_num, SOC_UART_RX_PIN_IDX)) { if (uart_num < SOC_UART_HP_NUM) { gpio_func_sel(rx_io_num, PIN_FUNC_GPIO); From 674113bfcc2e57a4a2979a6afd9fb98636a52f40 Mon Sep 17 00:00:00 2001 From: Song Ruo Jing Date: Tue, 15 Apr 2025 15:10:17 +0800 Subject: [PATCH 09/10] fix(gpio): add some detailed error log for gpio_pullup_en and gpio_pulldown_en --- components/esp_driver_gpio/src/gpio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/esp_driver_gpio/src/gpio.c b/components/esp_driver_gpio/src/gpio.c index b4071325b0..33f27668b7 100644 --- a/components/esp_driver_gpio/src/gpio.c +++ b/components/esp_driver_gpio/src/gpio.c @@ -76,7 +76,7 @@ static gpio_context_t gpio_context = { esp_err_t gpio_pullup_en(gpio_num_t gpio_num) { - GPIO_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG); + GPIO_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), "GPIO number error (input-only pad has no internal PU)", ESP_ERR_INVALID_ARG); if (!rtc_gpio_is_valid_gpio(gpio_num) || SOC_GPIO_SUPPORT_RTC_INDEPENDENT) { portENTER_CRITICAL(&gpio_context.gpio_spinlock); @@ -114,7 +114,7 @@ esp_err_t gpio_pullup_dis(gpio_num_t gpio_num) esp_err_t gpio_pulldown_en(gpio_num_t gpio_num) { - GPIO_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG); + GPIO_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), "GPIO number error (input-only pad has no internal PD)", ESP_ERR_INVALID_ARG); if (!rtc_gpio_is_valid_gpio(gpio_num) || SOC_GPIO_SUPPORT_RTC_INDEPENDENT) { portENTER_CRITICAL(&gpio_context.gpio_spinlock); From 266c576d2053eb0ac274862987de236a06012948 Mon Sep 17 00:00:00 2001 From: Song Ruo Jing Date: Wed, 21 May 2025 14:37:26 +0800 Subject: [PATCH 10/10] fix(ci): remove esp32c5 from the build template app for release/v5.3 --- tools/ci/build_template_app.sh | 37 ++-------------------------------- 1 file changed, 2 insertions(+), 35 deletions(-) diff --git a/tools/ci/build_template_app.sh b/tools/ci/build_template_app.sh index 8d3de5beab..0a13bdad28 100755 --- a/tools/ci/build_template_app.sh +++ b/tools/ci/build_template_app.sh @@ -64,7 +64,7 @@ build_stage2() { --size-file size.json \ --keep-going \ --collect-size-info size_info.txt \ - --default-build-targets esp32 esp32s2 esp32s3 esp32c2 esp32c3 esp32c5 esp32c6 esp32h2 esp32p4 esp32c61 + --default-build-targets esp32 esp32s2 esp32s3 esp32c2 esp32c3 esp32c6 esp32h2 esp32p4 esp32c61 } build_stage1() { @@ -78,36 +78,7 @@ build_stage1() { --build-log ${BUILD_LOG_CMAKE} \ --size-file size.json \ --collect-size-info size_info.txt \ - --default-build-targets esp32 esp32s2 esp32s3 esp32c2 esp32c3 esp32c5 esp32c6 esp32h2 esp32p4 esp32c61 -} - -# TODO: IDF-9197 remove the additional test for esp32c5 beta3 -build_c5beta3() { - # Update the config to select C5 beta3 - C5BETA3_CFG="CONFIG_IDF_TARGET_ESP32C5_BETA3_VERSION=y\nCONFIG_IDF_TARGET_ESP32C5_MP_VERSION=n" - if [ $1 = 1 ] - then - echo "${C5BETA3_CFG}" >> ${TEMPLATE_APP_PATH}/sdkconfig.ci2.Og - CONFIG_STR=$(get_config_str sdkconfig.ci2.*=) - KEEP_GOING="" - else - echo "${C5BETA3_CFG}" >> ${TEMPLATE_APP_PATH}/sdkconfig.ci.O0 - echo "${C5BETA3_CFG}" >> ${TEMPLATE_APP_PATH}/sdkconfig.ci.Os - echo "${C5BETA3_CFG}" >> ${TEMPLATE_APP_PATH}/sdkconfig.ci.O2 - CONFIG_STR=$(get_config_str sdkconfig.ci.*=) - KEEP_GOING=" --keep-going" - fi - python -m idf_build_apps build -vv \ - -p ${TEMPLATE_APP_PATH} \ - -t esp32c5 \ - ${CONFIG_STR} \ - --work-dir ${BUILD_PATH}/cmake \ - --build-dir ${BUILD_DIR} \ - --build-log ${BUILD_LOG_CMAKE} \ - --size-file size.json \ - ${KEEP_GOING} \ - --collect-size-info size_info.txt \ - --default-build-targets esp32c5 + --default-build-targets esp32 esp32s2 esp32s3 esp32c2 esp32c3 esp32c6 esp32h2 esp32p4 esp32c61 } # Default arguments @@ -135,7 +106,3 @@ then else build_stage2 fi - -# TODO: IDF-9197 remove the additional test for esp32c5 beta3 -echo "Build ESP32-C5 beta3 additionally" -build_c5beta3 ${STAGE}