From 9d6f70f7154aa01a02d3de1c669241e3a1439218 Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Thu, 21 Feb 2019 05:23:41 +1100 Subject: [PATCH] stm32: Make default USB_VCP stream go through uos.dupterm for main REPL. Use uos.dupterm for REPL configuration of the main USB_VCP(0) stream on dupterm slot 1, if USB is enabled. This means dupterm can also be used to disable the boot REPL port if desired, via uos.dupterm(None, 1). For efficiency this adds a simple hook to the global uos.dupterm code to work with streams that are known to be native streams. --- extmod/misc.h | 1 + extmod/uos_dupterm.c | 25 +++++++++++++++++++++++++ ports/stm32/main.c | 4 ++++ ports/stm32/moduos.c | 13 +++++++++++++ ports/stm32/mpconfigport.h | 3 ++- ports/stm32/mphalport.c | 12 ------------ ports/stm32/usb.c | 27 ++++++++++++++++++++------- ports/stm32/usb.h | 5 +++++ ports/stm32/usbd_cdc_interface.c | 5 ----- 9 files changed, 70 insertions(+), 25 deletions(-) diff --git a/extmod/misc.h b/extmod/misc.h index d6f6d859c..dae6bec4a 100644 --- a/extmod/misc.h +++ b/extmod/misc.h @@ -35,6 +35,7 @@ MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_uos_dupterm_obj); #if MICROPY_PY_OS_DUPTERM +bool mp_uos_dupterm_is_builtin_stream(mp_const_obj_t stream); int mp_uos_dupterm_rx_chr(void); void mp_uos_dupterm_tx_strn(const char *str, size_t len); void mp_uos_deactivate(size_t dupterm_idx, const char *msg, mp_obj_t exc); diff --git a/extmod/uos_dupterm.c b/extmod/uos_dupterm.c index dec3e1a40..42cb21444 100644 --- a/extmod/uos_dupterm.c +++ b/extmod/uos_dupterm.c @@ -32,6 +32,7 @@ #include "py/objtuple.h" #include "py/objarray.h" #include "py/stream.h" +#include "extmod/misc.h" #include "lib/utils/interrupt_char.h" #if MICROPY_PY_OS_DUPTERM @@ -58,6 +59,20 @@ int mp_uos_dupterm_rx_chr(void) { continue; } + #if MICROPY_PY_UOS_DUPTERM_BUILTIN_STREAM + if (mp_uos_dupterm_is_builtin_stream(MP_STATE_VM(dupterm_objs[idx]))) { + byte buf[1]; + int errcode = 0; + const mp_stream_p_t *stream_p = mp_get_stream(MP_STATE_VM(dupterm_objs[idx])); + mp_uint_t out_sz = stream_p->read(MP_STATE_VM(dupterm_objs[idx]), buf, 1, &errcode); + if (errcode == 0 && out_sz != 0) { + return buf[0]; + } else { + continue; + } + } + #endif + nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { byte buf[1]; @@ -98,6 +113,16 @@ void mp_uos_dupterm_tx_strn(const char *str, size_t len) { if (MP_STATE_VM(dupterm_objs[idx]) == MP_OBJ_NULL) { continue; } + + #if MICROPY_PY_UOS_DUPTERM_BUILTIN_STREAM + if (mp_uos_dupterm_is_builtin_stream(MP_STATE_VM(dupterm_objs[idx]))) { + int errcode = 0; + const mp_stream_p_t *stream_p = mp_get_stream(MP_STATE_VM(dupterm_objs[idx])); + stream_p->write(MP_STATE_VM(dupterm_objs[idx]), str, len, &errcode); + continue; + } + #endif + nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { mp_stream_write(MP_STATE_VM(dupterm_objs[idx]), str, len, MP_STREAM_RW_WRITE); diff --git a/ports/stm32/main.c b/ports/stm32/main.c index 48b4692bc..c1d27a968 100644 --- a/ports/stm32/main.c +++ b/ports/stm32/main.c @@ -630,6 +630,10 @@ soft_reset: #if MICROPY_HW_ENABLE_USB pyb_usb_init0(); + + // Activate USB_VCP(0) on dupterm slot 1 for the REPL + MP_STATE_VM(dupterm_objs[1]) = MP_OBJ_FROM_PTR(&pyb_usb_vcp_obj); + usb_vcp_attach_to_repl(&pyb_usb_vcp_obj, true); #endif // Initialise the local flash filesystem. diff --git a/ports/stm32/moduos.c b/ports/stm32/moduos.c index f492b0b75..ffecccd17 100644 --- a/ports/stm32/moduos.c +++ b/ports/stm32/moduos.c @@ -38,6 +38,7 @@ #include "extmod/vfs_fat.h" #include "genhdr/mpversion.h" #include "rng.h" +#include "usb.h" #include "uart.h" #include "portmodules.h" @@ -108,14 +109,26 @@ STATIC mp_obj_t os_urandom(mp_obj_t num) { STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_urandom_obj, os_urandom); #endif +bool mp_uos_dupterm_is_builtin_stream(mp_const_obj_t stream) { + mp_obj_type_t *type = mp_obj_get_type(stream); + return type == &pyb_uart_type || type == &pyb_usb_vcp_type; +} + STATIC mp_obj_t uos_dupterm(size_t n_args, const mp_obj_t *args) { mp_obj_t prev_obj = mp_uos_dupterm_obj.fun.var(n_args, args); if (mp_obj_get_type(prev_obj) == &pyb_uart_type) { uart_attach_to_repl(MP_OBJ_TO_PTR(prev_obj), false); } + if (mp_obj_get_type(prev_obj) == &pyb_usb_vcp_type) { + usb_vcp_attach_to_repl(MP_OBJ_TO_PTR(prev_obj), false); + } + if (mp_obj_get_type(args[0]) == &pyb_uart_type) { uart_attach_to_repl(MP_OBJ_TO_PTR(args[0]), true); } + if (mp_obj_get_type(args[0]) == &pyb_usb_vcp_type) { + usb_vcp_attach_to_repl(MP_OBJ_TO_PTR(args[0]), true); + } return prev_obj; } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(uos_dupterm_obj, 1, 2, uos_dupterm); diff --git a/ports/stm32/mpconfigport.h b/ports/stm32/mpconfigport.h index 86f65fda2..7cb67a115 100644 --- a/ports/stm32/mpconfigport.h +++ b/ports/stm32/mpconfigport.h @@ -145,7 +145,8 @@ #define MICROPY_PY_USELECT (1) #define MICROPY_PY_UTIMEQ (1) #define MICROPY_PY_UTIME_MP_HAL (1) -#define MICROPY_PY_OS_DUPTERM (1) +#define MICROPY_PY_OS_DUPTERM (3) +#define MICROPY_PY_UOS_DUPTERM_BUILTIN_STREAM (1) #define MICROPY_PY_MACHINE (1) #define MICROPY_PY_MACHINE_PULSE (1) #define MICROPY_PY_MACHINE_PIN_MAKE_NEW mp_pin_make_new diff --git a/ports/stm32/mphalport.c b/ports/stm32/mphalport.c index 9e59eb613..c770b62d2 100644 --- a/ports/stm32/mphalport.c +++ b/ports/stm32/mphalport.c @@ -30,13 +30,6 @@ MP_WEAK int mp_hal_stdin_rx_chr(void) { } #endif #endif - - #if MICROPY_HW_ENABLE_USB - byte c; - if (usb_vcp_recv_byte(&c) != 0) { - return c; - } - #endif if (MP_STATE_PORT(pyb_stdio_uart) != NULL && uart_rx_any(MP_STATE_PORT(pyb_stdio_uart))) { return uart_rx_char(MP_STATE_PORT(pyb_stdio_uart)); } @@ -59,11 +52,6 @@ MP_WEAK void mp_hal_stdout_tx_strn(const char *str, size_t len) { #if 0 && defined(USE_HOST_MODE) && MICROPY_HW_HAS_LCD lcd_print_strn(str, len); #endif - #if MICROPY_HW_ENABLE_USB - if (usb_vcp_is_enabled()) { - usb_vcp_send_strn(str, len); - } - #endif mp_uos_dupterm_tx_strn(str, len); } diff --git a/ports/stm32/usb.c b/ports/stm32/usb.c index 1ff62b4ab..1db32c9ae 100644 --- a/ports/stm32/usb.c +++ b/ports/stm32/usb.c @@ -111,6 +111,10 @@ const mp_rom_obj_tuple_t pyb_usb_hid_keyboard_obj = { }; void pyb_usb_init0(void) { + usb_device.usbd_cdc_itf.attached_to_repl = false; + #if MICROPY_HW_USB_ENABLE_CDC2 + usb_device.usbd_cdc2_itf.attached_to_repl = false; + #endif mp_hal_set_interrupt_char(-1); MP_STATE_PORT(pyb_hid_report_desc) = MP_OBJ_NULL; } @@ -380,7 +384,7 @@ typedef struct _pyb_usb_vcp_obj_t { usbd_cdc_itf_t *cdc_itf; } pyb_usb_vcp_obj_t; -STATIC const pyb_usb_vcp_obj_t pyb_usb_vcp_obj = {{&pyb_usb_vcp_type}, &usb_device.usbd_cdc_itf}; +const pyb_usb_vcp_obj_t pyb_usb_vcp_obj = {{&pyb_usb_vcp_type}, &usb_device.usbd_cdc_itf}; #if MICROPY_HW_USB_ENABLE_CDC2 STATIC const pyb_usb_vcp_obj_t pyb_usb_vcp2_obj = {{&pyb_usb_vcp_type}, &usb_device.usbd_cdc2_itf}; #endif @@ -390,6 +394,10 @@ STATIC void pyb_usb_vcp_print(const mp_print_t *print, mp_obj_t self_in, mp_prin mp_printf(print, "USB_VCP(%u)", id); } +void usb_vcp_attach_to_repl(const pyb_usb_vcp_obj_t *self, bool attached) { + self->cdc_itf->attached_to_repl = attached; +} + /// \classmethod \constructor() /// Create a new USB_VCP object. STATIC mp_obj_t pyb_usb_vcp_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { @@ -566,13 +574,18 @@ STATIC mp_uint_t pyb_usb_vcp_read(mp_obj_t self_in, void *buf, mp_uint_t size, i STATIC mp_uint_t pyb_usb_vcp_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode) { pyb_usb_vcp_obj_t *self = MP_OBJ_TO_PTR(self_in); - int ret = usbd_cdc_tx(self->cdc_itf, (const byte*)buf, size, 0); - if (ret == 0) { - // return EAGAIN error to indicate non-blocking - *errcode = MP_EAGAIN; - return MP_STREAM_ERROR; + if (self->cdc_itf->attached_to_repl) { + usbd_cdc_tx_always(self->cdc_itf, (const byte*)buf, size); + return size; + } else { + int ret = usbd_cdc_tx(self->cdc_itf, (const byte*)buf, size, 0); + if (ret == 0) { + // return EAGAIN error to indicate non-blocking + *errcode = MP_EAGAIN; + return MP_STREAM_ERROR; + } + return ret; } - return ret; } STATIC mp_uint_t pyb_usb_vcp_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) { diff --git a/ports/stm32/usb.h b/ports/stm32/usb.h index 45a05882a..2a3861f21 100644 --- a/ports/stm32/usb.h +++ b/ports/stm32/usb.h @@ -49,12 +49,16 @@ typedef enum { USB_PHY_HS_ID = 1, } USB_PHY_ID; +typedef struct _pyb_usb_vcp_obj_t pyb_usb_vcp_obj_t; + extern mp_uint_t pyb_usb_flags; extern pyb_usb_storage_medium_t pyb_usb_storage_medium; extern const struct _mp_rom_obj_tuple_t pyb_usb_hid_mouse_obj; extern const struct _mp_rom_obj_tuple_t pyb_usb_hid_keyboard_obj; extern const mp_obj_type_t pyb_usb_vcp_type; extern const mp_obj_type_t pyb_usb_hid_type; +extern const pyb_usb_vcp_obj_t pyb_usb_vcp_obj; + MP_DECLARE_CONST_FUN_OBJ_KW(pyb_usb_mode_obj); MP_DECLARE_CONST_FUN_OBJ_0(pyb_have_cdc_obj); // deprecated MP_DECLARE_CONST_FUN_OBJ_1(pyb_hid_send_report_obj); // deprecated @@ -65,6 +69,7 @@ void pyb_usb_dev_deinit(void); bool usb_vcp_is_enabled(void); int usb_vcp_recv_byte(uint8_t *c); // if a byte is available, return 1 and put the byte in *c, else return 0 void usb_vcp_send_strn(const char* str, int len); +void usb_vcp_attach_to_repl(const pyb_usb_vcp_obj_t *self, bool attached); void pyb_usb_host_init(void); void pyb_usb_host_process(void); diff --git a/ports/stm32/usbd_cdc_interface.c b/ports/stm32/usbd_cdc_interface.c index bc35ff50c..586f2d525 100644 --- a/ports/stm32/usbd_cdc_interface.c +++ b/ports/stm32/usbd_cdc_interface.c @@ -74,11 +74,6 @@ uint8_t *usbd_cdc_init(usbd_cdc_state_t *cdc_in) { cdc->tx_buf_ptr_out_shadow = 0; cdc->tx_need_empty_packet = 0; cdc->connect_state = USBD_CDC_CONNECT_STATE_DISCONNECTED; - #if MICROPY_HW_USB_ENABLE_CDC2 - cdc->attached_to_repl = &cdc->base == cdc->base.usbd->cdc; - #else - cdc->attached_to_repl = 1; - #endif // Return the buffer to place the first USB OUT packet return cdc->rx_packet_buf;