OSD Home

- # - Serial chip types
- # - Serial chip registers
- # - Code snippets
- # - Links
- REPORT BUGS OR ERRORS IN THIS DOCUMENT

## Serial chip types

- 8250 and 8250B have no scratch register
- 8250A and 16450 have the scratch register but no FIFO
- 16550 has a FIFO but it doesn't work
- 16550A has a 16-byte FIFO
- 16650 has a 32-byte FIFO, on-chip flow control, and can run up to 460800 baud (4x normal)
- 16750 has a 64-byte FIFO, on-chip flow control, and can run up to 921600 baud (8x normal). This chip is NOT pin-compatible with the others.

8250-series chips (including 8250A) have these problems:

- They can not keep up with PC/AT I/O speed, so delays must be inserted between successive I/O instructions
- They transmit bad data when configured for 5 data bits with 1.5 stop bits
- They can occasionally drop received characters without posting a receive overrun error. This results in undetected data loss.
- They can transmit a single random character at power on

There is no way to distinguish between 8250A and 16450 in software.

## Serial chip registers

| Read | Write
--- | --- | ---
Register number | DLAB=0 | DLAB=1 | DLAB=0 | DLAB=1 | Register name(s) | Notes
0 | RBR | DLL | THR | DLL | Receiver Buffer Register Divisor Latch LSB Transmitter Holding Register
1 | IER | DLM | IER | DLM | Interrupt Enable Register Divisor Latch MSB
2 | IIR |  | Interrupt ID Register | 8250-16450 chips (no FIFO)
IIR | FCR | FIFO Control Register | 16550-series chips
IIR | FCR | EFR | Enhanced FIFO control Register | 16650+ chips
3 | LCR | Line Control Register
4 | MCR | Modem Control Register
5 | LSR | Line Status Register
6 | MSR | Modem Status Register
7 | SCR | SCRatch Register | 8250A and 16450+ chips

DLAB is bit b7 in the Line Control Register (see below).

The bit rate is normally 115200 divided by the 16-bit Divisor Latch value. According to one 16550A spec sheet, 'Using a value of 0 is not recommended.'

Reading RBR (register 0) clears the Receive Data and FIFO Timeout Interrupts.

Writing THR (register 0) clears the Transmit Holding Register Empty Interrupt. If you have nothing more to transmit, reading the Interrupt ID Register (IIR) will also clear this interrupt.

### Register 1: Interrupt Enable Register (IER)

b7 | b6 | b5 | b4 | b3 | b2 | b1 | b0
--- | --- | --- | --- | --- | --- | --- | ---
0 | 0 | 0 | 0 | EDSI | ELSI | ETBEI | ERBFI

b3 | EDSI | Enable moDem Status Interrupt (DCD, RI, DSR, CTS, etc.)
b2 | ELSI | Enable Line Status Interrupt (BI, FE, PE, or OE)
b1 | ETBEI | Enable Transmitter Buffer Empty Interrupt (when THR is empty).
b0 | ERBFI | Enable Receiver Buffer Full Interrupt. In FIFO mode, this bit also enables the FIFO timeout interrupt.

The receive FIFO timeout occurs automatically, when

- there is data in the receive FIFO, but
- not enough data in the FIFO to trigger a normal Receiver Buffer Full interrupt, and
- incoming data stops for a period of 4 character times or longer.

### Register 2: Interrupt ID Register (IIR; read-only)

b7 | b6 | b5 | b4 | b3 | b2 | b1 | b0
--- | --- | --- | --- | --- | --- | --- | ---
fe1 | fe0 | 0 | 0 | id2 | id1 | id0 | nint

