From d2e5eeb51d3364585c2fec13d5f44784e06da53e Mon Sep 17 00:00:00 2001 From: Robert Hancock Date: Wed, 7 Feb 2024 12:16:31 -0600 Subject: [PATCH] shell: backends: uart: avoid unnecessary TX IRQs The shell UART TX code would only disable the TX IRQ when no data was available in the TX ring buffer. However, it should also disable the IRQ when all data retrieved from the buffer has been written. Otherwise it will just result in another immediate TX IRQ which results in the IRQ finally being disabled. For this to work, since ring_buf_get_claim may not always return all available data in the ring buffer on a single call, we need to loop until either no data is left in the ring buffer or the UART was unable to consume any of the data. Signed-off-by: Robert Hancock --- subsys/shell/backends/shell_uart.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/subsys/shell/backends/shell_uart.c b/subsys/shell/backends/shell_uart.c index e80317664b9..5384977b614 100644 --- a/subsys/shell/backends/shell_uart.c +++ b/subsys/shell/backends/shell_uart.c @@ -166,7 +166,8 @@ static void dtr_timer_handler(struct k_timer *timer) static void uart_tx_handle(const struct device *dev, struct shell_uart_int_driven *sh_uart) { - uint32_t len; + uint32_t avail; + uint32_t written; const uint8_t *data; if (!uart_dtr_check(dev)) { @@ -176,16 +177,22 @@ static void uart_tx_handle(const struct device *dev, struct shell_uart_int_drive return; } - len = ring_buf_get_claim(&sh_uart->tx_ringbuf, (uint8_t **)&data, - sh_uart->tx_ringbuf.size); - if (len) { - int err; + do { + avail = ring_buf_get_claim(&sh_uart->tx_ringbuf, (uint8_t **)&data, + sh_uart->tx_ringbuf.size); + if (avail) { + int err; - len = uart_fifo_fill(dev, data, len); - err = ring_buf_get_finish(&sh_uart->tx_ringbuf, len); - __ASSERT_NO_MSG(err == 0); - ARG_UNUSED(err); - } else { + written = uart_fifo_fill(dev, data, avail); + err = ring_buf_get_finish(&sh_uart->tx_ringbuf, written); + __ASSERT_NO_MSG(err == 0); + ARG_UNUSED(err); + } else { + written = 0; + } + } while (avail && written); + + if (avail == 0) { uart_irq_tx_disable(dev); sh_uart->tx_busy = 0; }