串口和 UART 教程

摘要

本文讨论了如何在 FreeBSD 上使用串口硬件。

1. UART:它是什么以及如何工作

版权 ® 1996 Frank Durda IV [email protected],版权所有。1996年1月13日。

通用异步接收/发送器(UART)控制器是计算机串行通信子系统的关键组件。UART 将数据字节转换成单独的比特,并按顺序进行传输。在接收端,第二个 UART 将比特重新组装成完整的字节。

串行传输通常与调制解调器一起使用,以及在计算机、终端和其他设备之间进行非网络通信。

串行传输有两种主要形式:同步和异步。根据硬件支持的模式,通信子系统的名称通常会包含一个 A,表示支持异步通信;如果支持同步通信,则会包含一个 S。这两种形式将在下文中描述。

一些常见的缩写有:

  • UART:通用异步接收/发送器

  • USART:通用同步/异步接收/发送器

1.1. 同步串行传输

同步串行传输要求发送方和接收方共享时钟,或者发送方提供一个时钟脉冲或其他定时信号,以便接收方知道何时“读取”下一个数据位。在大多数同步串行通信中,如果在某一时刻没有可传输的数据,必须发送填充字符,以确保数据始终处于传输状态。同步通信通常更高效,因为发送方和接收方之间仅传输数据比特;如果需要额外的线路和电路来共享时钟信号,同步通信可能会更加昂贵。

一种同步传输形式被用于打印机和固定磁盘设备,其中数据通过一组线路传输,而时钟或脉冲信号通过另一条线路传输。打印机和固定磁盘设备通常不是串行设备,因为大多数固定磁盘接口标准通过使用为每个字节位单独的线路,在每个时钟脉冲或脉冲信号下传输一个完整的字数据。在 PC 行业中,这些设备被称为并行设备。

PC 上的标准串行通信硬件不支持同步操作。本模式仅用于比较目的。

1.2. 异步串行传输

异步传输允许数据在不需要发送时钟信号给接收方的情况下进行传输。相反,发送方和接收方必须事先约定好时间参数,并且在每个数据字中添加特殊的比特,用于同步发送和接收单元。

当一个数据字被送入 UART 进行异步传输时,会在每个要传输的数据字的开始添加一个称为“起始位”的比特。起始位用于提醒接收方即将发送一个数据字,并将接收方的时钟与发送方的时钟同步。这两个时钟必须足够准确,以确保在传输剩余比特时其频率偏差不超过 10%(这个要求是在机械电传打印机时代设定的,现代电子设备容易满足)。

在起始位之后,数据字的各个比特依次被传输,最低有效位(LSB)首先被传送。每个比特的传输时间都与其他比特相同,接收方在每个比特的周期大约过了一半的时间后,检查线路上的信号来判断该比特是 1 还是 0。例如,如果每个比特的传输时间是两秒钟,接收方将在一秒钟后检查信号,以确定它是 1 还是 0,然后等待两秒钟再检查下一个比特,依此类推。

发送方并不知道接收方何时“检查”该比特的值。发送方仅知道何时根据时钟开始传输下一个比特。

当整个数据字传输完毕后,发送方可能会添加一个奇偶校验位。该奇偶校验位由发送方生成,接收方可以用它来进行简单的错误检查。然后,发送方至少会发送一个停止位。

当接收方接收到所有数据比特后,它可以检查奇偶校验位(发送方和接收方必须约定是否使用奇偶校验位),然后接收方检查停止位。如果停止位未按时出现,UART 将认为整个数据字已经损坏,并在读取数据字时报告一个帧错误。帧错误的常见原因是发送方和接收方的时钟速度不同,或者信号中断。

无论数据是否正确接收,UART 会自动丢弃起始位、奇偶校验位和停止位。如果发送方和接收方配置一致,这些位不会传递给主机。

如果另一个数据字已准备好传输,新的数据字的起始位可以在上一个数据字的停止位发送完毕后立即发送。

由于异步数据是“自同步”的,如果没有数据需要传输,传输线路可以保持空闲。

1.3. 其他 UART 功能

除了将数据从并行转换为串行进行传输,并将串行数据转换为并行接收之外,UART 通常还提供额外的电路来指示传输介质的状态,并在远程设备无法接受更多数据时调节数据流。例如,当连接到 UART 的设备是调制解调器时,调制解调器可能会报告电话线上载波的存在,同时计算机可以通过提升或降低这些额外信号中的一个来指示调制解调器重置或不接听电话。每个额外信号的功能在 EIA RS232-C 标准中有所定义。

1.4. RS232-C 和 V.24 标准

在大多数计算机系统中,UART 连接到符合 EIA RS232-C 规范的电路上。还有一个名为 V.24 的 CCITT 标准,它与 RS232-C 中的规格相对应。

1.4.1. RS232-C 位分配(标记和空格)

在 RS232-C 中,1 的值称为 Mark(标记),0 的值称为 Space(空格)。当通信线路空闲时,该线路被认为处于“标记”状态,或持续传输 1 值。

起始位的值始终为 0(空格)。停止位的值始终为 1(标记)。这意味着在每个数据字的开始,线路上总会出现从标记(1)到空格(0)的过渡,即使多个数据字是连续传输的。这保证了发送方和接收方能够重新同步它们的时钟,无论传输的数据比特内容如何。

停止位和起始位之间的空闲时间不必是通信链路位速率的精确倍数(包括零倍),但为了简便,大多数 UART 都是按此方式设计的。

在 RS232-C 中,“标记”信号(1)由 -2 VDC 到 -12 VDC 之间的电压表示,“空格”信号(0)由 0 VDC 到 +12 VDC 之间的电压表示。发送器应发送 +12 VDC 或 -12 VDC,而接收器应允许长电缆中的一些电压损失。一些低功耗设备(如便携式计算机)中的发送器有时仅使用 +5 VDC 和 -5 VDC,但只要电缆长度较短,这些值仍然对 RS232-C 接收器是可接受的。

