UART Register

来自Jack's Lab
跳转到: 导航, 搜索

目录

1 8250, 16450, 16550

8250, 16450 and 16550 are all common types of UARTs.

The 8250 is an old chip which cannot run at high speed.

The 16450 is similar to the 8250 except that it supports data communications at higher speeds.

Both of these chips generate aninterrupt for every character that is sent or received. At high speed, the number of interrupts (nearly 4000 per port per second at 38 400 bps) can overwhelm a CPU, bringing system performance way down.

The 16550 is pin-compatible with the 16450 and, by default, runs in 16450 mode. It has a special mode in which the 16550 buffers all data with 16-byte internal buffers.


2 UART Registers

Base Address DLAB I/O Access Abbrv.

Register Name +0 0 Write THR Transmitter Holding Buffer +0 0 Read RBR Receiver Buffer +0 1 Read/Write DLL Divisor Latch Low Byte +1 0 Read/Write IER Interrupt Enable Register +1 1 Read/Write DLH Divisor Latch High Byte +2 x Read IIR Interrupt Identification Register +2 x Write FCR FIFO Control Register +3 x Read/Write LCR Line Control Register +4 x Read/Write MCR Modem Control Register +5 x Read LSR Line Status Register +6 x Read MSR Modem Status Register +7 x Read/Write SR Scratch Register Each register is 8 bit.

DLAB: Divisor Latch Access Bit (LCR[7])

When the DLAB is set to "1", the baud rate registers(DLH,DLL) can be set and when it is "0" the registers have a different context(THR/RBR; IER).


3 Initialization

3.1 Steps

a. Setting the DLAB

    This is allowing you to set the values of the Divisor Latch Byte

b. Determine divisor latch value

Using the following formula to determine what numbers you need to put into the Divisor Latch High and Low Bytes: divisor_latch_val = 115200/baud_rate

We have decided to set the speed to 38,400 bps which should be find for 16450's and 16550's. This requires a divisor of 3, thus:

       DLH = 0x00 
       DLL = 0x03

c. Setting up 8 bits, no parity and 1 stop bit which is normally used today

       LCR = 0x03

d. Clear the IER, THR/THB

      LER = 0x00
      THR = 0x00

e. Turns on the FIFO buffers(16550)

   Make the trigger level at 14 bytes: FCR[7:6] = 11b
   Enable the FIFO: FCR[0] = 1b
   Clear out the FIFO buffers: FCR[2:1] = 11b
   So, FCR = 0xc7

f. Set the DTR, RTS bits to 1

   MCR = 0x03

g. Only set the UART to interrupt when data is received.


3.2 Detailed Register Description

3.2.1 Line Control Register (LCR)

Bit Notes 7 Divisor Latch Access Bit (DLAB) 6 Set Break Enable 3, 4 & 5 Bit 5 Bit 4 Bit 3 Parity Select x x 0 No Parity 0 0 1 Odd Parity 0 1 1 Even Parity 1 0 1 Mark 1 1 1 Space 2 0 One Stop Bit 1 1.5 Stop Bits or 2 Stop Bits 0 & 1 Bit 1 Bit 0 Word Length 0 0 5 Bits 0 1 6 Bits 1 0 7 Bits 1 1 8 Bits This register control the serial data protocol(Tx & Rx).

For most serial data transmission, Word Length will be 8 bits. Some military encryption equipment only uses 5 data bits per serial "word", as did some TELEX equipment. Early ASCII teletype terminals only used 7 data bits, and indeed this heritage has been preserved with SMTP format that only uses 7-bit ASCII for e-mail messages.

In the case of 5 data bits, the RS-232 protocol instead sends out "1.5 stop bits". What this means is that one serial data "word" istransmitted with only 1 stop bit, and then the next one is transmitted with 2 stop bits.

Another thing to keep in mind is that the RS-232 standard only specifies that at least one data bit cycle will be kept a logical "1" at the end of each serial data word (in other words, a complete character from start bit, data bits, parity bits, and stop bits). If you are having timing problems between the two computers but are able to in general get the character sent across one at a time, you might want to add a second stop bit instead of reducing baud rate.This adds a one-bit penalty to the transmission speed per character instead of halving the transmission speed by dropping the baud rate (usually).


