summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--extmod/misc.h3
-rw-r--r--extmod/uos_dupterm.c96
-rw-r--r--ports/esp8266/esp_mphal.c37
-rw-r--r--ports/esp8266/main.c2
-rw-r--r--ports/esp8266/modules/webrepl.py4
-rw-r--r--ports/unix/unix_mphal.c17
-rw-r--r--py/mpstate.h2
-rw-r--r--py/runtime.c7
8 files changed, 95 insertions, 73 deletions
diff --git a/extmod/misc.h b/extmod/misc.h
index 6c13592c7..d6f6d859c 100644
--- a/extmod/misc.h
+++ b/extmod/misc.h
@@ -35,8 +35,9 @@
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_uos_dupterm_obj);
#if MICROPY_PY_OS_DUPTERM
+int mp_uos_dupterm_rx_chr(void);
void mp_uos_dupterm_tx_strn(const char *str, size_t len);
-void mp_uos_deactivate(const char *msg, mp_obj_t exc);
+void mp_uos_deactivate(size_t dupterm_idx, const char *msg, mp_obj_t exc);
#else
#define mp_uos_dupterm_tx_strn(s, l)
#endif
diff --git a/extmod/uos_dupterm.c b/extmod/uos_dupterm.c
index 1d6f02dce..d4326d326 100644
--- a/extmod/uos_dupterm.c
+++ b/extmod/uos_dupterm.c
@@ -4,6 +4,7 @@
* The MIT License (MIT)
*
* Copyright (c) 2016 Paul Sokolovsky
+ * Copyright (c) 2017 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -31,12 +32,13 @@
#include "py/objtuple.h"
#include "py/objarray.h"
#include "py/stream.h"
+#include "lib/utils/interrupt_char.h"
#if MICROPY_PY_OS_DUPTERM
-void mp_uos_deactivate(const char *msg, mp_obj_t exc) {
- mp_obj_t term = MP_STATE_PORT(term_obj);
- MP_STATE_PORT(term_obj) = NULL;
+void mp_uos_deactivate(size_t dupterm_idx, const char *msg, mp_obj_t exc) {
+ mp_obj_t term = MP_STATE_VM(dupterm_objs[dupterm_idx]);
+ MP_STATE_VM(dupterm_objs[dupterm_idx]) = MP_OBJ_NULL;
mp_printf(&mp_plat_print, msg);
if (exc != MP_OBJ_NULL) {
mp_obj_print_exception(&mp_plat_print, exc);
@@ -44,48 +46,94 @@ void mp_uos_deactivate(const char *msg, mp_obj_t exc) {
mp_stream_close(term);
}
+int mp_uos_dupterm_rx_chr(void) {
+ for (size_t idx = 0; idx < MICROPY_PY_OS_DUPTERM; ++idx) {
+ if (MP_STATE_VM(dupterm_objs[idx]) == MP_OBJ_NULL) {
+ continue;
+ }
+
+ nlr_buf_t nlr;
+ if (nlr_push(&nlr) == 0) {
+ mp_obj_t readinto_m[3];
+ mp_load_method(MP_STATE_VM(dupterm_objs[idx]), MP_QSTR_readinto, readinto_m);
+ readinto_m[2] = MP_STATE_VM(dupterm_arr_obj);
+ mp_obj_t res = mp_call_method_n_kw(1, 0, readinto_m);
+ if (res == mp_const_none) {
+ nlr_pop();
+ } else if (res == MP_OBJ_NEW_SMALL_INT(0)) {
+ mp_uos_deactivate(idx, "dupterm: EOF received, deactivating\n", MP_OBJ_NULL);
+ nlr_pop();
+ } else {
+ mp_buffer_info_t bufinfo;
+ mp_get_buffer_raise(MP_STATE_VM(dupterm_arr_obj), &bufinfo, MP_BUFFER_READ);
+ nlr_pop();
+ if (*(byte*)bufinfo.buf == mp_interrupt_char) {
+ // Signal keyboard interrupt to be raised as soon as the VM resumes
+ mp_keyboard_interrupt();
+ return -2;
+ }
+ return *(byte*)bufinfo.buf;
+ }
+ } else {
+ mp_uos_deactivate(idx, "dupterm: Exception in read() method, deactivating: ", nlr.ret_val);
+ }
+ }
+
+ // No chars available
+ return -1;
+}
+
void mp_uos_dupterm_tx_strn(const char *str, size_t len) {
- if (MP_STATE_PORT(term_obj) != MP_OBJ_NULL) {
+ for (size_t idx = 0; idx < MICROPY_PY_OS_DUPTERM; ++idx) {
+ if (MP_STATE_VM(dupterm_objs[idx]) == MP_OBJ_NULL) {
+ continue;
+ }
nlr_buf_t nlr;
if (nlr_push(&nlr) == 0) {
mp_obj_t write_m[3];
- mp_load_method(MP_STATE_PORT(term_obj), MP_QSTR_write, write_m);
+ mp_load_method(MP_STATE_VM(dupterm_objs[idx]), MP_QSTR_write, write_m);
- mp_obj_array_t *arr = MP_OBJ_TO_PTR(MP_STATE_PORT(dupterm_arr_obj));
+ mp_obj_array_t *arr = MP_OBJ_TO_PTR(MP_STATE_VM(dupterm_arr_obj));
void *org_items = arr->items;
arr->items = (void*)str;
arr->len = len;
- write_m[2] = MP_STATE_PORT(dupterm_arr_obj);
+ write_m[2] = MP_STATE_VM(dupterm_arr_obj);
mp_call_method_n_kw(1, 0, write_m);
- arr = MP_OBJ_TO_PTR(MP_STATE_PORT(dupterm_arr_obj));
+ arr = MP_OBJ_TO_PTR(MP_STATE_VM(dupterm_arr_obj));
arr->items = org_items;
arr->len = 1;
nlr_pop();
} else {
- mp_uos_deactivate("dupterm: Exception in write() method, deactivating: ", nlr.ret_val);
+ mp_uos_deactivate(idx, "dupterm: Exception in write() method, deactivating: ", nlr.ret_val);
}
}
}
STATIC mp_obj_t mp_uos_dupterm(size_t n_args, const mp_obj_t *args) {
- if (n_args == 0) {
- if (MP_STATE_PORT(term_obj) == MP_OBJ_NULL) {
- return mp_const_none;
- } else {
- return MP_STATE_PORT(term_obj);
- }
+ mp_int_t idx = 0;
+ if (n_args == 2) {
+ idx = mp_obj_get_int(args[1]);
+ }
+
+ if (idx < 0 || idx >= MICROPY_PY_OS_DUPTERM) {
+ mp_raise_ValueError("invalid dupterm index");
+ }
+
+ mp_obj_t previous_obj = MP_STATE_VM(dupterm_objs[idx]);
+ if (previous_obj == MP_OBJ_NULL) {
+ previous_obj = mp_const_none;
+ }
+ if (args[0] == mp_const_none) {
+ MP_STATE_VM(dupterm_objs[idx]) = MP_OBJ_NULL;
} else {
- if (args[0] == mp_const_none) {
- MP_STATE_PORT(term_obj) = MP_OBJ_NULL;
- } else {
- MP_STATE_PORT(term_obj) = args[0];
- if (MP_STATE_PORT(dupterm_arr_obj) == MP_OBJ_NULL) {
- MP_STATE_PORT(dupterm_arr_obj) = mp_obj_new_bytearray(1, "");
- }
+ MP_STATE_VM(dupterm_objs[idx]) = args[0];
+ if (MP_STATE_VM(dupterm_arr_obj) == MP_OBJ_NULL) {
+ MP_STATE_VM(dupterm_arr_obj) = mp_obj_new_bytearray(1, "");
}
- return mp_const_none;
}
+
+ return previous_obj;
}
-MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_uos_dupterm_obj, 0, 1, mp_uos_dupterm);
+MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_uos_dupterm_obj, 1, 2, mp_uos_dupterm);
#endif
diff --git a/ports/esp8266/esp_mphal.c b/ports/esp8266/esp_mphal.c
index 71d4c5062..9f4f051fd 100644
--- a/ports/esp8266/esp_mphal.c
+++ b/ports/esp8266/esp_mphal.c
@@ -155,41 +155,6 @@ void mp_hal_signal_input(void) {
#endif
}
-static int call_dupterm_read(void) {
- if (MP_STATE_PORT(term_obj) == NULL) {
- return -1;
- }
-
- nlr_buf_t nlr;
- if (nlr_push(&nlr) == 0) {
- mp_obj_t readinto_m[3];
- mp_load_method(MP_STATE_PORT(term_obj), MP_QSTR_readinto, readinto_m);
- readinto_m[2] = MP_STATE_PORT(dupterm_arr_obj);
- mp_obj_t res = mp_call_method_n_kw(1, 0, readinto_m);
- if (res == mp_const_none) {
- nlr_pop();
- return -2;
- }
- if (res == MP_OBJ_NEW_SMALL_INT(0)) {
- mp_uos_deactivate("dupterm: EOF received, deactivating\n", MP_OBJ_NULL);
- nlr_pop();
- return -1;
- }
- mp_buffer_info_t bufinfo;
- mp_get_buffer_raise(MP_STATE_PORT(dupterm_arr_obj), &bufinfo, MP_BUFFER_READ);
- nlr_pop();
- if (*(byte*)bufinfo.buf == mp_interrupt_char) {
- mp_keyboard_interrupt();
- return -2;
- }
- return *(byte*)bufinfo.buf;
- } else {
- mp_uos_deactivate("dupterm: Exception in read() method, deactivating: ", nlr.ret_val);
- }
-
- return -1;
-}
-
STATIC void dupterm_task_handler(os_event_t *evt) {
static byte lock;
if (lock) {
@@ -197,7 +162,7 @@ STATIC void dupterm_task_handler(os_event_t *evt) {
}
lock = 1;
while (1) {
- int c = call_dupterm_read();
+ int c = mp_uos_dupterm_rx_chr();
if (c < 0) {
break;
}
diff --git a/ports/esp8266/main.c b/ports/esp8266/main.c
index 7f5dca84e..d1b88a8ce 100644
--- a/ports/esp8266/main.c
+++ b/ports/esp8266/main.c
@@ -51,8 +51,6 @@ STATIC void mp_reset(void) {
mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_lib));
mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_));
mp_obj_list_init(mp_sys_argv, 0);
- MP_STATE_PORT(term_obj) = MP_OBJ_NULL;
- MP_STATE_PORT(dupterm_arr_obj) = MP_OBJ_NULL;
#if MICROPY_EMIT_XTENSA || MICROPY_EMIT_INLINE_XTENSA
extern void esp_native_code_init(void);
esp_native_code_init();
diff --git a/ports/esp8266/modules/webrepl.py b/ports/esp8266/modules/webrepl.py
index 5a76e9b26..aa156d148 100644
--- a/ports/esp8266/modules/webrepl.py
+++ b/ports/esp8266/modules/webrepl.py
@@ -31,7 +31,9 @@ def setup_conn(port, accept_handler):
def accept_conn(listen_sock):
global client_s
cl, remote_addr = listen_sock.accept()
- if uos.dupterm():
+ prev = uos.dupterm(None)
+ uos.dupterm(prev)
+ if prev:
print("\nConcurrent WebREPL connection from", remote_addr, "rejected")
cl.close()
return
diff --git a/ports/unix/unix_mphal.c b/ports/unix/unix_mphal.c
index 2b273d834..f27c62fd1 100644
--- a/ports/unix/unix_mphal.c
+++ b/ports/unix/unix_mphal.c
@@ -108,11 +108,11 @@ void mp_hal_stdio_mode_orig(void) {
#endif
#if MICROPY_PY_OS_DUPTERM
-static int call_dupterm_read(void) {
+static int call_dupterm_read(size_t idx) {
nlr_buf_t nlr;
if (nlr_push(&nlr) == 0) {
mp_obj_t read_m[3];
- mp_load_method(MP_STATE_PORT(term_obj), MP_QSTR_read, read_m);
+ mp_load_method(MP_STATE_VM(dupterm_objs[idx]), MP_QSTR_read, read_m);
read_m[2] = MP_OBJ_NEW_SMALL_INT(1);
mp_obj_t res = mp_call_method_n_kw(1, 0, read_m);
if (res == mp_const_none) {
@@ -122,18 +122,18 @@ static int call_dupterm_read(void) {
mp_get_buffer_raise(res, &bufinfo, MP_BUFFER_READ);
if (bufinfo.len == 0) {
mp_printf(&mp_plat_print, "dupterm: EOF received, deactivating\n");
- MP_STATE_PORT(term_obj) = NULL;
+ MP_STATE_VM(dupterm_objs[idx]) = MP_OBJ_NULL;
return -1;
}
nlr_pop();
return *(byte*)bufinfo.buf;
} else {
// Temporarily disable dupterm to avoid infinite recursion
- mp_obj_t save_term = MP_STATE_PORT(term_obj);
- MP_STATE_PORT(term_obj) = NULL;
+ mp_obj_t save_term = MP_STATE_VM(dupterm_objs[idx]);
+ MP_STATE_VM(dupterm_objs[idx]) = NULL;
mp_printf(&mp_plat_print, "dupterm: ");
mp_obj_print_exception(&mp_plat_print, nlr.ret_val);
- MP_STATE_PORT(term_obj) = save_term;
+ MP_STATE_VM(dupterm_objs[idx]) = save_term;
}
return -1;
@@ -143,10 +143,11 @@ static int call_dupterm_read(void) {
int mp_hal_stdin_rx_chr(void) {
unsigned char c;
#if MICROPY_PY_OS_DUPTERM
- if (MP_STATE_PORT(term_obj) != MP_OBJ_NULL) {
+ // TODO only support dupterm one slot at the moment
+ if (MP_STATE_VM(dupterm_objs[0]) != MP_OBJ_NULL) {
int c;
do {
- c = call_dupterm_read();
+ c = call_dupterm_read(0);
} while (c == -2);
if (c == -1) {
goto main_term;
diff --git a/py/mpstate.h b/py/mpstate.h
index eca14a9e4..6a39ebdea 100644
--- a/py/mpstate.h
+++ b/py/mpstate.h
@@ -168,7 +168,7 @@ typedef struct _mp_state_vm_t {
// root pointers for extmod
#if MICROPY_PY_OS_DUPTERM
- mp_obj_t term_obj;
+ mp_obj_t dupterm_objs[MICROPY_PY_OS_DUPTERM];
mp_obj_t dupterm_arr_obj;
#endif
diff --git a/py/runtime.c b/py/runtime.c
index 069548deb..17e5d235c 100644
--- a/py/runtime.c
+++ b/py/runtime.c
@@ -102,6 +102,13 @@ void mp_init(void) {
MP_STATE_VM(mp_module_builtins_override_dict) = NULL;
#endif
+ #if MICROPY_PY_OS_DUPTERM
+ for (size_t i = 0; i < MICROPY_PY_OS_DUPTERM; ++i) {
+ MP_STATE_VM(dupterm_objs[i]) = MP_OBJ_NULL;
+ }
+ MP_STATE_VM(dupterm_arr_obj) = MP_OBJ_NULL;
+ #endif
+
#if MICROPY_FSUSERMOUNT
// zero out the pointers to the user-mounted devices
memset(MP_STATE_VM(fs_user_mount), 0, sizeof(MP_STATE_VM(fs_user_mount)));