From d797c990d6d3b1e16474eac2ca400a775b19ebef Mon Sep 17 00:00:00 2001 From: Jim Paris Date: Mon, 31 Aug 2020 16:18:35 -0400 Subject: [PATCH] sys/stdio_uart: add stdio_uart_onlcr (pseudo-) module Add USE_MODULE += "stdio_uart_onlcr" to enable it. This is named after the "onlcr" stty flag, which does the same thing. Co-authored-by: Marian Buschsieweke --- makefiles/pseudomodules.inc.mk | 9 ++++++++- sys/Kconfig.stdio | 4 ++++ sys/include/stdio_uart.h | 25 +++++++++++++++++++++++++ sys/stdio_uart/stdio_uart.c | 28 +++++++++++++++++++++++++--- 4 files changed, 62 insertions(+), 4 deletions(-) diff --git a/makefiles/pseudomodules.inc.mk b/makefiles/pseudomodules.inc.mk index 64712a5f414e..69e24d96b43f 100644 --- a/makefiles/pseudomodules.inc.mk +++ b/makefiles/pseudomodules.inc.mk @@ -371,8 +371,15 @@ PSEUDOMODULES += stdio_available PSEUDOMODULES += stdio_cdc_acm PSEUDOMODULES += stdio_ethos PSEUDOMODULES += stdio_nimble_debug -PSEUDOMODULES += stdio_uart_rx PSEUDOMODULES += stdio_telnet +## @defgroup sys_stdio_uart_onlcr Support for DOS line endings in STDIO-UART +## @ingroup sys_stdio_uart +## @{ +## Enable this (pseudo-) module to emit DOS style line endings (`\r\n`) instead +## of UNIX style line endings (`\n`) via STDIO over UART. +PSEUDOMODULES += stdio_uart_onlcr +## @} +PSEUDOMODULES += stdio_uart_rx PSEUDOMODULES += stm32_eth PSEUDOMODULES += stm32_eth_auto PSEUDOMODULES += stm32_eth_link_up diff --git a/sys/Kconfig.stdio b/sys/Kconfig.stdio index 684a24e97518..7506943dda4a 100644 --- a/sys/Kconfig.stdio +++ b/sys/Kconfig.stdio @@ -34,6 +34,10 @@ config MODULE_STDIO_UART depends on HAS_PERIPH_UART select MODULE_PERIPH_UART +config MODULE_STDIO_UART_ONLCR + bool "Emit DOS line endings for STDIO output via UART" + depends on MODULE_STDIO_UART + config MODULE_STDIO_NATIVE bool "Native" depends on CPU_ARCH_NATIVE diff --git a/sys/include/stdio_uart.h b/sys/include/stdio_uart.h index 66238351e6e4..d695a76686c6 100644 --- a/sys/include/stdio_uart.h +++ b/sys/include/stdio_uart.h @@ -13,12 +13,37 @@ * * @brief Standard input/output backend using UART * + * ## Input + * * @warning Standard input is disabled by default on UART. To enable it, load * the `stdin` module in your application: * ``` * USEMODULE += stdin * ``` * + * ## UART Configuration + * + * @note Running `make BOARD= term` will launch `pyterm` with the + * correct parameters, so mostly you do not really need to care about + * the UART configuration. + * + * By convention RIOT boards used 8N1 encoding with a symbol rate of 115200 Bd + * for the UART used as stdio. However, some boards may have a different + * configuration due to hardware limitations. Most notably, many AVR boards use + * 9600 Bd as symbol rate instead, as they otherwise frequently loose an input + * character due to losing interrupts. + * + * By default UNIX style line endings (`\n`) are used. However, some terminal + * programs default to DOS style line endings (`\r\n`). It usually is better to + * configure the terminal program on the host to use UNIX style line endings. + * In scenarios this is not possible/desired, you can enable the (pseudo-) + * module @ref sys_stdio_uart_onlcr to emit DOS style line endings instead. + * + * RIOT's shell happily accepts both DOS and UNIX style line endings in any + * case, so typically no line ending conversion is needed on the input. + * + * ## STDIO from ISR + * * @attention Using STDIO over UART from interrupt context should be avoided, * except for debugging purposes * diff --git a/sys/stdio_uart/stdio_uart.c b/sys/stdio_uart/stdio_uart.c index be6cd8e9b75b..07c12a34f39f 100644 --- a/sys/stdio_uart/stdio_uart.c +++ b/sys/stdio_uart/stdio_uart.c @@ -28,6 +28,7 @@ */ #include +#include #include "stdio_uart.h" @@ -85,8 +86,29 @@ ssize_t stdio_read(void* buffer, size_t count) #endif } -ssize_t stdio_write(const void* buffer, size_t len) +ssize_t stdio_write(const void *buffer, size_t len) { - uart_write(STDIO_UART_DEV, (const uint8_t *)buffer, len); - return len; + ssize_t result = len; + if (IS_USED(MODULE_STDIO_UART_ONLCR)) { + static const uint8_t crlf[2] = { (uint8_t)'\r', (uint8_t)'\n' }; + const uint8_t *buf = buffer; + while (len) { + const uint8_t *pos = memchr(buf, '\n', len); + size_t chunk_len = (pos != NULL) + ? (uintptr_t)pos - (uintptr_t)buf + : len; + uart_write(STDIO_UART_DEV, buf, chunk_len); + buf += chunk_len; + len -= chunk_len; + if (len) { + uart_write(STDIO_UART_DEV, crlf, sizeof(crlf)); + buf++; + len--; + } + } + } + else { + uart_write(STDIO_UART_DEV, (const uint8_t *)buffer, len); + } + return result; }