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 <robert.hancock@calian.com>
This commit is contained in:
Robert Hancock 2024-02-07 12:16:31 -06:00 committed by Carles Cufí
commit d2e5eeb51d

View file

@ -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,
do {
avail = ring_buf_get_claim(&sh_uart->tx_ringbuf, (uint8_t **)&data,
sh_uart->tx_ringbuf.size);
if (len) {
if (avail) {
int err;
len = uart_fifo_fill(dev, data, len);
err = ring_buf_get_finish(&sh_uart->tx_ringbuf, len);
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;
}