About the puts and LOG_INFO and newlines ... and ESP32?

I’m just validating some build stuff on my laptop, and I built gcoap_dtls example, and then connected to it with screen /dev/ttyUSB0 115200, but also used minicom. {As a total aside, I’d sure like to have a tty console program that knew about flashing, and could be asked to get out of the way for the flashing program to do it’s thing, and then immediately reconnect to see the first boot}

I’m seeing:

rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DOUT, clock div:2
load:0x3fff0030,len:1540
load:0x40078000,len:12788
load:0x40080400,len:2848
entry 0x40080410
Pro cpu up.
Single core mode
Initializing. RAM available for dynamic allocation:
At 3FFAE6E0 len 00001920 (6 KiB): DRAM
At 3FFBCC18 len 000233E8 (140 KiB): DRAM
At 3FFE0440 len 0001FBC0 (126 KiB): D/IRAM
At 40078000 len 00008000 (32 KiB): IRAM
At 4008F820 len 000107E0 (65 KiB): IRAM

main(): This is RIOT! (Version: 2022.10-devel-857-g04b7e)
                                                         gcoap example app
                                                                          All up, running the shell w
                                                                                                     
> 

And what’s annoying me is the lack of a CR after the “This is RIOT”, and the “gcoap example app”

The first line is from core/lib/init.c, line 54: RIOT/init.c at master · RIOT-OS/RIOT · GitHub which CLEARLY has an appended \n.

The other two lines are using puts, and puts is supposed to put a trailing newline too.

So the problem is not the lack of trailing newlines, the problem is that the output driver doesn’t know to put CR in. The shell doesn’t know either. (Yes, I can configure minicom to do the wrong thing with LF, but…)

After some tracing around, i think that the logic is in puts(), which seems to be coming from the xtensa-esp32-elf, from libg_nano.a. Which is not part of RIOTOS. Investigating what comes from where, I conclude that maybe this tree is created by crosstool-ng?

minicom expects \r\n, but RIOT only sends \n. There’s a setting for minicom to add the linefeed.

(I use picocom, I start it using e.g., picocom --imap lfcrlf ...)

It’s not minicom’s issue, it’s really the standard. And the ESP32 boot messages have \r\n, as you can see from what I pasted. I think that RIOT’s puts() should send \r\n, but I’m unclear where that code is. I think it’s in a board support library.

I use

python -m serial.tools.miniterm /dev/ttyUSB0 115200

or

picocom -b 115200 --imap lfcrlf /dev/ttyUSB0
miniterm /dev/ttyUSB0 115200

also works.

Yes, like I said… I know how to teach my terminal program to do the wrong thing. I’m asking: how do I fix RIOT-OS to do the right thing? Specifically, am I correct that the puts() lives in an xtensa library that is built by crosstools-ng?

It is neither an ESP32 specific behavior nor a problem of puts. printf("...\n", ...) also produces only a LF. This is the behavior on all platforms and simply UNIX style. One of the goals of RIOT is that the behavior is identical on all platforms.

Unfortunately, the output of the Stage1 bootloader in ROM does not conform to this style, because the ROM function esp_rom_uart_putc is used, which explicitly replaces LF with CRLF. This behavior is also mimicked in ESP-IDF when, for example, USB CDC ACM is used for console output, for example in components/esp_system/port/soc/esp32s3/usb_console.c

I think that the behavior as generated by the newlib is correct. The output of stage1 bootloader with the additional CRs could be disabled by pin strapping.

It is Unix style that files end in LF, and that stdio can indicate end of lines with LF, but if you look into stty and termios, you’ll see that Unix terminals are configures to send CRLF when they see LF.
This is done in the terminal driver… I go back to mid-1980s with Unix, and dialup terminals and UUCP… can hacking SunOS3 and 4 tty drivers to act more sensibly.

The history is clear. It is also clear that CRLF is a leftover from the era of typewriters and completely unnecessary on modern terminals.

There’d be overhead if stdio had to replace \n with \r\n, potentially splitting one write into two where one is only two bytes, potentially being below dma threshold, …

Why not just configure your terminal to do the conversion? I haven’t had to deal with this while using RIOT in a decade.

But, there’s a PR proposing an implementation: stdio_uart: add stdio_uart_onlcr option to convert LF -> CRLF on output by jimparis · Pull Request #15619 · RIOT-OS/RIOT · GitHub

Kaspar Schleiser via RIOT notifications@riot-os.org wrote: > The history is clear. It is also clear that CRLF is a leftover from the > era of typewriters and completely unnecessary on modern terminals.

I think that I disagree. Modern terminals also support termios, but I don’t really think we want all of that in riot-os, right?

Every single one of those progress indicators you get from pv, dd, git, apt-get, works by using CR without LF. That indicates that CR still has value on its own.

> But, there's a PR proposing an implementation:
> https://github.com/RIOT-OS/RIOT/pull/15619

Thank you, I think we should merge it.