Serial port slow/delayed output

13 Feb 2011

Hi, I have been noticing in the past few days that every program that I compile/recompile, the serial output is delayed; it appears to be buffering and then simply dumping a batch. The following is a simple test code that should print test at every loop (2 seconds), the led does go on and off properly, although the serial output does not follow one printf per 2 seconds. To make sure that it's not the terminal software I was using, I tried this using putty under windows, and screen under OSX.

#include "mbed.h"

DigitalOut myled(LED1);

int main() {
    while(1) {
        myled = 1;
        printf("test");
        wait(1);
        myled = 0;
        wait(1);
    }
}

Anybody has any ideas of hwhat's going on? A change in labrary, or compiler, or my code is missing something?

Thanks!

14 Feb 2011

Try using a declared channel rather than using "stdout"

#include "mbed.h"

Serial pc(USBTX, USBRX);
DigitalOut myled(LED1);

int main() {
    // Set serial speed nice and high and set
    // your terminal to match it.
    pc.baud(115200);
    while(1) {
        myled = 1;
        pc.printf("test"); // <--- USE pc, not "stdout"
        wait(1);
        myled = 0;
        wait(1);
    }
}
14 Feb 2011

If you put a newline (\n) in each print, it should be immediate.

14 Feb 2011

Hi,

This is the expected (but perhaps unexpected!) behaviour. Here is the explanation.

When you call plain printf(...), you are basically calling fprintf(stdout,...), where stdout is a default filehandle for general output (others are stdin, and stderr). We map stdout to the UART0 which you see the result of on the mbed USB Serial port.

By default, the stdio libraries buffer stdout, which is why you don't see the results immediately; the buffer will only get flushed if it gets full enough, you force it to be flushed, or as Igor says, you send a new line character which by convention also forces a flush.

For example, the following code would not actually produce any output on a terminal:

#include "mbed.h"

int main() {
    fputc('h', stdout);
    fputc('i', stdout);
}

Because the buffer doesn't get full enough, and there is no newline, nothing ever gets output!

Adding a newline character will cause it to happen, but often that is not appropriate. But you can force it to happen. So for example, you can use fflush() to tell the library to flush the buffer:

#include "mbed.h"

int main() {
    fputc('h', stdout);
    fputc('i', stdout);
    fflush(stdout);   // flush this filehandle
}

or you could tell the library not to buffer it in the first place, using setbuf():

#include "mbed.h"

int main() {
    setbuf(stdout, NULL); // no buffering for this filehandle
    fputc('h', stdout);
    fputc('i', stdout);
}

Both of these code examples would give you the results you were after.

Alternatively, the Stream based mbed objects such as Serial do set buffering to off by default, as this is more expected behaviour. So, as Andy says, if you use the following code:

#include "mbed.h"

Serial out(USBTX, USBRX); // tx, rx

int main() {
    out.putc('h');
    out.putc('i');
}

You'll also get the right result.

The main thing is conventions here. Using plain printf() is commonly used for printing a diagnostic line of text to a terminal, for debugging for example. If the serial output is actually part of your application, you are better off declaring it explicitly with a proper Serial object. This also allows you to easily redirect it to another serial port if you wanted to.

It does however make me think perhaps I should force buffering off by default for stdout too, assuming that wouldn't adversely impact anyone. I suspect it is the more expected behaviour, so seems more appropriate.

Hope this makes things clear!

Simon

14 Feb 2011

Excellent thank you, and sorry about the previous typos ;) I like the declared output solution thank you. As for the \n suggestion, my example to go against this would be a simulated progress bar using dots. Printing an additional dot would be preferable rather than reprinting a new line which would be stored into a variable/array/pointer. Or to have to calculate a position etc...

Thanks again!

03 Jul 2011

Simon Ford wrote:

It does however make me think perhaps I should force buffering off by default for stdout too, assuming that wouldn't adversely impact anyone. I suspect it is the more expected behaviour, so seems more appropriate.

Has this change been made in the newer beta library? I would expect stdout/stderr/stdin to be connected to a tty where the channel would be interactive and without buffering to decrease latency. Calling fflush() on stdout isn't something that I have often seen in C code.

The RealView documentation appear to indicate that _sys_istty() should return 1 for interactive tty devices. The newlib documentation indicates the same expectation for its _isatty() thunking function.