diff --git a/docs/library/machine.UART.rst b/docs/library/machine.UART.rst index c3eca8f55a..072bdb7188 100644 --- a/docs/library/machine.UART.rst +++ b/docs/library/machine.UART.rst @@ -188,7 +188,7 @@ Methods For the rp2, esp8266 and nrf ports the call returns while the last byte is sent. If required, a one character wait time has to be added in the calling script. - Availability: rp2, esp32, esp8266, mimxrt, cc3200, stm32, nrf ports + Availability: rp2, esp32, esp8266, mimxrt, cc3200, stm32, nrf ports, renesas-ra .. method:: UART.txdone() @@ -201,7 +201,7 @@ Methods of a transfer is still being sent. If required, a one character wait time has to be added in the calling script. - Availability: rp2, esp32, esp8266, mimxrt, cc3200, stm32, nrf ports + Availability: rp2, esp32, esp8266, mimxrt, cc3200, stm32, nrf ports, renesas-ra Constants --------- diff --git a/ports/renesas-ra/machine_uart.c b/ports/renesas-ra/machine_uart.c index 86505ea0b9..f365223afa 100644 --- a/ports/renesas-ra/machine_uart.c +++ b/ports/renesas-ra/machine_uart.c @@ -409,6 +409,14 @@ STATIC mp_obj_t machine_uart_sendbreak(mp_obj_t self_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_sendbreak_obj, machine_uart_sendbreak); +// \method uart.txdone() +// Return `True` if all characters have been sent. +STATIC mp_obj_t machine_uart_txdone(mp_obj_t self_in) { + machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); + return uart_tx_busy(self) ? mp_const_false : mp_const_true; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_txdone_obj, machine_uart_txdone); + // irq(handler, trigger, hard) STATIC mp_obj_t machine_uart_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { mp_arg_val_t args[MP_IRQ_ARG_INIT_NUM_ARGS]; @@ -452,6 +460,8 @@ STATIC const mp_rom_map_elem_t machine_uart_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_uart_init_obj) }, { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_uart_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR_any), MP_ROM_PTR(&machine_uart_any_obj) }, + { MP_ROM_QSTR(MP_QSTR_txdone), MP_ROM_PTR(&machine_uart_txdone_obj) }, + { MP_ROM_QSTR(MP_QSTR_flush), MP_ROM_PTR(&mp_stream_flush_obj) }, /// \method read([nbytes]) { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, @@ -557,6 +567,19 @@ STATIC mp_uint_t machine_uart_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr if ((flags & MP_STREAM_POLL_WR) && uart_tx_avail(self)) { ret |= MP_STREAM_POLL_WR; } + } else if (request == MP_STREAM_FLUSH) { + // The timeout is estimated using the buffer size and the baudrate. + // Take the worst case assumptions at 13 bit symbol size times 2. + uint32_t timeout = mp_hal_ticks_ms() + + (uint32_t)(uart_tx_txbuf(self)) * 13000ll * 2 / self->baudrate; + do { + if (!uart_tx_busy(self)) { + return 0; + } + MICROPY_EVENT_POLL_HOOK + } while (mp_hal_ticks_ms() < timeout); + *errcode = MP_ETIMEDOUT; + ret = MP_STREAM_ERROR; } else { *errcode = MP_EINVAL; ret = MP_STREAM_ERROR; diff --git a/ports/renesas-ra/ra/ra_sci.c b/ports/renesas-ra/ra/ra_sci.c index 2e7c81c4ac..3f8bf24444 100644 --- a/ports/renesas-ra/ra/ra_sci.c +++ b/ports/renesas-ra/ra/ra_sci.c @@ -1026,6 +1026,16 @@ int ra_sci_tx_wait(uint32_t ch) { return (int)(tx_fifo[idx].len != (tx_fifo[idx].size - 1)); } +int ra_sci_tx_busy(uint32_t ch) { + uint32_t idx = ch_to_idx[ch]; + return (int)(tx_fifo[idx].busy); +} + +int ra_sci_tx_bufsize(uint32_t ch) { + uint32_t idx = ch_to_idx[ch]; + return (int)(tx_fifo[idx].size - 1); +} + void ra_sci_tx_break(uint32_t ch) { uint32_t idx = ch_to_idx[ch]; R_SCI0_Type *sci_reg = sci_regs[idx]; diff --git a/ports/renesas-ra/ra/ra_sci.h b/ports/renesas-ra/ra/ra_sci.h index 0a672f3672..87e4154e8e 100644 --- a/ports/renesas-ra/ra/ra_sci.h +++ b/ports/renesas-ra/ra/ra_sci.h @@ -52,6 +52,8 @@ bool ra_sci_is_rxirq_enable(uint32_t ch); void ra_sci_isr_te(uint32_t ch); int ra_sci_rx_ch(uint32_t ch); int ra_sci_rx_any(uint32_t ch); +int ra_sci_tx_busy(uint32_t ch); +int ra_sci_tx_bufsize(uint32_t ch); void ra_sci_tx_ch(uint32_t ch, int c); int ra_sci_tx_wait(uint32_t ch); void ra_sci_tx_break(uint32_t ch); diff --git a/ports/renesas-ra/uart.c b/ports/renesas-ra/uart.c index 0e2e9004cd..e41c68f0c4 100644 --- a/ports/renesas-ra/uart.c +++ b/ports/renesas-ra/uart.c @@ -420,6 +420,16 @@ mp_uint_t uart_tx_avail(machine_uart_obj_t *self) { return ra_sci_tx_wait(ch); } +mp_uint_t uart_tx_busy(machine_uart_obj_t *self) { + int ch = (int)self->uart_id; + return ra_sci_tx_busy(ch); +} + +mp_uint_t uart_tx_txbuf(machine_uart_obj_t *self) { + int ch = (int)self->uart_id; + return ra_sci_tx_bufsize(ch); +} + // Waits at most timeout milliseconds for at least 1 char to become ready for // reading (from buf or for direct reading). // Returns true if something available, false if not. diff --git a/ports/renesas-ra/uart.h b/ports/renesas-ra/uart.h index 9c7aea737d..245be24d1a 100644 --- a/ports/renesas-ra/uart.h +++ b/ports/renesas-ra/uart.h @@ -106,6 +106,8 @@ void uart_attach_to_repl(machine_uart_obj_t *self, bool attached); uint32_t uart_get_baudrate(machine_uart_obj_t *self); mp_uint_t uart_rx_any(machine_uart_obj_t *uart_obj); mp_uint_t uart_tx_avail(machine_uart_obj_t *uart_obj); +mp_uint_t uart_tx_busy(machine_uart_obj_t *uart_obj); +mp_uint_t uart_tx_txbuf(machine_uart_obj_t *self); bool uart_rx_wait(machine_uart_obj_t *self, uint32_t timeout); int uart_rx_char(machine_uart_obj_t *uart_obj); bool uart_tx_wait(machine_uart_obj_t *self, uint32_t timeout);