1.4.2. RS232-C 中的断开信号(Break)

RS232-C 还规定了一种名为 Break 的信号,其通过连续发送空格值(没有起始位或停止位)来产生。当数据线路上没有电流时,线路被认为正在发送 Break

Break 信号的持续时间必须超过发送一个完整字节及其起始位、停止位和奇偶校验位的时间。大多数 UART 可以区分帧错误和断开信号,但如果 UART 无法区分这两者,则可以使用帧错误检测来识别断开信号。

在电传打印机时代,全国各地的许多打印机通过串联连接(如新闻服务)工作,任何设备都可以通过暂时断开整个电路来引发 Break,从而打断其他正在发送信息的位置。这种方式用于允许有紧急新闻的地方中断当前正在传送信息的位置。

在现代系统中,断开信号有两种类型。如果断开的时间超过 1.6 秒,则认为是“调制解调器断开”,一些调制解调器可以被编程在检测到此信号时终止对话并挂起电话或进入调制解调器命令模式。如果断开的时间小于 1.6 秒,则表示数据断开,远程计算机需要对此信号做出响应。有时,这种断开形式被用作注意或中断信号,有时也被视为 ASCII 控制字符 C 的替代信号。

标记和空格在纸带系统中也等同于“孔”和“无孔”。

注意

纸带或任何其他字节值无法生成断开信号,因为字节始终以起始位和停止位发送。UART 通常能够响应主机处理器的特殊命令生成连续的空格信号。

1.4.3. RS232-C DTE 和 DCE 设备

RS232-C 规范定义了两种设备类型:数据终端设备(DTE)和数据载体设备(DCE)。通常,DTE 设备是终端(或计算机),而 DCE 设备是调制解调器。在电话线路的另一端,接收方调制解调器也是一个 DCE 设备,而连接到该调制解调器的计算机是一个 DTE 设备。DCE 设备在 DTE 设备传输的引脚上接收信号,反之亦然。

当两个设备都是 DTE 或都是 DCE 且必须连接在一起时,没有调制解调器或类似的媒体转换器介入,就必须使用 NULL 调制解调器。NULL 调制解调器会电气上重新排列电缆连接,使得发送器输出连接到另一个设备的接收器输入,反之亦然。类似的转换也会在所有控制信号上进行,使得每个设备都能看到另一个设备认为是 DCE(或 DTE)的信号。

DTE 和 DCE 设备生成的信号数量是不对称的。DTE 设备为 DCE 设备生成的信号少于 DTE 设备从 DCE 设备接收到的信号。

1.4.4. RS232-C 引脚分配

EIA RS232-C 规范(以及 ITU 等效的 V.24)要求使用 25 针连接器(通常是 DB25),并定义了该连接器中大多数引脚的用途。

在 IBM 个人计算机及类似系统中,通过 9 针连接器(DB9)提供了 RS232-C 信号的一个子集。PC 连接器未包括的信号主要涉及同步操作,而 IBM 为 IBM PC 选择的 UART 并不支持这种传输模式。

根据计算机制造商的不同,可能会使用 DB25、DB9 或两种类型的连接器进行 RS232-C 通信。(IBM PC 还使用 DB25 连接器进行并行打印机接口,这可能会导致一些混淆。)

以下是 DB25 和 DB9 连接器中 RS232-C 信号的引脚分配表:

DB25 RS232-C 引脚
DB9 IBM PC 引脚
EIA 电路符号
CCITT 电路符号
常见名称
信号源
描述

1

-

AA

101

PG/FG

-

框架/保护接地

2

3

BA

103

TD

DTE

传输数据

3

2

BB

104

RD

DCE

接收数据

4

7

CA

105

RTS

DTE

请求发送

5

8

CB

106

CTS

DCE

清除发送

6

6

CC

107

DSR

DCE

数据集准备

7

5

AV

102

SG/GND

-

信号接地

8

1

CF

109

DCD/CD

DCE

数据载体检测

9

-

-

-

-

-

测试保留

10

-

-

-

-

-

测试保留

11

-

-

-

-

-

测试保留

12

-

CI

122

SRLSD

DCE

次级接收线路信号检测器

13

-

SCB

121

SCTS

DCE

次级清除发送

14

-

SBA

118

STD

DTE

次级传输数据

15

-

DB

114

TSET

DCE

传输信号元时序

16

-

SBB

119

SRD

DCE

次级接收数据

17

-

DD

115

RSET

DCE

接收信号元时序

18

-

-

141

LOOP

DTE

本地回环

19

-

SCA

120

SRS

DTE

次级请求发送

20

4

CD

108.2

DTR

DTE

数据终端准备

21

-

-

-

RDL

DTE

远程数字回环

22

9

CE

125

RI

DCE

振铃指示器

23

-

CH

111

DSRS

DTE

数据信号速率选择器

24

-

DA

113

TSET

DTE

传输信号元时序

25

-

-

142

-

DCE

测试模式

1.5. 比特、波特率和符号

波特率是异步通信中传输速度的衡量标准。由于调制解调器通信技术的进步,这个术语在描述新设备的数据传输速率时经常被误用。

传统上,波特率表示的是实际通过媒体发送的比特数,而不是实际从一个 DTE 设备传输到另一个设备的数据量。波特计数包括由发送 UART 生成并由接收 UART 移除的开销位(起始位、停止位和校验位)。这意味着七位数据字实际需要 10 位才能完全传输。因此,一个能够以每秒 300 比特的速度传输数据的调制解调器,通常只能传输 30 个 7 位数据字(如果使用了校验位,并且包含了一个起始位和停止位)。

如果使用 8 位数据字并且使用了校验位,则数据传输速率下降到每秒 27.27 个数据字,因为此时发送一个 8 位数据字需要 11 位,而调制解调器仍然以每秒 300 比特的速度发送数据。

