LinuxQuestions.org
Visit the LQ Articles and Editorials section
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices

Reply
 
Search this Thread
Old 05-20-2009, 02:13 AM   #1
craftybones
LQ Newbie
 
Registered: May 2009
Posts: 9

Rep: Reputation: 0
Linux serial port jammed


Hello,

I have a specific problem concerning serial ports, termios and linux. I have some custom hardware that I communicate with over two serial ports. One of the serial ports is one way traffic and constantly provides certain updates as a set of 8 byte strings.

I am using termios to connect and talk to this and have been able to do so. However, on the channel that provides continuous updates, things go dead after a few seconds. Just completely dead. I have to disconnect and reconnect the serial port through termios for me to receive messages again.

A similar implementation of this works in windows, so we can ascertain that its not a hardware problem. The problem is either with termios or with my code.

I can post the code, but before I condense it and put it up, do people have any general suggestions I should look at?

Thank you,

Jay
 
Old 05-20-2009, 02:17 AM   #2
pcardout
Member
 
Registered: Jun 2003
Location: Socorro, New Mexico
Distribution: Debian ("lenny", "squeeze"), Ubuntu ("karmic", "oneiric")
Posts: 214

Rep: Reputation: 24
Minicom is a perfectly good serial communications tool for linux that lets you rapidly configure everything that might be
important (parity, software vs. hardware stop bits, baud rate, port used ... etc.). It would let you probe the
relevant parameters in linux. Perhaps the problem is all termios.

Without meaning to be too rude to the folks in Redmond, last time I used Hyperterm I found it a real bitch to figure out what
parameters it was setting exactly. Minicom is much more transparent. It could easily just be a software configuration problem.
Windows "works" but do you know why? Maybe minicom can help you figure it out so you can put proper parameters in your own code.

Last edited by pcardout; 05-20-2009 at 02:18 AM.
 
Old 05-20-2009, 02:53 AM   #3
craftybones
LQ Newbie
 
Registered: May 2009
Posts: 9

Original Poster
Rep: Reputation: 0
Hello,

Thank you for the quick reply. I have used minicom, setserial, stty and the usual host of tools, but it doesn't seem to be a setting problem. Here's another thing, when I use a plain old cat /dev/ttyS4 > dummy...it doesn't stop. It seems to be specific to termios and specific to this port. The other channel works great.

Jay
 
Old 05-20-2009, 03:47 AM   #4
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 453Reputation: 453Reputation: 453Reputation: 453Reputation: 453
The old trick is to set two stop bits at the transmitting side and one stop bit at the receiving side, and this trick has good physical explanation.

I think that some HW allows even 1.5 bits, which would also be OK (instead of the 2 bits).
 
Old 05-20-2009, 04:43 AM   #5
craftybones
LQ Newbie
 
Registered: May 2009
Posts: 9

Original Poster
Rep: Reputation: 0
Hello,

I am not sure about setting two bits but here is the code:

int connect(char *port) {
int connector;
struct termios options;

connector = open(port, O_RDWR | O_NOCTTY | O_NONBLOCK);
if (connector == -1) {
/* blah */
} else {
fcntl(connector, F_SETFL, FNDELAY); //FNDELAY is for non blocking read calls
}

tcgetattr(connector, &options);
cfsetispeed(&options, baud);
cfsetospeed(&options, baud);
options.c_iflag &= ~IGNBRK;
options.c_oflag &= ~OPOST;
options.c_lflag = 0;
options.c_cflag |= (CLOCAL | CREAD);
options.c_cflag |= PARENB;
options.c_cflag &= ~PARODD;
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8;
options.c_cflag &= ~CRTSCTS;

int status = tcsetattr(connector, TCSANOW, &options);
if ( status != 0 ) { /* blah */ }

return status;
}

To write to the port:

tcflush(maio_connector, TCOFLUSH);
nbytes = write(maio_connector, command, length)
if ( nbytes != length) { /* blah */ }

To read from the port:
if ((nbytes = read(maio_connector, buffer, sizeof(buffer) )) > 0)

While I am still clueless about what's wrong, I appreciate all your efforts in helping me out.

Thank you,

Jay
 
Old 05-20-2009, 12:15 PM   #6
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 453Reputation: 453Reputation: 453Reputation: 453Reputation: 453
Quote:
Originally Posted by craftybones View Post
Hello,

I am not sure about setting two bits but here is the code:

int connect(char *port) {
int connector;
struct termios options;

connector = open(port, O_RDWR | O_NOCTTY | O_NONBLOCK);
if (connector == -1) {
/* blah */
} else {
fcntl(connector, F_SETFL, FNDELAY); //FNDELAY is for non blocking read calls
}

tcgetattr(connector, &options);
cfsetispeed(&options, baud);
cfsetospeed(&options, baud);
options.c_iflag &= ~IGNBRK;
options.c_oflag &= ~OPOST;
options.c_lflag = 0;
options.c_cflag |= (CLOCAL | CREAD);
options.c_cflag |= PARENB;
options.c_cflag &= ~PARODD;
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8;
options.c_cflag &= ~CRTSCTS;

int status = tcsetattr(connector, TCSANOW, &options);
if ( status != 0 ) { /* blah */ }

return status;
}

