总体介绍
ZYNQ的UART 控制器是一款支持全双工异步通信的接收发送器,可编程配置多种波特率和 I/O 信号格式。该控制器支持自动奇偶校验生成和多主机检测模式。
UART 的操作由配置寄存器和模式寄存器控制。FIFO 状态、调制解调器信号及其他控制器功能可通过状态寄存器、中断状态寄存器和调制解调器状态寄存器读取。
控制器采用独立的接收(Rx)和发送(Tx)数据通路结构,每条通路均包含一个 64 字节的 FIFO。控制器对 Tx 和 Rx FIFO 中的数据进行串行化与解串,并包含模式切换功能,以支持 RxD 和 TxD 信号的各种环回配置。FIFO 中断状态位支持轮询或中断驱动处理方式。软件通过 Rx 和 Tx 数据端口寄存器读取和写入数据字节。
当 UART 用于类似调制解调器的应用时,调制解调器控制模块负责检测并生成调制解调器握手信号,同时根据握手协议控制接收和发送通路。
要点介绍
配置方式
UART模块通过控制寄存器和模式寄存器进行控制,用于选择 UART 的多种工作模式。
控制寄存器负责使能、禁用接收器和发送器模块,并可对其执行软复位。此外,该寄存器还能重启接收器超时计数器。
模式寄存器用于选择波特率发生器所使用的时钟,同时可配置发送和接收数据的数据位长度、校验位以及停止位。此外,该寄存器还根据需要选择 UART 的操作模式,可在正常 UART 模式、自动回显、本地环回或远程环回之间切换。
波特率发生器
波特率发生器为接收器和发送器提供位周期时钟,即波特率时钟。波特率时钟的实现方式是:分发基准时钟 uart_clk 与一个单周期时钟使能信号,从而模拟出以适当分频频率进行时钟计时的效果。UART模块的波特率发生器原理框图如下图所示

波特率发生器可以使用主时钟信号 uart_ref_clk,也可以使用主时钟 8 分频后的信号 uart_ref_clk/8。具体选择哪个时钟信号由模式寄存器(uart.mode_reg0)中的 CLKS 位决定。下文将选中的时钟称为 sel_clk。
sel_clk 时钟进一步分频,产生另外三个时钟:baud_sample、baud_tx_rate 和 baud_rx_rate。baud_tx_rate 是用于发送数据的目标波特率。baud_rx_rate 名义上与之相同,但会与接收到的输入数据重新同步。baud_sample 时钟运行在 (BDIV + 1) 倍于 baud_rx_rate 和 baud_tx_rate 的频率上,用于对接收数据进行过采样。
sel_clk 时钟频率除以波特率发生器寄存器中的 CD 字段值,产生 baud_sample 时钟使能信号。该寄存器的可编程取值范围为 1 到 65535。
baud_sample 时钟再除以 (BDIV + 1)。BDIV 是波特率分频寄存器中的一个可编程字段,取值范围为 4 到 255。其复位值为 15,意味着默认每个 baud_tx_clock / baud_rx_rate 周期对应 16 个 baud_sample 时钟。
baud_sample 时钟频率如公式 如下所示

baud_rx_rate 和 baud_tx_rate 时钟信号的频率如下:

++注意: 在向波特率发生器寄存器(uart.Baud_rate_gen_reg0)或波特率分频寄存器(uart.Baud_rate_divider_reg0)写入新值之前,必须禁止发送器和接收器。在重新使能它们之前,需要对发送器和接收器分别发出软复位++
以UART_Ref_Clk = 50 MHz,Uart_ref_clk/8 = 6.25 MHz为例,给出了 uart_ref_clk 时钟、波特率、时钟分频系数(CD 和 BDIV)以及误差率之间关系的一些示例如下表所示。