直到错误修正调制解调器出现之前,将字节每秒转换为波特率的公式很简单。这些调制解调器从主机计算机的 UART 接收串行位流(即使使用的是内部调制解调器,数据仍然通常是串行化的),并将这些位转换回字节。然后,这些字节被组合成数据包,通过电话线使用同步传输方法发送。这意味着 DTE(计算机)中 UART 添加的起始位、停止位和校验位,在发送调制解调器发送数据之前已被移除。当这些字节被远程调制解调器接收时,远程调制解调器会为数据字添加起始位、停止位和校验位,将其转换为串行格式,然后发送给远程计算机中的接收 UART,后者再剥离起始位、停止位和校验位。

进行所有这些额外转换的原因是为了让两个调制解调器执行错误校正,这意味着接收调制解调器能够要求发送调制解调器重新发送没有正确校验和的块数据。这一检查是由调制解调器处理的,而 DTE 设备通常并不知道这一过程正在发生。

通过剥离起始位、停止位和校验位,两个调制解调器之间共享的用于执行错误校正的附加数据位大多被隐藏在发送和接收 DTE 设备所看到的有效传输速率中。例如,如果一个调制解调器将十个 7 位数据字发送到另一个调制解调器,而不包括起始位、停止位和校验位,发送调制解调器将能够添加 30 位自己的信息,接收调制解调器可以用来进行错误校正,而不会影响实际数据的传输速度。

波特这一术语的使用进一步被调制解调器压缩技术所混淆。通过电话线传输的单个 8 位数据字可能表示多个传输给发送调制解调器的词汇。接收调制解调器将数据恢复到其原始内容,并将数据传递给接收 DTE。

现代调制解调器还包括缓冲区,允许比特在电话线(DCE 到 DCE)上的传输速率与比特在 DTE 和 DCE 之间的传输速率不同。通常,DTE 和 DCE 之间的传输速率高于 DCE 到 DCE 之间的传输速率,因为调制解调器使用了压缩技术。

由于描述字节所需的比特数在两个机器之间的传输过程中有所不同,加之 DTE-DCE 和 DCE-DCE 链路上使用的不同比特每秒速度,使用波特来描述总体通信速度会引起问题,可能会误传实际的传输速率。因此,比特每秒(bps)是描述 DCE 到 DCE 接口传输速率的正确术语,波特或比特每秒(bps)都是在连接两个系统的有线连接中使用的合适术语,或者如果使用的调制解调器没有执行错误修正或压缩技术。

现代高速调制解调器(2400、9600、14,400 和 19,200bps)实际上仍然以或低于 2400 波特,或者更准确地说,以 2400 符号每秒的速度运行。高速调制解调器能够使用一种叫做星座填充(Constellation Stuffing)的方法,在每个符号中编码更多的数据比特,这就是为什么调制解调器的有效比特每秒速率更高的原因,但调制解调器仍然在电话系统提供的有限音频带宽内运行。以 28,800 及更高速度运行的调制解调器具有可变的符号率,但技术是相同的。

1.6. IBM 个人计算机 UART

从原始的 IBM 个人计算机开始,IBM 选择了 National Semiconductor 的 INS8250 UART,用于 IBM PC 并行/串行适配器。IBM 及其他厂商的兼容计算机后续版本继续使用 INS8250 或改进版的 National Semiconductor UART 系列。

1.6.1. National Semiconductor UART 系列图

INS8250 UART 有多个版本和后续的更新。以下是每个主要版本的描述。

INS8250 此部分用于原始的 IBM PC 和 IBM PC/XT。该部分的原名为 INS8250 ACE(异步通信元素),采用 NMOS 技术制造。

8250 使用八个 I/O 端口,具有一个字节的发送缓冲区和一个字节的接收缓冲区。这个原始 UART 存在多个竞争条件和其他缺陷。原始的 IBM BIOS 包含代码来解决这些缺陷,但这使得 BIOS 依赖于这些缺陷的存在,因此后来的部件如 8250A、16450 或 16550 无法在原始的 IBM PC 或 IBM PC/XT 上使用。

INS8250-B 这是由 NMOS 技术制造的较慢版本的 INS8250。它包含与原始 INS8250 相同的问题。

INS8250A 这是一个改进版的 INS8250,使用 XMOS 技术并纠正了各种功能缺陷。INS8250A 最初被 PC 克隆计算机厂商使用,这些厂商使用了“清洁”的 BIOS 设计。由于芯片的修正,这个部分不能与兼容 INS8250 或 INS8250B 的 BIOS 一起使用。

INS82C50A 这是 INS8250A 的 CMOS 版本(低功耗),具有相似的功能特性。

NS16450 与 NS8250A 相同,进行了一些改进,使其可以与更快的 CPU 总线设计一起使用。IBM 在 IBM AT 中使用了这个部分,并更新了 IBM BIOS,使其不再依赖于 INS8250 中的缺陷。

NS16C450 这是 NS16450 的 CMOS 版本(低功耗)。

NS16550 与 NS16450 相同,具有 16 字节的发送和接收缓冲区,但该缓冲区设计存在缺陷,无法可靠使用。

NS16550A 与 NS16550 相同,但修正了缓冲区缺陷。NS16550A 及其后续产品已成为 PC 行业中最受欢迎的 UART 设计,主要是因为它能够可靠地处理操作系统中响应较慢的中断时的较高数据速率。

NS16C552 该组件由两个 NS16C550A CMOS UART 组成,封装在一个单一的封装内。

PC16550D 与 NS16550A 相同,修正了细微的缺陷。这是 16550 系列的 D 版本,是 National Semiconductor 提供的最新设计。

1.6.2. NS16550AF 和 PC16550D 是相同的

National 在几年前重新组织了他们的零件编号系统,NS16550AFN 不再以这个名称存在。(如果你有一个 NS16550AFN,查看部件上的日期代码,这通常是一个四位数字,通常以 9 开头。数字的前两位表示年份,后两位表示该部件包装的年份中的周数。如果你有一个 NS16550AFN,它可能已经是几年前的部件。)

