diff --git a/ports/rp2/CMakeLists.txt b/ports/rp2/CMakeLists.txt index d58fb56877..a5e4217347 100644 --- a/ports/rp2/CMakeLists.txt +++ b/ports/rp2/CMakeLists.txt @@ -72,6 +72,7 @@ set(MICROPY_SOURCE_LIB ${MICROPY_DIR}/shared/readline/readline.c ${MICROPY_DIR}/shared/runtime/gchelper_m0.s ${MICROPY_DIR}/shared/runtime/gchelper_native.c + ${MICROPY_DIR}/shared/runtime/interrupt_char.c ${MICROPY_DIR}/shared/runtime/mpirq.c ${MICROPY_DIR}/shared/runtime/pyexec.c ${MICROPY_DIR}/shared/runtime/stdout_helpers.c diff --git a/ports/rp2/mphalport.c b/ports/rp2/mphalport.c index c4169fb66c..4a5221caec 100644 --- a/ports/rp2/mphalport.c +++ b/ports/rp2/mphalport.c @@ -28,50 +28,69 @@ #include "py/stream.h" #include "py/mphal.h" #include "extmod/misc.h" +#include "shared/runtime/interrupt_char.h" #include "shared/timeutils/timeutils.h" #include "tusb.h" #include "uart.h" #include "hardware/rtc.h" -#if MICROPY_HW_ENABLE_UART_REPL +#if MICROPY_HW_ENABLE_UART_REPL || MICROPY_HW_ENABLE_USBDEV -#ifndef UART_BUFFER_LEN -// reasonably big so we can paste -#define UART_BUFFER_LEN 256 +#ifndef MICROPY_HW_STDIN_BUFFER_LEN +#define MICROPY_HW_STDIN_BUFFER_LEN 512 #endif -STATIC uint8_t stdin_ringbuf_array[UART_BUFFER_LEN]; +STATIC uint8_t stdin_ringbuf_array[MICROPY_HW_STDIN_BUFFER_LEN]; ringbuf_t stdin_ringbuf = { stdin_ringbuf_array, sizeof(stdin_ringbuf_array) }; #endif -#if MICROPY_KBD_EXCEPTION +#if MICROPY_HW_ENABLE_USBDEV -int mp_interrupt_char = -1; +uint8_t cdc_itf_pending; // keep track of cdc interfaces which need attention to poll -void tud_cdc_rx_wanted_cb(uint8_t itf, char wanted_char) { - (void)itf; - (void)wanted_char; - tud_cdc_read_char(); // discard interrupt char - mp_sched_keyboard_interrupt(); +void poll_cdc_interfaces(void) { + // any CDC interfaces left to poll? + if (cdc_itf_pending && ringbuf_free(&stdin_ringbuf)) { + for (uint8_t itf = 0; itf < 8; ++itf) { + if (cdc_itf_pending & (1 << itf)) { + tud_cdc_rx_cb(itf); + if (!cdc_itf_pending) { + break; + } + } + } + } } -void mp_hal_set_interrupt_char(int c) { - mp_interrupt_char = c; - tud_cdc_set_wanted_char(c); +void tud_cdc_rx_cb(uint8_t itf) { + // consume pending USB data immediately to free usb buffer and keep the endpoint from stalling. + // in case the ringbuffer is full, mark the CDC interface that need attention later on for polling + cdc_itf_pending &= ~(1 << itf); + for (uint32_t bytes_avail = tud_cdc_n_available(itf); bytes_avail > 0; --bytes_avail) { + if (ringbuf_free(&stdin_ringbuf)) { + int data_char = tud_cdc_read_char(); + if (data_char == mp_interrupt_char) { + mp_sched_keyboard_interrupt(); + } else { + ringbuf_put(&stdin_ringbuf, data_char); + } + } else { + cdc_itf_pending |= (1 << itf); + return; + } + } } #endif uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) { uintptr_t ret = 0; - #if MICROPY_HW_ENABLE_UART_REPL - if ((poll_flags & MP_STREAM_POLL_RD) && ringbuf_peek(&stdin_ringbuf) != -1) { - ret |= MP_STREAM_POLL_RD; - } - #endif #if MICROPY_HW_ENABLE_USBDEV - if (tud_cdc_connected() && tud_cdc_available()) { + poll_cdc_interfaces(); + #endif + #if MICROPY_HW_ENABLE_UART_REPL || MICROPY_HW_ENABLE_USBDEV + if ((poll_flags & MP_STREAM_POLL_RD) && ringbuf_peek(&stdin_ringbuf) != -1) { ret |= MP_STREAM_POLL_RD; } #endif @@ -84,21 +103,14 @@ uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) { // Receive single character int mp_hal_stdin_rx_chr(void) { for (;;) { - #if MICROPY_HW_ENABLE_UART_REPL + #if MICROPY_HW_ENABLE_USBDEV + poll_cdc_interfaces(); + #endif + int c = ringbuf_get(&stdin_ringbuf); if (c != -1) { return c; } - #endif - #if MICROPY_HW_ENABLE_USBDEV - if (tud_cdc_connected() && tud_cdc_available()) { - uint8_t buf[1]; - uint32_t count = tud_cdc_read(buf, sizeof(buf)); - if (count) { - return buf[0]; - } - } - #endif #if MICROPY_PY_OS_DUPTERM int dupterm_c = mp_uos_dupterm_rx_chr(); if (dupterm_c >= 0) { @@ -123,11 +135,9 @@ void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) { n = CFG_TUD_CDC_EP_BUFSIZE; } while (n > tud_cdc_write_available()) { - tud_task(); - tud_cdc_write_flush(); + MICROPY_EVENT_POLL_HOOK } uint32_t n2 = tud_cdc_write(str + i, n); - tud_task(); tud_cdc_write_flush(); i += n2; }