3.2.2 FIFO Control Register (FCR)

Bit Notes 7 & 6 Bit 7 Bit 6 Interrupt Trigger Level (16 byte) Trigger Level (64 byte) 0 0 1 Byte 1 Byte 0 1 4 Bytes 16 Bytes 1 0 8 Bytes 32 Bytes 1 1 14 Bytes 56 Bytes 5 Enable 64 Byte FIFO (16750) 4 Reserved 3 DMA Mode Select 2 Clear Transmit FIFO 1 Clear Receive FIFO 0 Enable FIFOs FCR[0] = 0, turning the UART into 8250 compatibility mode. In effect this also renders the rest of the settings in this register to become useless.

FCR[2:1] are "automatically" reset, so if you set either of these to a logical "1" state you will not have to go and put them back to "0" later.

On a PC system FCR[3] is of little use and you can safely ignore it.

3.2.3 Modem Control Register

Bit Notes 7 Reserved 6 Reserved 5 Autoflow Control Enabled (16750) 4 Loopback Mode 3 Auxiliary Output 2 2 Auxiliary Output 1 1 Request To Send (RTS) 0 Data Terminal Ready (DTR) Of these outputs on a typical PC platform, only the Request to Send (RTS) and Data Terminal Ready (DTR) are actually connected to the output of the PC on the DB-9 connector.

3.3 Determining the type of UART via software

The first procedure we do is to set bit 0 to '1' in the FIFO control register. This tries to enable the FIFO buffers. Then we read bits 6 and 7 from the interrupt identification register. If both bits are '1' then the FIFO buffers are enabled. This would mean the UART is a 16550a. If the FIFO's were enabled but not usable then it would be a 16550. If there is no FIFO buffer enabled it is most likely to be a 16450 UART, but could be a 8250, 8250A or 8250B on very old systems. AT's have a fast bus speed which the 8250 series of UART can't handle to well thus it is very unlikely to be found in any AT. However if you wish to test for them as well you can follow the same test as above to distinguish 16550's or 16550A's from the rest. If no FIFOs are enabled then a possible UART is the 16450, 8250, 8250A or 8250B. Once it is established the it could be one of these four chips, try writing a byte to the scratch register and then read it back and compare the results. If the results match then you must have a scratch register, if they don't you either don't have a scratch register, or it doesn't work to well.

From the descriptions of the UART above if you read back your byte from the scratch register then the UART must be a 16450 or 8250A. (Both have scratch registers) If you don't read back your byte then it's either a 8250 or 8250B.

The 16750 has 64 byte FIFO's, thus the easiest way to test for it's presence is to enable the 64 byte buffer using the FIFO Control Register and then read back the status of the Interrupt Identification Register. However I have never tested this.


4 Transmit Data

4.1 poll mode (recommended)

  1. define LSR_DATA (*(unsigned char *)(UART_LSR_ADDR));

void uart_put(const char* format) {

   const char* p;
   for (p = format; *p; p++) {
       while ((LSR_DATA & 0x20) == 0);        /* poll until THR is empty. */
       (*(unsigned char *)(UART_THR_ADDR)) = c;
   }

}

LSR[6] = 1 indicates that all characters have been transmitted (including the FIFO, if active), and the "shift register" is done transmitting as well.

LSR[5] = 1 merely tells you that the UART is capable of receiving more characters, including into the FIFO for transmitting.


4.2 Interrupt mode

5 Recevie Data

5.1 poll mode

do { 
    c = inportb(PORT1 + 5);              /* Check to see if char has been */
                                      
    if (c & 1) {ch = inportb(PORT1);   /* If so, then get Char */
        printf("%c",ch);}                          /* Print Char to Screen */

    if (kbhit()){ch = getch();                /* If key pressed, get Char */
                   outportb(PORT1, ch);}    /* Send Char to Serial Port */

    } while (ch !=27);                           /* Quit when ESC (ASC 27) is pressed */

LSR[0] = 1 simply inform you that it is time to read the Receiver Buffer (RBR). On UARTs with a FIFO that is active, this bit will remain in a logical "1" state until you have read all of the contents of the FIFO.


