From a00c9d56db775ee5fc14c2db60eb07bab8e872dd Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 9 Nov 2023 16:56:21 +1100 Subject: [PATCH] rp2/mphalport: Run TinyUSB stack while waiting for CDC input/output. The recent change in bcbdee235719d459a4cd60d51021454fba54cd0f means that TinyUSB can no longer be run from within a soft (or hard) IRQ handler, ie when the scheduler is locked. That means that Python code that calls `print(...)` from within a scheduled function may block indefinitely if the USB CDC buffers are full. This commit fixes that problem by explicitly running the TinyUSB stack when waiting within stdio tx/rx functions. Signed-off-by: Damien George --- ports/rp2/mphalport.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/ports/rp2/mphalport.c b/ports/rp2/mphalport.c index d1bba43642..4b1c1fa1f5 100644 --- a/ports/rp2/mphalport.c +++ b/ports/rp2/mphalport.c @@ -30,6 +30,7 @@ #include "extmod/misc.h" #include "shared/runtime/interrupt_char.h" #include "shared/timeutils/timeutils.h" +#include "shared/tinyusb/mp_usbd.h" #include "tusb.h" #include "uart.h" #include "hardware/rtc.h" @@ -54,6 +55,19 @@ ringbuf_t stdin_ringbuf = { stdin_ringbuf_array, sizeof(stdin_ringbuf_array) }; #endif +#if MICROPY_HW_USB_CDC +// Explicitly run the USB stack in case the scheduler is locked (eg we are in an +// interrupt handler) and there is in/out data pending on the USB CDC interface. +#define MICROPY_EVENT_POLL_HOOK_WITH_USB \ + do { \ + MICROPY_EVENT_POLL_HOOK; \ + mp_usbd_task(); \ + } while (0) + +#else +#define MICROPY_EVENT_POLL_HOOK_WITH_USB MICROPY_EVENT_POLL_HOOK +#endif + #if MICROPY_HW_USB_CDC uint8_t cdc_itf_pending; // keep track of cdc interfaces which need attention to poll @@ -135,7 +149,7 @@ int mp_hal_stdin_rx_chr(void) { return dupterm_c; } #endif - MICROPY_EVENT_POLL_HOOK + MICROPY_EVENT_POLL_HOOK_WITH_USB; } } @@ -155,7 +169,7 @@ void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) { 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) { - MICROPY_EVENT_POLL_HOOK + MICROPY_EVENT_POLL_HOOK_WITH_USB; } if (timeout >= MICROPY_HW_USB_CDC_TX_TIMEOUT) { break;