[ Table Of Contents ][ Answer Guy Current Index ] greetings   Meet the Gang   1   2   3   4   5   6   7   8   9 [ Index of Past Answers ]


(?) The Answer Gang (!)


By Jim Dennis, Ben Okopnik, Dan Wilder, Breen, Chris, and the Gang, the Editors of Linux Gazette... and You!
Send questions (or interesting answers) to [email protected]

There is no guarantee that your questions here will ever be answered. Readers at confidential sites must provide permission to publish. However, you can be published anonymously - just let us know!

TAG Member bios | FAQ | Knowledge base


(?) Serial Programming on an i486 in Linux

From V Sreejith

Answered By Chris Gianakopoulos, Ben Okopnik, Heather Stern

hi all,

This is my first posting. Here I have a problem related with linux serial programming in C.Hope u can help me in this.

I have a C program that communicates with a remote terminal unit via serial port.The program uses termios structure to initialise the port. The program works as expected in kernel version 2.4.2-2 on an i686 macine.

This same program when tested on a 586 (Kernel 2.2.14-12 on an i586) machine fails to read the port properly. Writing to the port was working properly. The setserial and stty commands produced the same result on both machines.

(!) [Chris G.] What does "failing to read the port properly" mean? Do the data look rather odd? Does it look garbled?

(?) Later i found that minicom(communicating with hyperterminal in windows) also showed the same problem while reading the port on the 486 macine. Writing to the port was working properly. Communication was proper when hyperterminal was used on both sides.

Here is the o/p of the setserial command.

/dev/ttyS0, Line 0, UART: 16550A, Port: 0x03f8, IRQ: 4

Baud_base: 115200, close_delay: 50, divisor: 0
closing_wait: 3000
Flags: spd_normal skip_test

and here is the settings on the port using stty command while my program is running.

(!) [Chris G.] I am guessing that your baud rate is 115200 baud.

(?)

speed 9600 baud; rows 0; columns 0; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D;
eol = <undef>;
eol2 = <undef>; start = ^Q; stop = ^S; susp = ^Z;
rprnt = ^R; werase = ^W;
lnext = ^V; flush = ^O; min = 1; time = 0;
-parenb -parodd cs8 hupcl -cstopb cread clocal
-crtscts
-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr
-igncr icrnl ixon -ixoff
-iuclc -ixany -imaxbel
opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel
nl0 cr0 tab0 bs0 vt0
ff0
isig icanon iexten echo echoe echok -echonl -noflsh
-xcase -tostop -echoprt
echoctl echoke
(!) [Chris G.] I am guessing that your baud rate is 9600 baud.

(?) If anybody knows what is creating the problem... please do help..

regards, sree

(!) [Chris G.] Hey Sree, Are you running both sides of the link at the same data rate? The parameters that you displayed give me the indication that the data rates are not the same.
When you type on one terminal, do you see anything displayed on the other terminal? If they are different, one cause could be mismatched baud rate. Your stty parameters seem okay -- if they are not, someone else will probably jump in and correct me.
Get back to me (at you convience of course), and let me know what you see on the displays.
I hope that this helps, Chris Gianakopoulos

(?) hi chris,

I think this isn't the problem of the code as this same code is working as expected in an i686 machine.

(!) [Ben] I agree with you here, Sree; if "minicom", etc. are having problems, then your programming isn't what's at fault - it's "lower down". That could still mean that there are problems with the baud rate, however - the "lower down" part means anything from the serial port settings, through hardware initialization, to actual hardware problems (the last of which you've eliminated by trying it in Wind*ws.)

(?) So it couldn't be the problem of baudrate,parity etc. Ofcourse my baudrate is 9600 and the stty command showed that i have initialised the port as expected.stty command showed the same o/p for i686 and i586(not i486 ..sorry for the mistake).

