Putting Serial-Port Technology in Perspective, Part 2

Source: PC Mag May 26, 1992
Author: Douglas Boling

In the previous issue we reviewed the basic concepts of serial communications. This time, we'll discuss their specific implementations in today's PCs.

To provide for the full needs of a serial port, including the associated control lines for RS-232 communication, requires the services of a chip called a Universal Asynchronous Receiver/Transmitter (UART). The processor controls the UART by writing to its registers. The National Semiconductor INS-8250 UART was used in the original PC, and its register set has become the de facto standard for all serial ports on PC compatibles.

The starting address for the UART I/O ports will vary with the COM port being used. The original PC and PC-XT specified two serial ports, the first starting at I/O address 3F8h and the second port at I/O address 2F8h. The IBM PS/2 Hardware Technical Reference specifies eight possible serial ports with corresponding register locations. The PC BIOS keeps a list of the base addresses for the first four serial ports in the BIOS data area, starting at address 40:0h.

Sending data out through the serial port is a simple matter of writing the data bytes to the UART's Transmit Data register. Data the UART receives is made available to the processor in the Receive Data register. The CPU can poll the UART to determine when to read or write data to it, or, for maximum efficiency, the UART can be programmed to interrupt the CPU when data needs to be written or read.

Figure 1: There have been three major revisions of this register set. Dark blue indicates the changes that resulted from the first upgrade, the 16450 and 8250A chips. Light blue shows the revisions that accompanied the 16550. Pink shows the changes introduced with the IBM Type 3 serial port. Addresses 0 and 1 are also used for the Baud Divisor Latch Register.

The register set for the 8250 family of UARTs is shown in Figure 1. There have been three major revisions of this register set, all backward-compatible with earlier versions. The different shadings in the figure indicate which registers are included in each version. The figure also shows the functions of the individual bits in each of the registers, as well as their offset from the base address of the UART.

The Transmit Data and Receive Data registers are the first members in the 8250 set. If the processor writes a value to the Transmit Data register, the 8250 will immediately copy the data into an internal register and shift it out the transmit line of the serial port. The Receive Data register returns the last data to be received on the Receive Data line of the serial port. Note that if the Receive Data register is not read before the next byte has been received, the byte currently in the Receive Data register will be lost. The 8250 detects this condition and sets the overrun bit in the Line Status register.

The 8250 can be programmed to interrupt the processor when data needs to be read from the Receive Data register or written to the Transmit Data register. The Interrupt Enable register determines the conditions under which the UART will interrupt the processor. Specifically, the chip can be programmed to interrupt when it needs data, when the modem-status lines change, or when an error condition is detected. The modem-status interrupts occur whenever the Data Set Ready (DSR), Clear to Send (CTS), Data Carrier Detect (DCD), or Ring Indicator (RI) line has changed.

The error conditions detected are framing errors, parity errors, overrun errors, and break detection. When the processor reads the Interrupt Identification register, the reason for an interrupt can be determined. The primary control register for the 8250 is the Line Control register. The bits in the Line Control register control, among other things, the size of the data word, the number of stop bits, and the parity configuration. The data word size can be configured from five to eight bits, and one or two stop bits can be selected. Odd, even, or stick parity can also be set.

Bit 7 of the Line Control register controls access to the Baud Rate Divisor registers. When this bit is 1, the I/O address that normally accesses the Transmit Data and Receive Data registers and the Interrupt Enable register accesses the Baud Rate Divisor register instead.

The Baud Rate Divisor register is a 16-bit counter that determines the speed at which the 8250 transmits and receives data. To set the baud rate on a PC, the 8250 is driven by a 1.8432-MHz clock. With each clock cycle the Divisor register is decremented by one count. When the Divisor register reaches 0, the counter is reset and one bit of data is transmitted to or received from the UART.

Different baud rates can be set by placing different values in the Divisor register. A value of 96 (60h) in the register causes the 8250 to operate at example. Putting a value of 1,200 baud, for 12 in the Divisor register will result in a baud rate of 9,600. While the original PC only supported baud rates up to 9,600, the baud rate can be set to a maximum of 115,200 by using a divisor of 1. Note that the baud rate and bps rate are the same in a purely digital circuit such as that of the UART.

Figure 1: There have been three major revisions of this register set. Dark blue indicates the changes that resulted from the first upgrade, the 16450 and 8250A chips. Light blue shows the revisions that accompanied the 16550. Pink shows the changes introduced with the IBM Type 3 serial port. Addresses 0 and 1 are also used for the Baud Divisor Latch Register.

