Unexpected results testing serial loopback using echo and cat

catechoserial port

So I have a standard RS232 serial port that is looped back to itself by simply running a wire from Tx to Rx. I'm testing loopback by running echo and cat in two separate terminals:

cat /dev/ttyS1
echo "hi" > /dev/ttyS1

My issue is with the output. I would expect to see one "hi" come back on the terminal running cat but instead I get this:

hi
[2 newlines]
hi
[4 newlines]
hi
[8 newlines]
hi
[16 newlines]
hi
[32 newlines]
hi

…and so on until I ctrl+c cat.

After interrupting cat, if I run it again it will not output "hi"s until I run echo a second time.

Is this normal? Any idea why I'm seeing this behavior?

Edit: By newline, I mean ASCII 0x0A. There are no carriage returns in this output.

Best Answer

Thanks to the second comment by Bruce, I was able to figure out the problem on my own.

After running stty -a -F /dev/ttyS1, there were 3 options I found to contribute to the problem: "echo", "onlcr", and "icrnl".

Since this serial port is looped back to itself, here is what happened after running echo "hi" > /dev/ttyS1:

  1. The echo command appends a newline to the end of the message by default, so "hi" + LF is sent out to /dev/ttyS1
  2. Because "onlcr" was set, the serial device converted the LF to CRLF so the physical message sent out the Tx line was "hi" + CRLF
  3. Because "icrnl" was set, the physical messaged received on the Rx line converted the CR to LF. So the message outputted by 'cat' was "hi" + LFLF.
  4. Because "echo" was set, the message received on the Rx ("hi" + LFLF), was then sent back out on the Tx line.
  5. Because of onlcr, "hi" + LFLF became "hi" + CRLFCRLF.
  6. Because of icrnl, "hi" + CRLFCRLF became "hi" + LFLFLFLF
  7. Because of echo, "hi" + LFLFLFLF was then sent out the Tx

And so on...

In order to fix this problem, I ran the following command:

stty -F /dev/ttyS1 -echo -onlcr

Disabling "echo" prevents an infinite loop of messages and disabling "onlcr" prevents the serial device from converting LF to CRLF on output. Now cat receives one "hi" (with a single newline!) for each time I run echo.

CR = carriage return (ASCII 0x0D); LF = line feed or newline (ASCII 0x0A)

Related Question