Serial Ports: Difference between revisions

[unchecked revision][unchecked revision]
Content deleted Content added
Added in the Modem Control Register and Modem Status Register information from the 16550 datasheet
m Bot: Replace main article with main template
 
(14 intermediate revisions by 6 users not shown)
Line 39:
The addresses for COM ports can vary depending on how they are connected to the machine and how the BIOS is configured. Some BIOS configuration utilities allow you to see and set what these are, so if you in doubt for a test machine, this might be a good place to look to get you started.
 
For the most part, the first two COM ports will be at the addresses specified, the addresses for further COM ports isare less reliable.
{| {{wikitable}}
! COM Port
Line 51:
|-
| COM4 || 0x2E8
|-
| COM5 || 0x5F8
|-
| COM6 || 0x4F8
|-
| COM7 || 0x5E8
|-
| COM8 || 0x4E8
|}
 
Line 60 ⟶ 68:
! IO Port Offset
! Setting of DLAB
! I/O Access
! Register mapped to this port
|-
| +0 || 0 || DataRead register. Reading this registers read from the|| Receive buffer. Writing to this register writes to the Transmit buffer.
|-
| +10 || 0 || InterruptWrite || EnableTransmit Registerbuffer.
|-
| +1 || 0 || Read/Write || Interrupt Enable Register.
| +0 || 1 || With DLAB set to 1, this is the least significant byte of the divisor value for setting the baud rate.
|-
| +10 || 1 || Read/Write || With DLAB set to 1, this is the mostleast significant byte of the divisor value for setting the baud rate.
|-
| +1 || 1 || Read/Write || With DLAB set to 1, this is the most significant byte of the divisor value.
| +2 || - || Interrupt Identification and FIFO control registers
|-
| +2 || - || Read || Interrupt Identification
| +3 || - || Line Control Register. The most significant bit of this register is the DLAB.
|-
| +42 || - || ModemWrite Control|| FIFO control Register.registers
|-
| +53 || - || Read/Write || Line StatusControl Register. The most significant bit of this register is the DLAB.
|-
| +64 || - || Read/Write || Modem StatusControl Register.
|-
| +75 || - || ScratchRead || Line Status Register.
|-
| +6 || - || Read || Modem Status Register.
|-
| +7 || - || Read/Write || Scratch Register.
|}
 
Line 100 ⟶ 113:
# Send the most significant byte of the divisor value to [PORT + 1].
# Clear the most significant bit of the Line Control Register.
 
====Line Control Register====
The Line Control register sets the general connection parameters.
 
{| class="wikitable"
|-
! Bit 7
! Bit 6
! Bits 5-3
! Bit 2
! Bits 1-0
|-
| Divisor Latch Access Bit
| Break Enable Bit
| Parity Bits
| Stop Bits
| Data Bits
|}
 
====Data Bits====
Line 119 ⟶ 150:
|}
 
====Stop bitsBits====
The serial controller can be configured to send a number of bits after each character of data. These reliable bits can be used to by the controller to verify that the sending and receiving devices are in phase.
 
Line 135 ⟶ 166:
|}
 
====Parity Bits====
The controller can be made to add or expect a parity bit at the end of each character of data transmitted. With this parity bit, if a single bit of data is inverted by interference, a parity error can be raised. The parity type can be NONE, EVEN, ODD, MARK or SPACE.
 
Line 145 ⟶ 176:
 
To set the port parity, set bits 3, 4 and 5 of the Line Control Register [PORT + 3].
 