b7-b6 | fe1-fe0 | When FIFOs are enabled, these bits identify the serial chip:
fe1 | fe0 | chip
--- | --- | ---
0 | 0 | 8250/16450 (no FIFO)
0 | 1 | UNKNOWN
1 | 0 | 16550 (defective FIFO)
1 | 1 | 16550A+
b3-b1 | id2-id0 | These bits identify the interrupt source:
id2 | id1 | id0 | Priority | Interrupt source
--- | --- | --- | --- | ---
0 | 0 | 0 | 4th | Modem status changed (DCD, RI, DSR, CTS, etc.)
0 | 0 | 1 | 3rd | THR or transmit FIFO empty
0 | 1 | 0 | 2nd | RBR or receive FIFO full
0 | 1 | 1 | 1st | Line status changed (BI, FE, PE, or OE)
1 | 0 | 0 | - | -
1 | 0 | 1 | - | -
1 | 1 | 0 | 2nd | (16550+ only) Receive FIFO timeout
1 | 1 | 1 | - | -
b0 | nint | This bit =0 if the chip is currently signalling an interrupt. This bit is ACTIVE LOW.

### Register 2: FIFO Control Register (FCR; write-only; 16550+)

b7 | b6 | b5 | b4 | b3 | b2 | b1 | b0
--- | --- | --- | --- | --- | --- | --- | ---
trig1 | trig0 | 0 | 0 | dma | rtf | rrf | fe

b7-b6 | trig1-trig0 | Receiver FIFO interrupt trigger level:
| Receive FIFO size (bytes)
--- | ---
trig1 | trig0 | 16550 | 16650 | 16750
0 | 0 | 1 | 8 | 1
0 | 1 | 4 | 16 | 16
1 | 0 | 8 | 24 | 32
1 | 1 | 14 | 28 | 56
b3 | dma | ?
b2 | rtf | Reset Transmit FIFO. The transmitter shift register is not affected. This bit is self-clearing.
b1 | rrf | Reset Receive FIFO. The receiver shift register is not affected. This bit is self-clearing.
b0 | fe | Enable FIFOs. Setting or clearing this bit clears the FIFOs. b7-b1 will not be written unless b0=1

### Register 2: Enhanced FIFO control Register (EFR; write-only; 16650+)

?

### Register 3: Line Control Register (LCR)

b7 | b6 | b5 | b4 | b3 | b2 | b1 | b0
--- | --- | --- | --- | --- | --- | --- | ---
DLAB | BREAK | STICK | EPS | PEN | STB | WLS1 | WLS0

b7 | DLAB | Divisor Latch Access Bit. Enables access to bit rate divisor latch in registers 0 and 1
b6 | BREAK | Setting this bit causes the serial output to send a continuous 'space' condition
b5 | STICK | Stick parity
b4 | EPS | Even Parity Select
b3 | PEN | Parity ENable:
STICK | EPS | PEN | Parity
--- | --- | --- | ---
- | - | 0 | None
0 | 0 | 1 | Odd
0 | 1 | 1 | Even
1 | 0 | 1 | Stuck-at-1 (mark parity)
1 | 1 | 1 | Stuck-at-0 (space parity)
b2 | STB | number of STop Bits
b1-b0 | WLS1-WLS0 | Word Length Select:
STB | WLS1 | WLS0 | Data bits | Stop bits
--- | --- | --- | --- | ---
0 | 0 | 0 | 5 | 1
0 | 0 | 1 | 6 | 1
0 | 1 | 0 | 7 | 1
0 | 1 | 1 | 8 | 1
1 | 0 | 0 | 5 | 1.5
1 | 0 | 1 | 6 | 2
1 | 1 | 0 | 7 | 2
1 | 1 | 1 | 8 | 2

Parity is an optional extra bit sent with each data byte. It lets the receiver detect single-bit transmission errors.

### Register 4: Modem Control Register (MCR)

b7 | b6 | b5 | b4 | b3 | b2 | b1 | b0
--- | --- | --- | --- | --- | --- | --- | ---
clkx4 | iren | it/fc | LOOP | Out2 | Out1 | RTS | DTR

