Parcourir la source

Merge branch 'bugfix/uart_fifo_ovf_workaround' into 'master'

driver(uart): fix uart rx fifo length error after overflow.

See merge request !1735

Angus Gratton il y a 8 ans
Parent
commit
f482e9e54c

+ 10 - 10
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 <<esp32_technical_reference_manual>> 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;

+ 14 - 1
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 ; */

+ 8 - 2
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;