新的编号形式为 PC16550DV,后缀字母有细微差别,取决于封装材料及其形状。(编号系统的描述可以在下面找到。)

需要理解的是,在一些商店中,你可能需要支付 $15(美国)购买 1990 年制造的 NS16550AFN,而在旁边的货架上是新的 PC16550DN 部件,包含了 National 自 AFN 部件开始生产以来做的一些小修正,PC16550DN 可能是在过去六个月内生产的,并且其价格是 NS16550AFN 的一半(在批量购买时最低可达 $5),因为这些部件比较容易获得。

随着 NS16550AFN 芯片的供应继续减少,价格可能会继续上涨,直到更多人发现并接受 PC16550DN 实际上与旧部件编号具有相同功能。

1.6.3. National Semiconductor 部件编号系统

1.6.4. National Semiconductor 部件编号系统

旧的 NSnnnnnrqp 部件编号现在采用 PCnnnnnrgp 格式。

  • r 是修订字段。当前 National Semiconductor 的 16550 修订版本是 D

  • p 是封装类型字段。类型如下所示:

"F"
QFP
(四方扁平封装) L 引脚类型

"N"

DIP

(双列直插封装) 直插孔引脚类型

"V"

LPCC

(塑料芯片载体封装) J 引脚类型

  • g 是产品等级字段。如果封装类型字母前有一个 I,则表示“工业”等级部件,它具有比标准部件更高的规格,但不如军规(Milspec)部件高。这个字段是可选的。

因此,我们以前称为 NS16550AFN(DIP 封装)现在被称为 PC16550DN 或 PC16550DIN。

1.7. 其他供应商和类似的 UART

多年来,8250、8250A、16450 和 16550 被其他芯片供应商许可或复制。在 8250、8250A 和 16450 的情况下,精确的电路(“大单元”)被许可给许多供应商,包括 Western Digital 和 Intel。其他供应商则通过逆向工程获取该部件或制作出具有类似行为的仿真件。

在内部调制解调器中,调制解调器设计师通常会使用调制解调器微处理器来模拟 8250A/16450,而模拟的 UART 通常会有一个隐藏的缓冲区,包含数百个字节。由于缓冲区的大小,这些仿真可以像 16550A 一样可靠地处理高速数据。然而,大多数操作系统仍然报告该 UART 只是一个 8250A 或 16450,并且可能不会有效利用仿真 UART 中存在的额外缓冲区,除非使用特定的驱动程序。

一些调制解调器制造商受到市场压力,放弃了具有数百字节缓冲区的设计,转而使用 16550A UART,这样产品在市场比较中会有更好的表现,尽管这一做法可能会降低有效性能。

一个常见的误解是,所有标有“16550A”的部件在性能上都是相同的。实际上,存在差异,而且在这些 16550A 克隆中,大多数都存在明显的缺陷。

当开发 NS16550 时,National Semiconductor 获得了该设计的多个专利,并且限制了许可,使得其他供应商很难提供具有类似功能的芯片。由于专利的原因,逆向工程设计和仿真必须避免侵犯专利的权利。因此,这些仿制品几乎从未能与 NS16550A 或 PC16550D 完全一致,而这两个部件是大多数计算机和调制解调器制造商希望购买的部件,但有时不愿意支付获得正品部件所需的价格。

这些克隆 16550A 部件中的一些差异无关紧要,而另一些差异则可能导致该设备根本无法在特定的操作系统或驱动程序中使用。这些差异可能出现在使用其他驱动程序时,或者在发生某些未经过充分测试的事件时。这是因为大多数调制解调器供应商和 16550 克隆制造商使用 Windows® for Workgroups 3.11 中的 Microsoft 驱动程序和 Microsoft® MS-DOS® 实用程序作为与 NS16550A 兼容性的主要测试方法。由于这个过于简单的标准,如果使用不同的操作系统,则可能会由于克隆和正品部件之间的细微差异而出现问题。

National Semiconductor 提供了一款名为 COMTEST 的程序,该程序执行独立于操作系统驱动程序的兼容性测试。需要记住的是,这种程序的目的是展示竞争对手产品的缺陷,因此该程序会报告在被测试部件中出现的重大差异以及极其微妙的行为差异。

在本文档作者于 1994 年进行的一系列测试中,测试了由 National Semiconductor、TI、StarTech 和 CMD 以及嵌入在内部调制解调器中的大单元和仿真件制造的部件。以下列出了其中一些组件的差异计数。由于这些测试是在 1994 年进行的,因此它们可能无法反映当前来自供应商的特定产品的性能。

需要注意的是,COMTEST 在检测到过多问题或某些类型的问题时通常会中止。在这项测试中,COMTEST 已经过修改,以便无论遇到多少差异都不会中止。

1.7.1. COMTEST 测试结果

供应商
部件编号
错误(即“差异”报告)

National

(PC16550DV)

0

National

(NS16550AFN)

0

National

(NS16C552V)

0

TI

(TL16550AFN)

3

CMD

(16C550PE)

19

StarTech

(ST16C550J)

23

Rockwell

内部包含 16550 或仿真(RC144DPi/C3000-25)

117

Sierra

内部包含 16550 的调制解调器(SC11951/SC11351)

91

说明: 到目前为止,本文档的作者没有发现任何非 National 的部件在使用 COMTEST 程序时报告零差异。还应注意,National 曾推出过五个版本的 16550,而最新的部件在行为上与经典的 NS16550AFN(被认为是功能基准)有所不同。COMTEST 对 National 产品线的差异视而不见,并在 National 部件(除了原始 16550)上报告零错误,即使在 A、B 和 C 版本的部件中有官方的错误描述。因此,必须考虑到 COMTEST 中的这种偏见。

1.7.2. COMTEST 报告差异的含义

