Page 4 of 5

Re: Using the tx/rx pins not for UART

Posted: Thu Jan 19, 2017 2:05 pm
by torkinp

Am kinda new to all this, apologies if my question is in the wrong place, or misguided. I suspect I'm missing something simple/obvious.

I'm connecting a modem type device to the TX & RX pins of my esp8266 running micropython. The device sends strings such as 'OK' (and lots of other messages). When it does, it appears the REPL on the esp steps in and processes this data just as if I had typed in 'OK' in a terminal program, resulting in a mess.

I just want to be able to send and receive data over the RX & TX pins.

Do I need to disable the REPL or something?

Any advice/info much appreciated.


Re: Using the tx/rx pins not for UART

Posted: Sat Jan 21, 2017 4:38 pm
by mmh
In the frame work of this discussion I would like to propose that we route mp_hal_debug_rx_strn_cooked through mp_hal_stdout_tx_char instead of directly to the uart. In that way once we have a networked device and our webrepl connection the diagnostics messages will appear on the networked console.

I think that makes sense what do you guys think?

Re: Using the tx/rx pins not for UART

Posted: Mon Jan 23, 2017 5:23 am
by mmh
I used the code patch provided here and I'm curious if there is an intent to add it to the mainline of micropython, I choose to add a simple python function in espmodule to disable the uart programmaticly we should probably consider making it a toggle. I'm including my project blurb here which is just for fun!

I started this project as a place to dig into micropython as I want a nice platform for the robots my 10 year old son is working on, I pulled a some pieces together including pyduino (Firmata) that didn't work at all and started to make it work, the code can read and write the digital pins and receive the analog updates atm. my setup is a ESP01 --> mini pro with a mcp1700 5v to 3.3v power converter. I use gpio2 to reset the pro mini removing the junk that ESP spits out by synchronizing at start up through a reset of the mini pro. The two boards are connect serially over TX->RX and RX->TX. I have a small update to micorpython which this group developed that disables the use of the uart still need to figure out how to get that into the mainline of micropython. But this scheme does work like a charm.

I plan to figure out how to get this to work in async fashion and get our/your micro python patch considered for inclusion into the mainline. I probably could use help on my api function name that is used to disable the stdio function over uart.

I looked at many variants of the pymata stuff and found that to learn this stuff starting with the simplest thing made a lot of sense, there is no threading yet on micropython so porting the fuller implementations of pyFirmata would have been a lot more work to make progress. Now that I have a handle on Firmata I will probably circle back to a fuller implementation or just cherry pick features as needed not sure yet.

Any help ideas would be greatly appreciated this is all very new to me.

Re: Using the tx/rx pins not for UART

Posted: Wed Jan 25, 2017 3:36 am
by mhanuel
Mi mmh,

Does your patch include the one made by brad? Should I apply brad patch then yours?

Are you able to debug using webREPL after disabling the UART0 on esp8266?

Please let me know,

Re: Using the tx/rx pins not for UART

Posted: Thu Jan 26, 2017 12:08 am
by mmh
I enhanced brads work/patch and added an explicit enable and disable control through a platform specific function esp.uart_nostdio(enable) when a 1 is passed it disables the uart as stdio and when it is set to 0 it re-enables it. please review.

Code: Select all

diff --git a/esp8266/esp_mphal.c b/esp8266/esp_mphal.c
index f5e284f..331040e 100644
--- a/esp8266/esp_mphal.c
+++ b/esp8266/esp_mphal.c
@@ -38,6 +38,10 @@
 STATIC byte input_buf_array[256];
 ringbuf_t input_buf = {input_buf_array, sizeof(input_buf_array)};
