前言
本文从操作系统使用 16550 的角度来学习 16550。主要解析通用的串口寄存器的作用。
16550 串口由一系列寄存器控制串口行为。不同的具体设备寄存器的偏移不同,寄存器的长度可能不同。
例如,在 AXI UART 16550
中,各寄存器长度都为 32 bit
,各寄存器详细信息如下表所示:
在 byterunner 提供的文档中,各寄存器的长度为 8 bit。详细信息如下所示:
16550 简介
UART(Universal Asynchronous Receiver/Transmitter)
是一种常用的串行通信接口,用于在设备之间进行数据传输。它能够将并行数据转换为串行数据,以便通过一条通信线路发送,并在接收端再将串行数据转换回并行数据。
16550 是 UART 的一种标准实现,它定义了一系列特性,如数据缓冲区、错误检测机制等,以提高数据传输的可靠性。由于其广泛的应用和成熟的技术,16550 成为了事实上的标准,被大多数个人计算机采用。
上图为一个 16550 实现的引脚图,其兼容当前工业 16550 标准。允许配置 FIFO,队列大小默认为 16,代表输入和发送队列可同时存在的数据为 16 个字节。
16550 数据传输控制
数据传输形式:不论输入或输出,首先以开始一位的 0 bit 打头表示数据传输开始。其次是用户配置的可能为 5bit、6bit、7bit、8bit 的字符数据。若用户配置了使用奇偶校验,奇偶校验位会出现在数据传输中的 bit 位之中。最后是 1bit
或 多 bit 的 stop bit
停止位 用于表示传输结束。
数据传输的更多控制可以通过 LCR
寄存器实现,全称 Line Control Register
。
Register | Bit7 | Bit6 | Bit5 | Bit4 | Bit3 | Bit2 | Bit1和 Bit0 |
---|---|---|---|---|---|---|---|
LCR | divisor latch Access Bit | set break | set parity | even parity | parity enable | stop bits | word length |
1 bit 和 0 bit 的组合: 00、01、10、11分别代表 5bit、6bit、7bit、8bit 的字长。
2 bit 为0,则数据传输结束时的 stop bit
数量为 1。若该位为 1,则除 5bit 字长发送 1.5 个 stop bit 之外,其余字长均发送两个 stop bit。
5bit 到 3bit 的组合:xx0表示禁用奇偶校验,001表示奇校验,011表示偶校验。其余暂不考虑。
6bit 位被设置(即为1),它会在传输线上强制产生一个“断开”(Break)条件。这意味着串行输出引脚(TXD)会被强制到空闲状态(通常是逻辑0)。
7bit 除数值访问位,此bit 置为 1,则可以访问 DLL
寄存器和 DLM
寄存器。下面会详细介绍。
16550 数据传输流
数据传输流中主要涉及三个寄存器:THR
、RHR
和 LSR
寄存器,全称分别为 Transmit Holding Register
、Receive Holding Register
和 Line Status Register
,下面会慢慢介绍。
数据输出流程:串口待输出数据位于 THR(Transmit Honding Register)
寄存器。经由 TSR(Transmit Shift Register)
寄存器通过移位为主的操作变为串行数据放在 txd
引脚以串行数据形式送出串口。起始位,停止位以及如果开启奇偶校验,则奇偶校验数据也会随数据发送。
数据输入流程:串口输入数据经由输入引脚 rxd 串行输入,数据由 RSR(Receive Shift Register)
寄存器接收,并通过以移位为主(可能包含奇偶校验等其余操作)的操作把数据还原为字的形式存储在 RSR 中。一旦数据达到用户配置的 5bit、6bit、7bit、8bit 字大小,若 RHR(Receive Holding Register)
寄存器不空,则会把数据送往 RHR 寄存器。
LSR
寄存器负责提供数据传输的状态给 CPU
。
当数据接收完毕,LSR(Line Status Register)
寄存器的一些 bit 会指示是否在接收过程中发生错误。
同时在数据接收和发送尚未发生时,LSR(Line Status Register)
寄存器的一些 bit 会指示发送和接收寄存器的状态。
具体如下:
Register | Bit7 | Bit6 | Bit5 | Bit4 | Bit3 | Bit2 | Bit1 | Bit0 |
---|---|---|---|---|---|---|---|---|
LSR | 0/FIFO Error | transmit empty | transmit holding empty | break interrupt | framing error | parity error | overrun error | receive data ready |
0:receive data ready:有数据已经被接收并存储在 RHR 寄存器。
1:Overrun Error:当UART接收到一个新的字符并且试图将其存储在接收缓冲区中时,如果微处理器(或CPU)未能及时从接收保持寄存器(RHR)中读取先前接收到的字符,就会发生溢出错误。
2:parity error:奇偶校验错误
3:framing error:帧格式错误发生在接收端检测到停止位不是预期的逻辑电平(通常是高电平 逻辑1)时。
4:break interrupt:当 RXD(接收数据)引脚被持续保持在一个低电平(逻辑0)超过一个完整字符的时间长度时,就会触发断开中断。
5:transmit holding empty:该 bit 为1,则THR 寄存器为空,否则 THR 寄存器不空
6:transmit empty:该 bit 为 1,则 THR 寄存器和 TSR 寄存器都为空。在 FIFO 模式下该 bit 一直为 1,不论 THR 和 TSR 的状态是否为空。
7:0/FIFO Error:该 bit 为 1,则在 FIFO 中至少发生了四种错误的一种。
波特率配置
波特率表示每秒传输的 bit 数。同一个 16550 设备支持多种不同的波特率配置,用户可自行配置。波特率配置中涉及两个寄存器,DLL 和 DLM,全称分别为 Divisor Latch (Least Significant Byte) Register
除数锁寄存器低位和 Divisor Latch (Most Significant Byte) Register
除数锁寄存器高位。
除数值和时钟频率以及波特率之间的计算公式为: D i v i s i o r = 输入时钟频率 / ( 16 × 所需波特率 ) Divisior={{输入时钟频率} /({16 × 所需波特率})} Divisior=输入时钟频率/(16×所需波特率)
以 1.8432 M H Z 1.8432MHZ 1.8432MHZ 的输入频率以及 9600 9600 9600 波特率为例,除数值为: 1843200 / ( 16 ∗ 9600 ) = 12 1843200 / (16 * 9600) = 12 1843200/(16∗9600)=12
DLL
寄存器和 DLM
寄存器分别存储除数值的低 8 bit 和 高 8 bit。访问这两个寄存器,需要 LCR
寄存器的最高 bit 置为1。该 bit 含义为 DLAB
,全称为 Divisor Latch Access Bit
。
另外,访问 THR 和 RHR 这两个寄存器时,要始终保持 DLAB
这个 bit 位为 0。否则重叠的寄存器地址会使得寄存器访问到 DLL 和 DLM。
下表为 byteRunner 提供的寄存器偏移供参考,具体的 16550 实现可能不同,以及各寄存器的读写权限。左侧为只读,右侧为只写。
16550六种信号
信号用于UART 和 调制解调器之间的通信,主要涉及 MCR
调制解调器控制和 MSR
调制解调器状态寄存器,全称分别为 Modem Control Register 和 Modem Status Register。
两种流向调制解调器的信号:
DTR(Data Terminal Ready)
: DTR信号通常用来告诉调制解调器,终端设备(如计算机)已经准备好通信了。
Request To Send (RTS)
:RTS信号通常用于通知调制解调器,终端设备希望开始发送数据。
MCR
寄存器的 0bit
位用于控制 DTR
信号,其为 1,则发送 DTR
信号。MCR
寄存器的 1bit
用于控制 RTS
信号,其为1,则发送 RTS
信号。
Register | Bit7 | Bit6 | Bit5 | Bit4 | Bit3 | Bit2 | Bit1 | Bit0 |
---|---|---|---|---|---|---|---|---|
MCR | 0 | 0 | 0 | loop back | OUT2 | OUT1 | RTS | DTR |
(MCR 寄存器其余 bit 位由后面详细解释)
四种由调制解调器发出的信号:
Clear To Send (CTS)
:清除发送信号,由调制解调器发出,表明现在可以安全地开始传输数据。
Data Set Ready (DSR)
:数据设备准备好信号,表明调制解调器已经准备好进行通信。
Ring Indicator (RI)
:通知计算机或相关设备有呼叫或消息到达。
Carrier Detect (CD)
:载波检测信号,表明调制解调器检测到了来自远程调制解调器的载波信号。
根据 MSR
寄存器的内容可以读取调制解调器的信号。MSR
寄存器 0bit
用于表示 CTS
信号发生变化,MSR
寄存器 1bit
用于表示 DSR
信号发生变化,MSR
寄存器 2bit
用于表示 RI
信号发生变化,MSR
寄存器 3bit
用于表示 CD
信号发生变化。MSR
寄存器 4bit
用于表示调制解调器的 CTS
信号。MSR
寄存器 5bit
用于表示调制解调器的 DSR
信号。MSR
寄存器 6bit
用于表示调制解调器的 RI
信号。MSR
寄存器 7bit
用于表示调制解调器的 CD
信号。具体如下:
Register | Bit7 | Bit6 | Bit5 | Bit4 | Bit3 | Bit2 | Bit1 | Bit0 |
---|---|---|---|---|---|---|---|---|
MSR | CD | RI | DSR | CTS | delta CD | delta RI | delta DSR | delta CTS |
16550中断
IER 寄存器控制中断使能,即接收哪种类型的中断。寄存器全称为 Interrupt Enable Register。
Register | Bit7 | Bit6 | Bit5 | Bit4 | Bit3 | Bit2 | Bit1 | Bit0 |
---|---|---|---|---|---|---|---|---|
IER | 0 | 0 | 0 | 0 | modem status interrupt | receive line status interrupt | transmit holding register interrupt | Data Ready |
中断优先级按照从高到底依次为:
1:receive line status interrupt,当接收的数据发生错误时会产生这个中断。其与 LSR 寄存器的 bit 1-4 直接相关。
2:Data Ready / Reception Timeout:两个中断源表示同一种情况:有数据待从接收端的 FIFO 读取。
3:Transmitter Holding Register Empty:若未启用 FIFO,该中断表示 THR 寄存器为空。若启用 FIFO 则 FIFO 队列为空。
4: Modem Status:当调制解调器状态发生变化时会产生此中断,该中断与 MSR 寄存器的 bit 0-3 直接相关。
(TimeOut 的发生是由于 FIFO 模式的 16550 会在 FIFO 中有至少一个数据且超过 4 个字传输时间之后仍未接收到新数据时自动发送超时中断)
ISR 寄存器用于获取中断状态。全称为 Interupt Status Register。关于 ISR 部分实现可能功能上更多,我们此处使用 byteRunner 提供的功能介绍。会存在功能上更加扩展,兼容标准 16550 设备存在,其 ISR 寄存器可能会有更多功能,我们不在此处介绍。
Register | Bit7 | Bit6 | Bit5 | Bit4 | Bit3 | Bit2 | Bit1 | Bit0 |
---|---|---|---|---|---|---|---|---|
ISR | 1 | 1 | 0 | 0 | interrupt prior. bit 2 | interrupt prior. bit 1 | interrupt prior. bit 0 | interrupt status |
第 0bit
为0,则有中断存在。为1,则无中断发生。
bit 3-1 的组合分别为:000
,表示 Modem Status Interrupt
,优先级最低;001表示 TXRDY (Transmitter Holding Register Empty)
;010
表示Data Ready
;110
表示 Reception Timeout
;011
表示 receive line status interrupt
。
FCR 寄存器用于控制 FIFO 的状态。全称为 FIFO Control Register。
Register | Bit7 | Bit6 | Bit5 | Bit4 | Bit3 | Bit2 | Bit1 | Bit0 |
---|---|---|---|---|---|---|---|---|
FCR | RCVR trigger MSB | RCVR trigger LSB | 0 | 0 | DMA mode select | transmit FIFO reset | receiver FIFO reset | FIFO enable |
0bit
为1,则启用 FIFO
。在设置 FIFO
的 trigger level
之前需要先启用 FIFO。
1bit
用于重置 receiver FIFO
,内容清零,计数器清零,重置之后该位置为 0。
2bit
用于重置 transmit FIFO
,内容清零,计数器清零,重置之后该位置为 0。
3bit
置 1,设置 transmit
和 receive
工作在模式 1。此时在启用 FIFO
条件下,tramsmit FIFO
满时,tx ready
信号变为高电平,意义为无效,没有空间再放置待传输字符。receiver FIFO
中的字符数量大于等于 trigger level
时,rx ready
信号有效。直到 receicer FIFO
为空。
bit 7-6
用于设置 trigger level
,即在 FIFO
中的字符数量达到某个阈值之后,触发中断。00
表示一个字符,01
表示 4
个字符,10
表示8个字符,11
表示14个字符。
另外,很重要的一点,MCR 寄存器中的 OUT1 和 OUT2 是 generous purpose bit 位,即并没有赋特定含义。但在 16550 默认情况下,会设置 OUT2 bit 位 表示全局中断掩码。
因此,在多数情况下,MCR 的 OUT2 在设备启动时很有必要置为 1,否则任何中断都将不会触发。
总结
16550 串口通用寄存器就是这些,还有一些扩展功能包括 DMA tx End 和 DMA rx End 等等留待大家自己解决。
完结撒花!~