需要理解的是,COMTEST 报告的差异数量并不能揭示哪些差异是重要的,哪些是无关紧要的。例如,上述列出的两个具有内部 UART 的调制解调器报告的差异中,有大约一半是由于克隆 UART 不支持五位和六位字符模式所致。真实的 16550、16450 和 8250 UART 都支持这些模式,并且 COMTEST 会检查这些模式的功能,因此报告了五十多个差异。然而,几乎没有现代调制解调器支持五位或六位字符,特别是那些具有错误纠正和压缩功能的调制解调器。因此,与五位和六位字符模式相关的差异可以忽略不计。

COMTEST 报告的许多差异与时序有关。在许多克隆设计中,当主机从一个端口读取时,某些其他端口中的状态位可能不会像 真实的 NS16550AFN 那样在相同的时间内更新(有些更新得更快,有些则更慢),而 COMTEST 会查找这些差异。这意味着,差异的数量可能具有误导性,一个设备可能只有一到两个差异,但它们非常严重,而另一个设备可能在更新状态寄存器的速度上与参考部件有所不同(但这通常不会影响正确编写的驱动程序的操作),可能会报告几十个差异。

COMTEST 可以作为一种筛选工具,提醒管理员可能存在不兼容的部件,这些部件可能会导致问题,或者需要作为特殊情况来处理。

如果你在调制解调器中运行 COMTEST,或者调制解调器连接到串口,你需要先向调制解调器发送 ATE0&W 命令,以便调制解调器不会回显任何测试字符。如果忘记执行此操作,COMTEST 至少会报告以下一个差异:

1.8. 8250/16450/16550 寄存器

8250/16450/16550 UART 占用八个连续的 I/O 端口地址。在 IBM PC 中,这些端口有两个定义的位置,通常统称为 COM1COM2。PC 克隆机和附加卡的制造商创建了另外两个区域,称为 COM3COM4,但是这些额外的 COM 端口在某些系统上与其他硬件发生冲突。最常见的冲突是与提供 IBM 8514 模拟的显卡发生冲突。

COM1 位于从 0x3f8 到 0x3ff,通常使用 IRQ 4。COM2 位于从 0x2f8 到 0x2ff,通常使用 IRQ 3。COM3 位于从 0x3e8 到 0x3ef,没有标准的 IRQ。COM4 位于从 0x2e8 到 0x2ef,没有标准的 IRQ。

下面是 8250/16450/16550 UART 的 I/O 端口介绍。

I/O 端口
访问权限
描述

+0x00

写入 (DLAB==0)

传输保持寄存器 (THR)。写入此端口的信息被视为数据字,并由 UART 传输。

+0x00

读取 (DLAB==0)

接收缓冲寄存器 (RBR)。由 UART 从串行链路接收到的任何数据字都通过读取此端口由主机访问。

+0x00

写入/读取 (DLAB==1)

除数锁存 LSB (DLL)。此值将从主输入时钟(在 IBM PC 中,主时钟为 1.8432MHz)进行除法,结果时钟将决定 UART 的波特率。此寄存器保存除数的第 0 至 7 位。

+0x01

写入/读取 (DLAB==1)

除数锁存 MSB (DLH)。此值将从主输入时钟(在 IBM PC 中,主时钟为 1.8432MHz)进行除法,结果时钟将决定 UART 的波特率。此寄存器保存除数的第 8 至 15 位。

+0x01

写入/读取 (DLAB==0)

中断使能寄存器 (IER) 8250/16450/16550 UART 将事件分类为四个类别中的一个。每个类别可以配置为在发生任何事件时生成中断。8250/16450/16550 UART 会生成一个外部中断信号,无论启用类别中有多少事件发生。由主机处理器响应中断,然后轮询启用的中断类别(通常所有类别都有中断启用),以确定中断的真正原因。 位 7 → 保留,总是 0。 位 6 → 保留,总是 0。 位 5 → 保留,总是 0。 位 4 → 保留,总是 0。 位 3 → 启用调制解调器状态中断 (EDSSI)。将此位设置为 "1" 允许 UART 在状态行之一或多个发生变化时生成中断。 位 2 → 启用接收线状态中断 (ELSI)。将此位设置为 "1" 时,UART 会在检测到传入数据中的错误(或 BREAK 信号)时生成中断。 位 1 → 启用传输保持寄存器空中断 (ETBEI)。将此位设置为 "1" 时,UART 会在 UART 有足够空间容纳一个或多个额外字符以便传输时生成中断。 位 0 → 启用接收数据可用中断 (ERBFI)。将此位设置为 "1" 时,UART 会在接收到足够的字符超过 FIFO 的触发级别,或者 FIFO 定时器到期(数据过时),或当 FIFO 被禁用时接收到一个字符时生成中断。

+0x02

写入

FIFO 控制寄存器 (FCR)(此端口在 8250 和 16450 UART 中不存在。) 位 7 → 接收触发位 #1 位 6 → 接收触发位 #0 这两个位控制在 FIFO 激活时接收器生成中断的时机。 7 6 在生成中断之前接收多少字 0 0 1 0 1 4 1 0 8 1 1 14 位 5 → 保留,总是 0。 位 4 → 保留,总是 0。 位 3 → DMA 模式选择。如果位 0 设置为 "1"(启用 FIFO),设置此位会将 -RXRDY 和 -TXRDY 信号的操作从模式 0 改为模式 1。 位 2 → 传输 FIFO 重置。当写入 "1" 时,FIFO 的内容将被丢弃。当前正在传输的任何字将完整发送。此功能在中止传输时非常有用。 位 1 → 接收 FIFO 重置。当写入 "1" 时,FIFO 的内容将被丢弃。当前在移位寄存器中正在组装的任何字将完整接收。 位 0 → 16550 FIFO 启用。当设置时,传输和接收 FIFO 都会启用。当启用或禁用 FIFO 时,保持寄存器、移位寄存器或 FIFO 中的任何内容都会丢失。

+0x02

读取

