diff --git a/esp8266/modesp.c b/esp8266/modesp.c
index e04a3b365b6821a77293de140439e1300073ddaa..3a82cc1f20730ec2c61ddb9443a1982c4ab341f3 100644
--- a/esp8266/modesp.c
+++ b/esp8266/modesp.c
@@ -35,6 +35,8 @@
 #include "py/runtime.h"
 #include "netutils.h"
 #include "queue.h"
+#include "ets_sys.h"
+#include "uart.h"
 #include "user_interface.h"
 #include "espconn.h"
 #include "spi_flash.h"
@@ -514,6 +516,16 @@ void error_check(bool status, const char *msg) {
     }
 }
 
+STATIC mp_obj_t esp_osdebug(mp_obj_t val) {
+    if (val == mp_const_none) {
+        uart_os_config(-1);
+    } else {
+        uart_os_config(mp_obj_get_int(val));
+    }
+    return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_osdebug_obj, esp_osdebug);
+
 STATIC mp_obj_t esp_sleep_type(mp_uint_t n_args, const mp_obj_t *args) {
     if (n_args == 0) {
         return mp_obj_new_int(wifi_get_sleep_type());
@@ -608,6 +620,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_3(esp_neopixel_write_obj, esp_neopixel_write_);
 STATIC const mp_map_elem_t esp_module_globals_table[] = {
     { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_esp) },
 
+    { MP_OBJ_NEW_QSTR(MP_QSTR_osdebug), (mp_obj_t)&esp_osdebug_obj },
     { MP_OBJ_NEW_QSTR(MP_QSTR_sleep_type), (mp_obj_t)&esp_sleep_type_obj },
     { MP_OBJ_NEW_QSTR(MP_QSTR_deepsleep), (mp_obj_t)&esp_deepsleep_obj },
     { MP_OBJ_NEW_QSTR(MP_QSTR_flash_id), (mp_obj_t)&esp_flash_id_obj },
diff --git a/esp8266/qstrdefsport.h b/esp8266/qstrdefsport.h
index 36e34e85aae8d2f291b87a14e4592e1ef587dab7..12f72a3e208f0791180de8049438faa0a40bc66a 100644
--- a/esp8266/qstrdefsport.h
+++ b/esp8266/qstrdefsport.h
@@ -58,6 +58,7 @@ Q(connect)
 Q(disconnect)
 Q(wifi_mode)
 Q(phy_mode)
+Q(osdebug)
 Q(sleep_type)
 Q(deepsleep)
 Q(adc)
diff --git a/esp8266/uart.c b/esp8266/uart.c
index 0d180aa55b284b46b48a723dca7acb871441240d..f371935399e1887b097a0eca2f59d36ab860bba8 100644
--- a/esp8266/uart.c
+++ b/esp8266/uart.c
@@ -24,6 +24,9 @@
 // UartDev is defined and initialized in rom code.
 extern UartDevice UartDev;
 
+// the uart to which OS messages go; -1 to disable
+static int uart_os = UART_OS;
+
 /* unused
 // circular buffer for RX buffering
 #define RX_BUF_SIZE (256)
@@ -134,15 +137,23 @@ void uart_flush(uint8 uart) {
 *******************************************************************************/
 static void ICACHE_FLASH_ATTR
 uart_os_write_char(char c) {
+    if (uart_os == -1) {
+        return;
+    }
     if (c == '\n') {
-        uart_tx_one_char(UART_OS, '\r');
-        uart_tx_one_char(UART_OS, '\n');
+        uart_tx_one_char(uart_os, '\r');
+        uart_tx_one_char(uart_os, '\n');
     } else if (c == '\r') {
     } else {
-        uart_tx_one_char(UART_OS, c);
+        uart_tx_one_char(uart_os, c);
     }
 }
 
+void ICACHE_FLASH_ATTR
+uart_os_config(int uart) {
+    uart_os = uart;
+}
+
 /******************************************************************************
  * FunctionName : uart0_rx_intr_handler
  * Description  : Internal used function
diff --git a/esp8266/uart.h b/esp8266/uart.h
index ed0dcfb4457c3a904c1329f7f622f7653a07cc4f..2f762db5a2b368c2550acd06f8f6e92023e563e7 100644
--- a/esp8266/uart.h
+++ b/esp8266/uart.h
@@ -93,5 +93,6 @@ void uart_init(UartBautRate uart0_br, UartBautRate uart1_br);
 int uart0_rx(void);
 void uart_tx_one_char(uint8 uart, uint8 TxChar);
 void uart_flush(uint8 uart);
+void uart_os_config(int uart);
 
 #endif // _INCLUDED_UART_H_