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.
This commit is contained in:
houwenxiang 2020-05-01 20:40:24 +08:00
parent b52ed2d2a5
commit 46713a5275
4 changed files with 11 additions and 5 deletions

View file

@ -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_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_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)); 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_rxfifo_rst(&(uart_context[uart_num].hal));
uart_hal_txfifo_rst(&(uart_context[uart_num].hal)); uart_hal_txfifo_rst(&(uart_context[uart_num].hal));
return ESP_OK; return ESP_OK;

View file

@ -111,7 +111,8 @@ void IRAM_ATTR esp_restart_noos(void)
// Reset timer/spi/uart // Reset timer/spi/uart
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, 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); DPORT_REG_WRITE(DPORT_PERIP_RST_EN_REG, 0);
// Set CPU back to XTAL source, no PLL, same as hard reset // Set CPU back to XTAL source, no PLL, same as hard reset

View file

@ -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 * @brief Reset the UART txfifo
* @note On ESP32, this function is reserved for UART1 and UART2.
* *
* @param hal Context of the HAL layer * @param hal Context of the HAL layer
* *

View file

@ -219,14 +219,20 @@ static inline void uart_ll_rxfifo_rst(uart_dev_t *hw)
/** /**
* @brief Reset the UART hw txfifo. * @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. * @param hw Beginning address of the peripheral registers.
* *
* @return None * @return None
*/ */
static inline void uart_ll_txfifo_rst(uart_dev_t *hw) static inline void uart_ll_txfifo_rst(uart_dev_t *hw)
{ {
hw->conf0.txfifo_rst = 1; if (hw == &UART0) {
hw->conf0.txfifo_rst = 0; hw->conf0.txfifo_rst = 1;
hw->conf0.txfifo_rst = 0;
}
} }
/** /**