From 38e7b842c6bc8122753cbf0845eb141f28fbcb72 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 22 Mar 2023 00:14:46 +1100 Subject: [PATCH] ports: Implement simple write polling for stdout. This is a best-effort implementation of write polling. It's difficult to do correctly because if there are multiple output streams (eg UART and USB CDC) then some may not be writeable while others are. A full solution should also have a return value from mp_hal_stdout_tx_strn(), returning the number of bytes written to the stream(s). That's also hard to define. The renesas-ra and stm32 ports already implement a similar best-effort mechanism for write polling. Fixes issue #11026. Signed-off-by: Damien George --- ports/esp32/mphalport.c | 3 +++ ports/esp8266/esp_mphal.c | 3 +++ ports/mimxrt/mphalport.c | 3 +++ ports/nrf/drivers/bluetooth/ble_uart.c | 3 +++ ports/nrf/drivers/usb/usb_cdc.c | 3 +++ ports/nrf/mphalport.c | 3 +++ ports/pic16bit/pic16bit_mphal.c | 3 +++ ports/rp2/mphalport.c | 9 +++++++++ ports/samd/mphalport.c | 4 ++++ ports/teensy/teensy_hal.c | 5 +++++ 10 files changed, 39 insertions(+) diff --git a/ports/esp32/mphalport.c b/ports/esp32/mphalport.c index 2aaeb9755f..b187b422d5 100644 --- a/ports/esp32/mphalport.c +++ b/ports/esp32/mphalport.c @@ -88,6 +88,9 @@ uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) { if ((poll_flags & MP_STREAM_POLL_RD) && stdin_ringbuf.iget != stdin_ringbuf.iput) { ret |= MP_STREAM_POLL_RD; } + if (poll_flags & MP_STREAM_POLL_WR) { + ret |= MP_STREAM_POLL_WR; + } return ret; } diff --git a/ports/esp8266/esp_mphal.c b/ports/esp8266/esp_mphal.c index 3cb4807333..219e614841 100644 --- a/ports/esp8266/esp_mphal.c +++ b/ports/esp8266/esp_mphal.c @@ -62,6 +62,9 @@ uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) { if ((poll_flags & MP_STREAM_POLL_RD) && stdin_ringbuf.iget != stdin_ringbuf.iput) { ret |= MP_STREAM_POLL_RD; } + if (poll_flags & MP_STREAM_POLL_WR) { + ret |= mp_uos_dupterm_poll(poll_flags); + } return ret; } diff --git a/ports/mimxrt/mphalport.c b/ports/mimxrt/mphalport.c index 2730b9a855..beb471ab80 100644 --- a/ports/mimxrt/mphalport.c +++ b/ports/mimxrt/mphalport.c @@ -86,6 +86,9 @@ uintptr_t mp_hal_stdio_poll(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) { + ret |= MP_STREAM_POLL_WR; + } #if MICROPY_PY_OS_DUPTERM ret |= mp_uos_dupterm_poll(poll_flags); #endif diff --git a/ports/nrf/drivers/bluetooth/ble_uart.c b/ports/nrf/drivers/bluetooth/ble_uart.c index 3020f1af62..3206573703 100644 --- a/ports/nrf/drivers/bluetooth/ble_uart.c +++ b/ports/nrf/drivers/bluetooth/ble_uart.c @@ -164,6 +164,9 @@ uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) { && !isBufferEmpty(mp_rx_ring_buffer)) { ret |= MP_STREAM_POLL_RD; } + if ((poll_flags & MP_STREAM_POLL_WR) && ble_uart_enabled()) { + ret |= MP_STREAM_POLL_WR; + } return ret; } #endif diff --git a/ports/nrf/drivers/usb/usb_cdc.c b/ports/nrf/drivers/usb/usb_cdc.c index 16d69fff66..e33a425482 100644 --- a/ports/nrf/drivers/usb/usb_cdc.c +++ b/ports/nrf/drivers/usb/usb_cdc.c @@ -213,6 +213,9 @@ uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) { ret |= MP_STREAM_POLL_RD; } } + if (poll_flags & MP_STREAM_POLL_WR) { + ret |= MP_STREAM_POLL_WR; + } return ret; } diff --git a/ports/nrf/mphalport.c b/ports/nrf/mphalport.c index 9405cb2e3a..a2eec7fceb 100644 --- a/ports/nrf/mphalport.c +++ b/ports/nrf/mphalport.c @@ -179,6 +179,9 @@ uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) { && uart_rx_any(MP_STATE_PORT(board_stdio_uart))) { ret |= MP_STREAM_POLL_RD; } + if ((poll_flags & MP_STREAM_POLL_WR) && MP_STATE_PORT(board_stdio_uart) != NULL) { + ret |= MP_STREAM_POLL_WR; + } return ret; } diff --git a/ports/pic16bit/pic16bit_mphal.c b/ports/pic16bit/pic16bit_mphal.c index 48e8af87de..b2c80ba1be 100644 --- a/ports/pic16bit/pic16bit_mphal.c +++ b/ports/pic16bit/pic16bit_mphal.c @@ -57,6 +57,9 @@ uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) { if ((poll_flags & MP_STREAM_POLL_RD) && uart_rx_any()) { ret |= MP_STREAM_POLL_RD; } + if (poll_flags & MP_STREAM_POLL_WR) { + ret |= MP_STREAM_POLL_WR; + } return ret; } diff --git a/ports/rp2/mphalport.c b/ports/rp2/mphalport.c index 510d486d96..f56c2bda13 100644 --- a/ports/rp2/mphalport.c +++ b/ports/rp2/mphalport.c @@ -98,6 +98,15 @@ uintptr_t mp_hal_stdio_poll(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) { + #if MICROPY_HW_ENABLE_UART_REPL + ret |= MP_STREAM_POLL_WR; + #else + if (tud_cdc_connected() && tud_cdc_write_available() > 0) { + ret |= MP_STREAM_POLL_WR; + } + #endif + } #endif #if MICROPY_PY_OS_DUPTERM ret |= mp_uos_dupterm_poll(poll_flags); diff --git a/ports/samd/mphalport.c b/ports/samd/mphalport.c index d7511e61fb..3dc6b70a8d 100644 --- a/ports/samd/mphalport.c +++ b/ports/samd/mphalport.c @@ -162,6 +162,10 @@ uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) { ret |= MP_STREAM_POLL_RD; } + if ((poll_flags & MP_STREAM_POLL_WR) && tud_cdc_connected() && tud_cdc_write_available() > 0) { + ret |= MP_STREAM_POLL_WR; + } + #if MICROPY_PY_OS_DUPTERM ret |= mp_uos_dupterm_poll(poll_flags); #endif diff --git a/ports/teensy/teensy_hal.c b/ports/teensy/teensy_hal.c index 93103319b5..62a8265177 100644 --- a/ports/teensy/teensy_hal.c +++ b/ports/teensy/teensy_hal.c @@ -32,6 +32,11 @@ uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) { ret |= MP_STREAM_POLL_RD; } } + if (poll_flags & MP_STREAM_POLL_WR) { + if (MP_STATE_PORT(pyb_stdio_uart) != NULL || usb_vcp_is_enabled()) { + ret |= MP_STREAM_POLL_WR; + } + } return ret; }