Enable non-blocking reads for Mbed OS I/O target redefines

I’ve been using the standard C I/O library functions to print and get characters (ie, using scanf & printf directly).

However, this results in the loss of some functionality - specifically, there is no (obvious) way to enable/disable whether reads are blocking or not, or identifying if a character has been typed. Normally, I would call BufferedSerial::set_blocking(false) to stop blocking, and BufferedSerial::readable() to identify if a character is available.

Are there alternatives to this functionality without passing around the original BufferedSerial object? This is especially difficult to do because I’m defining the global object in mbed_app.json, not in mbed_override_console.

Hello Jasper,

The scanf & printf use the console for input and output. In a library (or in the main function) you can get the the associated FileHandle’s as:

    FileHandle* console_in = mbed_file_handle(STDIN_FILENO);
    FileHandle* console_out = mbed_file_handle(STDOUT_FILENO);

After that you can enable non-blocking as console_in.set_blocking(false) or check if characters are available as console_in.readable().

See also Hitchhiker's Guide to Printf in Mbed 6 - #41 by Hans_Waldherr

1 Like

Thanks for the help here! However, it seems like some functionality doesn’t work when I use the redirected serial.

For example, I am trying to flush the output buffers without entering a new line. When I explicitly use a BufferedSerial, calling BufferedSerial::sync() immediately flushes the buffer. However, when I use the redirected printf calls, even when I get the FileHandle for stdout, calling console_out->sync() does not actually flush the buffers.

Working code:

#include "mbed.h"

BufferedSerial serial(CONSOLE_TX, CONSOLE_RX, 115200);
int main()
{
    char *pre_buf = "before sync";
    char *post_buf = "after sync\r\n";
    for (int i = 0; i < 10; ++i)
    {
        serial.write(pre_buf, 11);

        serial.sync();

        ThisThread::sleep_for(1s);

        serial.write(post_buf, 12);
    }
}

This prints out before sync before after sync, as expected.

Non-working code:

#include "mbed.h"

int main()
{
    while (true)
    {
        printf("nothing");

        FileHandle* console_out = mbed_file_handle(STDOUT_FILENO);
        BufferedSerial* stdout_serial = reinterpret_cast<BufferedSerial*>(console_out);
        stdout_serial->sync();

        ThisThread::sleep_for(1s);
        printf("Now something?\r\n");
    }
}

This code prints nothing until the second printf statement, with a newline, is reached.

For reference, the relevant parts of mbed_app.json:

{
    "target_overrides":
    {
        "*":
        {
            "platform.stdio-baud-rate": 115200,
            "platform.stdio-buffered-serial": 1,
            "target.printf_lib": "std"
        }
    }
}