{| {{wikitable}}
! Bit 5
Line 166 ⟶ 196:
To communicate with a serial port in interrupt mode, the interrupt-enable-register (see table above) must be set correctly. To determine which interrupts should be enabled, a value with the following bits (0 = disabled, 1 = enabled) must be written to the interrupt-enable-register:
{| {{wikitable}}
! Bit 7-4
! Bit 3
! Bit 2
! Bit 1
! Bit 0
|-
| Reserved
| Modem Status
| Receiver Line Status
| Transmitter Holding Register Empty
| Received Data Available
|}
 
===First In First Out Control Register===
The First In / First Out Control Register (FCR) is for controlling the FIFO buffers. Access this register by writing to port offset +2.
{| class="wikitable"
|-
! Bits 7-6
! Bits 5-4
! Bit 3
! Bit 2
! Bit 1
! Bit 0
|-
| Interrupt Trigger Level
| Reserved
| DMA Mode Select
| Clear Transmit FIFO
| Clear Receive FIFO
| Enable FIFO's
|}
 
====Clear Transmit FIFO and Clear Receive FIFO====
Bit 2 being set clears the Transmit FIFO buffer while Bit 1 being set clears the Receive FIFO buffer. Both bits will set themselves back to 0 after they are done being cleared.
 
====Interrupt Trigger Level====
The Interrupt Trigger Level is used to configure how much data must be received in the FIFO Receive buffer before triggering a Received Data Available Interrupt.
{| {{wikitable}}
! Bit 7
! Bit 6
! Trigger Level
|-
| 0 || 0 || 1 Byte
|-
| 0 || 1 || 4 Bytes
|-
| 1 || 0 || 8 Bytes
|-
| 1 || 1 || 14 Bytes
|}
 
===Interrupt Identification Register===
The Interrupt Identification Register (IIR) is for identifying pending interrupts. Access this register by reading from port offset +2.
{| class="wikitable"
|-
! Bits 7-6
! Bits 5-4
! Bit 3
! Bit 2-1
! Bit 0
|-
| FIFO Buffer State
| Reserved
| Timeout Interrupt Pending (UART 16550) or Reserved
| Interrupt State
| Interrupt Pending
|}
 
====Interrupt State====
After Interrupt Pending is set, the Interrupt State shows the interrupt that has occurred. They have varying levels of priority, with high-value interrupts handled first, and low-value interrupts being handled last.
{| {{wikitable}}
! Bit 2
! Bit 1
! Interrupt
! Priority
|-
| 0 || 0 || Modem Status || 4 (Lowest)
| 0 || Data available
|-
| 0 || 1 || Transmitter emptyHolding Register Empty || 3
|-
| 1 || 0 || Received Data Available || 2
|-
| 1 || 1 || Receiver Line Status || 1 (Highest)
|}
 
====FIFO Buffer State====
{| {{wikitable}}
! Bit 7
! Bit 6
! State
|-
| 20 || Break/error0 || No FIFO
|-
| 0 || 1 || FIFO Enabled but Unusable
| 3 || Status change
|-
| 4-71 || Unused0 || FIFO Enabled
|}
 
Line 194 ⟶ 308:
| 1 || Request to Send (RTS) || Controls the Request to Send Pin
|-
| 2 || Out 1 || Controls a hardware pin (OUT2OUT1) which is unused in PC implementations
|-
| 3 || Out 2 || Controls a hardware pin (OUT2) which is unusedused to enable the IRQ in PC implementations
|-
| 4 || Loop || Provides a local loopback feature for diagnostic testing of the UART
Line 207 ⟶ 321:
|}
 
Most PC serial ports use OUT2 to control a circuit that disconnects (tristates) the IRQ line. This makes it possible for multiple serial ports to share a single IRQ line, as long as only one port is enabled at a time.
While the two OUT pins are unused in PC implementations, they could be used for status LED's in certain instances however, they are never wired to the serial port itself.
Loopback mode is a diagnostic feature. When bit 4 is set to logic 1,
the following occur the transmitter Serial Output (SOUT) is set to the Marking (logic 1) state; the receiver Serial
Line 220 ⟶ 334:
by the Interrupt Enable Register.
 
===Line statusStatus registerRegister===
The line status register is useful to check for errors and enable polling.
{| {{wikitable}}
Line 274 ⟶ 388:
 
===Terminals===
:''{{Main article: [[|Terminals]]}}
 
Once you can send and receive bytes with confidence, you probably want to connect the serial port to a terminal (or more likely a terminal emulator these days). Those send specific byte sequences when a key is pressed, and can interpret codes to move the cursor on the screen and change color for example.
Line 281 ⟶ 395:
==Example Code==
===Initialization===
<sourcesyntaxhighlight lang="C">
#define PORT 0x3f8 // COM1
 
Line 305 ⟶ 419:
return 0;
}
</syntaxhighlight>
</source>
 
Notice that the initialization code above writes to [PORT + 1] twice with different values. This is once to write to the Divisor register along with [PORT + 0] and once to write to the Interrupt register as detailed in the previous section. The second write to the Line Control register [PORT + 3] clears the DLAB again as well as setting various other bits.
 
===Receiving data===
<sourcesyntaxhighlight lang="C">
int serial_received() {
return inb(PORT + 5) & 1;
Line 320 ⟶ 434:
return inb(PORT);
}
</syntaxhighlight>
</source>
 
===Sending data===
 
<sourcesyntaxhighlight lang="C">
int is_transmit_empty() {
return inb(PORT + 5) & 0x20;
Line 334 ⟶ 448:
outb(PORT,a);
}
</syntaxhighlight>
</source>
 
==Glossary==
 
;Baud Rate
:is theThe speed at which the serial line switches between it's two states. This is not equivalent to bps, due to the fact there are start and stop bits. On an 8/N/1 line, 10 baud = 1 byte. Modems are more complex than plain serial lines due to having multiple waveforms, but for the purposes of OSDev this is irrelevant.
:The fastest baud rate a serial port can reliably run at is generally 115200 baud.
;baud rate divisor
;Baud Rate Divisor
:fastest rate a serial port can run, the number 115200.
:The value the is used by the UART to divide its internal clock by in order to get the actual intended baud rate.
;stop bits
;Stop Bits
:the NULL bit(s) sent between each character to synchronize the transmitter and the receiver.
:The NULL bit(s) sent between each character to synchronize the transmitter and the receiver.
;UART
:forFor Universal Asynchronous Receiver/Transceiver: the chip that picks a byte a send it bit per bit on the serial line and vice versa.
 
== Related Links ==