diff --git a/lib/tinyusb b/lib/tinyusb index 1fdf29075d4e6..d10b65ada4be7 160000 --- a/lib/tinyusb +++ b/lib/tinyusb @@ -1 +1 @@ -Subproject commit 1fdf29075d4e613eacfa881166015263797db0f6 +Subproject commit d10b65ada4be7d5754b3128e80a9b4db72bdb23f diff --git a/ports/mimxrt/tusb_config.h b/ports/mimxrt/tusb_config.h index 862fb6c52d2e5..607f36446f858 100644 --- a/ports/mimxrt/tusb_config.h +++ b/ports/mimxrt/tusb_config.h @@ -32,5 +32,6 @@ #define CFG_TUD_CDC (1) #define CFG_TUD_CDC_RX_BUFSIZE (512) #define CFG_TUD_CDC_TX_BUFSIZE (512) +#define CFG_TUD_CDC_PERSISTENT_TX_BUFF (1) #endif // MICROPY_INCLUDED_MIMXRT_TUSB_CONFIG_H diff --git a/shared/tinyusb/mp_usbd_cdc.c b/shared/tinyusb/mp_usbd_cdc.c index 6d789ff5e81ca..cec06f307e55f 100644 --- a/shared/tinyusb/mp_usbd_cdc.c +++ b/shared/tinyusb/mp_usbd_cdc.c @@ -58,7 +58,9 @@ uintptr_t mp_usbd_cdc_poll_interfaces(uintptr_t poll_flags) { if ((poll_flags & MP_STREAM_POLL_RD) && ringbuf_peek(&stdin_ringbuf) != -1) { ret |= MP_STREAM_POLL_RD; } - if ((poll_flags & MP_STREAM_POLL_WR) && tud_cdc_connected() && tud_cdc_write_available() > 0) { + if ((poll_flags & MP_STREAM_POLL_WR) && + (!tud_cdc_connected() || (tud_cdc_connected() && tud_cdc_write_available() > 0))) { + // Always allow write when not connected, fifo will retain latest. // When connected operate as blocking, only allow if space is available. ret |= MP_STREAM_POLL_WR; } @@ -93,42 +95,60 @@ void tud_cdc_rx_cb(uint8_t itf) { mp_uint_t mp_usbd_cdc_tx_strn(const char *str, mp_uint_t len) { size_t i = 0; - if (tud_cdc_connected()) { - while (i < len) { - uint32_t n = len - i; - if (n > CFG_TUD_CDC_EP_BUFSIZE) { - n = CFG_TUD_CDC_EP_BUFSIZE; - } - int timeout = 0; - // Wait with a max of USC_CDC_TIMEOUT ms - while (n > tud_cdc_write_available() && timeout++ < MICROPY_HW_USB_CDC_TX_TIMEOUT) { + while (i < len) { + uint32_t n = len - i; + if (n > CFG_TUD_CDC_EP_BUFSIZE) { + n = CFG_TUD_CDC_EP_BUFSIZE; + } + int timeout = 0; + if (tud_cdc_connected()) { + // If cdc port is connected but the buffer is full, + // wait for up to USC_CDC_TIMEOUT ms + while (n > tud_cdc_write_available() + && timeout++ < MICROPY_HW_USB_CDC_TX_TIMEOUT) { mp_event_wait_ms(1); // Explicitly run the USB stack as the scheduler may be locked (eg we // are in an interrupt handler), while there is data pending. mp_usbd_task(); } - if (timeout >= MICROPY_HW_USB_CDC_TX_TIMEOUT) { + // Limit write to available space in tx buffer when connected. + n = MIN(n, tud_cdc_write_available()); + if (n == 0) { break; } - uint32_t n2 = tud_cdc_write(str + i, n); - tud_cdc_write_flush(); - i += n2; } + // When not connected we always write to usb fifo, ensuring it has latest data. + uint32_t n2 = tud_cdc_write(str + i, n); + tud_cdc_write_flush(); + i += n2; } return i; } +static int8_t cdc_connected_flush_delay = 0; + +void tud_sof_cb(uint32_t frame_count) { + if (--cdc_connected_flush_delay < 0) { + // Finished on-connection delay, disable SOF interrupt again. + // Finished on-connection delay, disable SOF interrupt again. + tud_sof_cb_enable(false); + tud_cdc_write_flush(); + } +} + #endif -#if MICROPY_HW_USB_CDC_1200BPS_TOUCH && MICROPY_HW_ENABLE_USBDEV +#if MICROPY_HW_ENABLE_USBDEV && (MICROPY_HW_USB_CDC_1200BPS_TOUCH || MICROPY_HW_USB_CDC) +#if MICROPY_HW_USB_CDC_1200BPS_TOUCH static mp_sched_node_t mp_bootloader_sched_node; static void usbd_cdc_run_bootloader_task(mp_sched_node_t *node) { mp_hal_delay_ms(250); machine_bootloader(0, NULL); } +#endif void #if MICROPY_HW_USB_EXTERNAL_TINYUSB @@ -137,6 +157,16 @@ mp_usbd_line_state_cb tud_cdc_line_state_cb #endif (uint8_t itf, bool dtr, bool rts) { + #if MICROPY_HW_USB_CDC + if (dtr) { + // A host application has started to open the cdc serial port. + // Wait a few ms for host to be ready then send tx buffer. + // High speed connection SOF fires at 125us, full speed at 1ms. + cdc_connected_flush_delay = (tud_speed_get() == TUSB_SPEED_HIGH) ? 128 : 16; + tud_sof_cb_enable(true); + } + #endif + #if MICROPY_HW_USB_CDC_1200BPS_TOUCH if (dtr == false && rts == false) { // Device is disconnected. cdc_line_coding_t line_coding; @@ -146,6 +176,7 @@ tud_cdc_line_state_cb mp_sched_schedule_node(&mp_bootloader_sched_node, usbd_cdc_run_bootloader_task); } } + #endif } #endif diff --git a/shared/tinyusb/tusb_config.h b/shared/tinyusb/tusb_config.h index ab47321afdc04..1f8f5e5f6dc56 100644 --- a/shared/tinyusb/tusb_config.h +++ b/shared/tinyusb/tusb_config.h @@ -79,6 +79,7 @@ #if CFG_TUD_CDC #define CFG_TUD_CDC_RX_BUFSIZE ((CFG_TUD_MAX_SPEED == OPT_MODE_HIGH_SPEED) ? 512 : 256) #define CFG_TUD_CDC_TX_BUFSIZE ((CFG_TUD_MAX_SPEED == OPT_MODE_HIGH_SPEED) ? 512 : 256) +#define CFG_TUD_CDC_PERSISTENT_TX_BUFF (1) #endif // MSC Configuration