From 79b2d4ff222636075a9b6530e1694fa277132106 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 17 Jul 2025 16:49:26 +1000 Subject: [PATCH] esp32/machine_uart: Improve sendbreak so it doesn't reconfig the UART. Currently, `UART.sendbreak()` on esp32 will reconfigure the UART to a slower baudrate and send out a null byte, to synthesise a break condition. That's not great because it changes the baudrate of the RX path as well, which could miss incoming bytes while sending the break. This commit changes the sendbreak implementation to just reconfigure the TX pin as GPIO in output mode, and hold the pin low for the required duration. Signed-off-by: Damien George --- ports/esp32/machine_uart.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/ports/esp32/machine_uart.c b/ports/esp32/machine_uart.c index 982d9a7e27..661c07138e 100644 --- a/ports/esp32/machine_uart.c +++ b/ports/esp32/machine_uart.c @@ -508,20 +508,21 @@ static bool mp_machine_uart_txdone(machine_uart_obj_t *self) { } static void mp_machine_uart_sendbreak(machine_uart_obj_t *self) { - // Save settings + // Calculate the length of the break, as 13 bits. uint32_t baudrate; check_esp_err(uart_get_baudrate(self->uart_num, &baudrate)); + uint32_t break_delay_us = 13000000 / baudrate; - // Synthesise the break condition by reducing the baud rate, - // and cater for the worst case of 5 data bits, no parity. - check_esp_err(uart_wait_tx_done(self->uart_num, pdMS_TO_TICKS(1000))); - check_esp_err(uart_set_baudrate(self->uart_num, baudrate * 6 / 15)); - char buf[1] = {0}; - uart_write_bytes(self->uart_num, buf, 1); + // Wait for any outstanding data to be transmitted. check_esp_err(uart_wait_tx_done(self->uart_num, pdMS_TO_TICKS(1000))); - // Restore original setting - check_esp_err(uart_set_baudrate(self->uart_num, baudrate)); + // Set the TX pin to output, pull it low, and wait for the break period. + mp_hal_pin_output(self->tx); + mp_hal_pin_write(self->tx, 0); + mp_hal_delay_us(break_delay_us); + + // Restore original UART pin settings. + check_esp_err(uart_set_pin(self->uart_num, self->tx, self->rx, self->rts, self->cts)); } // Configure the timer used for IRQ_RXIDLE