In many serial communications systems, flow-control techniques are widely used to ensure that a fast transmitter won’t swamp a slower receiver with data. A simple and commonly used technique for flow control to transfer ASCII data over asynchronous data links is the “XON/XOFF” method. This is a purely software-based “in-band” signaling scheme that doesn’t need any extra hardware lines or controls.
Two reserved control characters of the ASCII character set, designated as XON (control Q or 11H) and XOFF (control S or 13H), are used for this purpose. Whenever the receiver sends an XOFF character during data transfer, the transmitter will stop transmission. It will resume transmission only after receiving an XON character.
This scheme, although very elegant, has two drawbacks. First, it can’t be used for binary data transfer in which special characters aren’t able to be earmarked. Second, in the case of full-duplex bidirectional data transfer, the transmitter must examine each and every data byte received to check for XON/XOFF, which is simply wasted overhead. Because many embedded multi-microprocessor systems employ full-duplex binary data transmission, these become serious drawbacks that are typically overcome by using hardware “out-ofband” flow control.
The method proposed here overcomes both of these shortcomings while preserving the other benefits of an “in-band” software-based flowcontrol scheme.
To realize this capability, there must be a means of identifying the XON/XOFF control signals from data bytes. This can be achieved on many popular UARTs by utilizing an obscure feature found in most UART devices. Most UARTs can transmit and recognize (interrupt on) what is called the “BREAK” condition. This is nothing but a “Space” or Low in the Transmit Line of duration equal to or greater than an entire async character transmission time (including stop bits) (Fig 1). In this method, the receiver can send a BREAK to toggle the Pause or Continue-Transmission state of the transmitter. However, if the transmitter and the receiver aren’t synchronized at the start, the above scheme will not work properly.
Therefore, we need to identify specifically the Pause or Continue command from the receiver, rather than just toggling between the two states. To accomplish this, the XON or XOFF code is sent immediately following the transmission of a “BREAK” character. The transmitter looks at the data immediately following a BREAK detection interrupt to decide whether to pause or resume transmission. With this arrangement, the method becomes data-transparent and can be used for binary data transfer. Also, because the UART can interrupt the CPU on detection of the BREAK condition, the CPU won’t waste time looking at each data byte to detect XON/XOFF.
The C program demonstrates this technique using data transfer between two PCs (with 8250 compatible UARTs) (see the listing). The PC COM ports are interconnected using a Null-Modem cable. Usually, each PC continuously transmits a stream of characters to the other. In the example, only printable ASCII characters (digits 0 to 9) are sent to simplify displaying of the data. Generally, though, any binary data can be sent.
When a key is pressed, an XOFF command is sent to the transmitter and the transmission is stopped. It will be resumed by pressing any key a second time by sending the Continue XON) command. Note that this example illustrates involves only the toggling of the state on receipt of a BREAK interrupt. It is simple to extend this by transmitting XON/XOFF codes following the BREAK to indicate the requested action (i.e., Pause or Continue.). In addition, the example demonstrates the use of an interrupt routine to recognize the BREAK.
To transmit a BREAK, Bit 6 (Set BREAK) of the Line Control Register is set to 1 (Fig. 2). The UART then makes its TX line Low until a zero is written to this bit. To make the duration of the break equate one character transmission delay, a NULL character (00 Hex) is transmitted. Bit 6 of the Line Status Register (Tx Machine Status) indicates when this delay is over, then the BREAK bit is reset. To enable detection of the BREAK, bit 2 of the Interrupt Enable Register (Interrupt-on-Rx-Error condition) is set during the UART initialization. Bit 0 set to 1 enables Receive Data interrupts. In the ISR, bits 1 and 2 of the Interrupt Identification Register indicate the interrupt type.
In this scheme, no CPU overhead is wasted examining each character to detect XON/XOFF characters. Also, because the BREAK isn’t a legitimate data character, it is datatransparent and can be used for binary data exchange. The program was compiled using Borland C version 4.5 and tested using two PCs interconnected as shown (Fig. 3).