中断标识寄存器 位 7 → FIFO 启用。在 8250/16450 UART 上,此位为 0。 位 6 → FIFO 启用。在 8250/16450 UART 上,此位为 0。 位 5 → 保留,总是 0。 位 4 → 保留,总是 0。 位 3 → 中断 ID 位 #2。在 8250/16450 UART 上,此位为 0。 位 2 → 中断 ID 位 #1 位 1 → 中断 ID 位 #0。这三个位组合报告了导致当前中断的事件类别。这些类别有优先级,因此如果多个类别的事件同时发生,UART 将首先报告更重要的事件,主机必须按报告的顺序解决这些事件。所有导致当前中断的事件必须解决后,才会生成新的中断。(这是 PC 架构的限制。) 2 1 0 优先级 描述 0 1 1 第一接收错误(OE,PE,BI 或 FE) 0 1 0 第二接收数据可用 1 1 0 第二触发级别识别(接收缓冲区中的过时数据) 0 0 1 第三传输器有空间传输更多字(THRE) 0 0 0 第四调制解调器状态变化(-CTS,-DSR,-RI 或 -DCD) 位 0 → 中断待处理位。如果此位设置为 "0",则至少有一个中断待处理。

+0x03

写入/读取

行控制寄存器 (LCR) 位 7 → 除数锁存访问位 (DLAB)。当设置时,禁用对数据传输/接收寄存器 (THR/RBR) 和中断使能寄存器 (IER) 的访问。对这些端口的任何访问现在都将重定向到除数锁存寄存器。设置此位、加载除数寄存器并清除 DLAB 时,应禁用中断。 位 6 → 设置断开。当设置为 "1" 时,传输器开始传输连续间隔,直到此位设置为 "0"。这会覆盖正在传输的任何字符位。 位 5 → 固定奇偶校验。当启用奇偶校验时,设置此位会根据位 4 的值始终将奇偶校验设置为 "1" 或 "0"。 位 4 → 偶校验选择 (EPS)。当启用奇偶校验且位 5 为 "0" 时,设置此位会传输并期望偶校验。否则,使用奇校验。 位 3 → 奇偶校验使能 (PEN)。当设置为 "1" 时,在数据的最后一位和停止位之间插入一个奇偶校验位。UART 还会期望接收到的数据中存在奇偶校验位。 位 2 → 停止位数 (STB)。如果设置为 "1" 且使用 5 位数据字,则每个数据字传输并期望 1.5 个停止位。对于 6、7 和 8 位数据字,则传输并期望 2 个停止位。当此位设置为 "0" 时,每个数据字使用 1 个停止位。 位 1 → 字长选择位 #1 (WLSB1) 位 0 → 字长选择位 #0 (WLSB0) 这两位一起指定每个数据字的位数。 1 0 字长 0 0 5 数据位 0 1 6 数据位 1 0 7 数据位 1 1 8 数据位

+0x04

写入/读取

调制解调器控制寄存器 (MCR) 位 7 → 保留,总是 0。 位 6 → 保留,总是 0。 位 5 → 保留,总是 0。 位 4 → 环回使能。当设置为 "1" 时,UART 的传输器和接收器内部连接在一起,以允许诊断操作。此外,UART 调制解调器控制输出连接到 UART 调制解调器控制输入。CTS 连接到 RTS,DTR 连接到 DSR,OUT1 连接到 RI,OUT 2 连接到 DCD。 位 3 → OUT 2。一个辅助输出,主机处理器可以将其设置为高或低。在 IBM PC 串行适配器(以及大多数克隆机)中,OUT 2 用于三态(禁用)来自 8250/16450/16550 UART 的中断信号。 位 2 → OUT 1。一个辅助输出,主机处理器可以将其设置为高或低。在 IBM PC 串行适配器中未使用此输出。 位 1 → 请求发送 (RTS)。当设置为 "1" 时,UART 的 -RTS 输出为低(活动)。 位 0 → 数据终端就绪 (DTR)。当设置为 "1" 时,UART 的 -DTR 输出为低(活动)。

+0x05

写入/读取

行状态寄存器 (LSR) 位 7 → 接收 FIFO 错误。在 8250/16450 UART 上,此位为 0。当 FIFO 中的任何字节存在以下一个或多个错误条件时,此位设置为 "1":PE、FE 或 BI。 位 6 → 传输器空 (TEMT)。当设置为 "1" 时,传输 FIFO 或传输移位寄存器中没有剩余的字。传输器完全空闲。 位 5 → 传输保持寄存器空 (THRE)。当设置为 "1" 时,FIFO(或保持寄存器)现在有足够的空间传输至少一个额外的字。传输器可能仍在传输时,此位为 "1"。 位 4 → 断开中断 (BI)。接收器检测到一个断开信号。 位 3 → 帧错误 (FE)。检测到开始位,但停止位未按预期时间出现。接收到的字可能被破坏。 位 2 → 奇偶校验错误 (PE)。接收到的字的奇偶校验位不正确。 位 1 → 溢出错误 (OE)。接收到一个新字,但接收缓冲区没有空间。移位寄存器中的新到字被丢弃。在 8250/16450 UART 上,保持寄存器中的字被丢弃,新到字被放入保持寄存器。 位 0 → 数据就绪 (DR)。接收 FIFO 中有一个或多个字,主机可以读取。在此位设置之前,必须完全接收一个字,并将其从移位寄存器移动到 FIFO(或对于 8250/16450 设计,移动到保持寄存器)。

+0x06

写入/读取