发送FIFO
发送 FIFO(TxFIFO)用于存储从 APB 接口写入的数据,直到这些数据被发送模块取出并加载到其移位寄存器中。TxFIFO 的最大数据宽度为 8 位。通过对 TxFIFO 寄存器执行写操作,可将数据加载到 TxFIFO 中。
当数据被加载到 TxFIFO 后,TxFIFO 的空标志会被清零,并保持低电平状态,直到 TxFIFO 中的最后一个字被取出并加载到发送移位寄存器中。这意味着主机软件还有一个完整串行字时间的时间窗口来准备下一个数据,从而能够响应空标志的置位,并在不影响发送时序的情况下向 TxFIFO 写入下一个字。
TxFIFO 满中断状态(TFULL)表示 TxFIFO 已完全填满,阻止任何进一步的数据加载到 TxFIFO 中。如果此时再次对 TxFIFO 执行 APB 写操作,则会触发上溢,且写入的数据不会被加载到 TxFIFO 中。发送 FIFO 几乎满标志(TNFULL)指示 FIFO 中剩余的可用空间不足以再写入一个编程字长(该字长由模式寄存器的 WSIZE 位控制)的数据。
TxFIFO 几乎满标志(TNFULL)表示 TxFIFO 中仅剩一个字节的空闲空间。可以基于 TxFIFO 的填充水平设置一个阈值触发(TTRIG)。通过发送触发寄存器可配置该阈值,当 TxFIFO 的填充水平达到该编程值时,触发条件生效。
发送数据流
发送模块从 TxFIFO 中取出并行数据,并将其加载到发送移位寄存器中,以便进行串行化处理。发送模块将起始位、数据位、校验位和停止位以串行数据流的形式逐位移出。数据在发送波特率时钟使能信号(baud_tx_rate)的下降沿进行发送,且最低有效位(LSB)在前。下图展示了一个典型的发送数据流。

接收FIFO
接收 FIFO(RxFIFO)用于存储由接收串行移位寄存器接收到的数据。RxFIFO 的最大数据宽度为 8 位。
当数据被加载到 RxFIFO 后,RxFIFO 的空标志会被清零,并保持低电平状态,直到 RxFIFO 中的所有数据都通过 APB 接口被读出为止。从空的 RxFIFO 中读取数据将返回 0。
RxFIFO 满状态(Chnl_int_sts_reg0RFUL 和 Channel_sts_reg0RFUL 位)表示 RxFIFO 已满,并阻止任何进一步的数据加载到 RxFIFO 中。当 RxFIFO 中有了空闲空间后,接收器中暂存的任何字符将被加载到 RxFIFO 中。
可以基于 RxFIFO 的填充水平设置一个阈值触发(RTRIG)。通过接收触发水平寄存器(Rcvr_FIFO_trigger_level0)可配置该阈值,当 RxFIFO 的填充水平越过该编程值时,触发条件生效。可配置范围为 1 到 63。
接收数据采样
UART 使用 UARTx REF_CLK 和时钟使能信号(baud_sample)对 UARTx_RxD 信号进行连续过采样。当采样检测到信号跳变为低电平时,这可能指示起始位的开始。当 UART 检测到 UART_RxD 输入为低电平后,它会等待 BDIV 个波特率时钟周期的一半(即 BDIV/2 个周期,使其采样落于这一位数据的中心附近),然后再次采样三次。如果这三次采样结果仍均为低电平,则接收器将其视为一个有效的起始位,如图所示(图中默认 BDIV = 15)

当识别到有效的起始位后,接收器的波特率时钟使能信号(baud_rx_rate)会重新同步,从而使得后续对输入 UART RxD 信号的采样点落于每个比特的理论中点附近,如图所示:

当重新同步后的 baud_rx_rate 信号为高电平时,会对最近采样的三个比特位进行比较。逻辑值通过多数表决确定:其中两个采样值相同即决定该数据位的值。当某个串行数据位的值被确定后,它会被移入接收移位寄存器。当一个完整的字符组装完毕后,该寄存器的内容随后被推入 RxFIFO。
接收校验错误
每次接收到一个字符时,接收器会根据 uart.mode_reg0PAR 位字段计算所接收数据位的奇偶校验结果,然后将该结果与接收到的奇偶校验位进行比较。如果检测到差异,奇偶校验错误位 uart.Chnl_int_sts_reg0PARE 会被置为 1。若中断已使能,则会产生一个中断。
接收帧错误
当接收器在一帧结束时未能接收到有效的停止位时,帧错误位 uart.Chnl_int_sts_reg0FRAME 会被置为 1。若中断已使能,则会产生一个中断
接收溢出错误
当接收到一个字符时,控制器会检查 RxFIFO 是否有空余空间。如果有,则将该字符写入 RxFIFO。如果 RxFIFO 已满,则控制器等待。如果在后续检测到 RxD 上的起始位时 RxFIFO 仍然为满,则数据会丢失,并且控制器会设置接收溢出中断位 uart.Chnl_int_sts_reg0ROVR = 1。若中断已使能,则会产生一个中断。
接收超时机制
接收器超时机制使接收器能够检测 RxD 信号处于不活动状态(持续高电平)。超时周期通过写入 uart.Rcvr_timeout_reg0RTO 位字段进行编程。该超时机制使用一个 10 位递减计数器。每当 RxD 信号上接收到新的起始位,或者软件向 uart.Control_reg0RSTTO 写入 1 时(无论之前的 RSTTO 值为何),计数器都会重载并开始递减计数。
如果在 1,023 个位周期内没有发生起始位接收或复位超时操作,则会产生超时。中断状态寄存器中的接收器超时错误位 TIMEOUT 将被置位,同时需要向控制寄存器中的 RSTTO 位写入 1 以重启超时计数器,此时计数器会装载新编程的超时值。
计数器的高 8 位从 RTO 位字段的值重载,低 2 位初始化为 0。计数器由 UART 位时钟驱动。例如,若 RTO = 0xFF,则超时周期为 1,023 个位时钟(256 × 4 − 1)。若向 RTO 位写入 0,则超时机制被禁用。
当递减计数器递减到 0 时,接收器超时发生,控制器将设置超时中断状态位 uart.Chnl_int_sts_reg0TIMEOUT = 1。若中断已使能(uart.Intrpt_mask_reg0TIMEOUT = 1),则会向 PS 中断控制器断言 IRQ 信号。
每当超时中断发生时,通过向 Chnl_int_sts_reg0TIMEOUT 位写 1 来清除该中断。软件必须设置 uart.Control_reg0RSTTO = 1 以产生后续的接收器超时中断。
IO模式切换
模式开关控制控制器内部 RxD 和 TxD 信号的路径,如图 所示。无论 UARTx TxD/RxD I/O 信号在 MIO-EMIO 路由中如何连接,通过模式开关实现的环回功能均独立生效。如图 19-7 所示,共有四种工作模式,由 uart.mode_reg0CHMODE 寄存器位字段控制:正常模式、自动回显模式、本地环回模式和远程环回模式。

正常模式
正常模式用于标准UART操作
自动回显模式
回显模式在 RxD 引脚上接收数据,模式开关会将该数据同时路由至接收器内部和 TxD 引脚。此时,来自发送器的数据无法从控制器向外发送。
本地环回模式
本地环回模式不连接 RxD 或 TxD 引脚,而是将发送的数据直接环回至接收器。
远端环回模式
远程环回模式将 RxD 信号连接到 TxD 信号。在此模式下,控制器无法在 TxD 上发送任何数据,也无法在 RxD 上接收任何数据
串口间互联
PS 中的两个 UART 控制器的 I/O 信号可以相互连接。在此模式下,通过设置 slcr.LOOPUA0_LOOP_UA1 位 = 1,可以将一个 UART 控制器的 RxD 和 CTS 输入信号连接到另一个 UART 控制器的 TxD 和 RTS 输出信号。其他流控信号不进行连接。这种 UART 到 UART 的连接独立于 MIO-EMIO 的编程配置。
状态和中断寄存器
UART有两个可供软件读取的状态寄存器。两者均反映原始状态。Chnl_int_sts_reg0 寄存器既可读取状态,也可产生中断。Channel_sts_reg0 寄存器仅用于读取状态。
Chnl_int_sts_reg0 寄存器是粘性的:一旦某位置位,该位将保持置位状态,直到软件将其清零。写入 1 即可清除相应位。该寄存器与 Intrpt_mask_reg0 掩码寄存器按位相"与"。如果任何按位"与"的结果为 1,则 UART 会向 PS 中断控制器断言中断信号。
Channel_sts_reg0:只读原始状态,写操作被忽略。
各种 FIFO 和系统指示信号分别路由到 uart.Channel_sts_reg0 寄存器和/或 uart.Chnl_int_sts_reg0 寄存器,如下图:

