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
do.
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

Cheers,

Pablo Benito
Desarrollo de Producto Electrónico
CEMITEC
pbenito@cemitec.com
Tlf: + 34 848 42 08 00
www.cemitec.com

#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);
tcsetattr(fd,TCSANOW,&options);
tcflush(fd,TCIOFLUSH);

// Enable reading LSR register
ioperm(0x3FD,1,1);

usleep(1000);

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

//Send Hello World!
write(fd,msg,strlen(msg));

// 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

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


//Set RTS high
ioctl(fd,TIOCMGET,&status);
status |= TIOCM_RTS;
ioctl(fd,TIOCMSET,&status);

usleep(10000);
close(fd);
return 0;

}






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

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/devio/base/read_and_write_operations.asp


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? ->
 aaaspam@sourceware.org
Cygwin Co-Project Leader
aaaspam@duffek.com
TimeSys, Inc.



Attachment: Signals - tcdrain.PNG
Description: PNG image

Attachment: Signals - ioperm.PNG
Description: PNG image

--
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
Problem reports:       http://cygwin.com/problems.html
Documentation:         http://cygwin.com/docs.html
FAQ:                   http://cygwin.com/faq/

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