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.
This commit is contained in:
Paul Sokolovsky 2015-06-01 01:27:39 +03:00
parent 3ac2d06bd1
commit 2fc1e64319
2 changed files with 30 additions and 9 deletions

View File

@ -27,6 +27,9 @@
#ifndef _INCLUDED_MPHAL_H_
#define _INCLUDED_MPHAL_H_
// SDK functions not declared in SDK itself
void ets_isr_mask(unsigned);
void mp_hal_init(void);
void mp_hal_feed_watchdog(void);
void mp_hal_udelay(uint32_t);

View File

@ -20,6 +20,7 @@
#include "esp_mphal.h"
#define RX_BUF_SIZE (256)
#define UART_REPL UART0
// UartDev is defined and initialized in rom code.
extern UartDevice UartDev;
@ -135,8 +136,7 @@ static void uart0_rx_intr_handler(void *para) {
* uart1 and uart0 respectively
*/
uint8 RcvChar;
uint8 uart_no = UART0;
uint8 uart_no = UART_REPL;
if (UART_FRM_ERR_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_FRM_ERR_INT_ST)) {
// frame error
@ -145,23 +145,22 @@ static void uart0_rx_intr_handler(void *para) {
if (UART_RXFIFO_FULL_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_RXFIFO_FULL_INT_ST)) {
// fifo full
WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_RXFIFO_FULL_INT_CLR);
goto read_chars;
} else if (UART_RXFIFO_TOUT_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_RXFIFO_TOUT_INT_ST)) {
WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_RXFIFO_TOUT_INT_CLR);
read_chars:
while (READ_PERI_REG(UART_STATUS(uart_no)) & (UART_RXFIFO_CNT << UART_RXFIFO_CNT_S)) {
RcvChar = READ_PERI_REG(UART_FIFO(uart_no)) & 0xff;
#if 1 //MICROPY_REPL_EVENT_DRIVEN is not available here
system_os_post(UART_TASK_ID, 0, RcvChar);
ETS_UART_INTR_DISABLE();
system_os_post(UART_TASK_ID, 0, 0);
#else
while (READ_PERI_REG(UART_STATUS(uart_no)) & (UART_RXFIFO_CNT << UART_RXFIFO_CNT_S)) {
uint8 RcvChar = READ_PERI_REG(UART_FIFO(uart_no)) & 0xff;
uint16_t rx_buf_in_next = (rx_buf_in + 1) % RX_BUF_SIZE;
if (rx_buf_in_next != rx_buf_out) {
rx_buf[rx_buf_in] = RcvChar;
rx_buf_in = rx_buf_in_next;
}
#endif
}
#endif
}
}
@ -175,6 +174,13 @@ int uart0_rx(void) {
}
}
int uart_rx_one_char(uint8 uart_no) {
if (READ_PERI_REG(UART_STATUS(uart_no)) & (UART_RXFIFO_CNT << UART_RXFIFO_CNT_S)) {
return READ_PERI_REG(UART_FIFO(uart_no)) & 0xff;
}
return -1;
}
/******************************************************************************
* FunctionName : uart_init
* Description : user interface for init uart
@ -206,7 +212,19 @@ void ICACHE_FLASH_ATTR uart_reattach() {
void soft_reset(void);
void uart_task_handler(os_event_t *evt) {
int ret = pyexec_event_repl_process_char(evt->par);
int c, ret = 0;
while ((c = uart_rx_one_char(UART_REPL)) >= 0) {
ret = pyexec_event_repl_process_char(c);
if (ret & PYEXEC_FORCED_EXIT) {
break;
}
}
// Clear pending FIFO interrupts
WRITE_PERI_REG(UART_INT_CLR(UART_REPL), UART_RXFIFO_TOUT_INT_CLR | UART_RXFIFO_FULL_INT_ST);
// Enable UART interrupts, so our task will receive events again from IRQ handler
ETS_UART_INTR_ENABLE();
if (ret & PYEXEC_FORCED_EXIT) {
soft_reset();
}