Merge branch 'bugfix/fix_uart_module_enable_issue_v4.2' into 'release/v4.2'

driver(uart): fix uart module reset issue (release V4.2)

See merge request espressif/esp-idf!11969
This commit is contained in:
Michael (XIAO Xufeng) 2021-03-24 11:05:00 +00:00
commit 7dbd5e1855
4 changed files with 18 additions and 11 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_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));

View File

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

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
* @note On ESP32, this function is reserved for UART1 and UART2.
*
* @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.
*
* 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 {