b7 | clkx4 | [16750 only] Enables x4 clock (?)
b6 | iren | [16650 only] IR enable (?)
b5 | it/fc | [16650 only] Interrupt type select (?) [16750 only] Flow control enable (?)
b4 | LOOP | Loopback. Serial chip signals are disconnected from the outside world and internally looped back as shown here: DTR ---> DSR RTS ---> CTS OUT1 ---> RI OUT2 ---> DCD Tx ---> Rx In some serial chips, loopback is not supported at all. In other chips, the handshaking lines are looped back as shown, but there is no Tx --> Rx loopback.
b3 | Out2 | User-defined output bit. For most serial ports, this bit must be set to enable interrupts from the chip.
b2 | Out1 | User-defined output bit.
b1 | RTS | Ready To Send handshaking output.
b0 | DTR | Data Terminal Ready handshaking output.

### Register 5 (read-only): Line Status Register (LSR)

Reading this register clears the Line Status Interrupt.

b7 | b6 | b5 | b4 | b3 | b2 | b1 | b0
--- | --- | --- | --- | --- | --- | --- | ---
rfe | TEMT | THRE | BI | FE | PE | OE | DR

b7 | rfe | [16550+] Receive FIFO error. Indicates that at least one byte in the receive FIFO contains a parity error, framing error, or BREAK. If the FIFOs are disabled or the chip has no FIFOs, this bit =0
b6 | TEMT | Transmitter Empty. Indicates that the THR, FIFO, and transmit shift register are all empty. This bit does not generate an interrupt. If you want to use stick parity to transmit 9-bit values, you can't change the stick parity value until the transmitter is empty, so you must poll this bit. You must also disable the FIFOs to send 9-bit values.
b5 | THRE | Transmitter Holding Register Empty. Set when transmitter is ready to accept a new character.
b4 | BI | Break Indication. This bit is set if a BREAK is received. BREAK is a 'space' condition that lasts for at least ???
b3 | FE | Framing error (invalid stop bit) in received data.
b2 | PE | Parity error in received data.
b1 | OE | Overrun error. New data was received before the old data in the Receiver Buffer Fegister or FIFO was read.
b0 | DR | Data ready. This bit is set when a complete character has been received and transferred to the Receiver Buffer Register or FIFO. The error bits are set when the associated byte is at the top of the FIFO.

### Register 6: Modem Status Register (MSR)

Reading this register clears the Modem Status Interrupt.

b7 | b6 | b5 | b4 | b3 | b2 | b1 | b0
--- | --- | --- | --- | --- | --- | --- | ---
DCD | RI | DSR | CTS | DDCD | TERI | DDSR | DCTS

b7 | DCD | Data Carrier Detect handshaking input.
b6 | RI | Ring Indication handshaking input.
b5 | DSR | Data Set Ready handshaking input.
b4 | CTS | Clear To Send handshaking input.
b3 | DDCD | Delta DCD. Set if DCD line changed state.
b2 | TERI | Trailing Edge RI.
b1 | DDSR | Delta DSR. Set if DSR line changed state.
b0 | DCTS | Delta CTS. Set if CTS line changed state.

### Register 7: Scratch Register (SCR)

b7 | b6 | b5 | b4 | b3 | b2 | b1 | b0
--- | --- | --- | --- | --- | --- | --- | ---
- | - | - | - | - | - | - | -

You can store whatever you want in this register. It is not present, however, in 8250 and 8250B chips.

## Code snippets

Serial port demo/driver code

Simple polled serial output (good for debugging)

## Links

Specs for National Semiconductor PC16550D serial chip: http://www.national.com/ds/PC/PC16550D.pdf

## TO DO

    - info on using DMA with serial chips (b3 in FCR)
    - Enhanced FIFO control Register (EFR; 16650+ chips)
    - clkx4, iren, it/fc bits in reg 4 (16650/16570 chips)

## REPORT BUGS OR ERRORS IN THIS DOCUMENT