|
12 <reference xml:lang="en" id="GUID-0E6C7017-E430-51C0-A5D6-1798B0DCC6BC"><title>Handshaking Configuration Options</title><shortdesc>This section describes the configuration that can be set to define the handshaking for a port. </shortdesc><prolog><metadata><keywords/></metadata></prolog><refbody><section><title>Introduction</title> <p>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. </p> <p>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 <codeph>TCommConfig</codeph> 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. </p> <p>Since multiple handshaking mechanisms may be active simultaneously, the handshaking is defined by a bit field called <xref href="GUID-36D2446E-E288-332B-9356-3DA0C3D8C989.dita"><apiname>TCommConfig.iHandshake</apiname></xref>. See the tutorials for examples which use this bitmask, for example <xref href="GUID-294EF1C3-E7EC-5B93-B4F4-ECA50DD6993F.dita">How to Terminate Write Requests Early: Tutorial</xref>. </p> </section> <section><title>iHandshake bit field</title> <p>The <xref href="GUID-FA42F645-D2A8-384B-9FE6-6495EACFA479.dita#GUID-FA42F645-D2A8-384B-9FE6-6495EACFA479/GUID-268250D5-7943-39ED-ABF4-77E6539DFEF2"><apiname>TCommConfigV01::iHandshake</apiname></xref> field is a bit field that can be used to set the handshaking for a port. The format of the bit field is: </p> <table id="GUID-287F6E31-8C77-5CED-BC87-46DF1C81485C"><tgroup cols="4"><colspec colname="col0"/><colspec colname="col1"/><colspec colname="col2"/><colspec colname="col3"/><thead><row><entry> Bit </entry> </row> <row><entry> Description </entry> </row> <row><entry> Terminal</entry> </row> </thead> <tbody><row><entry><p> <codeph>0x08</codeph> </p> </entry> <entry><p> <codeph>0x04</codeph> </p> </entry> <entry><p> <codeph>0x02</codeph> </p> </entry> <entry><p> <codeph>0x01</codeph> </p> </entry> </row> <row><entry><p> <codeph>KConfigFailCTS</codeph> </p> </entry> <entry><p> <codeph>KConfigObeyCTS</codeph> </p> </entry> <entry><p> <codeph>KConfigSendXoff</codeph> </p> </entry> <entry><p> <codeph>KConfigObeyXoff</codeph> </p> </entry> </row> <row><entry><p>DTE </p> </entry> <entry><p>DTE </p> </entry> <entry><p>DTE </p> </entry> <entry><p>DTE </p> </entry> </row> </tbody> </tgroup> </table> <p> </p> <table id="GUID-78EB8319-9C95-5275-B5CE-1CD2F2255979"><tgroup cols="4"><colspec colname="col0"/><colspec colname="col1"/><colspec colname="col2"/><colspec colname="col3"/><thead><row><entry> Bit </entry> </row> <row><entry> Description </entry> </row> <row><entry> Terminal</entry> </row> </thead> <tbody><row><entry><p> <codeph>0x80</codeph> </p> </entry> <entry><p> <codeph>0x40</codeph> </p> </entry> <entry><p> <codeph>0x20</codeph> </p> </entry> <entry><p> <codeph>0x10</codeph> </p> </entry> </row> <row><entry><p> <codeph>KConfigFailDCD</codeph> </p> </entry> <entry><p> <codeph>KConfigObeyDCD</codeph> </p> </entry> <entry><p> <codeph>KConfigFailDSR</codeph> </p> </entry> <entry><p> <codeph>KConfigObeyDSR</codeph> </p> </entry> </row> <row><entry><p>DTE </p> </entry> <entry><p>DTE </p> </entry> <entry><p>DTE </p> </entry> <entry><p>DTE </p> </entry> </row> </tbody> </tgroup> </table> <p> </p> <table id="GUID-9EC32691-4B38-5AE5-87E3-FE1B039DED7B"><tgroup cols="4"><colspec colname="col0"/><colspec colname="col1"/><colspec colname="col2"/><colspec colname="col3"/><thead><row><entry> Bit </entry> </row> <row><entry> Description </entry> </row> <row><entry> Terminal</entry> </row> </thead> <tbody><row><entry><p> <codeph>0x800</codeph> </p> </entry> <entry><p> <codeph>0x400</codeph> </p> </entry> <entry><p> <codeph>0x200</codeph> </p> </entry> <entry><p> <codeph>0100</codeph> </p> </entry> </row> <row><entry><p> <codeph>KConfigFailDTR</codeph> </p> </entry> <entry><p> <codeph>KConfigObeyDTR</codeph> </p> </entry> <entry><p> <codeph>KConfigFreeDTR</codeph> </p> </entry> <entry><p> <codeph>KConfigFreeRTS</codeph> </p> </entry> </row> <row><entry><p>DCE </p> </entry> <entry><p>DCE </p> </entry> <entry><p>DTE </p> </entry> <entry><p>DTE </p> </entry> </row> </tbody> </tgroup> </table> <p> </p> <table id="GUID-A575C70A-09AA-5B65-8BFC-F61F41A8DB76"><tgroup cols="4"><colspec colname="col0"/><colspec colname="col1"/><colspec colname="col2"/><colspec colname="col3"/><thead><row><entry> Bit </entry> </row> <row><entry> Description </entry> </row> <row><entry> Terminal</entry> </row> </thead> <tbody><row><entry><p> <codeph>0x8000</codeph> </p> </entry> <entry><p> <codeph>0x4000</codeph> </p> </entry> <entry><p> <codeph>0x2000</codeph> </p> </entry> <entry><p> <codeph>01000</codeph> </p> </entry> </row> <row><entry><p> <codeph>KConfigFreeCTS</codeph> </p> </entry> <entry><p> <codeph>KConfigFreeDSR</codeph> </p> </entry> <entry><p> <codeph>KConfigFailRTS</codeph> </p> </entry> <entry><p> <codeph>KConfigObeyRTS</codeph> </p> </entry> </row> <row><entry><p>DCE </p> </entry> <entry><p>DCE </p> </entry> <entry><p>DCE </p> </entry> <entry><p>DCE </p> </entry> </row> </tbody> </tgroup> </table> <p> </p> <table id="GUID-6C7A78E2-E612-592F-B222-91A5F6E501AE"><tgroup cols="4"><colspec colname="col0"/><colspec colname="col1"/><colspec colname="col2"/><colspec colname="col3"/><thead><row><entry> Bit </entry> </row> <row><entry> Description </entry> </row> <row><entry> Terminal </entry> </row> </thead> <tbody><row><entry><p> <codeph>0x80000000</codeph> </p> </entry> <entry><p>Bits 0x40000 to </p> </entry> <entry><p> <codeph>0x20000</codeph> </p> </entry> <entry><p> <codeph>0x10000</codeph> </p> </entry> </row> <row><entry><p> <codeph>KConfigWriteBufferedComplete</codeph> </p> </entry> <entry><p>0x40000000 unused </p> </entry> <entry><p> <codeph>KConfigFreeRI</codeph> </p> </entry> <entry><p> <codeph>KConfigFreeDCD</codeph> </p> </entry> </row> <row><entry/><entry/><entry><p>DCE </p> </entry> <entry><p>DCE </p> </entry> </row> </tbody> </tgroup> </table> </section> <section><title>Flow control when sending</title> <p>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. </p> <p>Hardware flow control causes transmission to stop when any specified permutation of the modem input line <keyword>CTS</keyword>, <keyword>DSR</keyword> or <keyword>DCD</keyword> are low and the flow is only resumed when the relevant lines go high. </p> <p>Software flow control causes transmission to stop when a configurable <keyword>XOFF</keyword> character is received and transmission is only resumed when the corresponding <keyword>XON</keyword> character is received. </p> <p>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. </p> </section> <section><title>Flow control when receiving </title> <p>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. </p> <p>Hardware flow control is where we drop the signal levels on one or both of the modem outputs <keyword>DTR</keyword> and <keyword>RTS</keyword> to stop the incoming data and then raise the signals again to restart. </p> <p>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 <codeph>KConfigSendXoff</codeph> bit of <codeph>iHandshake</codeph>, while hardware flow control is enabled by setting either one or both of the <codeph>KConfigFreeRTS</codeph> and <codeph>KConfigFreeDTR</codeph> bits, which indicate whether or not the RTS and DTR outputs are under driver control or follow the user-defined settings. See <xref href="GUID-B6392845-B724-35FF-80A5-3911B64535B9.dita"><apiname>SetSignals()</apiname></xref> for more information. </p> <p>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. </p> </section> <section><title>Flow control thresholds</title> <p>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 <keyword>high water |
|
13 mark</keyword>), 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. </p> <p>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 <keyword>low water |
|
14 mark</keyword>) 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. </p> <ul><li id="GUID-3311BE0E-1D5A-5A51-A5C7-86EE0EA5BFAC"><p>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. </p> </li> <li id="GUID-934E819E-CD25-55E2-9969-0DBED0F44EBE"><p>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 </p> </li> <li id="GUID-F08D93E3-9714-5E80-9454-CDB1442C9CC5"><p>It is possible to force the serial drivers to use this more stringent high water mark when using hardware flow control. </p> </li> <li id="GUID-4F977649-CC0B-5050-B399-4996D826C4F7"><p>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. </p> </li> </ul> </section> <section><title>Handshaking latency and buffer sizes</title> <p>It takes a finite amount of time to respond to flow control and other handshaking events. The term <keyword>latency</keyword> 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. </p> <p>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. </p> <p>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 <xref href="GUID-3B4E8ED5-72F7-3E51-B188-3C1045526DDF.dita#GUID-3B4E8ED5-72F7-3E51-B188-3C1045526DDF/GUID-A82AF127-0CCC-364B-9331-E0E40874FA4B"><apiname>RComm::SetReceiveBufferLength()</apiname></xref>. In the situation just described, we would need to set a receive buffer size of around 16K to guarantee no data loss. </p> <p>(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.) </p> </section> <section><title>Internal FIFO Buffer Control</title> <p>As well as the buffers in the serial port drivers, the components used to implement many RS232 ports include a small internal <keyword>FIFO</keyword> buffer which can be switched on or off. The presence of such an internal buffer is signified by the <codeph>iFifo</codeph> byte in <codeph>TCommCaps</codeph> being set, and the FIFO can be enabled or disabled by setting or clearing the <codeph>iFifo</codeph> byte in <codeph>TCommConfig</codeph> 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. </p> </section> <section><title>Software Flow Control and Binary Data</title> <p>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. </p> <p>Different policies are used for solving Software Flow Control when transmitting binary data. The policy depends on the direction in which the handshaking operates: </p> <ul><li id="GUID-C3F42B0B-E2F9-597B-BA72-A9777850C257"><p>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 <codeph>KConfigObeyXoff</codeph> bit in <codeph>iHandshake</codeph> to enable software flow control when sending. </p> </li> <li id="GUID-86E3CB07-E515-5480-9A4A-6F5AEB1F82ED"><p>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 <codeph>KConfigSendXoff</codeph> bit in <codeph>iHandshake</codeph> to enable software flow control only when receiving. </p> </li> </ul> </section> <section><title>Changing software flow control characters</title> <p>The default software flow control characters are ASCII DC1 (decimal 17) for XON and DC3 (decimal 19) for XOFF. </p> <p>Change the <codeph>iXonChar</codeph> and <codeph>iXoffChar</codeph> fields of <codeph>TCommConfig</codeph> 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 <codeph>iHandshake</codeph> field. </p> </section> <section><title>Cancellation of reads and writes</title> <p>The next three of the handshaking bitmasks are named <codeph>KConfigFailxxx</codeph>, 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. </p> <p>An <codeph>RComm</codeph> send or receive request can be set to terminate early with a <xref href="GUID-4F00C029-B015-3BD6-A492-BAA6F4F6ED1B.dita"><apiname>KErrCommsLineFail</apiname></xref> error if any specified combination of the control lines fail. To enable this, set one or more of the handshaking bits <xref href="GUID-89B7755D-693B-3AA4-9FB9-456AC2DB64C3.dita"><apiname>KConfigFailCTS</apiname></xref>, <xref href="GUID-DA744B94-D03B-3D99-B4E2-769A6AB6AB45.dita"><apiname>KConfigFailDSR</apiname></xref>, and <xref href="GUID-E9728D97-73CF-3F9A-8C92-94F3D1AC49B8.dita"><apiname>KConfigFailDCD</apiname></xref>. If multiple failure conditions are enabled, an application can use <xref href="GUID-3B4E8ED5-72F7-3E51-B188-3C1045526DDF.dita#GUID-3B4E8ED5-72F7-3E51-B188-3C1045526DDF/GUID-B2A751BB-6784-31B8-8808-F5BFC087427B"><apiname>RComm::Signals()</apiname></xref> to discover the reason for the comms line failure. </p> </section> <section><title>Handshaking capability checks</title> <p>As with the speed and data format, it is possible to use <xref href="GUID-3B4E8ED5-72F7-3E51-B188-3C1045526DDF.dita#GUID-3B4E8ED5-72F7-3E51-B188-3C1045526DDF/GUID-4A6ECC68-EBC7-3B6C-94AE-9272669F6FF2"><apiname>RComm::Caps()</apiname></xref> to find out whether a specified handshaking mode is supported or not. Set the matching bitmasks with the <xref href="GUID-8FD727E7-68D6-3E80-913D-6ACBEB092559.dita"><apiname>TCommCaps.iHandshake</apiname></xref> field to discover specific capabilities of the port. </p> </section> </refbody></reference> |