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.
This commit is contained in:
Andrew Leech 2019-02-21 05:23:41 +11:00 committed by Damien George
parent 0fb15fc3f4
commit 9d6f70f715
9 changed files with 70 additions and 25 deletions

View File

@ -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);

View File

@ -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);

View File

@ -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.

View File

@ -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);

View File

@ -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

View File

@ -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);
}

View File

@ -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) {

View File

@ -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);

View File

@ -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;