This is the mail archive of the cygwin mailing list for the Cygwin project.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Serial programming - Writing bytes in a blocking mode - Problem with tcdrain() ?

Hi Christopher,

thanks for your attention,

I've been working on it, and I've found a workaround for the problem using
the ioperm libraries, accessing the UART LSR register of the serial port.
In this way I'm able to know exactly when the output buffer is empty.

>I wonder if you're just seeing the effects of a buffer on the comm
>device itself not draining even though Windows has flushed everything
>from its own memory.

I'm not reading any buffer, the idea of my program is the following: Put
the RTS signal low, write some bytes, wait until everything is transmitted
and then raise again the RTS signal... I plugged the oscilloscope to see
those two signals and this is what it happened:

(See attached file: Signals - tcdrain.PNG)

To me, seeing this I think that tcdrain is not doing what it is supposed to
Then I used the ioperm, reading the LSR register to check when the output
is empty. This is the result, it works !! :
(See attached file: Signals - ioperm.PNG)

And here is the code that I'm using to generate those signals. Obviously, I
compile it with the -lioperm option in order to use ioperm libraries.
Hope it would be usefull for you


Pablo Benito
Desarrollo de Producto Electrónico
Tlf: + 34 848 42 08 00

#include <termios.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/io.h>
#include <sys/ioctl.h>

#define PORT "/dev/ttyS0" //Comm Device

int main() {

int fd;
char *msg ="Hello world!";
int status;
struct termios options;

fd = open(PORT, O_RDWR | O_NOCTTY );

tcgetattr(fd,&options); /* get current port settings */
      options.c_cflag&= ~CSIZE;
      options.c_cflag |= CS8 | CLOCAL | CREAD;
      cfsetispeed(&options, B38400);
      cfsetospeed(&options, B38400);

// Enable reading LSR register


// Set RTS low
ioctl(fd, TIOCMGET, &status );
status &= ~TIOCM_RTS;

//Send Hello World!

// Wait until output buffer is empty
// The first line uses tcdrain to wait, the second checks the LSR byte
// Uncomment the method you want to use to wait

//while (inb(0x3FD)!=0x60){}

//Set RTS high
status |= TIOCM_RTS;

return 0;


Corinna and I looked at the implementation of tcdrain in cygwin.  It's
simple.  It just calls FlushFileBuffers and, according to Microsoft:

it should be doing the right thing.

I wonder if you're just seeing the effects of a buffer on the comm
device itself not draining even though Windows has flushed everything
from its own memory.
Christopher Faylor                                     spammer? ->
Cygwin Co-Project Leader
TimeSys, Inc.

Attachment: Signals - tcdrain.PNG
Description: PNG image

Attachment: Signals - ioperm.PNG
Description: PNG image

Unsubscribe info:
Problem reports:

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]