Page 1 of 1

Serial ports - carrier detect question

Posted: Fri Mar 20, 2015 11:14 am
by Malleus
Hi there,

I'm not really sure if this a wiring question, a Linux question, or a software question. But I figured General Programming was probably the best place for it.

My OS is still in a pretty basic state. I've been progressing (slowly) using a quick set of routines to dump information out to a "serial port". The main device I use for testing is a Raspberry Pi, which doesn't have a full serial port - just a mini-UART. Basically, no parities or flow control. So I've just had an 8N1 connection, Rx->Tx, Tx->Rx wiring. All good.

I've recently been writing a more complete serial port driver which (on the Pi) commandeers some GPIO pins and adds support for RTS/CTS and XON/XOFF flow control. Works well; happy with that.

However, in the near future I want to support carrier detection and this is where its getting complicated. If hardware flow control is enabled (RTS/CTS) then I want the OS to know if another computer connects to that serial port, and when it disconnects. Essentially, the OS program that is going to use the serial port (when the debugging is removed) needs to reset when the connection to the remote terminal ends.

Since RTS/CTS is used for flow, I thought DTR from the remote computer might go to a DCD pin on the Pi. But on Linux, PuTTY doesn't seem to change the state of DTR when it connects (if RTS/CTS flow control is in use). Note: I'm not sure whether DTR->DCD can even work like that. This seems to be a case of a null-modem connection, but the whole carrier detect thing seems to have been solely designed for modems telling a host computer when a line is available.

I suppose my questions are:
  • Can DTR be used to support DCD? Do other terminal packages on Linux/Windows/Mac etc. respond as I need them to? i.e. Using RTS/CTS for flow, and changing the state of DTR when they connect?
  • If not, is there a standard way of detecting the presence of another machine in a null-modem situation?
If the worst comes to the worst, I could make a custom connection (possibly using bespoke software). But it would be much better if someone could just connect the device (e.g. to the Pi) to their computer using a USB serial port, and then access the functionality using standard terminal software.

BTW I have a 3.3v USB serial adapter that I'm currently using. If you want to see the pins that it has available - http://i00.i.aliimg.com/wsphoto/v3/1127 ... 2-0-To.jpg

Many thanks.

M

Re: Serial ports - carrier detect question

Posted: Thu Apr 28, 2016 2:55 pm
by Don
Malleus wrote: I've recently been writing a more complete serial port driver which (on the Pi) commandeers some GPIO pins and adds support for RTS/CTS and XON/XOFF flow control. Works well; happy with that.
Note that you need to think carefully about how the device with which you are communicating reacts to changes in flow control/handshaking. I.e., just because you say "STOP" doesn't mean the device will be able to stop-on-a-dime. The other device might not see your "directive" until it has already committed additional characters to transmit. So, if you haven't made provisions to handle "a few more" (where "few" is a dubious term), you can experience lost characters or overruns.

Consider that sending a flow control character requires a full character transmission time AFTER the character has been placed in the serializer (which can be one or more character times after you have passed it to the UART hardware) before the other device will even see it as "received". [neglecting transmission times]

Then, the far device has to identify that as a request to throttle output and opt not to push additional characters into its UART. Even though there may alrady be characters enqueued IN that UART!

For hardware handshaking, you also have to make assumptions about how quickly the far end device can "notice" the change in state: is it interrupt driven? what level IRQ? or, polled? (some devices examine the line just as they are getting ready to load the Tx register in the UART and defer that action IF they sense they are being held off)

Note that you should probably also arrange for a means of passing error information up "in-band" so a process can know where an overrun occurred in the data stream -- instead of just "it happened". Likewise, encode special operations in-band so you can insert things like long breaks WHERE YOU WANT THEM instead of asynchronously wrt the data stream (i.e., flush()-ing the output buffer before forcing spacing)
<carrier detect>
Can DTR be used to support DCD? Do other terminal packages on Linux/Windows/Mac etc. respond as I need them to? i.e. Using RTS/CTS for flow, and changing the state of DTR when they connect?
Computers and tty's are DTE. Chances are, you are NOT designing a modem (DCE).

A DTE asserts DTR to indicate to the DCE (EIA232 was written with the notion of DTE<->DCE) that it is "ready". Likewise, the DCE uses DCD to indicate when it is ready.

Historically (RS232 has been bastardized over the years), the DTE asserts DTR to tell the DCE (modem), "OK, you can now perform your function" (i.e., handle incoming calls). When a call arrived, the DCE (modem) would assert DCD to alert the DTE of the call. When the caller "hangs up", DCD is released and the computer (DTE) realizes that the connection has been broken.

Likewise, if the computer releases DTR, the modem knows to abort the connection.

Usually, there are two devices associated with each "serial port"; one that blocks until DCD is present (useful for waiting for an incoming call -- from a modem) and one that doesn't so you can talk to the modem itself -- or, another DTE via null modem! (imagine two DTE's each waiting for the other to indicate their readiness).

There are also control flags (e.g., CLOCAL) that can dynamically alter the behavior of the driver. You should probably consult termios(3), stty(1), etc. to see what hooks you may want/need to implement.
If not, is there a standard way of detecting the presence of another machine in a null-modem situation?
[/quote]

A null-modem essentially twists the DCD/DTR signals. So, if two DTE devices are intercommunicating, each one can use DTR to signal to the other it's presence/readiness -- as well as its abandonment of the connection.

[But, again, the tty drivers in each have to be configured to do this -- either explicitly with a termios(3) call or implicitly in the configuration of the device that is being used for the interface]

<shrug> Hopefully clarifies the situation a bit. A comprehensive tty driver is really a fairly substantial bit of code to write -- and test!

Good luck!