To write to the port:

tcflush(maio_connector, TCOFLUSH);
nbytes = write(maio_connector, command, length)
if ( nbytes != length) { /* blah */ }

To read from the port:
if ((nbytes = read(maio_connector, buffer, sizeof(buffer) )) > 0)

While I am still clueless about what's wrong, I appreciate all your efforts in helping me out.

Thank you,

Jay
I have entered into yahoo.com search field

termios stop bits
.

The very first match is:

http://www.kernel.org/doc/Documentation/serial/driver
.

Using 'stop' as search item in the above I come to:

Code:
  set_termios(port,termios,oldtermios)
	Change the port parameters, including word length, parity, stop
	bits.  Update read_status_mask and ignore_status_mask to indicate
	the types of events we are interested in receiving.  Relevant
	termios->c_cflag bits are:
		CSIZE	- word size
		CSTOPB	- 2 stop bits
.
 
Old 05-20-2009, 03:25 PM   #7
theNbomr
LQ 5k Club
 
Registered: Aug 2005
Distribution: OpenSuse, Fedora, Redhat, Debian
Posts: 5,395
Blog Entries: 2

Rep: Reputation: 903Reputation: 903Reputation: 903Reputation: 903Reputation: 903Reputation: 903Reputation: 903Reputation: 903
Quote:
Originally Posted by Sergei Steshenko View Post
The old trick is to set two stop bits at the transmitting side and one stop bit at the receiving side, and this trick has good physical explanation.

I think that some HW allows even 1.5 bits, which would also be OK (instead of the 2 bits).
Not saying you are wrong, but what about craftybones' problem is suggestive that the number of stop bits is the cause of the problem? To me, it seems just as likely that something about the data stream is affecting the behavior of the connection. Perhaps embedded escape sequences that are being trapped, or XOFFs being sent and freezing the connection.
In applications such as craftybones is crafting, it always seems to make the most sense to me, to invoke RAW mode ( c_lflag &= ~ICANON ), to remove the line-oriented treatment of incoming data. If this is done, it may also be prudent to specifically set VMIN & VTIME in the c_cc[] array. If the receiver is in canonical mode, it is possible that the receiver is simply waiting for an End-Of-Line character, and blocking until such a character is received.
craftybones has cleared CRTSCTS, so that should take care of hardware flow control getting in the way.

Some decent sources of information, in case you haven't found them already:
Serial Programming Howto
Serial Howto
Serial Programming Guide for POSIX Operating Systems
Terminal Concepts in GNU/Linux

--- rod.
 
Old 05-20-2009, 03:53 PM   #8
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 453Reputation: 453Reputation: 453Reputation: 453Reputation: 453
Quote:
Originally Posted by theNbomr View Post
Not saying you are wrong, but what about craftybones' problem is suggestive that the number of stop bits is the cause of the problem? To me, it seems just as likely that something about the data stream is affecting the behavior of the connection. Perhaps embedded escape sequences that are being trapped, or XOFFs being sent and freezing the connection.
In applications such as craftybones is crafting, it always seems to make the most sense to me, to invoke RAW mode ( c_lflag &= ~ICANON ), to remove the line-oriented treatment of incoming data. If this is done, it may also be prudent to specifically set VMIN & VTIME in the c_cc[] array. If the receiver is in canonical mode, it is possible that the receiver is simply waiting for an End-Of-Line character, and blocking until such a character is received.
craftybones has cleared CRTSCTS, so that should take care of hardware flow control getting in the way.

Some decent sources of information, in case you haven't found them already:
Serial Programming Howto
Serial Howto
Serial Programming Guide for POSIX Operating Systems
Terminal Concepts in GNU/Linux

--- rod.
I am not saying I am definitely right, but I had a similar problem 20 years ago - the communications just stopped after some time (minutes or seconds - I already do not remember).

Regarding the stop bits on both sides - receiver and transmitter are not synchronized WRT their clock frequency. And the stop bit at receiving side should be no shorter than full length, but the receiver can easily deal with linger than necessary stop bits - it's the same as no start bit yet and thus OK.

There is even a special term in communications - I think it's called "bit shaving", i.e. a part of bit duration is "shaved off" - that's regarding 1.5 bits.
 
Old 05-20-2009, 06:59 PM   #9
craftybones
LQ Newbie
 
Registered: May 2009
Posts: 9

Original Poster
Rep: Reputation: 0
Hello all,

I have tried setting the stop bits to two but the behavior doesn't change. When I said I didn't know about the stop bits, I meant that I didn't know if changing it was going to help.

