diff --git a/esp8266/esp_mphal.c b/esp8266/esp_mphal.c
index 3681a028dab83e0e3c6fa9efd2278ab78826debd..c8a88c725ee65b91057e8e5466e49eec04e9f817 100644
--- a/esp8266/esp_mphal.c
+++ b/esp8266/esp_mphal.c
@@ -39,6 +39,8 @@ extern void ets_wdt_disable(void);
 extern void wdt_feed(void);
 extern void ets_delay_us();
 
+STATIC byte input_buf_array[256];
+ringbuf_t input_buf = {input_buf_array, sizeof(input_buf_array)};
 void mp_hal_debug_tx_strn_cooked(void *env, const char *str, uint32_t len);
 const mp_print_t mp_debug_print = {NULL, mp_hal_debug_tx_strn_cooked};
 
@@ -151,3 +153,7 @@ void __assert_func(const char *file, int line, const char *func, const char *exp
     nlr_raise(mp_obj_new_exception_msg(&mp_type_AssertionError,
         "C-level assert"));
 }
+
+void mp_hal_signal_input(void) {
+    system_os_post(UART_TASK_ID, 0, 0);
+}
diff --git a/esp8266/esp_mphal.h b/esp8266/esp_mphal.h
index 9a08f5a14d5b8a3326c693c8da0a6a932d83df33..bedf80b19fa1c3083631cdc9b6f6c784c89079e6 100644
--- a/esp8266/esp_mphal.h
+++ b/esp8266/esp_mphal.h
@@ -27,10 +27,16 @@
 #ifndef _INCLUDED_MPHAL_H_
 #define _INCLUDED_MPHAL_H_
 
+#include "py/ringbuf.h"
+
 struct _mp_print_t;
 // Structure for UART-only output via mp_printf()
 extern const struct _mp_print_t mp_debug_print;
 
+extern ringbuf_t input_buf;
+// Call this after putting data to input_buf
+void mp_hal_signal_input(void);
+
 void mp_hal_init(void);
 void mp_hal_rtc_init(void);
 void mp_hal_feed_watchdog(void);
diff --git a/esp8266/uart.c b/esp8266/uart.c
index 4f45a952ba81ce92d2527ce80d481d36d03037a4..c4d08eac4b45a5fc83708cabacda4f7c56c8edb5 100644
--- a/esp8266/uart.c
+++ b/esp8266/uart.c
@@ -159,7 +159,18 @@ static void uart0_rx_intr_handler(void *para) {
         read_chars:
 #if 1 //MICROPY_REPL_EVENT_DRIVEN is not available here
         ETS_UART_INTR_DISABLE();
-        system_os_post(UART_TASK_ID, 0, 0);
+
+        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;
+            ringbuf_put(&input_buf, RcvChar);
+        }
+
+        mp_hal_signal_input();
+
+        // Clear pending FIFO interrupts
+        WRITE_PERI_REG(UART_INT_CLR(UART_REPL), UART_RXFIFO_TOUT_INT_CLR | UART_RXFIFO_FULL_INT_ST);
+        ETS_UART_INTR_ENABLE();
+
 #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;
@@ -224,7 +235,7 @@ void mp_keyboard_interrupt(void);
 int interrupt_char;
 void uart_task_handler(os_event_t *evt) {
     int c, ret = 0;
-    while ((c = uart_rx_one_char(UART_REPL)) >= 0) {
+    while ((c = ringbuf_get(&input_buf)) >= 0) {
         if (c == interrupt_char) {
             mp_keyboard_interrupt();
         }
@@ -234,11 +245,6 @@ void uart_task_handler(os_event_t *evt) {
         }
     }
 
-    // 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();
     }