]> granicus.if.org Git - esp-idf/commitdiff
bugfix(uart): workaround for uart fifo reset issue
authorWangjialin <wangjialin@espressif.com>
Tue, 7 Nov 2017 10:19:23 +0000 (18:19 +0800)
committerWangjialin <wangjialin@espressif.com>
Mon, 13 Nov 2017 07:23:00 +0000 (15:23 +0800)
Reported from github:
https://github.com/espressif/esp-idf/issues/1219
https://github.com/espressif/esp-idf/issues/1202

After providing a simple code to digital team, they confirmed that this is a hardware bug.

Root cause:
The fifo reset signal is incorrectly connected
If we want to reset tx fifo of UART2, we have to set txfifo_rst bit of both UART1 and UART2
If we want to reset rx fifo of UART2, we have to set rxfifo_rst bit of both UART1 and UART2

Workaround:
we don't use fifo rst bit in driver.

Documentation:
Digital team would update TRM and give more explanation about this issue.

components/driver/uart.c

index 4a2a1640eae14508205f131b20faaefd8ecb86b3..2b9642f259aa12995c0d0759ded3da7f86d02ae7 100644 (file)
@@ -268,15 +268,13 @@ esp_err_t uart_get_hw_flow_ctrl(uart_port_t uart_num, uart_hw_flowcontrol_t* flo
     return ESP_OK;
 }
 
-static esp_err_t uart_reset_fifo(uart_port_t uart_num)
+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);
-    UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);
-    UART[uart_num]->conf0.rxfifo_rst = 1;
-    UART[uart_num]->conf0.rxfifo_rst = 0;
-    UART[uart_num]->conf0.txfifo_rst = 1;
-    UART[uart_num]->conf0.txfifo_rst = 0;
-    UART_EXIT_CRITICAL(&uart_spinlock[uart_num]);
+    // Read all data from the FIFO
+    while (UART[uart_num]->status.rxfifo_cnt) {
+        READ_PERI_REG(UART_FIFO_REG(uart_num));
+    }
     return ESP_OK;
 }
 
@@ -695,8 +693,11 @@ static void uart_rx_intr_handler_default(void *param)
             }
         } else if(uart_intr_status & UART_RXFIFO_OVF_INT_ST_M) {
             UART_ENTER_CRITICAL_ISR(&uart_spinlock[uart_num]);
-            uart_reg->conf0.rxfifo_rst = 1;
-            uart_reg->conf0.rxfifo_rst = 0;
+            // 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_reg->int_clr.rxfifo_ovf = 1;
             UART_EXIT_CRITICAL_ISR(&uart_spinlock[uart_num]);
             uart_event.type = UART_FIFO_OVF;
@@ -1009,7 +1010,7 @@ esp_err_t uart_flush(uart_port_t uart_num)
     p_uart->rx_ptr = NULL;
     p_uart->rx_cur_remain = 0;
     p_uart->rx_head_ptr = NULL;
-    uart_reset_fifo(uart_num);
+    uart_reset_rx_fifo(uart_num);
     uart_enable_rx_intr(p_uart_obj[uart_num]->uart_num);
     xSemaphoreGive(p_uart->rx_mux);
     return ESP_OK;