The suggestion to remove canonical is interesting. I think its worth a shot. I'll do that when I get to work and give you guys a shout. Thanks a ton.

Jayanth
 
Old 05-20-2009, 07:04 PM   #10
theNbomr
LQ 5k Club
 
Registered: Aug 2005
Distribution: OpenSuse, Fedora, Redhat, Debian
Posts: 5,395
Blog Entries: 2

Rep: Reputation: 903Reputation: 903Reputation: 903Reputation: 903Reputation: 903Reputation: 903Reputation: 903Reputation: 903
Yes, the number of stop bits sent can be arbitrarily large, since the state of a stop bit (mark) is the same as the state of the idle period between frames, and there is no specific delimiter between the end of the last stop bit and the beginning of the idle state. I suppose that if the receiver is expecting two stop bits while the sender is transmitting only one, there is a possibility of a framing error by seeing the subsequent start bit unexpectedly. Since craftybones has not set 'CSTOPB', his receiver should be expecting only one stop bit, however. If I recall correctly, on a 8250 family UART (I know this was not specified, but they are fairly ubiquitous), a 1.5 stop-bit width is only possible on a 5-bit data word, which I have yet to see used in practice.
One question that remains unanswered is what exact failure mode is exhibited? There are at least two possibilities that come immediately to mind. First, the read() call can return zero in perpetuity, or second, the read() call can block perpetually. This assumes that there are no other errors in the program that would have the reported result. From a cursory inspection of the supplied code, I see no errors in logic, although there is evidently much code removed from the sample.
--- rod.

Last edited by theNbomr; 05-20-2009 at 07:05 PM.
 
Old 05-20-2009, 07:25 PM   #11
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 453Reputation: 453Reputation: 453Reputation: 453Reputation: 453
Quote:
Originally Posted by craftybones View Post
Hello all,

I have tried setting the stop bits to two but the behavior doesn't change. When I said I didn't know about the stop bits, I meant that I didn't know if changing it was going to help.

The suggestion to remove canonical is interesting. I think its worth a shot. I'll do that when I get to work and give you guys a shout. Thanks a ton.

Jayanth

Did you do this only on the transmitting side. Rather, if it's bidirectional link, both sides transmitters have to have 2 stop bits while both sides receivers have to to have one stop bit.
 
Old 05-21-2009, 01:46 AM   #12
craftybones
LQ Newbie
 
Registered: May 2009
Posts: 9

Original Poster
Rep: Reputation: 0
Hello,

It seems like the read call is blocking!!! So perhaps setting the VMIN and VTIME is perhaps appropriate. Let me check and get back.

Thank you,

Jayanth
 
Old 05-21-2009, 02:07 AM   #13
craftybones
LQ Newbie
 
Registered: May 2009
Posts: 9

Original Poster
Rep: Reputation: 0
Ok, so I set VMIN and VTIME to zero values, positive values...but now, instead of blocking, read just returns 0. I have flushed the buffers, and I still get a read of 0 bytes. Now I am totally clueless.

Jayanth
 
Old 05-21-2009, 04:14 AM   #14
craftybones
LQ Newbie
 
Registered: May 2009
Posts: 9

Original Poster
Rep: Reputation: 0
Hello,

Turns out that closing and opening the connection again fixes the problem, but this is still a hack as I need to keep opening and closing connections and there is no guarantee that this will always work either.

Any ideas?

Jay
 
Old 05-21-2009, 04:33 AM   #15
wje_lq
Member
 
Registered: Sep 2007
Location: Mariposa
Distribution: Debian lenny, Slackware 12
Posts: 808

Rep: Reputation: 178Reputation: 178
  1. By now you're removing the canonical bit, yes? This is very important.
  2. VMIN must be 1 and VTIME must be 0. You'll get one byte per read().
  3. I wrote a program which uses the modem. You're not interested in modem complications, but the advantages to you of this program are these:
    1. It's rather short, so it's not too difficult to understand the source.
    2. It's very, very thoroughly documented.
    Download the source from here, rip out what you don't need, play with it, and come back here with questions. (My time will be very limited until next Tuesday, but I'll do what I can even before then.)

    I intend to leave the program at that URL for at least two weeks.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Resetting a serial port in Linux? gauravparihar Linux - Newbie 1 03-23-2009 06:41 AM
linux serial port to router console port connection? frankie_fix Linux - General 3 02-26-2007 09:32 PM
squid port jammed open Law1213 Linux - Software 4 02-14-2006 02:08 PM
Using serial port card(PCMCIA) with IPAQ running Linux, can't find ttyS0 port d2army Linux - Laptop and Netbook 0 11-12-2005 08:07 PM
Windows to Linux via serial port longnam Linux - Networking 1 05-01-2005 06:50 AM


All times are GMT -5. The time now is 07:45 PM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration