From e9f238889b1a30ae5ccb0702c55445f74c1a6e3b Mon Sep 17 00:00:00 2001 From: Kamil Kasperczyk Date: Wed, 1 Sep 2021 12:46:48 +0200 Subject: [PATCH] shell: uart: Add waiting on DTR signal before sending data Problem: In some cases, as described in: https://github.com/zephyrproject-rtos/zephyr/issues/36948 shell backend sends characters to output before serial device is ready for it. It results in observing additional characters inserted on the shell input after device boot. Solution: Added waiting on DTR signal before sending anything to the output. Fixes: #36948 Signed-off-by: Kamil Kasperczyk --- subsys/shell/Kconfig.backends | 7 +++++++ subsys/shell/shell_uart.c | 21 +++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/subsys/shell/Kconfig.backends b/subsys/shell/Kconfig.backends index ceef58f3612..5f4b4f6cc91 100644 --- a/subsys/shell/Kconfig.backends +++ b/subsys/shell/Kconfig.backends @@ -71,6 +71,13 @@ config SHELL_BACKEND_SERIAL_RX_POLL_PERIOD help Determines how often UART is polled for RX byte. +config SHELL_BACKEND_SERIAL_CHECK_DTR + bool "Check DTR signal before TX" + default y if USB_UART_CONSOLE + depends on UART_LINE_CTRL + help + Check DTR signal before TX. + module = SHELL_BACKEND_SERIAL default-timeout = 100 source "subsys/shell/Kconfig.template.shell_log_queue_timeout" diff --git a/subsys/shell/shell_uart.c b/subsys/shell/shell_uart.c index 9945b283a2b..64b53e29fc7 100644 --- a/subsys/shell/shell_uart.c +++ b/subsys/shell/shell_uart.c @@ -101,6 +101,25 @@ static void uart_rx_handle(const struct device *dev, } } +static void uart_dtr_wait(const struct device *dev) +{ + if (IS_ENABLED(CONFIG_SHELL_BACKEND_SERIAL_CHECK_DTR)) { + int dtr, err; + + while (true) { + err = uart_line_ctrl_get(dev, UART_LINE_CTRL_DTR, &dtr); + if (err == -ENOSYS || err == -ENOTSUP) { + break; + } + if (dtr) { + break; + } + /* Give CPU resources to low priority threads. */ + k_sleep(K_MSEC(100)); + } + } +} + static void uart_tx_handle(const struct device *dev, const struct shell_uart *sh_uart) { @@ -111,6 +130,8 @@ static void uart_tx_handle(const struct device *dev, len = ring_buf_get_claim(sh_uart->tx_ringbuf, (uint8_t **)&data, sh_uart->tx_ringbuf->size); if (len) { + /* Wait for DTR signal before sending anything to output. */ + uart_dtr_wait(dev); len = uart_fifo_fill(dev, data, len); err = ring_buf_get_finish(sh_uart->tx_ringbuf, len); __ASSERT_NO_MSG(err == 0);