diff --git a/ports/cc3200/hal/cc3200_hal.c b/ports/cc3200/hal/cc3200_hal.c index 56dd2b2b8..8bfd2fda1 100644 --- a/ports/cc3200/hal/cc3200_hal.c +++ b/ports/cc3200/hal/cc3200_hal.c @@ -140,10 +140,15 @@ void mp_hal_delay_ms(mp_uint_t delay) { } } -void mp_hal_stdout_tx_strn(const char *str, size_t len) { - mp_os_dupterm_tx_strn(str, len); +mp_uint_t mp_hal_stdout_tx_strn(const char *str, size_t len) { + mp_uint_t ret = len; + int dupterm_res = mp_os_dupterm_tx_strn(str, len); + if (dupterm_res >= 0) { + ret = dupterm_res; + } // and also to telnet telnet_tx_strn(str, len); + return ret; } int mp_hal_stdin_rx_chr(void) { diff --git a/ports/esp32/mphalport.c b/ports/esp32/mphalport.c index 8e14bda59..fb322dff6 100644 --- a/ports/esp32/mphalport.c +++ b/ports/esp32/mphalport.c @@ -125,24 +125,34 @@ int mp_hal_stdin_rx_chr(void) { } } -void mp_hal_stdout_tx_strn(const char *str, size_t len) { +mp_uint_t mp_hal_stdout_tx_strn(const char *str, size_t len) { // Only release the GIL if many characters are being sent + mp_uint_t ret = len; + bool did_write = false; bool release_gil = len > 20; if (release_gil) { MP_THREAD_GIL_EXIT(); } #if CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG usb_serial_jtag_tx_strn(str, len); + did_write = true; #elif CONFIG_USB_OTG_SUPPORTED usb_tx_strn(str, len); + did_write = true; #endif #if MICROPY_HW_ENABLE_UART_REPL uart_stdout_tx_strn(str, len); + did_write = true; #endif if (release_gil) { MP_THREAD_GIL_ENTER(); } - mp_os_dupterm_tx_strn(str, len); + int dupterm_res = mp_os_dupterm_tx_strn(str, len); + if (dupterm_res >= 0) { + did_write = true; + ret = MIN((mp_uint_t)dupterm_res, ret); + } + return did_write ? ret : 0; } uint32_t mp_hal_ticks_ms(void) { diff --git a/ports/esp8266/esp_mphal.c b/ports/esp8266/esp_mphal.c index 394c9796c..6f158058d 100644 --- a/ports/esp8266/esp_mphal.c +++ b/ports/esp8266/esp_mphal.c @@ -94,8 +94,14 @@ void mp_hal_debug_str(const char *str) { } #endif -void mp_hal_stdout_tx_strn(const char *str, uint32_t len) { - mp_os_dupterm_tx_strn(str, len); +mp_uint_t mp_hal_stdout_tx_strn(const char *str, uint32_t len) { + int dupterm_res = mp_os_dupterm_tx_strn(str, len); + if (dupterm_res < 0) { + // no outputs, nothing was written + return 0; + } else { + return dupterm_res; + } } void mp_hal_debug_tx_strn_cooked(void *env, const char *str, uint32_t len) { diff --git a/ports/mimxrt/mphalport.c b/ports/mimxrt/mphalport.c index 2114baaae..be4b1d8b5 100644 --- a/ports/mimxrt/mphalport.c +++ b/ports/mimxrt/mphalport.c @@ -112,9 +112,12 @@ int mp_hal_stdin_rx_chr(void) { } } -void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) { +mp_uint_t mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) { + mp_uint_t ret = len; + bool did_write = false; if (tud_cdc_connected()) { - for (size_t i = 0; i < len;) { + size_t i = 0; + while (i < len) { uint32_t n = len - i; if (n > CFG_TUD_CDC_EP_BUFSIZE) { n = CFG_TUD_CDC_EP_BUFSIZE; @@ -125,6 +128,7 @@ void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) { MICROPY_EVENT_POLL_HOOK } if (ticks_us64() >= timeout) { + ret = i; break; } @@ -132,10 +136,17 @@ void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) { tud_cdc_write_flush(); i += n2; } + did_write = true; + ret = MIN(i, ret); } #if MICROPY_PY_OS_DUPTERM - mp_os_dupterm_tx_strn(str, len); + int dupterm_res = mp_os_dupterm_tx_strn(str, len); + if (dupterm_res >= 0) { + did_write = true; + ret = MIN((mp_uint_t)dupterm_res, ret); + } #endif + return did_write ? ret : 0; } uint64_t mp_hal_time_ns(void) { diff --git a/ports/minimal/uart_core.c b/ports/minimal/uart_core.c index c7af24404..a3dfe697e 100644 --- a/ports/minimal/uart_core.c +++ b/ports/minimal/uart_core.c @@ -29,10 +29,14 @@ int mp_hal_stdin_rx_chr(void) { } // Send string of given length -void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) { +mp_uint_t mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) { + mp_uint_t ret = len; #if MICROPY_MIN_USE_STDOUT int r = write(STDOUT_FILENO, str, len); - (void)r; + if (r >= 0) { + // in case of an error in the syscall, report no bytes written + ret = 0; + } #elif MICROPY_MIN_USE_STM32_MCU while (len--) { // wait for TXE @@ -41,4 +45,5 @@ void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) { USART1->DR = *str++; } #endif + return ret; } diff --git a/ports/nrf/drivers/bluetooth/ble_uart.c b/ports/nrf/drivers/bluetooth/ble_uart.c index 320657370..4ea811572 100644 --- a/ports/nrf/drivers/bluetooth/ble_uart.c +++ b/ports/nrf/drivers/bluetooth/ble_uart.c @@ -110,10 +110,11 @@ int mp_hal_stdin_rx_chr(void) { return (int)byte; } -void mp_hal_stdout_tx_strn(const char *str, size_t len) { +mp_uint_t mp_hal_stdout_tx_strn(const char *str, size_t len) { // Not connected: drop output - if (!ble_uart_enabled()) return; + if (!ble_uart_enabled()) return 0; + mp_uint_t ret = len; uint8_t *buf = (uint8_t *)str; size_t send_len; @@ -134,6 +135,7 @@ void mp_hal_stdout_tx_strn(const char *str, size_t len) { len -= send_len; buf += send_len; } + return ret; } void ble_uart_tx_char(char c) { diff --git a/ports/nrf/drivers/usb/usb_cdc.c b/ports/nrf/drivers/usb/usb_cdc.c index e33a42548..3ca2acbf3 100644 --- a/ports/nrf/drivers/usb/usb_cdc.c +++ b/ports/nrf/drivers/usb/usb_cdc.c @@ -231,12 +231,12 @@ int mp_hal_stdin_rx_chr(void) { return 0; } -void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) { - +mp_uint_t mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) { for (const char *top = str + len; str < top; str++) { ringbuf_put((ringbuf_t*)&tx_ringbuf, *str); usb_cdc_loop(); } + return len; } void mp_hal_stdout_tx_strn_cooked(const char *str, mp_uint_t len) { diff --git a/ports/nrf/mphalport.c b/ports/nrf/mphalport.c index f6c934a8b..c964a26c2 100644 --- a/ports/nrf/mphalport.c +++ b/ports/nrf/mphalport.c @@ -196,10 +196,12 @@ int mp_hal_stdin_rx_chr(void) { return 0; } -void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) { +mp_uint_t mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) { if (MP_STATE_VM(dupterm_objs[0]) != MP_OBJ_NULL) { uart_tx_strn(MP_STATE_VM(dupterm_objs[0]), str, len); + return len; } + return 0; } void mp_hal_stdout_tx_strn_cooked(const char *str, mp_uint_t len) { diff --git a/ports/pic16bit/pic16bit_mphal.c b/ports/pic16bit/pic16bit_mphal.c index b2c80ba1b..f58abf783 100644 --- a/ports/pic16bit/pic16bit_mphal.c +++ b/ports/pic16bit/pic16bit_mphal.c @@ -75,10 +75,12 @@ void mp_hal_stdout_tx_str(const char *str) { mp_hal_stdout_tx_strn(str, strlen(str)); } -void mp_hal_stdout_tx_strn(const char *str, size_t len) { +mp_uint_t mp_hal_stdout_tx_strn(const char *str, size_t len) { + mp_uint_t ret = len; for (; len > 0; --len) { uart_tx_char(*str++); } + return ret; } void mp_hal_stdout_tx_strn_cooked(const char *str, size_t len) { diff --git a/ports/powerpc/uart_lpc_serial.c b/ports/powerpc/uart_lpc_serial.c index 760615041..405bf2d1e 100644 --- a/ports/powerpc/uart_lpc_serial.c +++ b/ports/powerpc/uart_lpc_serial.c @@ -108,7 +108,7 @@ int mp_hal_stdin_rx_chr(void) { } -void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) { +mp_uint_t mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) { int i; for (i = 0; i < len; i++) { while (lpc_uart_tx_full()) { @@ -116,4 +116,5 @@ void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) { } lpc_uart_reg_write(REG_RBR, str[i]); } + return len; } diff --git a/ports/powerpc/uart_potato.c b/ports/powerpc/uart_potato.c index 29f21934d..089e4e2be 100644 --- a/ports/powerpc/uart_potato.c +++ b/ports/powerpc/uart_potato.c @@ -118,7 +118,7 @@ int mp_hal_stdin_rx_chr(void) { return (char)(val & 0x000000ff); } -void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) { +mp_uint_t mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) { int i; for (i = 0; i < len; i++) { @@ -129,4 +129,5 @@ void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) { } potato_uart_reg_write(POTATO_CONSOLE_TX, val); } + return len; } diff --git a/ports/renesas-ra/mphalport.c b/ports/renesas-ra/mphalport.c index 91705129c..8a8bfd8dc 100644 --- a/ports/renesas-ra/mphalport.c +++ b/ports/renesas-ra/mphalport.c @@ -154,16 +154,20 @@ int mp_hal_stdin_rx_chr(void) { } // Send string of given length -void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) { +mp_uint_t mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) { + mp_uint_t ret = len; + bool did_write = false; #if MICROPY_HW_ENABLE_UART_REPL if (MP_STATE_PORT(pyb_stdio_uart) != NULL) { uart_tx_strn(MP_STATE_PORT(pyb_stdio_uart), str, len); + did_write = true; } #endif #if MICROPY_HW_USB_CDC if (tud_cdc_connected()) { - for (size_t i = 0; i < len;) { + size_t i = 0; + while (i < len) { uint32_t n = len - i; if (n > CFG_TUD_CDC_EP_BUFSIZE) { n = CFG_TUD_CDC_EP_BUFSIZE; @@ -180,12 +184,20 @@ void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) { tud_cdc_write_flush(); i += n2; } + ret = MIN(i, ret); + did_write = true; } #endif #if MICROPY_PY_OS_DUPTERM - mp_os_dupterm_tx_strn(str, len); + int dupterm_res = mp_os_dupterm_tx_strn(str, len); + if (dupterm_res >= 0) { + did_write = true; + ret = MIN((mp_uint_t)dupterm_res, ret); + } #endif + + return did_write ? ret : 0; } void mp_hal_ticks_cpu_enable(void) { diff --git a/ports/rp2/mphalport.c b/ports/rp2/mphalport.c index 1c784fd73..c5ae221e9 100644 --- a/ports/rp2/mphalport.c +++ b/ports/rp2/mphalport.c @@ -151,14 +151,18 @@ int mp_hal_stdin_rx_chr(void) { } // Send string of given length -void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) { +mp_uint_t mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) { + mp_uint_t ret = len; + bool did_write = false; #if MICROPY_HW_ENABLE_UART_REPL mp_uart_write_strn(str, len); + did_write = true; #endif #if MICROPY_HW_USB_CDC if (tud_cdc_connected()) { - for (size_t i = 0; i < len;) { + size_t i = 0; + while (i < len) { uint32_t n = len - i; if (n > CFG_TUD_CDC_EP_BUFSIZE) { n = CFG_TUD_CDC_EP_BUFSIZE; @@ -173,18 +177,26 @@ void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) { mp_usbd_task(); } if (timeout >= MICROPY_HW_USB_CDC_TX_TIMEOUT) { + ret = i; break; } uint32_t n2 = tud_cdc_write(str + i, n); tud_cdc_write_flush(); i += n2; } + ret = MIN(i, ret); + did_write = true; } #endif #if MICROPY_PY_OS_DUPTERM - mp_os_dupterm_tx_strn(str, len); + int dupterm_res = mp_os_dupterm_tx_strn(str, len); + if (dupterm_res >= 0) { + did_write = true; + ret = MIN((mp_uint_t)dupterm_res, ret); + } #endif + return did_write ? ret : 0; } void mp_hal_delay_ms(mp_uint_t ms) { diff --git a/ports/samd/mphalport.c b/ports/samd/mphalport.c index 3c803403f..de1650c99 100644 --- a/ports/samd/mphalport.c +++ b/ports/samd/mphalport.c @@ -200,9 +200,12 @@ int mp_hal_stdin_rx_chr(void) { } } -void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) { +mp_uint_t mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) { + mp_uint_t ret = len; + bool did_write = false; if (tud_cdc_connected()) { - for (size_t i = 0; i < len;) { + size_t i = 0; + while (i < len) { uint32_t n = len - i; if (n > CFG_TUD_CDC_EP_BUFSIZE) { n = CFG_TUD_CDC_EP_BUFSIZE; @@ -213,14 +216,22 @@ void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) { MICROPY_EVENT_POLL_HOOK_WITH_USB; } if (timeout >= MICROPY_HW_USB_CDC_TX_TIMEOUT) { + ret = i; break; } uint32_t n2 = tud_cdc_write(str + i, n); tud_cdc_write_flush(); i += n2; } + ret = MIN(i, ret); + did_write = true; } #if MICROPY_PY_OS_DUPTERM - mp_os_dupterm_tx_strn(str, len); + int dupterm_res = mp_os_dupterm_tx_strn(str, len); + if (dupterm_res >= 0) { + did_write = true; + ret = MIN((mp_uint_t)dupterm_res, ret); + } #endif + return did_write ? ret : 0; } diff --git a/ports/stm32/mphalport.c b/ports/stm32/mphalport.c index f8a5d66fc..dfd50cebd 100644 --- a/ports/stm32/mphalport.c +++ b/ports/stm32/mphalport.c @@ -57,14 +57,22 @@ MP_WEAK int mp_hal_stdin_rx_chr(void) { } } -MP_WEAK void mp_hal_stdout_tx_strn(const char *str, size_t len) { +MP_WEAK mp_uint_t mp_hal_stdout_tx_strn(const char *str, size_t len) { + mp_uint_t ret = len; + bool did_write = false; if (MP_STATE_PORT(pyb_stdio_uart) != NULL) { uart_tx_strn(MP_STATE_PORT(pyb_stdio_uart), str, len); + did_write = true; } #if 0 && defined(USE_HOST_MODE) && MICROPY_HW_HAS_LCD lcd_print_strn(str, len); #endif - mp_os_dupterm_tx_strn(str, len); + int dupterm_res = mp_os_dupterm_tx_strn(str, len); + if (dupterm_res >= 0) { + did_write = true; + ret = MIN((mp_uint_t)dupterm_res, ret); + } + return did_write ? ret : 0; } #if __CORTEX_M >= 0x03 diff --git a/ports/unix/unix_mphal.c b/ports/unix/unix_mphal.c index 8d6539c88..24c0fa3cd 100644 --- a/ports/unix/unix_mphal.c +++ b/ports/unix/unix_mphal.c @@ -184,10 +184,15 @@ main_term:; return c; } -void mp_hal_stdout_tx_strn(const char *str, size_t len) { +mp_uint_t mp_hal_stdout_tx_strn(const char *str, size_t len) { ssize_t ret; MP_HAL_RETRY_SYSCALL(ret, write(STDOUT_FILENO, str, len), {}); - mp_os_dupterm_tx_strn(str, len); + mp_uint_t written = ret < 0 ? 0 : ret; + int dupterm_res = mp_os_dupterm_tx_strn(str, len); + if (dupterm_res >= 0) { + written = MIN((mp_uint_t)dupterm_res, written); + } + return written; } // cooked is same as uncooked because the terminal does some postprocessing diff --git a/ports/webassembly/mphalport.c b/ports/webassembly/mphalport.c index c938a6392..f91a50901 100644 --- a/ports/webassembly/mphalport.c +++ b/ports/webassembly/mphalport.c @@ -27,8 +27,9 @@ #include "library.h" #include "mphalport.h" -void mp_hal_stdout_tx_strn(const char *str, size_t len) { +mp_uint_t mp_hal_stdout_tx_strn(const char *str, size_t len) { mp_js_write(str, len); + return len; } void mp_hal_delay_ms(mp_uint_t ms) { diff --git a/ports/webassembly/mphalport.h b/ports/webassembly/mphalport.h index 89efee697..1b3179698 100644 --- a/ports/webassembly/mphalport.h +++ b/ports/webassembly/mphalport.h @@ -28,7 +28,7 @@ #include "shared/runtime/interrupt_char.h" #define mp_hal_stdin_rx_chr() (0) -void mp_hal_stdout_tx_strn(const char *str, size_t len); +mp_uint_t mp_hal_stdout_tx_strn(const char *str, size_t len); void mp_hal_delay_ms(mp_uint_t ms); void mp_hal_delay_us(mp_uint_t us); diff --git a/ports/windows/windows_mphal.c b/ports/windows/windows_mphal.c index d1bbb931a..f88491707 100644 --- a/ports/windows/windows_mphal.c +++ b/ports/windows/windows_mphal.c @@ -221,10 +221,11 @@ int mp_hal_stdin_rx_chr(void) { } } -void mp_hal_stdout_tx_strn(const char *str, size_t len) { +mp_uint_t mp_hal_stdout_tx_strn(const char *str, size_t len) { MP_THREAD_GIL_EXIT(); - write(STDOUT_FILENO, str, len); + int ret = write(STDOUT_FILENO, str, len); MP_THREAD_GIL_ENTER(); + return ret < 0 ? 0 : ret; // return the number of bytes written, so in case of an error in the syscall, return 0 } void mp_hal_stdout_tx_strn_cooked(const char *str, size_t len) { diff --git a/ports/zephyr/uart_core.c b/ports/zephyr/uart_core.c index 1d37f2209..3f70cc0a1 100644 --- a/ports/zephyr/uart_core.c +++ b/ports/zephyr/uart_core.c @@ -44,7 +44,8 @@ int mp_hal_stdin_rx_chr(void) { } // Send string of given length -void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) { +mp_uint_t mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) { + mp_uint_t ret = len; #ifdef CONFIG_CONSOLE_SUBSYS while (len--) { char c = *str++; @@ -60,4 +61,5 @@ void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) { uart_poll_out(uart_console_dev, *str++); } #endif + return ret; } diff --git a/py/mphal.h b/py/mphal.h index 81cf50918..a4f222d0b 100644 --- a/py/mphal.h +++ b/py/mphal.h @@ -56,7 +56,7 @@ void mp_hal_stdout_tx_str(const char *str); #endif #ifndef mp_hal_stdout_tx_strn -void mp_hal_stdout_tx_strn(const char *str, size_t len); +mp_uint_t mp_hal_stdout_tx_strn(const char *str, size_t len); #endif #ifndef mp_hal_stdout_tx_strn_cooked diff --git a/shared/runtime/sys_stdio_mphal.c b/shared/runtime/sys_stdio_mphal.c index 84ce5828e..b7a35a5cb 100644 --- a/shared/runtime/sys_stdio_mphal.c +++ b/shared/runtime/sys_stdio_mphal.c @@ -142,8 +142,7 @@ STATIC mp_uint_t stdio_buffer_read(mp_obj_t self_in, void *buf, mp_uint_t size, } STATIC mp_uint_t stdio_buffer_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode) { - mp_hal_stdout_tx_strn(buf, size); - return size; + return mp_hal_stdout_tx_strn(buf, size); } STATIC const mp_stream_p_t stdio_buffer_obj_stream_p = {