Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

stdio_uart: add stdio_uart_onlcr option to convert LF -> CRLF on output #15619

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
stdio_uart: add stdio_uart_onlcr option to convert LF -> CRLF on output
Add USE_MODULE += "stdio_uart_onlcr" to enable it.
This is named after the "onlcr" stty flag, which does the same thing.
  • Loading branch information
jimparis committed Dec 16, 2020
commit 91640724b342a50678c3714fedd2df01de56c3c7
1 change: 1 addition & 0 deletions makefiles/pseudomodules.inc.mk
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ PSEUDOMODULES += soft_uart_modecfg
PSEUDOMODULES += stdin
PSEUDOMODULES += stdio_cdc_acm
PSEUDOMODULES += stdio_ethos
PSEUDOMODULES += stdio_uart_onlcr
PSEUDOMODULES += stdio_uart_rx
PSEUDOMODULES += stm32_eth
PSEUDOMODULES += stm32_eth_auto
Expand Down
12 changes: 12 additions & 0 deletions sys/stdio_uart/stdio_uart.c
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,19 @@ ssize_t stdio_write(const void* buffer, size_t len)
#ifdef MODULE_STDIO_ETHOS
ethos_send_frame(&ethos, (const uint8_t *)buffer, len, ETHOS_FRAME_TYPE_TEXT);
#else
#ifdef MODULE_STDIO_UART_ONLCR
const uint8_t *buf = (const uint8_t *)buffer;
const uint8_t cr = '\r';
size_t rem = len;
while (rem--) {
if (*buf == '\n')
uart_write(STDIO_UART_DEV, &cr, 1);
uart_write(STDIO_UART_DEV, buf, 1);
buf++;
}
#else
uart_write(STDIO_UART_DEV, (const uint8_t *)buffer, len);
#endif
#endif
return len;
Comment on lines +95 to 109
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#ifdef MODULE_STDIO_UART_ONLCR
const uint8_t *buf = (const uint8_t *)buffer;
const uint8_t cr = '\r';
size_t rem = len;
while (rem--) {
if (*buf == '\n')
uart_write(STDIO_UART_DEV, &cr, 1);
uart_write(STDIO_UART_DEV, buf, 1);
buf++;
}
#else
uart_write(STDIO_UART_DEV, (const uint8_t *)buffer, len);
#endif
#endif
return len;
ssize_t result = len;
if (IS_USED(MODULE_STDIO_UART_CRLF)) {
static const uint8_t crlf[2] = { (uint8_t)'\r', (uint8_t)'\n' };
while (len) {
size_t chunk_len = 0;
const uint8_t *buf = buffer;
while ((chunk_len < len) && (buf[chunk_len] != (uint8_t)'\n')) {
chunk_len++;
}
uart_write(STDIO_UART_DEV, buf, chunk_len);
buf += chunk_len;
len -= chunk_len;
if (chunk_len) {
uart_write(STDIO_UART_DEV, crlf, sizeof(crlf));
buf++;
len--;
}
}
}
else {
uart_write(STDIO_UART_DEV, (const uint8_t *)buffer, len);
}
return result;

Three things:

  • The current implementation that writes one char at a time. However, some UART drivers do support DMA. In that case this would keep the CPU busy all the time, while without CRLF conversion the CPU would only need to setup the DMA transfer to the UART peripheral (and like attend to an IRQ once it is done). The suggested change will be more efficient, as it will result in two DMA transfers per line rather than in one DMA transfer per character
  • There is no need for preprocessor conditionals here, you can just use a C level if. That way, the compile tests will check syntactical correctness for both branches. And with any optimization level better than -O0 the compiler will eliminate the dead branch, so that there is no overhead to pay
  • I am personally not super happy with name stdio_uart_onlcr, as it is not immediately clear to me what onlcr stands for. How about something like stdio_uart_crlf instead?

}