How to block until WiringPi finishes to sent serial data (UART)?

706 views Asked by At

Device description (for context, skip it if you don't feel comfortable with electronic):

For a simple device, the communication is done in half-duplex UART (TX and RX are on the same wire), in the following way:

  • One pin (write-mode) indicate if the UART is sending or receiving (1: TX, 0:RX)
  • One pin write to the wire (TX).
  • One pin read from the wire (RX).

When the write-mode is in TX (writing), the RX pin is in high-impedance and TX in transmitting. While the write-mode is in RX (reading), the TXpin is in high-impedance and RXreceiving.

This is just for context, I do not expect electronic question/answers here.

WiringPI sample:

For this to happens, I have the following sample:

#include <wiringPi.h>
#include <wiringSerial.h>

int main()
{
    wiringPiSetup ();
    auto fd = serialOpen ("/dev/ttyAMA0", 115200);
    
    pinMode(0, OUTPUT);
    
    for(size_t i=0; i<10; ++i)
    {
        digitalWrite(0, HIGH);
        serialPutchar(fd, '\x55');
        digitalWrite(0, LOW);
        delay(1000);
    }

    serialClose(fd);
}

Using an oscilloscope, I can clearly see that the write-mode pin is reset before the UART end to send the data.

Obviously, I tried to add some "delay" or empty-loop to adjust, but this is not reliable for μs times (due to usual precision in timers on OS).

The question:

How to synchronize, so the write-mode pin is reset just after the UART byte is sent? (No more than approximately 150μs later).

2

There are 2 answers

6
zgyarmati On BEST ANSWER

I see 2 ways to implement this:

1. I can't test this right now, but it seems you could use the

 void serialFlush (int fd) ;

According to the docs "This discards all data received, or waiting to be send down the given device" see at http://wiringpi.com/reference/serial-library/

(Edit: after re-reading that sentence, it's clear that it would indeed flush also the data to be written, so this option is out...)

  1. Using tcdrain() (https://linux.die.net/man/3/tcdrain), where you pass the fd given back by serialOpen()
2
KamilCuk On

Set blocking on the file descriptor.

How to restore file descriptor operation to blocking mode can be found in many places. You may use code from this answer and do:

set_blocking_mode(fd, 1);
serialPutchar(fd, '\x55');

After that write() inside serialPutchar will be blocking. Note that fd is opened with O_NONBLOCK in serialOpen().