Using printf with \r does not print anything

username
Posts: 488
Joined: Thu May 03, 2018 1:18 pm

Using printf with \r does not print anything

Postby username » Sun Aug 20, 2023 5:02 am

Using M5Stamp ESP32S3 Module. ESP-IDF 5.1
https://shop.m5stack.com/products/m5sta ... 2s3-module

When I printf with \n or \r\n things work fine in the terminal. Yet if I just use \r I get nothing.

Code: Select all

#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

void app_main(void)
{
    u_int16_t a=0;
    u_int16_t b=0;

    while(1)
    {
        printf("%u : %u\r",a++,b+=2);
        vTaskDelay(100 / portTICK_PERIOD_MS);
    }
    
}
In the terminal I get:

Code: Select all

I (45) boot: ESP-IDF GIT-NOTFOUND 2nd stage bootloader
I (45) boot: compile time Aug 19 2023 23:45:27
I (46) boot: Multicore bootloader
I (49) boot: chip revision: v0.1
I (53) boot.esp32s3: Boot SPI Speed : 80MHz
I (57) boot.esp32s3: SPI Mode       : DIO
I (62) boot.esp32s3: SPI Flash Size : 8MB
I (67) boot: Enabling RNG early entropy source...
I (72) boot: Partition Table:
I (76) boot: ## Label            Usage          Type ST Offset   Length
I (83) boot:  0 nvs              WiFi data        01 02 00009000 00006000
I (91) boot:  1 phy_init         RF data          01 01 0000f000 00001000
I (98) boot:  2 factory          factory app      00 00 00010000 00100000
I (106) boot: End of partition table
I (110) esp_image: segment 0: paddr=00010020 vaddr=3c020020 size=09ce0h ( 40160) map
I (123) esp_image: segment 1: paddr=00019d08 vaddr=3fc91400 size=027f8h ( 10232) load
I (128) esp_image: segment 2: paddr=0001c508 vaddr=40374000 size=03b10h ( 15120) load
I (138) esp_image: segment 3: paddr=00020020 vaddr=42000020 size=17774h ( 96116) map
I (154) esp_image: segment 4: paddr=0003779c vaddr=40377b10 size=09830h ( 38960) load
I (166) boot: Loaded app from partition at offset 0x10000
I (167) boot: Disabling RNG early entropy source...
I (178) cpu_start: Multicore app
I (178) cpu_start: Pro cpu up.
I (178) cpu_start: Starting app cpu, entry point is 0x40375244
0x40375244: call_start_cpu1 at J:/ESP_5.1/esp/esp-idf/components/esp_system/port/cpu_start.c:154

I (0) cpu_start: App cpu up.
I (196) cpu_start: Pro cpu start user code
I (197) cpu_start: cpu freq: 160000000 Hz
I (197) cpu_start: Application information:
I (200) cpu_start: Project name:     test
I (204) cpu_start: App version:      1
I (209) cpu_start: Compile time:     Aug 19 2023 23:45:03
I (215) cpu_start: ELF file SHA256:  04421aca5e014a02...
I (221) cpu_start: ESP-IDF:          GIT-NOTFOUND
I (226) cpu_start: Min chip rev:     v0.0
I (231) cpu_start: Max chip rev:     v0.99 
I (236) cpu_start: Chip rev:         v0.1
I (240) heap_init: Initializing. RAM available for dynamic allocation:
I (248) heap_init: At 3FC94448 len 000552C8 (340 KiB): DRAM
I (254) heap_init: At 3FCE9710 len 00005724 (21 KiB): STACK/DRAM
I (261) heap_init: At 3FCF0000 len 00008000 (32 KiB): DRAM
I (267) heap_init: At 600FE010 len 00001FF0 (7 KiB): RTCRAM
I (274) spi_flash: detected chip: gd
I (277) spi_flash: flash io: dio
I (281) sleep: Configure to isolate all GPIO pins in sleep state
I (288) sleep: Enable automatic switching of GPIO sleep configuration
I (295) app_start: Starting scheduler on CPU0
I (300) app_start: Starting scheduler on CPU1
I (300) main_task: Started on CPU0
I (310) main_task: Calling app_main()
Nothing prints out. Yet if I change the printf to: printf("%u : %u\n",a++,b+=2);
it works just fine.

Code: Select all

...I (310) main_task: Calling app_main()
0 : 2
1 : 4
2 : 6
3 : 8
4 : 10
5 : 12
6 : 14
7 : 16
8 : 18
9 : 20
10 : 22
11 : 24
12 : 26
13 : 28
14 : 30
15 : 32
16 : 34
17 : 36
18 : 38
19 : 40
20 : 42
21 : 44
22 : 46
23 : 48
24 : 50
25 : 52
26 : 54
27 : 56
28 : 58
29 : 60
30 : 62
31 : 64
32 : 66
33 : 68
34 : 70
35 : 72...

Any ideas why using printf with \r does not work? I have also tried Tera Term and PuTTY. Both have same results as the IDE's built in terminal.

MicroController
Posts: 1385
Joined: Mon Oct 17, 2022 7:38 pm
Location: Europe, Germany

Re: Using printf with \r does not print anything

Postby MicroController » Sun Aug 20, 2023 6:20 pm

