Merge branch 'bugfix/fix_uart_reset_issue_on_esp32c3' into 'master'

bugfix(uart): reset uart0 core before uart apb reset

Closes IDF-3362

See merge request espressif/esp-idf!12749
This commit is contained in:
Michael (XIAO Xufeng) 2021-07-22 07:20:58 +00:00
commit fbb6b1b11a
6 changed files with 32 additions and 9 deletions

View File

@ -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));

View File

@ -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);

View File

@ -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) {

View File

@ -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) {

View File

@ -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
*

View File

@ -245,6 +245,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)