The Modem Control register allows the processor to set the RS-232 control lines that link the computer and modem. Bits 1 and 0 control the state of the modem's Request to Send (RTS) and Data Terminal Ready (DTR) lines. Bit 4 of this register loops the output of the transmitter back into the receiver, allowing the CPU to test most of the UART circuitry. Two general-purpose lines, Out 1 and Out 2, are provided. Out 1 is not used for PC serial ports, but Out 2 provides an additional control over the serial interrupt. The Out 2 bit must be set if the UART is to interrupt the processor, regardless of the state of the Interrupt Control register.

The Line Status register lets the processor read the state of the UART. When in a polling mode, the processor reads this register to determine when to read or write a byte of data from or to the UART. Any error conditions in the UART are also indicated in the Line Status register. The Modem Status register can be read to determine the state of the DCD, RI, DSR, or CTS line. The register also contains bits that are set when the state of any of those lines changes. This allows the processor to determine whether any of the lines has changed state since the last time the register was read.


The first upgrade on the 8250 was the 16450 UART, used in the PC AT. The 16450 provides a faster interface between the UART and the processor, but its only functional difference from the 8250 was the addition of a scratch register where the processor could store a byte of data. The PC Convertible, IBM's first laptop computer, used an 8250A, which is functionally identical to the 16450.

With the release of the PS/2 models in 1987 came the 16550 UART. Here the story gets a little muddy. The original PS/2 Models 50, 60, and 80 used an early version of the 16550 with a bug that disabled its main feature: a set of FIFO (first in, first out) queues that would have dramatically improved serial performance. The 16550 was replaced by the 16550A in the PS/2 Model 70. This fixed the bug in the FIFO section of the chip: improved versions of the Models 60 and 80 also use the 16550A. But the only way to determine if the 16550s in the PS/2 can use the FIFO queues is to test the serial chip. To confuse matters further, while improved versions of the PS/2 Model 50 incorporate the 16550A, IBM does not support using the FIFO queues on the Model 50!

The FIFO queues of the 16550A represent a significant development for serial communications. Faster serial-port and modem speeds mean that the CPU must spend more and more of its attention servicing the UART. For example, while the processor must read the UART every 6 milliseconds for a serial port at 1,200 baud, it must read the UART every 83 microseconds at 9,600 baud. This increased load is compounded by multitasking operating systems such as Enhanced-mode Windows and OS/2. In a multitasking operating system, the computer may be too busy to service the serial port.

This is where the FIFO queues come in. The queues consist of small buffers that hold up to 16 bytes of data. After filling the transmit FIFO queue with 16 bytes of data, the processor will not bother with the serial port again until all 16 bytes have been transmitted. The receive FIFO queue works the same way. When the 16550A UART needs service, the processor can read the last 16 bytes of data received. By using the FIFO queues, a 16550A UART running at 9,600 baud needs only the same service time as a 16450 UART running at 600 baud.

One additional register and several control bits have been added to the Interrupt Enable and Interrupt ID registers in the 16550A. The additional register is the write-only FIFO Control register. This register enables the transmit and receive FIFO queues, clears the queue contents, and sets the interrupt trigger level of the queues.

The 16550A can be set to interrupt the processor when the receive FIFO queue holds 1, 4, 8, or 16 bytes of data. Although the processor is interrupted when the appropriate level is reached, the UART continues to store its data in the FIFO queue. This allows the operating system enough time to complete its current task before having to service the UART.

The Interrupt ID register in the 16550A UART has been expanded to encompass interrupts from the FIFO queues. Bits 6 and 7 indicate whether the UART is in FIFO mode. Bit 3 indicates that the interrupt was caused by a character time-out condition in the receive FIFO queue. This interrupt allows the processor to read the last few words in a serial transmission when there are not enough data words received to trigger a FIFO full interrupt.

Using the FIFO queues in a serial communications program is really quite simple. Once initialized in FIFO mode, the UART will wait until the FIFO queue is full before interrupting the processor for service. The interrupt routine repeatedly reads the Receive register until the queue is empty. On the transmit side, a communications program writes enough words to the UART to fill the transmit FIFO queue. The UART will then not need data to transmit until the transmit FIFO queue has been exhausted.

To determine whether the UART in a computer contains usable FIFO queues, a program only needs to set some bits in the UART register and check the response. The assembly language routine, SERTYPE, in Figure 2 determines if the FIFO queues are available.


The routine in Figure 2 first sets bit 0 of the FIFO Control register and then reads the Interrupt Identification register. If bits 6 and 7 are both 0, the UART is a 16550 and the FIFO queues should not be used. If the bits are both 1, the UART is a 16550A and the queues can be used.

If the 16550A is detected, the PC identification bytes are checked to see if the computer is a PS/2 Model 50. If it is a Model 50, the routine indicates that the FIFO queues are not found, since this PC does not support FIFO mode. The routine then goes on to check for the presence of an enhanced DMA serial port. The new DMA serial port is the latest and most exciting development in PC serial ports.


