当前位置: 首页 > news >正文

【Linux驱动开发】Linux UART 通信详解:从硬件到驱动再到应用

Linux UART 通信详解:从硬件到驱动再到应用

UART(Universal Asynchronous Receiver/Transmitter)是嵌入式与 PC 领域最常见、最基础的异步串行通信接口。Linux 内核将其抽象为 TTY/串口子系统,为上层提供统一、可移植的访问方式。本文从硬件原理、协议帧格式、底层驱动框架、内核与用户态接口、实际应用到调试方法,系统梳理 Linux UART 通信的全景。


1. 硬件原理

1.1 物理层

  • 信号线:TX(发送)、RX(接收)、GND(地)即可通信;可选 RTS/CTS(硬件流控)、DTR/DSR、RI/DCD(调制解调器状态)。
  • 电平标准
    • TTL(3.3 V / 5 V)直接接 MCU/SoC;
    • RS-232:±3~15 V,需电平转换芯片(MAX3232 等);
    • RS-485:差分、半双工、抗干扰,需收发器(MAX3485 等)。
  • 波特率:常见 9600、115200、921600、3 M、4 Mbps(受芯片与时钟限制)。

1.2 UART 控制器内部框图

在这里插入图片描述

  • 发送端:TX FIFO → 并串转换 → 发送移位寄存器 → TX 引脚;
  • 接收端:RX 引脚 → 接收移位寄存器 → 并串转换 → RX FIFO;
  • 波特率生成器:基于输入时钟分频(div = clk / (baud × oversample),通常 16× 过采样);
  • 中断/DMA:TX FIFO 空、RX FIFO 触发阈值、帧错误、Break、Overrun 等;
  • 流控:RTS/CTS 自动拉低/拉高,或软件流控 XON/XOFF。

2. 协议帧格式

UART 是异步字节流协议,无共享时钟,靠“起始位”同步。

在这里插入图片描述

字段位数说明
起始位1低电平
数据位5~9LSB 在前,常见 8 位
校验位0/1可选奇/偶/标记/空间
停止位1/1.5/2高电平,常见 1 位

空闲位:线路保持高电平;Break:故意拉低 > 一帧时间,用于唤醒或信号。


3. Linux 内核驱动框架

Linux 把 UART 纳入 TTY 子系统,分层:

在这里插入图片描述

3.1 核心数据结构

  • struct uart_driver:一个芯片厂商驱动实例,注册到内核;
  • struct uart_port:描述一组寄存器/IO 映射、IRQ、FIFO 深度等;
  • struct uart_ops:底层回调(startup/shutdown/tx_empty/set_mctrl/…);
  • struct tty_port:与 TTY 层交互,管理缓冲、流量控制、线路规程;
  • struct tty_driver:TTY 层向上提供字符设备(/dev/ttyS*, /dev/ttyAMA*, /dev/ttyUSB* 等)。

3.2 注册流程(简化)

  1. 驱动 module_init()uart_register_driver()
  2. 设备树/ACPI 或平台代码探测到端口 → uart_add_one_port()
  3. TTY 层自动创建设备节点,用户空间 open(/dev/ttyS0) 即关联到该端口;
  4. 线路规程(N_TTY 默认,或 N_PPS/N_IRDA/…)负责把字节流加工成行缓冲/包。

3.3 数据收发

  • 轮询(早期)uart_console_write() 在启动阶段;
  • 中断:RX 触发 → serial_in() 读 FIFO → tty_insert_flip_char()tty_flip_buffer_push() → 用户 read()
  • DMA
    • 散聚 DMA(dmaengine)把 UART FIFO 与内存环形缓冲绑定;
    • 减少 CPU 介入,115200×8×N 路同时收发无压力;
    • 需要驱动实现 dma_rx_push/dma_tx_submit

3.4 流控实现

  • 软件流控 (XON/XOFF):线路规程识别 ^S/^Q,驱动自动停/启 TX;
  • 硬件流控 (RTS/CTS)
    • 驱动 set_mctrl() 拉高/拉低 RTS;
    • RX FIFO 快满 → 拉低 RTS;CTS 为低则硬件自动停 TX;
    • 与 RS-485 半双工联动:发数据前拉高 DE(Driver Enable),发完产生 TX-Done 中断 → 拉低 DE,避免总线冲突。

3.5 控制台与早期打印

  • console_initcall() 注册 struct console
  • 内核启动早期 printk()uart_console_write() 直接写 TX 寄存器,无中断;
  • 后期 console_on_rootfs → 切换到 TTY 层,支持 getty/login

4. 用户态访问与配置

4.1 基本操作

# 查看串口设备
$ dmesg | grep tty
$ ls -l /dev/ttyS* /dev/ttyAMA* /dev/ttyUSB*# 配置波特率 115200 8N1,无流控
$ stty -F /dev/ttyS0 115200 cs8 -cstopb -parenb -ixon -ixoff# 收发数据
$ cat /dev/ttyS0 &
$ echo "hello" > /dev/ttyS0

4.2 termios 编程

#include <termios.h>
#include <fcntl.h>
#include <unistd.h>int open_uart(const char *dev) {int fd = open(dev, O_RDWR | O_NOCTTY | O_NONBLOCK);struct termios tio;tcgetattr(fd, &tio);cfsetispeed(&tio, B115200);cfsetospeed(&tio, B115200);tio.c_cflag &= ~PARENB;   // 无校验tio.c_cflag &= ~CSTOPB;   // 1 停止位tio.c_cflag &= ~CSIZE;tio.c_cflag |= CS8;       // 8 数据位tio.c_cflag |= CREAD | CLOCAL;tcsetattr(fd, TCSANOW, &tio);return fd;
}