+// Separate buffer for duplicate terminal (WebREPL) so that UART can be detached from REPL
+STATIC byte dupterm_buf_array[256];
+ringbuf_t dupterm_buf = {dupterm_buf_array, sizeof(dupterm_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};
@@ -56,10 +60,17 @@ void mp_hal_delay_us(uint32_t us) {
 int mp_hal_stdin_rx_chr(void) {
     for (;;) {
-        int c = ringbuf_get(&input_buf);
+        //int c = ringbuf_get(&input_buf);
+        int c = uart_std_getc();
+        if (c != -1) {
+            return c;
+        }
+        // Read next char from duplicate terminal (WebREPL) - note that UART has priority when enabled
+        c = ringbuf_get(&dupterm_buf);
         if (c != -1) {
             return c;
         #if 0
         // Idles CPU but need more testing before enabling
         if (!ets_loop_iter()) {
@@ -72,7 +83,8 @@ int mp_hal_stdin_rx_chr(void) {
 void mp_hal_stdout_tx_char(char c) {
-    uart_tx_one_char(UART0, c);
+    //uart_tx_one_char(UART0, c);
+    uart_std_putc(c);
     mp_uos_dupterm_tx_strn(&c, 1);
@@ -195,7 +207,7 @@ STATIC void dupterm_task_handler(os_event_t *evt) {
         if (c < 0) {
-        ringbuf_put(&input_buf, c);
+        ringbuf_put(&dupterm_buf, c);
     lock = 0;
diff --git a/esp8266/modesp.c b/esp8266/modesp.c
index b7ce122..695c737 100644
--- a/esp8266/modesp.c
+++ b/esp8266/modesp.c
@@ -519,6 +519,15 @@ void error_check(bool status, const char *msg) {
+STATIC mp_obj_t esp_uart_nostdio(mp_obj_t val) {
+  extern  void uart_os_nostdio(int);
+  uart_os_nostdio(mp_obj_get_int(val));
+  return mp_const_none;
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_uart_nostdio_obj, esp_uart_nostdio);
 STATIC mp_obj_t esp_osdebug(mp_obj_t val) {
     if (val == mp_const_none) {
@@ -826,6 +835,7 @@ 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_uart_nostdio), (mp_obj_t)&esp_uart_nostdio_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/uart.c b/esp8266/uart.c
index 001a9c6..916671e 100644
--- a/esp8266/uart.c
+++ b/esp8266/uart.c
@@ -29,6 +29,7 @@ extern UartDevice UartDev;
 // the uart to which OS messages go; -1 to disable
 static int uart_os = UART_OS;
+static int uart_stdio_disable = 0;
 static os_event_t uart_evt_queue[16];
@@ -141,6 +142,11 @@ uart_os_config(int uart) {
     uart_os = uart;
+uart_os_nostdio(int dis) {
+  uart_stdio_disable = dis;
  * FunctionName : uart0_rx_intr_handler
  * Description  : Internal used function
@@ -170,7 +176,7 @@ static void uart0_rx_intr_handler(void *para) {
             uint8 RcvChar = READ_PERI_REG(UART_FIFO(uart_no)) & 0xff;
-            if (RcvChar == mp_interrupt_char) {
+            if (RcvChar == mp_interrupt_char && !uart_stdio_disable) {
             } else {
                 ringbuf_put(&input_buf, RcvChar);
@@ -200,6 +206,24 @@ bool uart_rx_wait(uint32_t timeout_us) {
+void uart_std_putc(uint8 c)
+  if (uart_stdio_disable) {
+    return;
+  }
+  uart_tx_one_char(UART0, c);
+// Returns char from the input buffer, else -1 if buffer is empty.
+int uart_std_getc(void) {
+  // DBE - Disconnect REPL
+  if (uart_stdio_disable) {  
+    return -1;
+  }
+  return ringbuf_get(&input_buf);
 // Returns char from the input buffer, else -1 if buffer is empty.
 int uart_rx_char(void) {
     return ringbuf_get(&input_buf);
diff --git a/esp8266/uart.h b/esp8266/uart.h
index 2b97683..9fd00cb 100644
--- a/esp8266/uart.h
+++ b/esp8266/uart.h
@@ -99,5 +99,8 @@ void uart_tx_one_char(uint8 uart, uint8 TxChar);
 void uart_flush(uint8 uart);
 void uart_os_config(int uart);
 void uart_setup(uint8 uart);
+// UART functions used by STDIO (REPL)
+int uart_std_getc(void);
+void uart_std_putc(uint8 c);
 #endif // _INCLUDED_UART_H_

Re: Using the tx/rx pins not for UART

Posted: Thu Jan 26, 2017 1:19 pm
by deshipu
Do you think it would make sense to make a pull request with this, instead of keeping it as some patches posted on a forum?

Re: Using the tx/rx pins not for UART

Posted: Thu Jan 26, 2017 7:22 pm
by mmh
sure is that nothing more than clicking a button or do you need permissions to do this?

Re: Using the tx/rx pins not for UART

Posted: Thu Jan 26, 2017 11:03 pm
by deshipu
You don't need any special permissions, anybody can submit a pull request: ... l-request/

Re: Using the tx/rx pins not for UART

Posted: Fri Jan 27, 2017 6:35 am
by mmh
do i need developers status?

mmh@pluto:~/esp/micropython$ git push --set-upstream origin mhoffma-esp8266-uart
Username for '': mhoffma
Password for '':
remote: Permission to micropython/micropython.git denied to mhoffma.
fatal: unable to access '': The requested URL returned error: 403

Re: Using the tx/rx pins not for UART

Posted: Fri Jan 27, 2017 6:44 am
by dhylands
You need to create a fork, and push your changes to your fork and then create the PR from your fork to the official one.