diff --git a/components/driver/uart.c b/components/driver/uart.c index 1a78b2beca..ca7f8e2d5c 100644 --- a/components/driver/uart.c +++ b/components/driver/uart.c @@ -187,10 +187,19 @@ static void uart_module_enable(uart_port_t uart_num) { UART_ENTER_CRITICAL(&(uart_context[uart_num].spinlock)); if (uart_context[uart_num].hw_enabled != true) { - if (uart_num != CONFIG_ESP_CONSOLE_UART_NUM) { - periph_module_reset(uart_periph_signal[uart_num].module); - } periph_module_enable(uart_periph_signal[uart_num].module); + if (uart_num != CONFIG_ESP_CONSOLE_UART_NUM) { + // Workaround for ESP32C3: enable core reset + // before enabling uart module clock + // to prevent uart output garbage value. + #if SOC_UART_REQUIRE_CORE_RESET + uart_hal_set_reset_core(&(uart_context[uart_num].hal), true); + periph_module_reset(uart_periph_signal[uart_num].module); + uart_hal_set_reset_core(&(uart_context[uart_num].hal), false); + #else + periph_module_reset(uart_periph_signal[uart_num].module); + #endif + } uart_context[uart_num].hw_enabled = true; } UART_EXIT_CRITICAL(&(uart_context[uart_num].spinlock)); diff --git a/components/hal/esp32c3/include/hal/clk_gate_ll.h b/components/hal/esp32c3/include/hal/clk_gate_ll.h index db38299d6a..f7382650d5 100644 --- a/components/hal/esp32c3/include/hal/clk_gate_ll.h +++ b/components/hal/esp32c3/include/hal/clk_gate_ll.h @@ -24,7 +24,6 @@ extern "C" { #include "soc/system_reg.h" #include "soc/syscon_reg.h" #include "soc/dport_access.h" -#include "soc/uart_reg.h" static inline uint32_t periph_ll_get_clk_en_mask(periph_module_t periph) { @@ -209,12 +208,6 @@ static inline void periph_ll_enable_clk_clear_rst(periph_module_t periph) static inline void periph_ll_disable_clk_set_rst(periph_module_t periph) { - // set UART_RST_CORE before setting SYSTEM_UART_RST on esp32c3 - if (periph == PERIPH_UART0_MODULE) { - SET_PERI_REG_MASK(UART_CLK_CONF_REG(0), UART_RST_CORE_M); - } else if (periph == PERIPH_UART1_MODULE) { - SET_PERI_REG_MASK(UART_CLK_CONF_REG(1), UART_RST_CORE_M); - } DPORT_CLEAR_PERI_REG_MASK(periph_ll_get_clk_en_reg(periph), periph_ll_get_clk_en_mask(periph)); DPORT_SET_PERI_REG_MASK(periph_ll_get_rst_en_reg(periph), periph_ll_get_rst_en_mask(periph, false)); } @@ -233,12 +226,6 @@ static inline void IRAM_ATTR periph_ll_wifi_bt_module_disable_clk_set_rst(void) static inline void periph_ll_reset(periph_module_t periph) { - // set UART_RST_CORE before setting SYSTEM_UART_RST on esp32c3 - if (periph == PERIPH_UART0_MODULE) { - SET_PERI_REG_MASK(UART_CLK_CONF_REG(0), UART_RST_CORE_M); - } else if (periph == PERIPH_UART1_MODULE) { - SET_PERI_REG_MASK(UART_CLK_CONF_REG(1), UART_RST_CORE_M); - } DPORT_SET_PERI_REG_MASK(periph_ll_get_rst_en_reg(periph), periph_ll_get_rst_en_mask(periph, false)); DPORT_CLEAR_PERI_REG_MASK(periph_ll_get_rst_en_reg(periph), periph_ll_get_rst_en_mask(periph, false)); } diff --git a/components/hal/esp32c3/include/hal/uart_ll.h b/components/hal/esp32c3/include/hal/uart_ll.h index 237dcb9e25..64f2f40b87 100644 --- a/components/hal/esp32c3/include/hal/uart_ll.h +++ b/components/hal/esp32c3/include/hal/uart_ll.h @@ -58,9 +58,8 @@ typedef enum { UART_INTR_CMD_CHAR_DET = (0x1 << 18), } uart_intr_t; -static inline void uart_ll_reset_core(uart_dev_t *hw) { - hw->clk_conf.rst_core = 1; - hw->clk_conf.rst_core = 0; +static inline void uart_ll_set_reset_core(uart_dev_t *hw, bool core_rst_en) { + hw->clk_conf.rst_core = core_rst_en; } static inline void uart_ll_sclk_enable(uart_dev_t *hw) { diff --git a/components/hal/esp32h2/include/hal/uart_ll.h b/components/hal/esp32h2/include/hal/uart_ll.h index c166e472f5..a917caadcb 100644 --- a/components/hal/esp32h2/include/hal/uart_ll.h +++ b/components/hal/esp32h2/include/hal/uart_ll.h @@ -58,9 +58,8 @@ typedef enum { UART_INTR_CMD_CHAR_DET = (0x1 << 18), } uart_intr_t; -static inline void uart_ll_reset_core(uart_dev_t *hw) { - hw->clk_conf.rst_core = 1; - hw->clk_conf.rst_core = 0; +static inline void uart_ll_set_reset_core(uart_dev_t *hw, bool core_rst_en) { + hw->clk_conf.rst_core = core_rst_en; } static inline void uart_ll_sclk_enable(uart_dev_t *hw) { diff --git a/components/hal/include/hal/uart_hal.h b/components/hal/include/hal/uart_hal.h index d236431dca..f7b9488806 100644 --- a/components/hal/include/hal/uart_hal.h +++ b/components/hal/include/hal/uart_hal.h @@ -124,6 +124,16 @@ typedef struct { */ #define uart_hal_is_tx_idle(hal) uart_ll_is_tx_idle((hal)->dev) +/** + * @brief Configure the UART core reset + * + * @param hal Context of the HAL layer + * @param Set true to enable the core reset, otherwise set it false + * + * @return None + */ +#define uart_hal_set_reset_core(hal, core_rst_en) uart_ll_set_reset_core((hal)->dev, core_rst_en) + /** * @brief Read data from the UART rxfifo * diff --git a/components/soc/esp32c3/include/soc/soc_caps.h b/components/soc/esp32c3/include/soc/soc_caps.h index 5b54f55865..da3e042cee 100644 --- a/components/soc/esp32c3/include/soc/soc_caps.h +++ b/components/soc/esp32c3/include/soc/soc_caps.h @@ -244,6 +244,7 @@ #define SOC_UART_SUPPORT_RTC_CLK (1) #define SOC_UART_SUPPORT_XTAL_CLK (1) +#define SOC_UART_REQUIRE_CORE_RESET (1) // UART has an extra TX_WAIT_SEND state when the FIFO is not empty and XOFF is enabled #define SOC_UART_SUPPORT_FSM_TX_WAIT_SEND (1)