From 492db0591d0c5643cb863b76600ab0bf5a204b64 Mon Sep 17 00:00:00 2001 From: kooho <2229179028@qq.com> Date: Wed, 3 Jan 2018 17:18:32 +0800 Subject: [PATCH] Fix uart fifo overflow bug --- components/driver/uart.c | 20 +++++++++---------- components/soc/esp32/include/soc/uart_reg.h | 15 +++++++++++++- .../soc/esp32/include/soc/uart_struct.h | 10 ++++++++-- 3 files changed, 32 insertions(+), 13 deletions(-) diff --git a/components/driver/uart.c b/components/driver/uart.c index d839a062f..2a2fa6553 100644 --- a/components/driver/uart.c +++ b/components/driver/uart.c @@ -271,8 +271,11 @@ esp_err_t uart_get_hw_flow_ctrl(uart_port_t uart_num, uart_hw_flowcontrol_t* flo static esp_err_t uart_reset_rx_fifo(uart_port_t uart_num) { UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL); - // Read all data from the FIFO - while (UART[uart_num]->status.rxfifo_cnt) { + //Due to hardware issue, we can not use fifo_rst to reset uart fifo. + //See description about UART_TXFIFO_RST and UART_RXFIFO_RST in <> v2.6 or later. + + // we read the data out and make `fifo_len == 0 && rd_addr == wr_addr`. + while(UART[uart_num]->status.rxfifo_cnt != 0 || (UART[uart_num]->mem_rx_status.wr_addr != UART[uart_num]->mem_rx_status.rd_addr)) { READ_PERI_REG(UART_FIFO_REG(uart_num)); } return ESP_OK; @@ -542,7 +545,6 @@ static void uart_rx_intr_handler_default(void *param) int rx_fifo_len = 0; uart_event_t uart_event; portBASE_TYPE HPTaskAwoken = 0; - while(uart_intr_status != 0x0) { buf_idx = 0; uart_event.type = UART_EVENT_MAX; @@ -690,14 +692,12 @@ static void uart_rx_intr_handler_default(void *param) uart_reg->int_clr.val = UART_RXFIFO_FULL_INT_CLR_M | UART_RXFIFO_TOUT_INT_CLR_M; UART_EXIT_CRITICAL_ISR(&uart_spinlock[uart_num]); uart_event.type = UART_BUFFER_FULL; - } - } else if(uart_intr_status & UART_RXFIFO_OVF_INT_ST_M) { + } + } + // When fifo overflows, we reset the fifo. + else if(uart_intr_status & UART_RXFIFO_OVF_INT_ST_M) { UART_ENTER_CRITICAL_ISR(&uart_spinlock[uart_num]); - // Read all data from the FIFO - rx_fifo_len = uart_reg->status.rxfifo_cnt; - for (int i = 0; i < rx_fifo_len; i++) { - READ_PERI_REG(UART_FIFO_REG(uart_num)); - } + uart_reset_rx_fifo(uart_num); uart_reg->int_clr.rxfifo_ovf = 1; UART_EXIT_CRITICAL_ISR(&uart_spinlock[uart_num]); uart_event.type = UART_FIFO_OVF; diff --git a/components/soc/esp32/include/soc/uart_reg.h b/components/soc/esp32/include/soc/uart_reg.h index 9d5ba2fb1..33b6e998e 100644 --- a/components/soc/esp32/include/soc/uart_reg.h +++ b/components/soc/esp32/include/soc/uart_reg.h @@ -1105,11 +1105,24 @@ #define UART_MEM_RX_STATUS_REG(i) (REG_UART_BASE(i) + 0x60) /* UART_MEM_RX_STATUS : RO ;bitpos:[23:0] ;default: 24'h0 ; */ -/*description: */ +/*description: This register stores the current uart rx mem read address + and rx mem write address */ #define UART_MEM_RX_STATUS 0x00FFFFFF #define UART_MEM_RX_STATUS_M ((UART_MEM_RX_STATUS_V)<<(UART_MEM_RX_STATUS_S)) #define UART_MEM_RX_STATUS_V 0xFFFFFF #define UART_MEM_RX_STATUS_S 0 +/* UART_MEM_RX_RD_ADDR : RO ;bitpos:[12:2] ;default: 11'h0 ; */ +/*description: This register stores the rx mem read address */ +#define UART_MEM_RX_RD_ADDR 0x000007FF +#define UART_MEM_RX_RD_ADDR_M ((UART_MEM_RX_RD_ADDR_V)<<(UART_MEM_RX_RD_ADDR_S)) +#define UART_MEM_RX_RD_ADDR_V (0x7FF) +#define UART_MEM_RX_RD_ADDR_S (2) +/* UART_MEM_RX_WR_ADDR : RO ;bitpos:[23:13] ;default: 11'h0 ; */ +/*description: This register stores the rx mem write address */ +#define UART_MEM_RX_WR_ADDR 0x000007FF +#define UART_MEM_RX_WR_ADDR_M ((UART_MEM_RX_WR_ADDR_V)<<(UART_MEM_RX_WR_ADDR_S)) +#define UART_MEM_RX_WR_ADDR_V (0x7FF) +#define UART_MEM_RX_WR_ADDR_S (13) #define UART_MEM_CNT_STATUS_REG(i) (REG_UART_BASE(i) + 0x64) /* UART_TX_MEM_CNT : RO ;bitpos:[5:3] ;default: 3'b0 ; */ diff --git a/components/soc/esp32/include/soc/uart_struct.h b/components/soc/esp32/include/soc/uart_struct.h index eb14620aa..59b84d2af 100644 --- a/components/soc/esp32/include/soc/uart_struct.h +++ b/components/soc/esp32/include/soc/uart_struct.h @@ -332,8 +332,14 @@ typedef volatile struct { } mem_tx_status; union { struct { - uint32_t status:24; - uint32_t reserved24: 8; + uint32_t status: 24; + uint32_t reserved24: 8; + }; + struct { + uint32_t reserved0: 2; + uint32_t rd_addr: 11; /*This register stores the rx mem read address.*/ + uint32_t wr_addr: 11; /*This register stores the rx mem write address.*/ + uint32_t reserved: 8; }; uint32_t val; } mem_rx_status;