This section describes the configuration that can be set to define the handshaking for a port.
In general, the speed at which data is transmitted is deliberately set to be faster than the speed with which it can be processed by the receiver. This results in a highly efficient utilisation of the available bandwidth and data transfers complete faster. When transmitting data over a line leased by time, such as a phone line, the higher utilisation results in a saving of money.
Consequently, input buffers linked to reliable flow
control mechanisms are essential for effective communications, as
the receiver needs a mechanism for throttling back the transmitter
and telling it to stop sending data. The TCommConfig
package enables flow control to be configured at the driver level,
and so applications do not need their own flow control. This reference
page describes the handshaking options available to control the flow
of data.
Since multiple handshaking mechanisms may be active simultaneously, the handshaking is defined by a bit field called TCommConfig.iHandshake. See the tutorials for examples which use this bitmask, for example How to Terminate Write Requests Early: Tutorial.
The TCommConfigV01::iHandshake field is a bit field that can be used to set the handshaking for a port. The format of the bit field is:
Bit | |||
---|---|---|---|
Description | |||
Terminal | |||
|
|
|
|
|
|
|
|
DTE |
DTE |
DTE |
DTE |
Bit | |||
---|---|---|---|
Description | |||
Terminal | |||
|
|
|
|
|
|
|
|
DTE |
DTE |
DTE |
DTE |
Bit | |||
---|---|---|---|
Description | |||
Terminal | |||
|
|
|
|
|
|
|
|
DCE |
DCE |
DTE |
DTE |
Bit | |||
---|---|---|---|
Description | |||
Terminal | |||
|
|
|
|
|
|
|
|
DCE |
DCE |
DCE |
DCE |
The first four of the handshaking bitmasks control what type of flow control is obeyed when sending data. Any combination of hardware flow control and software flow control can be set up.
Hardware flow control causes transmission to stop when any specified permutation of the modem input line CTS, DSR or DCD are low and the flow is only resumed when the relevant lines go high.
Software flow control causes transmission to stop when a configurable XOFF character is received and transmission is only resumed when the corresponding XON character is received.
The most common form of flow control for transmitted data is CTS handshaking. CTS handshaking causes flow to stop when the CTS input is low.
The next three of the handshaking bitmasks controls the type of flow control when receiving data, in the expectation that the transmitter will stop sending when instructed to. Any combination of hardware flow control or software flow control can be set.
Hardware flow control is where we drop the signal levels on one or both of the modem outputs DTR and RTS to stop the incoming data and then raise the signals again to restart.
Software flow
control is where we transmit our XOFF character to stop the incoming
data and then transmit XON when we are ready to resume. Software flow
control is enforced by setting the KConfigSendXoff
bit of iHandshake
, while hardware flow control
is enabled by setting either one or both of the KConfigFreeRTS
and KConfigFreeDTR
bits, which indicate whether
or not the RTS and DTR outputs are under driver control or follow
the user-defined settings. See RComm::SetSignals()
for more information.
The most common form of flow control when receiving data is RTS handshaking. In RTS handshaking we lower our RTS output when we are not able to receive anything and then raise it when we are once again in a position to handle incoming data.
Since the rate at which data is being placed in the input buffer can exceed the rate at which it is being taken out, it is probable that the buffer will gradually fill up. When a particular point (the high water mark), is reached and a suitable handshaking mode is enabled, a flow control event is triggered. This could be the transmission of an XOFF character or the lowering of either the RTS or DTR output signals, or any combination of these events.
Whatever action is taken will be taken as a signal by the transmitter, which will stop sending. The inward flow of data will then stop, and the buffer will begin to empty. When a particular point (the low water mark) is reached, a matching flow control event is triggered, which could be the transmission of an XON character or the raising of the RTS or DTR signals, or any combination of these events.
If hardware flow control is the only kind enabled for reception, the high water mark is normally set at the 75% full level, at which point one or both of the output signal will be lowered.
If XON/XOFF software flow control is enabled for reception (even if hardware handshaking is also enabled), the high water mark is set to be 5 bytes below the 50% full level, at which point an XOFF character is transmitted for every other character received. This more stringent level is deemed necessary because it normally takes longer for a transmitter to respond when software handshaking is being used
It is possible to force the serial drivers to use this more stringent high water mark when using hardware flow control.
In all cases, the low water mark is set at the 25% full level. Depending on the type of flow control enabled, any combination of sending an XON character or raising one or both of the output signals will occur at this point.
It takes a finite amount of time to respond to flow control and other handshaking events. The term latency is generally used in this context to refer to the time taken between the occurrence of a particular event and the response to it. The maximum handshaking latency in ultimately depends on the frequency of the system clock.
However, the high and low watermarks for inward flow control need to allow for the response times of the systems with which our serial port is communicating rather than the latency associated with our own responses. Suppose it takes one second for a system to which we are connected to respond to a request to stop sending data, and suppose our serial port is running at 38400 bps. This means that we should have at least 3840 bytes free in our buffer when the high water mark is reached, otherwise we may lose incoming data if our buffer overflows.
The input buffer levels at which these flow control
events occur are not something that can be altered. Instead, the recommended
way of adjusting the precise times at which flow control events will
occur is to alter the size of the receive buffer using the member
function RComm::SetReceiveBufferLength()
. In the
situation just described, we would need to set a receive buffer size
of around 16K to guarantee no data loss.
(In practise, it may well be possible to get away with a smaller buffer than this even when the sending system takes one second to respond, as we will almost certainly be removing data from the buffer during the latency period. However, the precise calculations would clearly depend on the processing requirements of the receiving application.)
As well as
the buffers in the serial port drivers, the components used to implement
many RS232 ports include a small internal FIFO buffer
which can be switched on or off. The presence of such an internal
buffer is signified by the iFifo
byte in TCommCaps
being set, and the FIFO can be enabled or disabled
by setting or clearing the iFifo
byte in TCommConfig
as appropriate. The default state is for any
FIFOs to be automatically enabled, as even a 16 byte FIFO (the usual
size) significantly reduces the load on the processor during serial
i/o operations, and applications should not disable this without good
reason.
A problem with Software Flow Control is that the characters that are inserted in the data to control the flow may also appear in the original data. Hardware flow control is the recommended handshaking method whenever there is a requirement for the transfer of binary data in either direction.
Different policies are used for solving Software Flow Control when transmitting binary data. The policy depends on the direction in which the handshaking operates:
Enabling software
flow control when sending does not affect the transmitted data but
it can affect the received data. When either of the flow control characters
are received, they are acted on by the serial drivers as required
and are not passed through to the client application. This policy
can be used to send data to a device such as a printer which implements
XON/XOFF handshaking. This policy is not recommended to receive binary
data from a modem. Set the KConfigObeyXoff
bit in iHandshake
to enable software flow control when sending.
Enabling software
flow control only when receiving has no effect on data transferred
in either direction. This does not prevent an application either receiving
or transmitting XON or XOFF. If an application uses XON and XOFF characters,
the meaning of these characters embedded in binary data being sent
is not going to be clear. Set the KConfigSendXoff
bit in iHandshake
to enable software flow control
only when receiving.
The default software flow control characters are ASCII DC1 (decimal 17) for XON and DC3 (decimal 19) for XOFF.
Change the iXonChar
and iXoffChar
fields of TCommConfig
to change the default software flow control
characters. Changing the defaults is not recommended. Setting the
defaults to zero is not recommended since this can cause unpredictable
behaviour. Disabling flow control must be done through the iHandshake
field.
The next
three of the handshaking bitmasks are named KConfigFailxxx
, and can be used to set up the conditions under which pending data
transfers are automatically cancelled. For example, this can manage
attempts to send data over a cable that has been pulled out, or disconnection
of a modem during a file download.
An RComm
send or receive request can be set to terminate early with a KErrCommsLineFail error if any specified combination of
the control lines fail. To enable this, set one or more of the handshaking
bits KConfigFailCTS, KConfigFailDSR, and KConfigFailDCD. If multiple failure conditions
are enabled, an application can use RComm::Signals()
to discover the reason for the comms line failure.
As with the
speed and data format, it is possible to use RComm::Caps()
to find out whether a specified handshaking mode is supported or
not. Set the matching bitmasks with the TCommCapsV01.iHandshake field to discover specific capabilities of the port.