(!) [Chris G.] That's ok. If you are at the same baud rate, you might expect things to work.
(!) [Ben] Why the "of course"? I almost always set my port speed to 115200. One of the few exceptions is when I'm reading from my Minolta Dimage V camera: it will not work with anything past 38400.
Have you tried your program on another 586, preferably a different make and model? It could be that the serial hardware on that specific machine is wonky, or that it's sufficiently strange that the serial driver is having problems. I would also urge you to study the "setserial" man page; if indeed the driver is having problems, "setserial" gives you _tons_ of configuration options, and you might be able to "configure the problem away."

(?) My problem(in an i586) is that i can't read from the port properly.I could get the no of bytes available on the port with an ioctl call.The program fails to read that bytes..

Sometimes it reads correctly a few bytes.. But most of the time the read function returns with Zero bytes read even if bytes are available on the port. Writing was working properly(verifying..by the return value of write function)

Earlier i thought it could be some problem with my code.Later minicom also showed the same problems.That is, whatever was typed on my keyboard was displayed on hyperteminal on the windows machine on the other side correctly.But when i typed something on the other side(in hyperterminal) it was not reaching here properly.That is, once it displayed some ..2 or 3 characters correctly and failed to show the rest.

(!) [Ben] Hmmm... that _does_ sound like a speed problem. If the port on the other machine was set to, say, 57600, and this machine was set to 9600, it would "miss" most of the characters sent to it (although the classic speed problem shows up as random garbage mixed with a few of the characters being sent.)

(?) When hyperteminal was used on these side also ..everything was ok. So i guess..there is no problem with the serial port.

Could this be some problem with the serial driver in linux.

i think the problem is more clear now...

sree

(!) [Ben] Wind*ws, depending on the version, sets the serial port speed to 57600 or 115200, if I remember correctly.
(!) [Chris G.] Hi sree,
You have got an interesting problem here. First, let me mention that I read Ben Okopnik's response, therefore, I will attempt to provide information that does not overlap his response. Take his response into consideration.
Let's pretend that your baud rates are the same on both sides. When you type on your Linux machine, the characters appear on the Hyperterminal display. So, you Linux machine can send, and your Hyperterminal machine can receive.
Now, when you type on your Hyperterminal machine, I get the impression, that the first few characters that you type appear on the Linux machine (my assumption may be wrong -- correct me if I am wrong). After that, when you type any more characters on your Hyperterminal machine, the Linux machine displays nothing. My first guess would be that flow is enabled on your Hyperterminal machine, and you are using a 3-wire connection.
Flow control being enabled would seem like a logical cause for your problem except for one thing. I get the impression that if you type ten characters on your Hyperterminal machine (excluding the enter key), that your ioctl() returns a value of ten. The results seem contradictory. I believe that you are telling me the truth -- therefore I am now confused.
One trick that I use to test a serial port on a computer is to test each serial port one at a time. Go ahead and remove the cable that connects your two computers. On your Hyperterminal computer, connect a serial cable to it, but, do not connect the other end of the cable to your Linux machine. On the cable, connect pins 2 and 3 together. This will connect your transmit data line to your receive data line. Bring up Hyperterminal and start to type characters. If things are working, you should see whatever you type appear on the display.
Do the same thing on your Linux machine. That is, connect a serial cable to the serial port of your Linux machine, and connect pins 2 and 3, of the connector, together. Bring up minicom, and go ahead and type characters on your Linux machine. If things are working, you should see whatever you type appear on the display of your Linux machine.
In both cases, we are performing a loopback test. If you do not see a proper display, you have isolated the machine for which a problem exists on a serial port.
If you do see proper display, I would expect the following causes: 1. Mismatched baud rates between the two computers (maybe not) 2. Problems with your RS-232 drivers (voltage level problems).
If you don't see proper display on each machine, I would expect the following causes: 1. Problems with your RS-232 drivers. 2. Flow control enabled (you could disable flow control)
Try Ben's suggestions too. My analysis may be incomplete.
Let me know what happens, and good luck, Chris Gianakopoulos

