Handshaking Configuration Options

This section describes the configuration that can be set to define the handshaking for a port.

Introduction

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.

iHandshake bit field

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

0x08

0x04

0x02

0x01

KConfigFailCTS

KConfigObeyCTS

KConfigSendXoff

KConfigObeyXoff

DTE

DTE

DTE

DTE

Bit
Description
Terminal

0x80

0x40

0x20

0x10

KConfigFailDCD

KConfigObeyDCD

KConfigFailDSR

KConfigObeyDSR

DTE

DTE

DTE

DTE

Bit
Description
Terminal

0x800

0x400

0x200

0100

KConfigFailDTR

KConfigObeyDTR

KConfigFreeDTR

KConfigFreeRTS

DCE

DCE

DTE

DTE

Bit
Description
Terminal

0x8000

0x4000

0x2000

01000

KConfigFreeCTS

KConfigFreeDSR

KConfigFailRTS

KConfigObeyRTS

DCE

DCE

DCE

DCE

Bit
Description
Terminal

0x80000000

Bits 0x40000 to

0x20000

0x10000

KConfigWriteBufferedComplete

0x40000000 unused

KConfigFreeRI

KConfigFreeDCD

   

DCE

DCE

Flow control when sending

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.

Flow control when receiving

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 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.

Flow control thresholds

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.

Handshaking latency and buffer sizes

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.)

Internal FIFO Buffer Control

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.

Software Flow Control and Binary Data

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.

Changing software flow control characters

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.

Cancellation of reads and writes

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.

Handshaking capability checks

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 TCommCaps.iHandshake field to discover specific capabilities of the port.