2. UART硬件架构:内部框图、发送器/接收器逻辑、移位寄存器与缓冲寄存器
UART(Universal Asynchronous Receiver/Transmitter)作为串行通信的核心外设,其硬件架构直接决定了驱动开发中中断配置、FIFO阈值设定以及数据流控制的底层行为。本节从硬件内部框图出发,逐层剖析发送器与接收器的工作逻辑,并重点阐释移位寄存器与缓冲寄存器在数据流中的角色。
2.1 UART内部框图与核心模块
一个完整的UART硬件模块通常包含以下功能单元:
- 总线接口单元(Bus Interface Unit):负责与CPU系统总线(如AMBA AHB/APB)进行寄存器读写交互。
- 波特率发生器(Baud Rate Generator):基于系统时钟分频产生收发时钟,决定串行通信速率。
- 发送器(Transmitter):包含发送移位寄存器(TSR)和发送缓冲寄存器(THR),负责将并行数据转换为串行比特流。
- 接收器(Receiver):包含接收移位寄存器(RSR)和接收缓冲寄存器(RBR),负责将串行比特流恢复为并行数据。
- 控制逻辑与状态寄存器:管理中断、FIFO控制、流控信号(RTS/CTS)以及线路状态(如帧错误、溢出错误)。
- FIFO存储器:可选深度(如16字节、64字节),用于缓解CPU响应延迟,降低中断频率。
架构要点: 移位寄存器与缓冲寄存器是UART数据路径的两级存储结构。缓冲寄存器面向CPU总线,移位寄存器面向串行线路,二者通过硬件握手完成数据搬运。
2.2 发送器逻辑:从并行到串行的转换
发送器的核心任务是将CPU写入的并行数据(通常为8位或9位)转换为符合UART帧格式的串行比特流,并通过TX引脚逐位发送。其工作流程如下:
- CPU写入THR:驱动程序将待发送的数据写入发送保持寄存器(THR)。若FIFO使能,数据先进入发送FIFO。
- 数据搬运至TSR:当发送移位寄存器(TSR)空闲时,硬件自动将THR(或FIFO头部)的数据并行加载到TSR。
- 串行移位输出:TSR在波特率时钟驱动下,从最低有效位(LSB)开始,逐位将数据移出到TX引脚,同时插入起始位(0)、可选的校验位和停止位(1)。
- 状态更新:发送完成后,硬件置位发送保持寄存器空(THRE)或发送完成(TC)状态位,并可触发中断。
驱动关注点: 在中断模式下,驱动应监控THRE中断或FIFO触发阈值中断。当THR空或FIFO低于阈值时,驱动及时填充下一批数据,避免发送停顿(TX underrun)。
2.3 接收器逻辑:从串行到并行的恢复
接收器负责从RX引脚采样串行比特流,检测起始位,逐位移入接收移位寄存器(RSR),并在完整接收一帧后并行传输到接收缓冲寄存器(RBR)或接收FIFO。关键步骤包括:
- 起始位检测:接收器持续采样RX引脚,检测到高电平到低电平的跳变后,确认起始位有效(通常在中点采样以抗干扰)。
- 数据位采样:在波特率时钟的每个位周期中点,依次采样数据位(LSB优先),移入RSR。
- 帧结束与校验:采样停止位,检查校验位(若使能),并检测帧错误(停止位不为1)或溢出错误。
- 数据传递:完整帧接收后,RSR内容并行加载到RBR(或FIFO),置位接收数据就绪(RDR)状态,触发接收中断。
常见错误处理: 若CPU未及时读取RBR而下一帧数据已到达,将发生溢出错误(Overrun Error),旧数据被覆盖。启用FIFO并合理配置接收触发阈值可显著降低溢出概率。
2.4 移位寄存器与缓冲寄存器的对比
移位寄存器与缓冲寄存器虽然都参与数据存储,但功能定位和硬件行为有本质区别。下表总结了二者的关键差异:
| 对比维度 | 移位寄存器(TSR / RSR) | 缓冲寄存器(THR / RBR) |
|---|---|---|
| 核心功能 | 串行 ↔ 并行转换,逐位移位 | 暂存数据,提供CPU访问接口 |
| CPU可访问性 | 不可直接读写(硬件内部使用) | 可直接读写(通过总线接口) |
| 数据流向 | 发送:THR → TSR → TX 接收:RX → RSR → RBR |
发送:CPU → THR → TSR 接收:RSR → RBR → CPU |
| 时钟域 | 波特率时钟(低速串行域) | 系统总线时钟(高速并行域) |
| 深度 | 通常为1帧(如8位或9位) | 1帧(无FIFO)或FIFO深度(16/64字节) |
| 中断触发 | 不直接触发中断 | THR空、RBR满、FIFO阈值等触发中断 |
2.5 FIFO与双缓冲的协同工作
在无FIFO的经典UART中,THR和RBR各自只有1字节深度,CPU必须在每个字节传输完成前响应中断,否则将导致数据丢失或发送停顿。引入FIFO后,数据路径变为:
- 发送路径:CPU → 发送FIFO → THR(FIFO头部) → TSR → TX
- 接收路径:RX → RSR → RBR(FIFO头部) → 接收FIFO → CPU
FIFO的引入使得CPU可以在一次中断服务中批量处理多个字节,显著降低中断频率。驱动开发中,FIFO触发阈值(如1/4、1/2、3/4满)的配置直接决定了实时性与CPU负载的平衡。
工程实践要点: 在Linux内核中,uart_port结构体的fifosize字段记录了FIFO深度;驱动通过uart_fifo_timeout()计算超时,并在中断处理中根据FIFO水位决定读写策略。阈值配置通常写在termios或平台数据中。
2.6 硬件架构对驱动设计的约束
理解UART硬件架构后,驱动开发者应关注以下硬件特性对软件设计的影响:
| 硬件特性 | 驱动设计约束 | 典型应对策略 |
|---|---|---|
| 双缓冲(THR/TSR) | 发送时CPU可连续写入两字节而不丢失 | 利用THRE中断,在中断中写入下一字节 |
| FIFO深度 | 决定中断频率和批量处理能力 | 根据波特率计算阈值,平衡实时性与CPU负载 |
| 接收溢出 | CPU未及时读取RBR/FIFO导致数据丢失 | 启用FIFO、提高中断优先级、使用DMA卸载 |
| 波特率误差 | 收发双方时钟偏差导致采样错误 | 选择误差<2%的分频系数,使用自动波特率检测 |
| 流控信号(RTS/CTS) | 硬件流控需驱动配置GPIO或专用引脚 | 在termios中设置CRTSCTS,驱动处理流控状态 |