6 months, 2 weeks ago.

Access to stdin/stdout Serial object

Hello,

I have defined TX/RX pins in mbed_app.json so stdin/stdout are mapped to it and I can use printf()/getchar() and such to access it.

I'd like to use the Serial.attach() method to detect communication with the board but I can't find the Serial object it is linked to.

Right now I defined a RawSerial object with the same pins and can use attach() on it. It's working, but I'm not sure it's the best thing to do, resource-wise.

Is there a better way to access the console as a Serial or RawSerial object?

Thanks!

Comment on this question

1 Answer

6 months, 2 weeks ago.

Hello Matthieu,

You can try to override the default console as below.

#include "mbed.h"

DigitalOut  led1(LED1);
RawSerial*  mySerial;

void onSerialReceived()
{
    char c = mySerial->getc();

    if (c == 't')
        led1 = !led1;
}

FileHandle* mbed::mbed_override_console(int)
{
    static UARTSerial   myConsole(PA_9, PA_10, 9600);
    mySerial = reinterpret_cast<RawSerial*>(&myConsole);
    mySerial->attach(onSerialReceived);
    return &myConsole;
}

int main()
{
    while (true) {
        printf("blink\r\n");
        wait(0.5);
    }
}

Thanks Zoltan! Just to be sure: the ISR is the onSerialReceived() function in that case? I think I felt the problem you're referring to because I'm trying to "reply" to the serial command within that function, which lead to a 0x80020115 error; but I'll ask a separate question for that.

posted by Matthieu Labas 03 Apr 2019

Yes, onSerialReceived is the ISR in the code above. Sorry, I modified (simplified) my answer in the meantime because if you use RawSerial instead of Serial you can call getc/putc in the ISR without having a system fault. So a code like below should work:

#include "mbed.h"

DigitalOut  led1(LED1);
RawSerial*  mySerial;

void onSerialReceived()
{
    mySerial->putc(mySerial->getc());
}

FileHandle* mbed::mbed_override_console(int)
{
    static UARTSerial   myConsole(PA_9, PA_10, 9600);
    mySerial = reinterpret_cast<RawSerial*>(&myConsole);
    mySerial->attach(onSerialReceived);
    return &myConsole;
}

int main()
{
    while (true) {
        led1 = !led1;
        printf("blink\r\n");
        wait(0.5);
    }
}
posted by Zoltan Hudak 03 Apr 2019

Looks promising, I'll try to test it asap. One last thing: is it ok to cast RawSerial* to FileHandle*? I don't see it anywhere in the RawSerial hierarchy... I guess it could work thanks to the virtual methods? (my C++ is sooo rusty...).

posted by Matthieu Labas 03 Apr 2019

Down-cast isn't always safe. But in this case it seems OK. To achieve safe down-cast you can use dynamic_cast and then test the returned pointer against NULL rather than to use reinterpret_cast or static_cast . But it requires a little bit of extra overhead to run.

posted by Zoltan Hudak 04 Apr 2019

Working great! In my case getc()/putc() is all I need but I'll probably ask "why" on a more generalist programming Q&A site like StackOverflow. Thanks again Zoltan!

posted by Matthieu Labas 05 Apr 2019

Hello, looks like a good approach. But when I try your source, I get: Error: Namespace "mbed" has no member "mbed_override_console" in "main.cpp", Line: 63, Col: 20 Seems mbed library has no longer got this function. What could it be that I am doing wrong? Cheers, Tarek

posted by Tarek Lule 25 May 2019

Tested with the latest mbed-os 5.12.4 and also with mbed 2 (aka mbed classic) and both still work. The mbed::mbed_override_console(int) function is declared in the mbed-os/platform/mbed_retarget.h file at line 134. Make sure your program includes the mbed.h header file.

posted by Zoltan Hudak 25 May 2019