调制解调器状态寄存器 (MSR) 位 7 → 数据载波检测 (DCD)。反映 UART 上 DCD 线的状态。 位 6 → 振铃指示 (RI)。反映 UART 上 RI 线的状态。 位 5 → 数据集就绪 (DSR)。反映 UART 上 DSR 线的状态。 位 4 → 清除发送 (CTS)。反映 UART 上 CTS 线的状态。 位 3 → 数据载波检测变化 (DDCD)。如果 -DCD 线自上次主机读取 MSR 后发生过状态变化,则设置为 "1"。 位 2 → 振铃指示变化 (TERI)。如果 -RI 线自上次主机读取 MSR 后经历了低到高的变化,则设置为 "1"。 位 1 → 数据集就绪变化 (DDSR)。如果 -DSR 线自上次主机读取 MSR 后发生过状态变化,则设置为 "1"。 位 0 → 清除发送变化 (DCTS)。如果 -CTS 线自上次主机读取 MSR 后发生过状态变化,则设置为 "1"。

+0x07

写入/读取

临时寄存器 (SCR)。此寄存器在 UART 中没有任何功能。主机可以将任何值写入此位置,并在之后从该位置读取。

1.9. 超越 16550A UART

尽管国家半导体公司(National Semiconductor)并未提供任何兼容 16550 的附加功能的组件,但其他一些供应商提供了此类组件。以下是其中的一些组件的描述。需要理解的是,要有效利用这些改进,可能需要由芯片供应商提供驱动程序,因为大多数流行的操作系统不支持超出 16550 所提供功能的特性。

ST16650 默认情况下,该组件与 NS16550A 相似,但可以选择启用扩展的 32 字节发送和接收缓冲区。由 StarTech 制造。

TIL16660 默认情况下,该组件的行为与 NS16550A 相似,但可以选择启用扩展的 64 字节发送和接收缓冲区。由德州仪器(Texas Instruments)制造。

Hayes ESP 这款专有插件卡包含 2048 字节的发送和接收缓冲区,支持最高 230.4Kbit/sec 的数据传输速率。由 Hayes 制造。

除了这些“傻”UART,许多供应商还生产智能串行通信板。此类设计通常提供一个微处理器,用于与多个 UART 连接,处理并缓存数据,然后在必要时通知主机处理器。由于 UART 并非直接由 PC 处理器访问,因此在这种通信系统中,供应商无需使用与 8250、16450 或 16550 UART 兼容的 UART。这使得设计人员可以自由选择具有更好性能特征的组件。

2. 配置 sio 驱动程序

sio 驱动程序提供对基于 NS8250、NS16450、NS16550 和 NS16550A 的 EIA RS-232C(CCITT V.24)通信接口的支持。还支持几种多端口卡。有关详细技术文档,请参阅 sio(4) 手册页面。

2.1. Digi International (DigiBoard) PC/8

由 Andrew Webster [email protected] 提供。1995年8月26日

以下是来自一台配有 Digi International PC/8 16550 的机器的配置片段。该设备连接了 8 台调制解调器,且运行良好。不要忘记添加 options COM_MULTIPORT,否则它将无法很好地工作!

设置此配置的诀窍在于标志的最高有效位(MSB)表示最后一个 SIO 端口,在此示例中为 11,因此标志为 0xb05。

2.2. Boca 16

由 Don Whiteside [email protected]提供。1995年8月26日

使用 FreeBSD 配置 Boca 16 端口板的步骤非常直接,但你需要做几件事才能使其正常工作:

  1. 你需要安装内核源代码,以便重新编译必要的选项,或者你需要其他人为你编译。默认的 2.0.5 内核没有启用多端口支持,你将需要为每个端口添加一个设备条目。

  2. 你需要知道 Boca 板的中断和 IO 设置,以便在内核中正确设置这些选项。

一个重要的注意事项 - Boca 16 的实际 UART 芯片位于连接盒中,而不是内部板上。所以如果你将连接盒拔掉,探测这些端口会失败。我从未测试过在断开连接盒后启动并重新连接的情况,我建议你也不要这样做。

如果你还没有设置自定义内核配置文件,请参考 内核配置 章节,了解 FreeBSD 手册中的一般程序。以下是针对 Boca 16 板的具体配置,假设你使用的是内核名称 MYKERNEL 并使用 vi 编辑。

  1. 将以下行添加到配置文件中:

  2. 在当前的 device sion 行所在的位置,你需要添加 16 个设备。以下示例适用于中断为 3,基础 IO 地址为 100h 的 Boca Board。每个端口的 IO 地址是从前一个端口加上 8 十六进制数,因此地址分别为 100h、108h、110h…。

    如果你使用的端口分配与示例完全相同,flags 条目 必须 与示例中的相同。flags 设置为 0xMYY,其中 M 表示主端口的次要编号(Boca 16 的最后一个端口),YY 表示是否启用了 FIFO(启用),是否使用 IRQ 共享(是),以及是否存在 AST/4 兼容的 IRQ 控制寄存器(没有)。在此示例中,

    表示主端口是 sio16。如果我添加了另一个板卡并分配了 sio17 到 sio28,那么该板卡上所有 16 个端口的 flags 将为 0x1C05,其中 1C 表示主端口的次要编号。不要更改 05 设置。

  3. 保存并完成内核配置,重新编译、安装并重启。假设你已经成功安装了重新编译的内核,并将其设置为正确的地址和 IRQ,你的启动信息应该会显示 Boca 端口的成功探测,如下所示:(显然,sio 数字、IO 和 IRQ 可能不同)

    如果信息滚动得太快看不清楚,运行:

    可以查看启动信息。

  4. 接下来,必须使用 /dev/MAKEDEV 脚本在 /dev 中为设备创建适当的条目。如果你正在运行支持 devfs(5) 的 FreeBSD 5.X 内核,则此步骤可以省略。 如果你确实需要创建 /dev 条目,请作为 root 用户运行以下命令:

    如果你出于某些原因不需要调用设备(call-out devices),则可以跳过创建 cua* 设备。

  5. 如果你想快速且不太精确地确认设备是否正常工作,可以将调制解调器插入每个端口,并且(以 root 身份)运行:

    对于你创建的每个设备,你应该看到 RX 灯闪烁,表示每个端口都正常工作。

2.3. 支持廉价的多 UART 卡