5.2 Interrupt mode (recommended)

6 Interrupt

6.1 Interrupt Enable Register (IER)

Bit Notes 7 Reserved 6 Reserved 5 Enables Low Power Mode (16750) 4 Enables Sleep Mode (16750) 3 Enable Modem Status Interrupt 2 Enable Receiver Line Status Interrupt 1 Enable Transmitter Holding Register Empty Interrupt 0 Enable Received Data Available Interrupt IER[0] = 1 indicates that there is some data waiting for you to pull off of the UART(u'll use more than the rest).

IER[1] = 1 is to let you know that the output buffer (on more advanced models of the chip like the 16550) has finished sending everything that you pushed into the buffer.

IER[2] = 1: something in the LSR register has probably changed. If you are going to write an efficient error handler for the UART that will give plain text descriptions to the end user of your application, this is something you should consider.

The Modem Status Interrupt is to notify you when something changes with an external modem connected to your computer. This can include things like the telephone "bell" ringing (you can simulate this in your software), that you have successfully connected to another modem (Carrier Detect has been turned on), or that somebody has "hung up" the telephone (Carrier Detect has turned off). It can also help you to know if the external modem or data equipment can continue to receive data (Clear to Send). Essentially this deals with the other wires in the RS-232 standard other than strictly the transmit and receive wires.


6.2 Interrupt Identification Register (IIR)

Bit Notes 7 and 6 Bit 6 Bit 7 0 0 No FIFO on chip 0 1 FIFO enabled, but not functioning 1 0 Reserved condition 1 1 FIFO enabled 5 64 Byte FIFO Enabled (16750 only) 4 Reserved 3, 2 and 1 Bit 3 Bit 2 Bit 1 Reset Method 0 0 0 Modem Status Interrupt Reading Modem Status Register(MSR) 0 0 1 Transmitter Holding Register Empty Interrupt Reading Interrupt Identification Register(IIR) or Writing to Transmit Holding Buffer(THR) 0 1 0 Received Data Available Interrupt Reading Receive Buffer Register(RBR) 0 1 1 Receiver Line Status Interrupt Reading Line Status Register(LSR) 1 0 0 Reserved N/A 1 0 1 Reserved N/A 1 1 0 Time-out Interrupt Pending (16550 & later) Reading Receive Buffer Register(RBR) 1 1 1 Reserved N/A 0 Interrupt Pending Flag When you access the register mentioned under the reset method, this will clear the interrupt condition for that UART. If multiple interrupts for the same UART have been triggered, either it won't clear the interrupt signal on the CPU (triggering a new hardware interrupt when you are done), or if you check back to this register (IIR) and query the Interrupt Pending Flag to see if there are more interrupts to process, you can move on and attempt to resolve any new interrupt issue that you may have to deal with, using appropriate application code.


7 Physical Layer

___________ ________________________________________
\1 2 3 4 5/ Looking at pins \1 2 3 4 5 6 7 8 9 10 11 12 13/
\6 7 8 9/ on male connector \14 15 16 17 18 19 20 21 22 23 24 25/
------ -----------------------------------
Pin #         Pin #         Acronym Full-Name Direction What-it-May-Do/Mean
9-pin         25-pin
3         2         TxD Transmit Data --> Transmits bytes out of PC
2         3         RxD Receive Data <-- Receives bytes into PC
7         4         RTS Request To Send --> RTS/CTS flow control
8         5         CTS Clear To Send <-- RTS/CTS flow control
6         6         DSR Data Set Ready <-- I'm ready to communicate
4         20         DTR Data Terminal Ready--> I'm ready to communicate
1         8         DCD Data Carrier Detect<-- Modem connected to another
9         22        RI Ring Indicator <-- Telephone line ringing
5         7         SG Signal Ground

9-Pin DB9 Connector
1 DCD Carrier Detect
2 RxD Receive Data
3 TxD Transmit Data
4 DTR Data Terminal Ready
5 SG Signal Ground
6 DSR Data Set Ready
7 RTS Request To Send
8 CTS Clear To Send
9 RI Ring Indicator
22 RI Ring Indicator










个人工具
名字空间

变换
操作
导航
工具箱