(?) Hi chris amd ben,

Sorry for the delay in replying as there was some problem with our mailserver.

(!) [Chris G.] No problem.

(?) Now, when you type on your Hyperterminal machine, I get the impression, that the first few characters that you type appear on the Linux machine

Not always...it appeared rarely...

(!) [Chris G.] Hmmmmmm.....

(?) (my assumption may be wrong -- correct me if I am wrong). After that, when you type any more characters on your Hyperterminal machine, the Linux machine displays nothing. My first guess would be that flow is enabled on your Hyperterminal machine, and you are using a 3-wire connection.

Hardware Flow Control is enabled in hyperterminal(That's the default..) That is set in minicom also.I changed only the baudrate. (I am in doubt about this cable whether it is using 3 pins only or more)

But the cable I use in my program uses the rts,cts pins and uses them in data transmission since the rtu expects that.Everything is working fine in 686 machine.

Flow control being enabled would seem like a logical cause for your problem except for one thing. I get the impression that if you type ten characters on your Hyperterminal machine (excluding the enter key), that your ioctl() returns a value of ten. The results seem contradictory. I believe that you are telling me the truth -- therefore I am now confused.

I haven't checked the ioctl call with hyperterminal.I am using minicom with hyperterminal.

(!) [Chris G.] Understood.

(?) The ioctl call is used in my program that communicates with an rtu through serial port. I am sending some data to the port and expecting some data in return. The ioctl call returns the no of bytes available on the port. But the read function fails to read them and returns zero bytes.

By using hyperterminal on both computers communication is perfect. So that proves there is no problem with port or cable.

(!) [Chris G.] I agree.

(?) If there is some problem with the settings mismatch in hyperterminal and minicom ...how is the communication working correctly in one direction?

(!) [Chris G.] The direction that is not working would be the one that is not getting the proper handshake -- if my flow control idea is valid.

(?) I will check with flow disabled in hyperterminal.

I want to know whether this is a problem of linux? I am asking this because ..when hyperterminal was used on both sides communication was working. Have anybody encountered this type of problem in 586.

(!) [Chris G.] That is what is odd. A serial port is not really associated with a processor -- Ok, ok, some embedded microprocessors do have lots of serial devices incorporated into their package. I would think that you are using something like a 16450, 16550, 8251, or someother UART or USART. It is just a device that is addressed by the Intel processor in I/O space. I understand what you mean, though. When you say 586, you are referring to your particular 586 motherboard with its oddly behaving serial interface (as far as its behavior with Linux is concerned).

(?) I am waiting to check this problem with another 486 machine.

I wan't to know more about the flow control aspect. What is its significance?

(!) [Heather] That's "ready to send" and "clear to send". One system says it wants to .. has data ready to go... and the other system has to give it the thumbs up... clear, you can send now.
(!) [Chris G.] When you want to send, you assert rts. Your system will monitor cts, and it will not send the data unless cts is asserted (when I say asserted, I mean set to an active state). If the computer, at the other end of the link, does not activate the cts line, your system will never send the data byte. It will be flow controlled. As a quick test, you could make a cable that jumpers rts to cts. That would be pins 7 and 8 on your db9 connector.

(?) I am using the rts/cts pins in my program. I do it like this.. I will make the rts pin high before writing and wait for cts to become low. Only when cts becomes low will i write to the port. However i am not using any setting/resetting while reading the port. Everything is working fine in 686.

bye sree

(!) [Chris G.] Okay. You seem to be troubleshooting things in a good manner. Don't forget to look at Ben O's suggestions, too.


This page edited and maintained by the Editors of Linux Gazette Copyright © 2001
Published in issue 73 of Linux Gazette December 2001
HTML script maintained by Heather Stern of Starshine Technical Services, http://www.starshine.org/


[ Table Of Contents ][ Answer Guy Current Index ] greetings   Meet the Gang   1   2   3   4   5   6   7   8   9 [ Index of Past Answers ]