4.3 高级:RAW 模式、非阻塞、select/epoll

  • cfmakeraw() 关闭行缓冲、回显;
  • VMIN=0 VTIME=0 实现非阻塞立即返回;
  • select/poll/epoll 监听可读/可写,配合环形缓冲实现高吞吐。

5. 实际应用场景

场景典型芯片/接口注意要点
启动控制台x86 /dev/ttyS0, ARM /dev/ttyAMA0波特率 115200,需在内核 console=ttyS0,115200
GPS 模块TTL 3.3 V,9600/115200注意电平匹配,用 PPS 线路授时
RS-485 传感器网络半双工,MAX3485需 GPIO 控制 DE/RE,驱动里 rs485conf
蓝牙 HCIUART H:4需硬件流控,波特率 921600
固件升级bootloader UART通常 8N1,115200,XMODEM/YMODEM

6. 调试与故障排查

6.1 信号测量

  • 示波器/逻辑分析仪:查看 TX/RX 波形,确认波特率、起始/停止位、抖动;
  • 差分探头测 RS-485 A/B 波形,检查反射/终端匹配(120 Ω)。

6.2 软件跟踪

  • dmesg 查看 Overrun/Framing Error;
  • cat /proc/tty/driver/serial 显示内部计数;
  • stty -F /dev/ttyS0 -a 查看当前配置;
  • setserial -a /dev/ttyS0 查看 UART 类型、FIFO 深度、端口/IRQ;
  • irqtop/perf 监测中断频率,判断是否频繁 Overrun。

6.3 常见故障

现象可能原因排查/解决
乱码波特率/格式不匹配双方 stty 对比,示波器测位宽
丢字节Overrun,RX FIFO 溢出提高波特率容错,启用 DMA,降低中断延迟
无响应TX/RX 反接交叉线 TX→RX,RX→TX;RS-485 A/B 接反
高误码电缆过长/无屏蔽降波特率,用 RS-485/422 差分,加终端电阻
流控失效线路未接/极性错万用表量 RTS/CTS 电平,驱动里 autocts

7. 性能优化要点

  • DMA 环形缓冲:减少每字节中断,CPU 占用 <1% @ 4 Mbps;
  • 中断亲和:把 UART IRQ 绑定到单独核,避免任务迁移;
  • FIFO 阈值调优:RX 触发 1/2 FIFO,平衡延迟与吞吐;
  • 内核抢占/实时:PREEMPT_RT 下,中断线程化,抖动 < 100 µs;
  • RS-485 切换延迟:DE→TX 使能后 ≥ 1 字符时间再发数据,避免首字节截断;
  • 用户态环形缓冲 + mmap:部分驱动支持 mmap() 直接访问 flip buffer,零拷贝。

8. 小结

UART 看似简单,却贯穿“物理层→帧格式→控制器→驱动→TTY 子系统→用户 API”完整链条。理解硬件过采样、FIFO/中断/DMA、线路规程与流控,是排查乱码/丢包/延迟的关键。Linux 提供标准化 TTY 接口,让同一套 termios/poll 代码可复用到 ttyS/ttyAMA/ttyUSB/ttyXR 等不同芯片。掌握上述原理与调试方法,可在嵌入式、工控、物联网、蓝牙/RS-485 多节点网络中快速定位问题并榨干最后一滴带宽。


附录:参考文档

  • Linux Kernel: Documentation/serial/, drivers/tty/serial/8250.c, serial_core.c
  • RS-232/485 标准:TIA/EIA-232-F, TIA-485-A
  • 芯片手册:TI MAX3232, MAX3485, CP2102, FT232RL, PL2303
  • LDD3 Chapter 18: “TTY Drivers”
  • 书籍:《Linux 设备驱动开发详解》《嵌入式 Linux 开发教程》

本文档示例基于 Linux 4.4.94,不同版本内核接口基本一致,DMA/RS-485 配置细节请以实际 SoC 手册与驱动为准。

http://www.dtcms.com/a/618429.html

相关文章:

  • 大型网站架构系列:分布式消息队列(一)
  • 煤矿传送带异物检测:深度学习如何提升煤矿安全?
  • Milvus-云原生和分布式的开源向量数据库-介绍
  • 在linux(Centos)中Mysql的端口修改保姆级教程
  • 哪个网站可以做优惠券wordpress博客文章404
  • wordpress active济南优化网站价格
  • 怎样在自己的网站上家程序数字营销工具
  • 【论文学习】超越自注意力:用于视觉任务的两种线性层外部注意力
  • Python一个类的特殊方法有哪些
  • 网站建设免费制作北京王府井在哪个区
  • 力扣-买卖股票的最佳时机
  • 利用canvas来实现图片添加文字 制作图片logo
  • 禅城区网站建设公司qq网页注册入口
  • c++音乐——《两只老虎》
  • 开发 必知 网站上饶哪有做网站的公司
  • pytest1-接口自动化测试场景
  • 江西网站建设企业网站备案和服务器备案
  • 机器学习--决策树算法(筛选病例)
  • 网站收录查询网做图片格式跟尺度用哪个网站好
  • Java 核心知识点笔记(集合、浮点存储、异常、反射、static/this关键字)
  • 二维差分算法高效解靶场问题
  • 免费的企业黄页网站永久免费网站模板如何使用 如何修改吗
  • 如何在树莓派部署Nginx并实现无公网ip远程访问内网制作的web网站
  • 北京网站建设方案书专业的企业智能建站制造厂家
  • Hystrix架构原理与使用详解
  • bash Buffering
  • 区块链论文速读 CCF A--USENIX Security 2025(6)
  • SAP FICO工单成本明细报表
  • 网站建设需要看什么书长沙专业企业建站联系人
  • 金华永康网站建设手机优化怎么关闭