TIP: 35
Title: Enhanced Support for Serial Communications
Version: $Revision: 1.12 $
Author: Rolf Schroedter <[email protected]>
State: Final
Type: Project
Vote: Done
Created: 06-Jun-2001
Post-History:
Tcl-Version: 8.4
~ Abstract
Tcl's support for RS-232 is very rudimentary. Mainly it allows to
setup the communication rate [[fconfigure -mode]] and to read and
write data with the standard Tcl functions. Real serial
communications are often more complex. Therefore it is proposed to
add support for hardware and software flow control, polling RS-232
(modem) status lines, and watching the input and output queue. This
is all to be implemented via additional [[fconfigure]] options.
~ Rationale
There is an undamped interest in serial communications, because it's
very easy to connect external hardware to a computer using the RS-232
ports.
However Tcl's support for serial communications is not complete. Real
applications often need more than setting the baud rate and to
read/write data bytes.
Especially if the external hardware is slow or the communication rate
is high one needs support for flow-control (hard- and software).
These features are provided by the operating system drivers, but Tcl's
[[fconfigure]] doesn't support it.
On the the other hand there are cases that the external hardware makes
static use of the RS-232 signals to signal external events via the
modem status lines or even to be powered by the RS-232 control lines.
Additionally for non-blocking serial I/O it may be interesting for the
Tcl application to know about the status of the input and output
queues to read a fixed size block or to support communication
timeouts.
At this opportunity it is proposed to move the documentation of the
serial port fconfigure options form the ''open.n'' man-page to
''fconfigure.n''.
~ Specification
It is proposed to have following set of [[fconfigure]] options for
serial communications:
-mode baud,parity,data,stop: ''(Windows and Unix)''. Already
implemented.
-handshake mode: ''(Windows and Unix)''. This option is used to
setup automatic handshake control. Note that not all handshake
modes maybe supported by your operating system. The mode
parameter is case-independent.
> If mode is ''none'' then any handshake is switched off.
''rtscts'' activates hardware handshake. For software handshake
''xonxoff'' the handshake characters can be redefined with
[[fconfigure -xchar]]. An additional hardware handshake
''dtrdsr'' is available only for Windows. There is no default
handshake configuration, the initial value depends on your
operating system settings. The -handshake option cannot be
queried, because the operating system settings may be ambiguous.
-xchar {xonChar xoffChar}: ''(Windows and Unix)''. This option is
used to change the software handshake characters. Normally the
operating system default should be DC1 (0x11 hex) and DC3 (0x13
hex) representing the ASCII standard XON and XOFF characters.
When queried -xchar returns a list of two characters representing
the XON and XOFF characters respectively.
-timeout msec: ''(Windows and Unix''. This option is used to set
the timeout for blocking read operations. It specifies the
maximum interval between the receiption of two bytes in
milliseconds. For Unix systems the granularity is 100 milliseconds.
The -timeout option does not affect write operations or
nonblocking reads. This option cannot be queried.
-ttycontrol {signal boolean signal boolean ...}: ''(Windows and
Unix)''. This option is used to setup the handshake output lines
permanently or to send a BREAK over the serial line. The
''signal'' names are case-independent.
> {RTS 1 DTR 0} sets the RTS output to high and the DTR output to
low. For POSIX systems {BREAK 1} sends a break signal
(zero-valued bits) for 0.25 to 0.5 seconds and {BREAK 0} does
nothing. For Windows the break is enabled and disabled with
{BREAK 1} and {BREAK 0} respectively. It's not a good idea to
change the RTS (or DTR) signal with active hardware handshake
''rtscts'' (or ''dtrdsr''). The result is unpredictable. The
-ttycontrol option cannot be queried.
-ttystatus: ''(Windows and Unix)''. The -ttystatus option can only
be queried. It returns the current modem status and handshake
input signals. The result is a list of signal,value pairs with a
fixed order, e.g. {CTS 1 DSR 0 RING 1 DCD 0}. The ''signal''
names are returned upper case.
-queue: ''(Windows and Unix)''. The -queue option can only be
queried. It returns a list of two integers representing the
current number of bytes in the input and output queue respectively.
-sysbuffer inSize:
-sysbuffer {inSize outSize}: ''(Windows only, Unix ?)''. This option
is used to change the size of Windows system buffers for a serial
channel. Especially at higher communication rates the default
input buffer size of 4096 bytes can overrun for latent systems.
The first form specifies the input buffer size, in the second form
both input and output buffers are defined.
-pollinterval msec: ''(Windows only)''. Already implemented.
-lasterror: ''(Windows only, Unix?)''. Already implemented for
Windows.
~ Implementation Details
For Unix (''termios.h'') systems the proposed changes are very
straight forward, because Unix channels can be configured blocking or
non-blocking. One only needs to add the serial [[fconfigure]] options
calling the appropriate ''ioctl()'' functions to configure the serial
port.
For Windows reading and writing files is generally blocking.
Especially with activated handshake the serial communication can stop
forever. Therefore the Windows implementation needs at least a
writing thread preventing Tcl's main application to block.
Additionally Windows provides a reach set of special APIs for serial
communication which needs to be translated to [[fconfigure]] options.
There is one special point about Windows: For making multiple threads
accessing a serial port, it needs to be opened with the OVERLAPPED
flag set. Tcl detects a serial port only after opening it without the
OVERLAPPED flag. Therefore this port has to be reopened, which
requires a little change to ''tclWinChan.c'' and ''tclWinPort.h''.
Macintosh systems - ?
~ Changed Files
tclUnixChan.c: Add [[fconfigure]] options.
tclWinPort.h: Declare a new function ''TclWinSerialReopen()''
tclWinChan.h: Call ''TclWinSerialReopen()'' after detecting the
serial port.
tclWinSerial.c: Partial rewrite of Tcl's serial driver. The current
implementation only performs blocking output. Add [[fconfigure]]
options.
fconfigure.n: Serial [[fconfigure]] options should be documented
here.
open.n: Serial port filenames are documented here. Add a link to
[[fconfigure]] for additional serial options.
~ Timeouts
It has also been proposed to add a [[fconfigure -timeout]] option
specifying read and write timeouts. Together with a blocking read a
timeout could be used to wait for an expected number of data bytes
from the serial port. There are two arguments against timeouts:
1. Adding timeout to blocking I/O at the driver level radically
changes the behaviour of write operations. This adds a lot
of oddity to serial communications.
2. Timeouts can easily be implemented at Tcl level using non-blocking
I/O together with Tcl's event loop. Additional support is given
by [[fconfigure -queue]].
July 03, 2001:
On the other hand timeout for read operations can easily be
implemented in a cross-platform way by using the VMIN/VTIME settings
for Unix and the COMTIMEOUTS for Windows.
That's why the author finally agrees with the -timeout proposal.
~ Restore settings at close ?
It has also been proposed that Tcl should not restore the original
serial ports settings at [[close $chan]]. IMO it doesn't hurt,
because anyway an application should care about setting up the serial
port properly before using. Without restoring a Tcl script could be
used as a ''poor'' stty, considering however that Tcl
does not provide a complete control over serial settings.
So the proposal is to remove the current save/restore mechanism
from the Unix implementation for serial ports.
~ Source code patches
The patches have been uploaded to the sourceforge patch tracker:
ID=438509 TIP#35 Patches: Serial Port Enhancements
file=tip35patch.tgz
~ Copyright
This document has been placed in the public domain.