Re: Issue with EOL and serial port access
From: Martin Woolley (martin_at_woolleynet.com)
Date: 03/02/04
- Next message: Martin Woolley: "Re: Issue with EOL and serial port access"
- Previous message: Lorinczy Zsigmond / Domonyik Mariann: "Re: Problem closing a socket while thread blocks in read()"
- In reply to: Floyd L. Davidson: "Re: Issue with EOL and serial port access"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Date: Tue, 2 Mar 2004 18:44:47 -0000
What an excellent reply. Thanks for this Floyd, I'll investigate as per your
suggestions. (btw this is the first C program I ever wrote.... skipped Hello
World and went straight for this!).
Martin
"Floyd L. Davidson" <floyd@barrow.com> wrote in message
news:87d67v6tej.fld@barrow.com...
> "Martin Woolley" <martin@woolleynet.com> wrote:
> >Hi
> >
> >I have some code which reads from a serial port. When I use it on one of
my
> >Linux boxes I see 0x0D0A terminating lines read from the device. This is
> >what I expect to see. But if I run the same code on a different Linux box
I
> >see 0x0A0A as the line terminator.
> >
> >Here are the options I'm setting in my code:
> >
> > options.c_cflag |= (CLOCAL | CREAD);
> > options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // raw mode
> > options.c_lflag &= ~ECHO;
> > options.c_oflag &= ~ECHO;
> > options.c_oflag &= ~OPOST;
> > options.c_cc[VMIN] = 0;
> > options.c_cc[VTIME] = 10;
> >
> >Most of the code that deals with serial port configuration, I got from
the
> >Linux Serial programming HowTo. ie I am pretty new to this and don't
> >understand it all!
>
> Unfortunately, that HOWTO has a number of errors and just does
> not mention some important issues. (I've heard that a new
> version has been submitted, but I've never seen it.)
>
> >Can anyone tell me how to ensure that I see 0x0D0A terminating all lines
> >read from the port please? My testing is all wiht /dev/ttyS0 btw.
>
> The trouble is probably (you don't show enough code to be
> positive) that you are not setting/clearing *all* of the options
> of the termios struct. Instead you are or'ing and and'ing in or
> out only certain options.
>
> The port's configuration is therefore dependant upon the
> pre-existing state of the port when it is opened. If the last
> program which used it left it with an option enabled that is a
> problem for your particular program, and is one you have not set
> or cleared, then your program will fail. A common example...
> if you run pppd on that port and use the command line "kill -9
> nnn" with the right PID for nnn to kill pppd, your program will
> be totally dead in the water when it attempts to use the port.
> That is because options.c_line will have a line discipline set
> for PPP protocols, not for using the port with a terminal.
>
> Below is an example of configuring the port which probably will
> cure whatever it is that is causing your problem. Assuming of
> course that you modify it to set whichever options match your
> needs.
>
> Another way to accomplish the same effect of setting all
> options, is to simply clear the entire termios structure using
> memset(); however, that technically violates the POSIX
> requirement that the struct be initialized by a valid return
> from tcgetattr(). (I don't know of an example where it would
> fail, but...)
>
> There is one other small gotcha in this too. tcsetattr() will
> return 0 if it can set any part of the port's configuration, but
> it makes no guarantee that all parts are as requested. Hence,
> even though you might ask for OPOST to be disabled, there is
> nothing in this code which verifies that it was in fact
> disabled. You could add verification (I've never seen anyone do
> it) by using code something like this, but it is not portable,
> and there is no guarantee that it is valid on all systems,
> though it is on Linux and most others. It is guaranteed only
> only to verify the c_cc[] member and everything that comes
> before it in the struct. It may fail if the baud values are
> prior to the c_cc[] member.
>
> #define TERMSIZE (offsetof (struct termios, c_cc[NCCS]))
>
> int
> serial_port_configuration(int fd)
> {
> struct termios tty, stty;
>
> ... /* all other code */
>
> if (tcsetattr(fd, TCSADRAIN, &tty) || tcgetattr(fd, &stty)) {
> perror("tcsetattr");
> return -1;
> }
>
> /* verify the changes were actually made */
> return memcmp(&tty, &stty, sizeof (struct termios)) ? -1 : 0;
> }
>
> The reason to compare only as far into the struct as the c_cc
> member is because the baud bits follow that (on Linux and most
> other systems, but that is arbitrary), and the bit pattern when
> you set both of them is not necessarily the same bit pattern
> that will be returned by tcgetattr(), hence even though it has
> succeeded, it will not compare equal if the baud bits are
> include.
>
> Here is the code example:
>
>
> #include <termios.h>
> #include <sys/ioctl.h> /* defines N_TTY */
>
> /*********************** CONFIGURATION ************************/
> #define BAUD B57600 /* B9600, B38400, B57600, B11500... */
> #define BITS CS8 /* CS5, CS6, CS7, CS8 */
> #define PARITY IGNPAR /* IGNPAR, PARENB, PARENB | PARODD */
> #define FLOWCTL CRTSCTS /* CRTSCTS, IXON | IXOFF | IXANY */
> #define CTLLOCAL 0 /* CLOCAL or 0 */
> /******************************************************************/
>
> #define CFLAGS (FLOWCTL | BITS | CTLLOCAL | CREAD)
> #define IFLAGS (IGNBRK | PARITY)
>
> int
> serial_port_configuration(int fd)
> {
> struct termios tty;
>
> tcgetattr(fd, &tty);
>
> tty.c_iflag = IFLAGS; /* input flags */
> tty.c_cflag = CFLAGS; /* control flags */
> tty.c_lflag = 0; /* local flags */
> tty.c_oflag = 0; /* output flags */
> tty.c_cc[VMIN] = 1; /* wait for 1 character */
> tty.c_cc[VTIME] = 0; /* turn off timer */
>
> #ifdef __linux__
> /* for linux only */
> tty.c_line = N_TTY; /* set line discipline */
> #endif
>
> cfsetospeed(&tty, BAUD); /* set bit rate */
> cfsetispeed(&tty, BAUD);
>
> if (tcsetattr(fd, TCSADRAIN, &tty) || tcgetattr(fd, &tty)) {
> perror("tcsetattr");
> return -1;
> }
>
> return 0;
> }
>
>
> --
> Floyd L. Davidson <http://web.newsguy.com/floyd_davidson>
> Ukpeagvik (Barrow, Alaska) floyd@barrow.com
- Next message: Martin Woolley: "Re: Issue with EOL and serial port access"
- Previous message: Lorinczy Zsigmond / Domonyik Mariann: "Re: Problem closing a socket while thread blocks in read()"
- In reply to: Floyd L. Davidson: "Re: Issue with EOL and serial port access"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Relevant Pages
|
|