Serial class in Mbed OS 6?

Hello,

In Mbed 5, i use:
Serial vcom(USBTX, USBRX);
vcom.printf(“Output serial”);

In Mbed 6, it is not working anymore.

I find Serialbase but i don’t see the parameters for it.
Any replacement for Serial with example please ?

Thanks

Hello Da Dude,

In Mbed OS 6 you can use either BufferedSerial or UnbufferedSerial.

You can also use the “serial console” to communicate with the PC over a virtual USB serial port associated with the USBTX, USBRX pins . It uses the STDIO device. Simply call the global printf function:

printf("Prints to the virtual serial port\r\n");

I works at 9600 bit/s.

For debug messages you can also call the global debug function. It works like the global printfbut it is automatically optimized away (no debug messages are printed) if you build the project using the release profile:

debug("This message is optimized away (not printed) in release build");

It is also possible to remap the “serial console” to other than the USBTX, USBRX pins.

Best regards, Zoltan

Note: If you need to be able to call pc.printf(), then my SerialStream library might be able to help since this function doesn’t exist for serial ports in vanilla Mbed.

Hi @hudakz

I’m currently working on RS485 implementation on mbed 6.17, but seems like the IRQ handler is not getting fired. I’m having a tranciever unit and measured all things correct. I can send the 8 bytes of instruction data, and I can see on the oscilloscope that there is a response, but I’m not able to catch the falling edge on the incoming data on the RX pin with the UnbufferedSerial or BufferedSerial library.
I’m using STM32L151CC and UART3. I’m thiking it might be something with the configuration of the UART3 pin map, because normally I would be able to attach a handler and read out what is sent.
Is there anyway to contact you, as it seems you have answered a lot of serial questions here on the forum.

Best, Martin

Hello Martin,

I am not 100% sure but I am afraid, Zoltan will not respond anymore.

  • Is it about Xdot_L151CC or a a custom target based on STM32L151CC?
  • So you see a falling edge with correct voltage level on MCU’s RX pin via oscilloscope, but MCU does nothing, right?

BR, Jan

1 Like

Hi @JohnnyK . Thank you for your response.

While browsing for a solution I saw that Zoltan had a health issue. I really hope he is OK.

It’s a custom target based on STM32L151CC. Let me try to clarify, this issue is about to exhaust me. I’m trying to get a RS485 sensor to work with my board. I’ve confirmed it’s working on via USB to RS485 unit and a simple nodejs program. So I’m trying to read holding registers 0 through 7 on the device and get a response. Below you’ll see my tranciever schematics, and in green are all the lines i’ve measured to be correct. DOUT/R goes to MCU UART3 on PB_11, and DIN/D connects to UART3 on PB_10. Note that i’ve attached the R11 for directional control from MCU and measured that it’s working as well.

I’ve measured the A/B line on the oscilloscope and it seems to be perfectly ok. Below a picture of turning on driver, sending the 8 byte instruction, turning off drive (reciever enable) and a response is coming from the sensor.

So I can confirm that the message is written and understood by the unit. However, only when I used UnbufferedSerial, not when I write with BufferedSerial.

When measuring directly on the MCU RX/TX lines of the UART3, it’s clear to see that I’m sending and recieving something. See picture below, yellow line is RX and red line is TX.

When trying to get those bytes I’ve tried multiple things, and I’m trying to get an overview myself. So for the above picture I’m running UnbufferedSerial with an attach callback to increment a counter and flash LED when called just for testing. Nothing happens, and the program actually stops with the last debug message being “Recieving”. See code below:

#include "mbed.h"
#include "mbed_trace.h"

#define TRACE_GROUP "TEST"

// Be sure power is turned on when cycled (e.g. restart after OTA)
DigitalOut POWER(POWER_KEEP_PIN, 1);
DigitalOut EXT_DISABLE(EN_SENSOR_PIN, 0);
DigitalOut DIRECTION(RS485_DIR, 1);
DigitalOut TEST_LED1(TEST_LED_1, 0);
DigitalOut TEST_LED2(TEST_LED_2, 0);
UnbufferedSerial RS485(RS485_TX, RS485_RX, MBED_CONF_SPIIO_APOLLO_CABLE_BAUD_RATE);

#define MODBUS_TRANSMIT 1
#define MODBUS_RECEIVE 0

int counter = 0;

void pre_transmit(void)
{
    tr_warn("pre-transmit");
    DIRECTION.write(MODBUS_TRANSMIT);
    TEST_LED1.write(1);
}

void post_transmit(void)
{
    tr_warn("post-transmit");
    DIRECTION.write(MODBUS_RECEIVE);
    TEST_LED1.write(0);
}

