Skip to content

Commit 2fc1e64

Browse files
committed
esp8266: Fix lost chars problem when block-xfering data (e.g., when pasting).
Pasting more or less sizable text into ESP8266 REPL leads to random chars missing in the received input. Apparent cause is that using RTOS messages to pass individual chars one by one is to slow and leads to UART FIFO overflow. So, instead of passing chars one by one, use RTOS msg to signal that input data is available in FIFO, and then let task handler to read data directly from FIFO. With this change, lost chars problem is gone, but the pasted text is truncated after some position. At least 500 chars can be pasted reliably (at 115200 baud), but 1K never pastes completely.
1 parent 3ac2d06 commit 2fc1e64

File tree

2 files changed

+30
-9
lines changed

2 files changed

+30
-9
lines changed

esp8266/esp_mphal.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@
2727
#ifndef _INCLUDED_MPHAL_H_
2828
#define _INCLUDED_MPHAL_H_
2929

30+
// SDK functions not declared in SDK itself
31+
void ets_isr_mask(unsigned);
32+
3033
void mp_hal_init(void);
3134
void mp_hal_feed_watchdog(void);
3235
void mp_hal_udelay(uint32_t);

esp8266/uart.c

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "esp_mphal.h"
2121

2222
#define RX_BUF_SIZE (256)
23+
#define UART_REPL UART0
2324

2425
// UartDev is defined and initialized in rom code.
2526
extern UartDevice UartDev;
@@ -135,8 +136,7 @@ static void uart0_rx_intr_handler(void *para) {
135136
* uart1 and uart0 respectively
136137
*/
137138

138-
uint8 RcvChar;
139-
uint8 uart_no = UART0;
139+
uint8 uart_no = UART_REPL;
140140

141141
if (UART_FRM_ERR_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_FRM_ERR_INT_ST)) {
142142
// frame error
@@ -145,23 +145,22 @@ static void uart0_rx_intr_handler(void *para) {
145145

146146
if (UART_RXFIFO_FULL_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_RXFIFO_FULL_INT_ST)) {
147147
// fifo full
148-
WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_RXFIFO_FULL_INT_CLR);
149148
goto read_chars;
150149
} else if (UART_RXFIFO_TOUT_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_RXFIFO_TOUT_INT_ST)) {
151-
WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_RXFIFO_TOUT_INT_CLR);
152150
read_chars:
153-
while (READ_PERI_REG(UART_STATUS(uart_no)) & (UART_RXFIFO_CNT << UART_RXFIFO_CNT_S)) {
154-
RcvChar = READ_PERI_REG(UART_FIFO(uart_no)) & 0xff;
155151
#if 1 //MICROPY_REPL_EVENT_DRIVEN is not available here
156-
system_os_post(UART_TASK_ID, 0, RcvChar);
152+
ETS_UART_INTR_DISABLE();
153+
system_os_post(UART_TASK_ID, 0, 0);
157154
#else
155+
while (READ_PERI_REG(UART_STATUS(uart_no)) & (UART_RXFIFO_CNT << UART_RXFIFO_CNT_S)) {
156+
uint8 RcvChar = READ_PERI_REG(UART_FIFO(uart_no)) & 0xff;
158157
uint16_t rx_buf_in_next = (rx_buf_in + 1) % RX_BUF_SIZE;
159158
if (rx_buf_in_next != rx_buf_out) {
160159
rx_buf[rx_buf_in] = RcvChar;
161160
rx_buf_in = rx_buf_in_next;
162161
}
163-
#endif
164162
}
163+
#endif
165164
}
166165
}
167166

@@ -175,6 +174,13 @@ int uart0_rx(void) {
175174
}
176175
}
177176

177+
int uart_rx_one_char(uint8 uart_no) {
178+
if (READ_PERI_REG(UART_STATUS(uart_no)) & (UART_RXFIFO_CNT << UART_RXFIFO_CNT_S)) {
179+
return READ_PERI_REG(UART_FIFO(uart_no)) & 0xff;
180+
}
181+
return -1;
182+
}
183+
178184
/******************************************************************************
179185
* FunctionName : uart_init
180186
* Description : user interface for init uart
@@ -206,7 +212,19 @@ void ICACHE_FLASH_ATTR uart_reattach() {
206212
void soft_reset(void);
207213

208214
void uart_task_handler(os_event_t *evt) {
209-
int ret = pyexec_event_repl_process_char(evt->par);
215+
int c, ret = 0;
216+
while ((c = uart_rx_one_char(UART_REPL)) >= 0) {
217+
ret = pyexec_event_repl_process_char(c);
218+
if (ret & PYEXEC_FORCED_EXIT) {
219+
break;
220+
}
221+
}
222+
223+
// Clear pending FIFO interrupts
224+
WRITE_PERI_REG(UART_INT_CLR(UART_REPL), UART_RXFIFO_TOUT_INT_CLR | UART_RXFIFO_FULL_INT_ST);
225+
// Enable UART interrupts, so our task will receive events again from IRQ handler
226+
ETS_UART_INTR_ENABLE();
227+
210228
if (ret & PYEXEC_FORCED_EXIT) {
211229
soft_reset();
212230
}

0 commit comments

Comments
 (0)