diff --git a/ports/zephyr-cp/common-hal/busio/UART.c b/ports/zephyr-cp/common-hal/busio/UART.c index 97ab44bb8c1..d7b1678bd9b 100644 --- a/ports/zephyr-cp/common-hal/busio/UART.c +++ b/ports/zephyr-cp/common-hal/busio/UART.c @@ -254,20 +254,28 @@ void common_hal_busio_uart_set_baudrate(busio_uart_obj_t *self, uint32_t baudrat uart_configure(self->uart_device, &config); } +// K_FOREVER reads as -1, which usb_cdc reports as None. +static mp_float_t timeout_to_seconds(k_timeout_t timeout) { + if (K_TIMEOUT_EQ(timeout, K_FOREVER)) { + return -1; + } + return (mp_float_t)k_ticks_to_us_floor64(timeout.ticks) / MICROPY_FLOAT_CONST(1000000.0); +} + mp_float_t common_hal_busio_uart_get_timeout(busio_uart_obj_t *self) { - return (mp_float_t)self->timeout.ticks / 1000000.0; + return timeout_to_seconds(self->timeout); } void common_hal_busio_uart_set_timeout(busio_uart_obj_t *self, mp_float_t timeout) { - self->timeout = K_USEC((uint64_t)(timeout * 1000000)); + self->timeout = timeout < 0 ? K_FOREVER : K_USEC((uint64_t)(timeout * 1000000)); } mp_float_t common_hal_busio_uart_get_write_timeout(busio_uart_obj_t *self) { - return (mp_float_t)self->write_timeout.ticks / 1000000.0; + return timeout_to_seconds(self->write_timeout); } void common_hal_busio_uart_set_write_timeout(busio_uart_obj_t *self, mp_float_t write_timeout) { - self->write_timeout = K_USEC((uint64_t)(write_timeout * 1000000)); + self->write_timeout = write_timeout < 0 ? K_FOREVER : K_USEC((uint64_t)(write_timeout * 1000000)); } uint32_t common_hal_busio_uart_rx_characters_available(busio_uart_obj_t *self) { diff --git a/ports/zephyr-cp/tests/test_busio_uart.py b/ports/zephyr-cp/tests/test_busio_uart.py new file mode 100644 index 00000000000..9d5a044e3ba --- /dev/null +++ b/ports/zephyr-cp/tests/test_busio_uart.py @@ -0,0 +1,28 @@ +# SPDX-FileCopyrightText: 2026 Mikey Sklar for Adafruit Industries +# SPDX-License-Identifier: MIT + +"""busio.UART on native_sim, through the console UART.""" + +import pytest + +TIMEOUT_CODE = """\ +import board + +uart = board.UART0() +for t in (0.5, 2, 0): + uart.timeout = t + print("timeout", uart.timeout) +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": TIMEOUT_CODE}) +def test_uart_timeout_reads_back_in_seconds(circuitpython): + """timeout reads back the seconds it was set to, not raw kernel ticks.""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert "timeout 0.5" in output + assert "timeout 2.0" in output + assert "timeout 0.0" in output + assert "done" in output