The improvements provided by FIFO queues can be significantly augmented by adding DMA support to the serial port. DMA support does more that just dump serial data into a buffer; it can scan the incoming data for special characters, and it can even provide its own flow control. On the IBM side, the new PS/2 Models 90, 95, and 57 incorporate the enhanced DMA serial ports, and other manufacturers either have done so or will.

The enhanced serial port also breaks one of the historic PC barriers by allowing the use of a faster baud clock. By setting a bit in one of the enhanced registers, the standard 1.8432-MHz clock can be switched to 11.0592 MHz. This raises the theoretical serial rate to 691,200 bits per second. As with earlier serial ports, the IBM models do not support the highest possible speed, but they set their limit at 345,600 bps, which is still very fast.

One of the difficulties of providing DMA support for a serial port is the need to scan for control characters among the received data. Normally, this process uses the CPU to compare a received data byte with a set of known control characters. With the DMA feature active, however, the processor may not read the received data until the DMA buffer is filled.

To avoid any wait for processor service, the enhanced serial port has compare registers that can be used to check for up to three special control characters. When such a character is found, the UART can be programmed to start or stop transmitting automatically, to delete the character, to interrupt the processor, or any combination of these events.

The new DMA serial port (a Type 3 serial port, in IBM lingo) is backward compatible with the earlier 8250 family of UARTs. While all previous registers are present, an entirely new set of registers has been added to control the enhanced features. The new registers are accessed by adding 8000h to the base address of the start of the conventional UART register set. For example, if a serial port normally starts at I/O address 3F8h, the enhanced register set will start at 83F8h. Figure 3 shows the new registers used by the Type 3 serial port. Their description will serve as something of a programmers' reference.

IBM Type 3 Expanded Register Set

Figure 3: The DMA serial port, or Type 3, is backward-compatible with the earlier 8250 family of UARTs. This illustration shows the new registers used to control the enhanced features, such as flow control and a faster baud clock.

The first of the enhanced registers, the Command register, controls the transmission of data in DMA mode. Data sending can be stopped and restarted, and any error conditions can be reset using bits 1 and 0 of the register. All of the other bits in this register are reserved.

The Interrupt ID register identifies all interrupts that can occur in both conventional and enhanced modes. In enhanced DMA mode, new sources of interrupts include Terminal counts on the transmit or receive DMA controllers or a compare register match on the received data.

Enhanced Function Register 1 controls the enabling of the DMA modes of the UART. This register also enables interrupts for the serial port, including DMA terminal count notification. Bit 5 of this register forces the UART to store a byte of status information with every byte of received data. By enabling this mode, you can half the number of data bytes that can be kept in the FIFO and DMA buffers, but it allows the processor to check the status of each data byte when it reads the DMA buffer.

IBM Type 3 Expanded Register Set (continued)

Enhanced Function Register 2 controls the baud clock and enables hardware flow control. Bit 7 paces the transmit rate, using the Receive Count register. Bits 5 and 4 cut the transmit and receive rate of the UART by a factor of 16, slowing the UART so that slower processors can keep up with the serial port. Bit 6 of this register determines whether the 1.8432- or 11.0592-MHz baud clock is used. Finally, the lower four bits of this register determine the hardware flow control of the serial port. When these bits are set, the UART will stop and start transmitting and receiving in accordance with the DSR, DCD, and CTS status lines.

Enhanced Function Register 3 controls access to the character compare registers. Bits 2 and 1 select which of the character compare registers is accessed. Bit 0 selects the character compare register or its accompanying character function register. The character compare register is the actual 8-bit byte to check. The character compare function register selects which event should occur when a matching character is found.

After setting the Enhanced Function Register 3 to access the proper character compare register, that register can be read and written at that character compare register address. If a character compare function register is selected, only bits 3-0 are used. More than one event can be programmed for each character match by enabling multiple events in a Character Compare Function register.

The final register in the enhanced register set is the Receive Character Count register. This register has two functions. The first is to keep a tally of the bytes received by the UART. The other is to act as a pacing register for transmitting data. When in the pacing mode, the UART slows transmission of data by dividing the baud clock by 256 times the value in this register.

The FIFO queues and DMA interface that enhance the performance of serial communications have their counterparts in the world of parallel ports, which will be the subject of a future Lab Notes.

Douglas Boling is a contributing editor to PC Magazine.

Putting Serial-Port Technology in Perspective, Part 1

Content created and/or collected by:
Louis F. Ohland, Peter H. Wendt, David L. Beem, William R. Walsh, Tatsuo Sunagawa, Tomáš Slavotínek, Jim Shorney, Tim N. Clarke, Kevin Bowling, and many others.

Ardent Tool of Capitalism is maintained by Tomáš Slavotínek.
Last update: 08 May 2024 - Changelog | About | Legal & Contact