由 Helge Oldach 提供 [email protected],1999 年 9 月

是否曾想过 FreeBSD 对你的 20 美元多功能 I/O 卡的支持,这种卡有两个(或更多)COM 端口,并且共享 IRQ?下面是如何做的:

通常,支持这类板卡的唯一选项是为每个端口使用独立的 IRQ。例如,如果你的 CPU 板上有一个板载 COM1 端口(即 sio0,I/O 地址 0x3F8,IRQ 4),并且你有一个扩展板带有两个 UART,通常需要将它们配置为 COM2(即 sio1,I/O 地址 0x2F8 和 IRQ 3),第三个端口(即 sio2)的 I/O 地址为 0x3E8 和 IRQ 5。显然,这浪费了 IRQ 资源,因为理论上应该可以通过 COM_MULTIPORT 配置(在前述部分中已介绍)使用单个 IRQ 来运行两个扩展板端口。

这类廉价 I/O 板通常具有一个 4x3 跳线矩阵,用于 COM 端口,如下所示:

上图显示了端口 A 连接到 IRQ 5,端口 B 连接到 IRQ 3。你具体板上的 IRQ 列可能有所不同——其他板可能会提供 IRQ 3、4、5 和 7 等跳线。

有人可能会认为,将两个端口都连接到 IRQ 3,使用手工制作的跳线将 IRQ 3 列中的三个连接点全部连接起来,就能解决问题,但事实并非如此。你不能复制 IRQ 3,因为每个 UART 的输出驱动器是以 "totem pole" 方式连接的,因此,如果其中一个 UART 驱动 IRQ 3,输出信号将不是你所预期的。根据扩展板或主板的实现,IRQ 3 线将始终保持高电平或始终保持低电平。

你需要将两个 UART 的 IRQ 驱动器解耦,以便只有在其中一个 UART 触发 IRQ 时,板卡的 IRQ 线才会变高,否则保持低电平。Joerg Wunsch 提出了一个解决方案:[email protected],即使用两个二极管(强烈推荐使用锗二极管或肖特基二极管)和一个 1 kOhm 电阻,组成一个“有线或”电路。以下是该电路的示意图,从上面的 4x3 跳线矩阵开始:

二极管的阴极连接到一个公共点,并且与一个 1 kOhm 的下拉电阻一起连接。必须将电阻连接到地面,以避免 IRQ 线在总线上漂浮。

现在我们可以配置内核了。以这个例子为例,我们可以配置:

请注意,sio1sio2flags 设置是至关重要的;有关详细信息,请参阅 sio(4)。 (通常,"flags" 属性中的 2 指的是 sio2,它包含 IRQ,而你肯定希望使用 5 的低半字节。)启用内核详细模式后,这应该会产生类似以下的输出:

尽管 /sys/i386/isa/sio.c 在上述 "irq maps" 数组的使用上有些晦涩,但基本思想是你在第一个、第三个和第四个位置观察到 0x1。这意味着相应的 IRQ 在输出时已设置,并在之后被清除,这正是我们所期望的。如果你的内核没有显示这种行为,那么大概率是你的接线出了问题。

3. 配置 cy 驱动

由 Alex Nash 提供,1996 年 6 月 6 日

Cyclades 多端口卡基于 cy 驱动,而不是其他多端口卡常用的 sio 驱动。配置过程很简单,步骤如下:

  1. 在内核配置文件中添加 cy 设备(请注意,你的 IRQ 和 I/O 内存设置可能不同)。

  2. 重新构建并安装新内核。

  3. 通过以下命令创建设备节点(以下示例假设是一个 8 端口板):

  4. 如果需要,可以通过复制串口设备(ttyd)条目并使用 ttyc 代替 ttyd,将拨号条目添加到 /etc/ttys 文件中。例如:

  5. 使用新内核重启。

4. 配置 si 驱动

由 Nick Sayer mailto:[email protected] 提供,1998 年 3 月 25 日

Specialix SI/XIO 和 SX 多端口卡使用 si 驱动。单台机器最多可以安装 4 张主卡。支持的主卡如下:

  • ISA SI/XIO 主卡(2 个版本)

  • EISA SI/XIO 主卡

  • PCI SI/XIO 主卡

  • ISA SX 主卡

  • PCI SX 主卡

尽管 SX 和 SI/XIO 主卡外观有所不同,但它们的功能基本相同。这些主卡不使用 I/O 地址,而是需要一个 32K 的内存区域。ISA 卡的出厂配置将内存区域放置在 0xd0000-0xd7fff。它们还需要一个 IRQ。PCI 卡将自动配置。

每张主卡最多可以连接 4 个外部模块。外部模块包含 4 个或 8 个串口。它们有以下几种类型:

  • SI 4 或 8 端口模块。每个端口支持最高 57600 bps。

  • XIO 8 端口模块。每个端口支持最高 115200 bps。一种类型的 XIO 模块有 7 个串口和 1 个并口。

  • SXDC 8 端口模块。每个端口支持最高 921600 bps。像 XIO 一样,某些模块也有一个并口。

要配置 ISA 主卡,请在内核配置文件中添加以下行,按需要修改数字:

有效的 IRQ 号码对于 SX ISA 主卡是 9、10、11、12 和 15,对于 SI/XIO ISA 主卡是 11、12 和 15。

要配置 EISA 或 PCI 主卡,请使用以下行:

添加配置条目后,重新构建并安装新内核。

注意

如果你使用的是 devfs(5) 在 FreeBSD 5.X 中,以下步骤不再需要。

在使用新内核重启后,你需要在 /dev 目录中创建设备节点。MAKEDEV 脚本会处理此操作。计算你有多少个端口,并输入以下命令:

(其中 nn 为端口数量)

如果希望在这些端口上出现登录提示,你需要将类似以下的行添加到 /etc/ttys 文件中:

根据需要更改终端类型。对于调制解调器,dialupunknown 就可以了。

最后更新于

这有帮助吗?