From 2b986fbd49f03bc25d1c13f3da4f2e253b73efb4 Mon Sep 17 00:00:00 2001 From: Wangjialin Date: Tue, 16 Mar 2021 00:50:31 +0800 Subject: [PATCH 1/2] For esp_restart API, reset uart0 core first, then reset uart0 apb side, so as to prevent uart output garbage after cpu reset. (UART0 RST bits will be cleared in ROM) Add UART0/1 core reset on esp32c3, in case uart driver would also reset uart hardwares. --- .../esp_system/port/soc/esp32c3/system_internal.c | 5 +++++ components/hal/esp32c3/include/hal/clk_gate_ll.h | 13 +++++++++++++ 2 files changed, 18 insertions(+) diff --git a/components/esp_system/port/soc/esp32c3/system_internal.c b/components/esp_system/port/soc/esp32c3/system_internal.c index 2dd27c0bf6..d915c769ae 100644 --- a/components/esp_system/port/soc/esp32c3/system_internal.c +++ b/components/esp_system/port/soc/esp32c3/system_internal.c @@ -30,6 +30,7 @@ #include "soc/rtc_periph.h" #include "soc/syscon_reg.h" #include "soc/system_reg.h" +#include "soc/uart_reg.h" #include "hal/wdt_hal.h" #include "cache_err_int.h" @@ -103,6 +104,10 @@ void IRAM_ATTR esp_restart_noos(void) REG_WRITE(SYSTEM_CORE_RST_EN_REG, 0); + // Reset uart0 core first, then reset apb side. + // rom will clear this bit, as well as SYSTEM_UART_RST + SET_PERI_REG_MASK(UART_CLK_CONF_REG(0), UART_RST_CORE_M); + // Reset timer/spi/uart SET_PERI_REG_MASK(SYSTEM_PERIP_RST_EN0_REG, SYSTEM_TIMERS_RST | SYSTEM_SPI01_RST | SYSTEM_UART_RST); diff --git a/components/hal/esp32c3/include/hal/clk_gate_ll.h b/components/hal/esp32c3/include/hal/clk_gate_ll.h index f7382650d5..db38299d6a 100644 --- a/components/hal/esp32c3/include/hal/clk_gate_ll.h +++ b/components/hal/esp32c3/include/hal/clk_gate_ll.h @@ -24,6 +24,7 @@ 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) { @@ -208,6 +209,12 @@ 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)); } @@ -226,6 +233,12 @@ 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)); } From 6317f5b481fc2a4f4ec22c6ae747195145f2d3f2 Mon Sep 17 00:00:00 2001 From: Chen Yi Qun Date: Thu, 15 Jul 2021 17:08:42 +0800 Subject: [PATCH 2/2] add uart core reset in uart_module_enable() --- components/driver/uart.c | 15 ++++++++++++--- components/hal/esp32c3/include/hal/clk_gate_ll.h | 13 ------------- components/hal/esp32c3/include/hal/uart_ll.h | 5 ++--- components/hal/esp32h2/include/hal/uart_ll.h | 5 ++--- components/hal/include/hal/uart_hal.h | 10 ++++++++++ components/soc/esp32c3/include/soc/soc_caps.h | 1 + 6 files changed, 27 insertions(+), 22 deletions(-) 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)