16550 UART
The 16550 UART (Universal Asynchronous Receiver/Transmitter) is an integrated circuit developed by National Semiconductor as an enhanced serial communication controller, primarily designed to interface computers with serial devices such as modems and terminals, featuring 16-byte transmit and receive FIFOs to reduce CPU interrupt overhead during high-speed data transfers.[1] Introduced in July 1987, the NS16550A (a key variant of the 16550 series) addressed limitations in earlier UARTs like the NS16450 by incorporating FIFO buffers, enabling baud rates up to 256 kbaud while maintaining full software and pin compatibility with its predecessor, except for two pins repurposed for DMA signaling (RXRDY and TXRDY).[2] This design improvement allowed for a fivefold increase in performance, mitigating data overruns in multitasking environments common to IBM PC, XT, AT, and compatible systems by buffering data and providing programmable interrupt triggers at 1, 4, 8, or 14 bytes in the receive FIFO.[2] The device supports configurable serial parameters, including 5- to 8-bit character lengths, odd/even/no parity, 1, 1.5, or 2 stop bits, and full modem control signals such as RTS, CTS, DTR, DSR, DCD, and RI, along with independent interrupt sources for receiver, transmitter, line status, and modem status events.[1] Key technical specifications include operation at 5V ±5% supply voltage, an input clock up to 8 MHz for programmable baud rate generation (dividing by 1 to 2¹⁶-1 to produce a 16x baud clock), and fabrication using National Semiconductor's advanced scaled N-channel silicon-gate MOS (XMOS) process for low power dissipation (maximum 1W).[1] It also includes a diagnostic loopback mode for testing and two DMA modes: Mode 0 for single transfers per interrupt and Mode 1 for multi-transfer operation, making it suitable for applications like multiport serial boards and terminal concentrators.[1] Widely adopted in personal computing during the late 1980s and 1990s, the 16550 UART became a de facto standard for PC serial ports, powering asynchronous communications in DOS and early Windows environments.[2] Although largely superseded by USB and integrated controllers, 16550 UARTs remain available in modern PCIe serial adapter cards for legacy and industrial applications.[3]History
Development and Origins
The 16550 UART was invented by National Semiconductor in the late 1980s as an integrated circuit to improve serial communication performance in personal computers.[4] This development addressed the limitations of earlier UART designs, particularly in handling the growing demands of serial ports for applications such as modems and terminals in IBM PC-compatible systems.[2] Key motivations for the 16550 stemmed from the performance bottlenecks in predecessors like the Intel 8250 and National Semiconductor's 16450, which featured only single-byte buffers. These older UARTs generated high interrupt rates and risked data overruns as CPU speeds increased and serial data rates rose, consuming significant processor bandwidth—for instance, up to 50% at 115 kbaud without adequate buffering.[4] The 16550 was designed to mitigate these issues while ensuring backward compatibility with the established Intel 8250 standard, which had become the de facto interface for serial ports since its inclusion in the original 1981 IBM PC.[2][4] Conceptual development of the 16550 occurred around 1987, with its initial release documented that same year to support higher baud rates up to 256 kbaud and reduce CPU intervention in data handling.[2] Production began shortly thereafter, enabling widespread integration into PC systems by 1989–1990, driven by the need for efficient serial communications in an era of expanding peripheral connectivity.[4] The primary innovation, 16-byte FIFO buffers, allowed for batched data processing to alleviate interrupt overhead, marking a significant evolution from the byte-at-a-time approach of prior UARTs.[2]Introduction and Variants
The 16550 UART, developed by National Semiconductor, was introduced in 1987 as an enhanced universal asynchronous receiver-transmitter (UART) featuring integrated 16-byte FIFO buffers to address the performance bottlenecks of prior designs like the 16450, which relied on single-byte buffering and struggled with data rates beyond 9600 baud.[2] This innovation enabled more efficient serial data handling in multitasking environments, maintaining full software compatibility with earlier UARTs while supporting higher throughput for applications such as modems and terminal interfaces.[2] The chip's design emphasized CPU independence through interrupt-driven operations and DMA support, making it suitable for emerging PC architectures.[2] The original 16550 saw rapid adoption in personal computing, serving as the inaugural serial interface chip in IBM's PS/2 line of computers released in 1987, where it powered COM ports on motherboards and expansion cards.[5] However, early production units suffered from a FIFO implementation flaw that limited its buffering effectiveness, prompting National Semiconductor to release the revised 16550A in 1987, which resolved the issue and established it as the industry standard for reliable serial communications.[6] By 1991–1992, the 16550A had become ubiquitous in x86-based systems, including motherboards from major vendors, facilitating stable operation at baud rates up to 115,200 bps—a common rate as a multiple of 9600 baud (×12), which traces back to 300 baud derived from 50/60 Hz mains frequencies—and reducing data overruns in high-speed scenarios like file transfers and remote access.[7][5] Key variants beyond National Semiconductor's offerings include compatible implementations from other manufacturers, such as Exar Corporation's ST16C550 series, which replicated the 16-byte FIFO and register interface for drop-in compatibility in legacy designs.[8] National Semiconductor's intellectual property licensing model spurred this proliferation, leading to widespread third-party adoption in PCs, servers, and embedded systems throughout the 1990s.[9]Architecture
Compatibility with Earlier UARTs
The 16550 UART was designed to maintain pin-for-pin compatibility with its predecessors, the 16450 and 8250, utilizing the same 40-pin DIP package to enable direct drop-in replacement on existing printed circuit boards without requiring modifications to hardware layouts. Specifically, it aligns with the 16450's pinout, except for pins 24 (repurposed from CSOUT to TXRDY) and 29 (repurposed from NC to RXRDY), which were often unused in prior implementations, allowing seamless upgrades in most serial port cards.[1][2] Functionally, the 16550 retains equivalence to the 8250 family by preserving core UART operations, including serial data transmission and reception, baud rate generation via the same programmable divider, and interrupt handling in non-FIFO mode. It employs identical I/O port addressing schemes, such as the standard base address of 0x3F8 for COM1 in IBM PC-compatible systems, ensuring that hardware interfaces remain unchanged.[2][10][11] Software compatibility is achieved through no alterations to established driver application programming interfaces (APIs) or BIOS-level routines developed for earlier UARTs, as the 16550 powers up in 16450-compatible mode by default. Advanced FIFO features can be selectively enabled via configuration bits in the FIFO Control Register (FCR), preventing disruptions to legacy applications that expect single-byte buffer behavior. Additionally, setting FCR bit 0 to zero disables the FIFOs entirely, providing exact emulation of the 16450 for environments requiring strict backward compatibility and reliability in mixed hardware setups.[1][2][10]Register Interface
The 16550 UART features a set of eight programmable registers accessible via an 8-bit offset addressing scheme, typically mapped to I/O ports or memory locations in a host system. These registers control data transmission and reception, interrupt handling, serial line parameters, baud rate generation, modem signals, and diagnostic functions. The interface maintains compatibility with the base address of earlier UARTs like the 8250, allowing seamless integration without altering existing system configurations.[1] The register map is determined by three address lines (A2, A1, A0) and the Divisor Latch Access Bit (DLAB) in the Line Control Register (LCR). When DLAB is 0, offset 0x00 accesses the Receiver Buffer Register (RBR) for reading received data and the Transmitter Holding Register (THR) for writing data to transmit, while offset 0x01 accesses the Interrupt Enable Register (IER). Offset 0x02 provides read access to the Interrupt Identification Register (IIR) and write access to the FIFO Control Register (FCR). Other offsets include the Line Control Register (LCR) at 0x03, Modem Control Register (MCR) at 0x04, Line Status Register (LSR) at 0x05, Modem Status Register (MSR) at 0x06, and Scratch Register (SCR) at 0x07. When DLAB is set to 1 via LCR bit 7, offsets 0x00 and 0x01 instead access the low and high bytes of the Divisor Latch Registers (DLL and DLM) for baud rate configuration.[1]| Offset | DLAB | Register (Read/Write) | Abbreviation | Default Value |
|---|---|---|---|---|
| 0x00 | 0 | Receiver Buffer / Transmitter Holding | RBR / THR | N/A |
| 0x01 | X | Interrupt Enable | IER | 0x00 |
| 0x02 | X | Interrupt Identification (R) / FIFO Control (W) | IIR / FCR | N/A |
| 0x03 | X | Line Control | LCR | 0x00 |
| 0x04 | X | Modem Control | MCR | 0x00 |
| 0x05 | X | Line Status | LSR | 0x60 |
| 0x06 | X | Modem Status | MSR | 0x00 |
| 0x07 | X | Scratch | SCR | 0x00 |
| 0x00 | 1 | Divisor Latch Low | DLL | 0x00 |
| 0x01 | 1 | Divisor Latch High | DLM | 0x00 |