diff --git a/components/driver/uart.c b/components/driver/uart.c index 3fbdeabee9..cf2791f14d 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; @@ -961,7 +959,7 @@ static void UART_ISR_ATTR uart_rx_intr_handler_default(void *param) // then postpone interrupt processing for next interrupt uart_event.type = UART_EVENT_MAX; } else { - // Workaround for RS485: If the RS485 half duplex mode is active + // Workaround for RS485: If the RS485 half duplex mode is active // and transmitter is in idle state then reset received buffer and reset RTS pin // skip this behavior for other UART modes UART_ENTER_CRITICAL_ISR(&(uart_context[uart_num].spinlock)); diff --git a/components/esp32/system_api_esp32.c b/components/esp32/system_api_esp32.c index d8b328749f..e0ea497bb4 100644 --- a/components/esp32/system_api_esp32.c +++ b/components/esp32/system_api_esp32.c @@ -121,7 +121,9 @@ 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_SPI2_RST | DPORT_SPI3_RST | DPORT_SPI_DMA_RST | DPORT_UART_RST | DPORT_UART1_RST | DPORT_UART2_RST); + DPORT_TIMERS_RST | DPORT_SPI01_RST | DPORT_SPI2_RST | DPORT_SPI3_RST | DPORT_SPI_DMA_RST | + //UART TX FIFO cannot be reset correctly on ESP32, so reset the UART memory by DPORT here. + 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 2be4adbe66..0c72c7e32d 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; + } } /** @@ -241,8 +247,8 @@ static inline uint32_t uart_ll_get_rxfifo_len(uart_dev_t *hw) uint32_t fifo_cnt = hw->status.rxfifo_cnt; typeof(hw->mem_rx_status) rx_status = hw->mem_rx_status; uint32_t len = 0; - - // When using DPort to read fifo, fifo_cnt is not credible, we need to calculate the real cnt based on the fifo read and write pointer. + + // When using DPort to read fifo, fifo_cnt is not credible, we need to calculate the real cnt based on the fifo read and write pointer. // When using AHB to read FIFO, we can use fifo_cnt to indicate the data length in fifo. if (rx_status.wr_addr > rx_status.rd_addr) { len = rx_status.wr_addr - rx_status.rd_addr; @@ -277,12 +283,12 @@ static inline uint32_t uart_ll_get_txfifo_len(uart_dev_t *hw) */ static inline void uart_ll_set_stop_bits(uart_dev_t *hw, uart_stop_bits_t stop_bit) { - //workaround for hardware issue, when UART stop bit set as 2-bit mode. + //workaround for hardware issue, when UART stop bit set as 2-bit mode. if(stop_bit == UART_STOP_BITS_2) { hw->rs485_conf.dl1_en = 1; hw->conf0.stop_bit_num = 0x1; } else { - hw->rs485_conf.dl1_en = 0; + hw->rs485_conf.dl1_en = 0; hw->conf0.stop_bit_num = stop_bit; } } @@ -297,7 +303,7 @@ static inline void uart_ll_set_stop_bits(uart_dev_t *hw, uart_stop_bits_t stop_b */ static inline void uart_ll_get_stop_bits(uart_dev_t *hw, uart_stop_bits_t *stop_bit) { - //workaround for hardware issue, when UART stop bit set as 2-bit mode. + //workaround for hardware issue, when UART stop bit set as 2-bit mode. if(hw->rs485_conf.dl1_en == 1 && hw->conf0.stop_bit_num == 0x1) { *stop_bit = UART_STOP_BITS_2; } else {