中断掩码寄存器
Intrpt_mask_reg0 是一个只读的中断掩码/使能寄存器,用于掩码 Chnl_int_sts_reg0 寄存器中的各个原始中断:
若掩码位 = 0,则该中断被屏蔽。
若掩码位 = 1,则该中断被使能。
该掩码由只写的 Intrpt_en_reg0 和 Intrpt_dis_reg0 寄存器控制。每个对应的使能/禁用中断位应设置为互斥(例如,要使能一个中断,向 Intrpt_en_reg0x 写入 1,同时向 Intrpt_dis_reg0x 写入 0)
通道状态
以下状态位位于 Channel_sts_reg0 寄存器中。
TACTIVE:发送器状态机活动状态。若处于活动状态,表示发送器当前正在移出一个字符。
RACTIVE:接收器状态机活动状态。若处于活动状态,表示接收器已检测到起始位,并且当前正在移入一个字符。
FDELT:接收器流延迟触发连续状态。FDELT 状态位用于监测 RxFIFO 的填充水平与流延迟触发水平之间的比较结果。
非FIFO中断
以下中断状态位位于 Chnl_int_sts_reg0 寄存器中。
TIMEOUT:接收器超时错误中断状态。当接收器超时计数器因长时间空闲而超时时,触发此事件。
PARE:接收器奇偶校验错误中断状态。当接收到的奇偶校验位与预期值不匹配时,触发此事件。
FRAME:接收器帧错误中断状态。当接收器未能检测到有效的停止位时,触发此事件。
DMSI:指示 DCD、DSR、RI 或 CTS 调制解调器流控信号上发生逻辑电平变化。这包括这些信号中任何一个上的高到低和低到高逻辑跳变。
FIFO中断
下表中列出的 FIFO 中断所对应的状态位如下图所示。这些中断状态位位于通道状态寄存器(uart.Channel_sts_reg0)和通道中断状态寄存器(uart.Chnl_int_sts_reg0)中,但 TOVR 和 ROVR 位不属于 uart.Channel_sts_reg0 寄存器。
FIFO 触发水平由以下位字段控制:
uart.Rcvr_FIFO_trigger_level0RTRIG,一个 6 位字段
uart.Tx_FIFO_trigger_level0TTRIG,一个 6 位字段


调制解调器控制模块
调制解调器控制模块用于协助调制解调器与 UART 之间的通信控制。它包含调制解调器状态寄存器、调制解调器控制寄存器、中断状态寄存器中的 DMSI 位以及通道状态寄存器中的 FDELT 位。当调制解调器状态寄存器中的 DCTS、DDSR、TERI 或 DDCD 位被置位时,将触发该事件。
只读的调制解调器状态寄存器用于读取 CTS(清除发送)、DCD(数据载波检测)、DSR(数据设备就绪)和 RI(振铃指示)等调制解调器输入信号的值。该寄存器还报告这些输入信号中任何一个的变化,并指示自动流控模式当前是否已使能。调制解调器状态寄存器中的位通过向特定位写入 1 来清除。
仅可读写的调制解调器控制寄存器用于设置 DTR(数据终端就绪)和 RTS(请求发送)输出,以及使能自动流控模式寄存器。
默认情况下,自动流控模式是禁用的,这意味着调制解调器的输入和输出完全在软件控制下工作。当通过设置调制解调器控制寄存器中的 FCM 位使能自动流控模式后,UART 的发送和接收状态将使用调制解调器握手输入和输出信号进行自动控制。
在自动流控模式下,请求发送(RTS)输出信号会根据接收 FIFO 的当前填充水平进行断言(有效)和去断言(无效),从而使远端发送器暂停发送,防止 UART 接收 FIFO 上溢。流延迟寄存器(`Flow_delay_reg0`)中的 `FDEL` 字段用于在接收 FIFO 上设置一个触发水平,当达到该水平时将导致 RTS 去断言。RTS 将保持低电平,直到 FIFO 的填充水平下降到比 `FDEL` 设定的值少 4 个字节以下。
此外,在自动流控模式下,UART 仅在清除发送(CTS)输入被断言时才进行发送。当 CTS 被去断言时,UART 会在下一个字符边界处暂停发送。
如果选择自动流控,则必须对流延迟寄存器进行编程,以便通过将 RTS 信号去断言来控制数据流入。编程值对应 RTS 信号将被去断言时的 RxFIFO 水平。当 RxFIFO 水平下降到比流延迟寄存器中编程值少 4 个字节时,RTS 信号将被重新断言。