void on_rx_interrupt(void)
{
    counter++;
    TEST_LED2 = !TEST_LED2;
}

// Main program
int main(void)
{

  mbed_trace_init();
  mbed_trace_config_set(TRACE_ACTIVE_LEVEL_ALL | TRACE_MODE_COLOR);

  uint8_t data[8] = { 0x01, 0x03, 0x00, 0x00, 0x00, 0x07, 0x04, 0x08 };

  // Register a callback to process a Rx (receive) interrupt.
  RS485.attach(&on_rx_interrupt, SerialBase::RxIrq);

  while(true)
  {
      pre_transmit();
      int written = RS485.write(data, 8);
      post_transmit();

      tr_debug("Recieving");

      ThisThread::sleep_for(5s);

      tr_debug("Counter: %i", counter);
  }

}

It is possible for me to read some bytes out if I do it very manually with timing from osciloscope, but I’m not catching it correctly. But I tried this and could read a few bytes (4-5) until the program halts for some reason. I did this by writing a simple for-loop after the send command and direction configuration like so:

do
        {
            RS485.read(&c, 1);
            tr_debug("0x%02X", c);
        } while(c != 0x03);

I’ve tried several RS485 and modbus libararies, but none of them work, so thats why i’m trying with a vanilla implementation just to get something out.

So there seems to be somthing with the interrupt, and to be honest when we go into HAL drivers i’m a complete newbie, and have little to no knowledge about how that works. I did check PeripheralPins which is based on the xdot, and it’s setup as UART with pull up, which is also confirmed by the sniffing on the TX/RX lines.

Been trying to step through the serial_api on the mbed-os target folder, it seems that UART3 is defined correctly but again, i’m really not an expert when we go that low level.

If it matters I’m running console (mbed_trace) on UART2 (115200), a cellular module on UART1 (115200) and this rs485 implementation on UART3 (9600). Here is the pin definition:

    // UART
    UART1_TX                = PA_9,
    UART1_RX                = PA_10,

    UART2_TX                = PA_2,
    UART2_RX                = PA_3,

    UART3_TX                = PB_10,
    UART3_RX                = PB_11,

Any help is appreciated. I’ll try today to shortcut the RS485 Tranciever and communicate directly on the UART, because I’ve been coding UART on mbed6 and STM32L151CC based targets before without problems really. The major difference here is the tranciever in between, but as I see on the RX/TX lines that one seems to work just fine.

Best, Martin

I recommend to make a simple test of UnbufferedSerial in loop without Interrupts (polling method).

I did something similar (but without interrupts) few months ago, my goal was create a tester of an ECU where is necesarry to simulate a car communication over K-Line bus. My project is based on STM32F4 (BlackPill) with a UART to to K-Line convertor and found the ECU received my commands and responce but the tester received nothing. I also did an analyze with the oscilloscope and I found the RX signal is little bit strange. Then I add addition pull-up ressistor between RX and 3v3, that solve my issue.

BR, Jan

Well, after countless hours I finally managed to get this to work. The worst part of it is, that I’m not 100% sure what fixed the issue. But will try to describe shortly what I did before it started to work.

First I did a test with a vanilla UART connection, meaning removing the RS485 tranciever completely from the circuit. I was noticing that the low bits were not totally grounded on the oscilloscope, but as you see in above image they were before. So I guess this was due to my flywire workmanship. Either way, I got this to work with a vanilla implementation of UnbufferedSerial with an attach function. Note that this one didn’t have any directional control. I simply just started an external unit and listened in on the response. Worked fine.

I then populated the RS485 tranciever again, to discover the exact same problem as before. Oscilloscope readings were fine, including MCU RX line, but attach function did not trigger and program got stalled.
The readout from the oscilloscope was as expected, so I tried to remove the RS485 RX pin from my BufferedSerial configuration, and just put it directly as an InterruptIn for a simple implementation of counting the falling edges with an LED blink. So that worked fine. Without knowing anything about it, this might have configured some internal MCU registry that I’ve managed to smash earlier, who knows. Because, after having confirmed that the pin is indeed capable of interrupting I reconfigured the UnbufferedSerial to include that RX pin again, and something happened. I now got into the interrupt function, and could read something.

I’m a little unsure if this is the exact chronology, because I also had to be very careful with the timing of when I changed direction and turned on the external unit for it to work properly. See my final timing in this screengrab:

Sorry that I can’t provide a better rundown of how I managed to fix it, but everything is working as expected now. And I guess the moral of the story is to just keep on digging. What a wonderful two weeks it has been.

And thank you @JohnnyK for sharing your story as well, it did not solve it directly, but indirectly it helped me to keep the moral high :smiley:

Best, Martin