Might be that the TX buffer is only flushed when (it's either full or) '\n' is encountered...

username
Posts: 488
Joined: Thu May 03, 2018 1:18 pm

Re: Using printf with \r does not print anything

Postby username » Sun Aug 20, 2023 8:50 pm

I don't think thats the case. printf should print regardless of whats in its buffer.

boarchuz
Posts: 575
Joined: Tue Aug 21, 2018 5:28 am

Re: Using printf with \r does not print anything

Postby boarchuz » Sun Aug 20, 2023 9:55 pm

He's right, put a "fflush(stdout);" in there.

MicroController
Posts: 1385
Joined: Mon Oct 17, 2022 7:38 pm
Location: Europe, Germany

Re: Using printf with \r does not print anything

Postby MicroController » Sun Aug 20, 2023 10:11 pm


username
Posts: 488
Joined: Thu May 03, 2018 1:18 pm

Re: Using printf with \r does not print anything

Postby username » Mon Aug 21, 2023 1:20 am

boarchuz wrote:He's right, put a "fflush(stdout);" in there.
I did add fflush(stdout); and same result.

Something is strange, because i just tried something simple like printf("A"); and even that does not work.
In the past I have never had to use fflush(stdout); before. So what's changed ?

RandomInternetGuy
Posts: 43
Joined: Fri Aug 11, 2023 4:56 am

Re: Using printf with \r does not print anything

Postby RandomInternetGuy » Tue Aug 22, 2023 7:48 am

I'm in the same camp as the others. I expect there to be a buffer in the stdout path that requires an explicit flush, a length of a certain length to be reached, or a NL to be emitted. You can experiment with each of those three paths.

Can you put your receiver in super-dumb mode where it doesn't interpret anything being sent to it, but just does a raw hex dump of anything it receives, immediately?


This is a bit of a stretch as it depends on your environment, but does your environment provide a stderr facility in addition to stdout? That's almost always unbuffered,

fprintf(stderr, "Approaching moon. reached %d/100 pct\r", n); // \r instead of \n so it overwrites line in place.

should have the same effect of an explicit flush on the channel after the write is complete. On systems that are more POSIX-y (UNIX-like) than raw ISO C, setvbuf(stdout, NULL, _IONBF, 0) (I think - double check the doc) would be appropriate to disable the buffering, but be aware that it'll lower performance as not everything writing to that open file handle gets shoved to the uart immediately, blocking everything follow that until it's done.

username
Posts: 488
Joined: Thu May 03, 2018 1:18 pm

Re: Using printf with \r does not print anything

Postby username » Tue Aug 22, 2023 1:48 pm

I would like to thank everyone for pitching in. Before you write me off as crazy consider this.

As I have mentioned in all my 25+ years I have never used fflush(stdout); before and printf would print without using \n.
Something has changed using printf, not sure what. Many times in the past when I dont want to flood the terminal I have used \r to keep printing on the same line. I am sure some of you have seen code for when your waiting for something to happen and you want to show your waiting by printing "." continually to the terminal until its done. For things like waiting to get an IP from the DHCP server. In the past you would do something like this and it worked just fine.

Code: Select all

#include <stdio.h>
#include <inttypes.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

void app_main(void)
{
    printf("Restarting in 10 seconds");

    for (int i = 10; i >= 0; i--) 
    {
        printf(".");
        vTaskDelay(1000 / portTICK_PERIOD_MS);
    }

}
Yet, This no longer works. In fact I have pulled older programs I wrote a couple years back and re-compiled them using 5.1 and they dont print anymore when I know for a fact they used to. So, something has changed.

RandomInternetGuy
Posts: 43
Joined: Fri Aug 11, 2023 4:56 am

Re: Using printf with \r does not print anything

Postby RandomInternetGuy » Tue Aug 22, 2023 9:19 pm

I'm not saying you're crazy. I'm saying that what you're observing is completely within the bounds of ISO C.

I took your program to MacOS, and tweaked it in "obvious" ways:

Code: Select all

 ✗ cat /tmp/m.c
#include <stdio.h>
#include <unistd.h>

void main(void) {
           printf("Restarting in 10 seconds");

    for (int i = 10; i >= 0; i--)
    {
        printf(".");
//      fflush(stdout);
        sleep(1);
    }
}
make /tmp/m

It sits silently and then, ten seconds later, blarps out the 'Restarting' and ten dots all at once. Uncommenting the fflush makes it give one dot per second. My experience has been mostly in UNIX-based systems and stdio buffering has just long been the norm there. Reducing the number of system calls is totally a worthy optimization there because ring transitions are expensive.

Totally legal. Totally expected.


Is it possible that some earlier version didn't implement buffering by default? Totally. That's legal, too. So it might have changed. I'm just saying that this behaviour IS legal ISO C and that an fflush or a newline is how you make it work like you are expecting.

I grew up with the cited book, but https://begriffs.com/posts/2019-01-19-i ... d-lib.html credits this change in ISO C 89, so maybe in systems before 1989 this was common, but like I said, the spec is written so that either is possible.

username
Posts: 488
Joined: Thu May 03, 2018 1:18 pm

Re: Using printf with \r does not print anything

Postby username » Tue Aug 22, 2023 11:35 pm

Well....I thank you and all for your time. I tried this on several devices, and even installed IDF v4.4.1 all with same results.
The really weird thing about all this is that (hope you believe me) \r did work on my espressif devices before.

In any event, if anyone else runs into this like you all said you can use fflush(stdout); or setbuf(stdout, NULL);

Thanks guys!

Who is online

Users browsing this forum: Google [Bot] and 108 guests