Skip to content

Commit 492db05

Browse files
committed
Fix uart fifo overflow bug
1 parent 2ddee72 commit 492db05

File tree

3 files changed

+32
-13
lines changed

3 files changed

+32
-13
lines changed

components/driver/uart.c

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -271,8 +271,11 @@ esp_err_t uart_get_hw_flow_ctrl(uart_port_t uart_num, uart_hw_flowcontrol_t* flo
271271
static esp_err_t uart_reset_rx_fifo(uart_port_t uart_num)
272272
{
273273
UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);
274-
// Read all data from the FIFO
275-
while (UART[uart_num]->status.rxfifo_cnt) {
274+
//Due to hardware issue, we can not use fifo_rst to reset uart fifo.
275+
//See description about UART_TXFIFO_RST and UART_RXFIFO_RST in <<esp32_technical_reference_manual>> v2.6 or later.
276+
277+
// we read the data out and make `fifo_len == 0 && rd_addr == wr_addr`.
278+
while(UART[uart_num]->status.rxfifo_cnt != 0 || (UART[uart_num]->mem_rx_status.wr_addr != UART[uart_num]->mem_rx_status.rd_addr)) {
276279
READ_PERI_REG(UART_FIFO_REG(uart_num));
277280
}
278281
return ESP_OK;
@@ -542,7 +545,6 @@ static void uart_rx_intr_handler_default(void *param)
542545
int rx_fifo_len = 0;
543546
uart_event_t uart_event;
544547
portBASE_TYPE HPTaskAwoken = 0;
545-
546548
while(uart_intr_status != 0x0) {
547549
buf_idx = 0;
548550
uart_event.type = UART_EVENT_MAX;
@@ -690,14 +692,12 @@ static void uart_rx_intr_handler_default(void *param)
690692
uart_reg->int_clr.val = UART_RXFIFO_FULL_INT_CLR_M | UART_RXFIFO_TOUT_INT_CLR_M;
691693
UART_EXIT_CRITICAL_ISR(&uart_spinlock[uart_num]);
692694
uart_event.type = UART_BUFFER_FULL;
693-
}
694-
} else if(uart_intr_status & UART_RXFIFO_OVF_INT_ST_M) {
695+
}
696+
}
697+
// When fifo overflows, we reset the fifo.
698+
else if(uart_intr_status & UART_RXFIFO_OVF_INT_ST_M) {
695699
UART_ENTER_CRITICAL_ISR(&uart_spinlock[uart_num]);
696-
// Read all data from the FIFO
697-
rx_fifo_len = uart_reg->status.rxfifo_cnt;
698-
for (int i = 0; i < rx_fifo_len; i++) {
699-
READ_PERI_REG(UART_FIFO_REG(uart_num));
700-
}
700+
uart_reset_rx_fifo(uart_num);
701701
uart_reg->int_clr.rxfifo_ovf = 1;
702702
UART_EXIT_CRITICAL_ISR(&uart_spinlock[uart_num]);
703703
uart_event.type = UART_FIFO_OVF;

components/soc/esp32/include/soc/uart_reg.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1105,11 +1105,24 @@
11051105

11061106
#define UART_MEM_RX_STATUS_REG(i) (REG_UART_BASE(i) + 0x60)
11071107
/* UART_MEM_RX_STATUS : RO ;bitpos:[23:0] ;default: 24'h0 ; */
1108-
/*description: */
1108+
/*description: This register stores the current uart rx mem read address
1109+
and rx mem write address */
11091110
#define UART_MEM_RX_STATUS 0x00FFFFFF
11101111
#define UART_MEM_RX_STATUS_M ((UART_MEM_RX_STATUS_V)<<(UART_MEM_RX_STATUS_S))
11111112
#define UART_MEM_RX_STATUS_V 0xFFFFFF
11121113
#define UART_MEM_RX_STATUS_S 0
1114+
/* UART_MEM_RX_RD_ADDR : RO ;bitpos:[12:2] ;default: 11'h0 ; */
1115+
/*description: This register stores the rx mem read address */
1116+
#define UART_MEM_RX_RD_ADDR 0x000007FF
1117+
#define UART_MEM_RX_RD_ADDR_M ((UART_MEM_RX_RD_ADDR_V)<<(UART_MEM_RX_RD_ADDR_S))
1118+
#define UART_MEM_RX_RD_ADDR_V (0x7FF)
1119+
#define UART_MEM_RX_RD_ADDR_S (2)
1120+
/* UART_MEM_RX_WR_ADDR : RO ;bitpos:[23:13] ;default: 11'h0 ; */
1121+
/*description: This register stores the rx mem write address */
1122+
#define UART_MEM_RX_WR_ADDR 0x000007FF
1123+
#define UART_MEM_RX_WR_ADDR_M ((UART_MEM_RX_WR_ADDR_V)<<(UART_MEM_RX_WR_ADDR_S))
1124+
#define UART_MEM_RX_WR_ADDR_V (0x7FF)
1125+
#define UART_MEM_RX_WR_ADDR_S (13)
11131126

11141127
#define UART_MEM_CNT_STATUS_REG(i) (REG_UART_BASE(i) + 0x64)
11151128
/* UART_TX_MEM_CNT : RO ;bitpos:[5:3] ;default: 3'b0 ; */

components/soc/esp32/include/soc/uart_struct.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -332,8 +332,14 @@ typedef volatile struct {
332332
} mem_tx_status;
333333
union {
334334
struct {
335-
uint32_t status:24;
336-
uint32_t reserved24: 8;
335+
uint32_t status: 24;
336+
uint32_t reserved24: 8;
337+
};
338+
struct {
339+
uint32_t reserved0: 2;
340+
uint32_t rd_addr: 11; /*This register stores the rx mem read address.*/
341+
uint32_t wr_addr: 11; /*This register stores the rx mem write address.*/
342+
uint32_t reserved: 8;
337343
};
338344
uint32_t val;
339345
} mem_rx_status;

0 commit comments

Comments
 (0)