From 46713a52752b4db1a5d594b7f9e6215405f6a67e Mon Sep 17 00:00:00 2001 From: houwenxiang Date: Fri, 1 May 2020 20:40:24 +0800 Subject: [PATCH] driver(uart): fix uart module reset issue On ESP32, due to fifo reset issue, UART2 will work incorrectly if reset the fifo of UART1(TX fifo and RX fifo). The software can workaround the RX fifo reset issue, while the TX fifo reset issue can not. When UART2 is used and UART1 is used as the log output port, a software reset can reproduce this issue. So we should reset the UART memory before the software reset to solve this problem. --- components/driver/uart.c | 2 -- components/esp32/system_api_esp32.c | 3 ++- components/soc/include/hal/uart_hal.h | 1 + components/soc/src/esp32/include/hal/uart_ll.h | 10 ++++++++-- 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/components/driver/uart.c b/components/driver/uart.c index 195da2ebab..be2575528b 100644 --- a/components/driver/uart.c +++ b/components/driver/uart.c @@ -632,8 +632,6 @@ esp_err_t uart_param_config(uart_port_t uart_num, const uart_config_t *uart_conf uart_hal_set_tx_idle_num(&(uart_context[uart_num].hal), UART_TX_IDLE_NUM_DEFAULT); uart_hal_set_hw_flow_ctrl(&(uart_context[uart_num].hal), uart_config->flow_ctrl, uart_config->rx_flow_ctrl_thresh); UART_EXIT_CRITICAL(&(uart_context[uart_num].spinlock)); - // The module reset do not reset TX and RX memory. - // reset FIFO to avoid garbage data remained in the FIFO. uart_hal_rxfifo_rst(&(uart_context[uart_num].hal)); uart_hal_txfifo_rst(&(uart_context[uart_num].hal)); return ESP_OK; diff --git a/components/esp32/system_api_esp32.c b/components/esp32/system_api_esp32.c index b93c222ce4..185ee2410b 100644 --- a/components/esp32/system_api_esp32.c +++ b/components/esp32/system_api_esp32.c @@ -111,7 +111,8 @@ void IRAM_ATTR esp_restart_noos(void) // Reset timer/spi/uart DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, - DPORT_TIMERS_RST | DPORT_SPI01_RST | DPORT_UART_RST | DPORT_UART1_RST | DPORT_UART2_RST); + //UART TX FIFO cannot be reset correctly on ESP32, so reset the UART memory by DPORT here. + DPORT_TIMERS_RST | DPORT_SPI01_RST | DPORT_UART_RST | DPORT_UART1_RST | DPORT_UART2_RST | DPORT_UART_MEM_RST); DPORT_REG_WRITE(DPORT_PERIP_RST_EN_REG, 0); // Set CPU back to XTAL source, no PLL, same as hard reset diff --git a/components/soc/include/hal/uart_hal.h b/components/soc/include/hal/uart_hal.h index 59ba28d5d7..ceec6a3469 100644 --- a/components/soc/include/hal/uart_hal.h +++ b/components/soc/include/hal/uart_hal.h @@ -150,6 +150,7 @@ void uart_hal_write_txfifo(uart_hal_context_t *hal, const uint8_t *buf, uint32_t /** * @brief Reset the UART txfifo + * @note On ESP32, this function is reserved for UART1 and UART2. * * @param hal Context of the HAL layer * diff --git a/components/soc/src/esp32/include/hal/uart_ll.h b/components/soc/src/esp32/include/hal/uart_ll.h index dc4a05bffe..847f619711 100644 --- a/components/soc/src/esp32/include/hal/uart_ll.h +++ b/components/soc/src/esp32/include/hal/uart_ll.h @@ -219,14 +219,20 @@ static inline void uart_ll_rxfifo_rst(uart_dev_t *hw) /** * @brief Reset the UART hw txfifo. * + * Note: Due to hardware issue, reset UART1's txfifo will also reset UART2's txfifo. + * So reserve this function for UART1 and UART2. Please do DPORT reset for UART and its memory at chip startup + * to ensure the TX FIFO is reset correctly at the beginning. + * * @param hw Beginning address of the peripheral registers. * * @return None */ static inline void uart_ll_txfifo_rst(uart_dev_t *hw) { - hw->conf0.txfifo_rst = 1; - hw->conf0.txfifo_rst = 0; + if (hw == &UART0) { + hw->conf0.txfifo_rst = 1; + hw->conf0.txfifo_rst = 0; + } } /**