Arm Mbed OS support forum

Trouble with PPPoS using RS485 (with direction pin), mbed OS 6

I am working on a PPPoS connection between PC and a custom embedded board using RS485. For the direction pin, I’ve tried various solutions, all of which seem suboptimal:

  1. Custom wrapper around BufferedSerial that sets the direction pin and resets it after a delay after writing. This made me able to send data once, then receive data infinitely, but none of the incoming data made it past pppos_input (see information below).
  2. Custom wrapper around UnbufferedSerial that sets the direction pin and resets it when receiving a TX empty interrupt (I did not implement sigio here, so this caused ppp_service to never start reading).
  3. Make a copy of entire BufferedSerial class and add direction pin functionality. This had the same result as the first option.

I tried to search for RS485 drivers for mbed OS, which I found, but all of them either 1) failed to use the direction pin or 2) made use of mbed OS 2 and its deprecated Serial API.

Anyway, with option 1 I can successfully send an LCP ConfReq and receive the corresponding ConfAck, but the input is never passed to ppp_input. I can see the packets are successfully obtained (albeit in bursted chunks), see the following debug logging (I patched it to print out the data, since PRINTPKT_SUPPORT does not work for mbed OS).

ppp phase changed[0]: phase=0
ppp_connect[0]: holdoff=0
ppp phase changed[0]: phase=3
pppos_connect: unit 0: connecting
ppp_start[0]
ppp phase changed[0]: phase=6
pppos_send_config[0]: out_accm=FF FF FF FF
ppp_send_config[0]
pppos_recv_config[0]: in_accm=FF FF FF FF
ppp_recv_config[0]
pppos_write[0]: len=24
ppp_start[0]: finished
pppos_input[0]: got 11 bytes:
7e ff 7d 23 c0 21 7d 21 7d 21 7d
pppos_input[0]: got 16 bytes:
20 7d 34 7d 22 7d 26 7d 20 7d 20 7d 20 7d 20 7d
pppos_input[0]: got 16 bytes:
25 7d 26 2b 91 64 49 7d 27 7d 22 7d 28 7d 22 e9
pppos_input[0]: got 2 bytes:
ab 7e

When I went on to debug this issue, I found that pppos.cpp :: pppos_input performs the following code:

if (ppp_call_callback(ppp->netif->service_ptr, pppos_input_callback, inp) != ERR_OK) {

I have verified that this code is executed, and ppp_call_callback returns ERR_OK.
However, the actual callback function never seems to be called (pppos_input_callback).
I’m new to mbed OS and not familliar with this callback functionality, and I can’t find information on how to debug this kind of issue. Perhaps you kind folk can point me in the right direction?

In the fashion of answering my own question in case other people experience something similar:
What ended up working for me was making a copy of BufferedSerial called BufferedSerialWithDirection. Add direction pin functionality in there based on TXE IRQ. Then remove the TX buffer functionality. Lastly, make the read non-busy wait. Just return -EAGAIN if there is nothing to read (LWIP expects this).

The following problems are solved:

  1. ppp_service wrapper around LWIP ppp now can properly use the sigio FileHandle functionality with my custom BufferedSerialWithDirection.
  2. LWIP being stuck in read (-EAGAIN causes LWIP to know there is currently nothing to read)
  3. Direction pin functionality is added
  4. Rx buffer is still implemented so LWIP doesn’t have to read every byte when it arrives

I would prefer inheriting from BufferedSerial, but I can’t add my own TXE IRQ handler then, because BufferedSerial’s inheritance of SerialBase is private and not protected. I didn’t want to have to change mbed OS code for this to work, so I made a modified copy instead.