Jasonangel
2023/05/03阅读:19主题:默认主题
UART 子系统
1、前言
UART:Universal Asynchronous Receiver/Transmitter,通用异步接收器/发送器。
串行接口 (Serial Interface)是指数据一位一位地顺序传送。区分于并行信号。
UART 包含 TTL 电平的串口和 RS232 电平的串口。TTL 电平是 3.3V 的,而 RS232 是负逻辑电平,它定义 +5 ~ +12V 为低电平,而 -12 ~ -5V 为高电平。

因为 UART 都是由 CPU、MCU 等控制器或专用芯片产生的,所以 UART 的原始电平一般为 TTL 电平即低电平 0V、高电平 3.3V 或 5V。所以,单独说 UART 指的就是 TTL 电平的异步串行通信协议。它有三根线,TX、RX 和 GND。
2、UART spec


起始位:每开始一次通信时发送方先发出一个逻辑”0”的信号(低电平),表示传输字符的开始。(总线空闲时为高电平)
数据位:数据位可以是5、6、7、8,9位等,构成一个字符(一般都是8位)。如ASCII码(7位),扩展BCD码(8位)。先发送最低位,最后发送最高位,‘0’低电平,‘1’高电平。
奇偶校验位:数据位加上这一位后,使得“1”的位数应为偶数(偶校验)或奇数(奇校验),以此来校验数据传送的正确性。校验位其实是调整个数,串口校验分几种方式:
1、无校验(no parity)。
2、奇校验(odd parity):如果数据位中“1”的数目是偶数,则校验位为“1”,如果“1”的数目是奇数,校验位为“0”。
3、偶校验(even parity):如果数据为中“1”的数目是偶数,则校验位为“0”,如果为奇数,校验位为“1”。
4、mark parity:校验位始终为1(不常用)。
5、parity:校验位始终为0(不常用)。
停止位:高电平 1/1.5/2 bit。
空闲位:当总线处于空闲状态时,信号线的状态为‘1’即高电平,表示当前线路上没有数据传输。
3、Linux UART driver
采用的是 8250 通用驱动
drivers/tty/serial/8250/8250_core.c
drivers/tty/serial/8250/8250_dma.c //dma 实现
drivers/tty/serial/8250/8250_dw.c //design ware ip 相关操作
drivers/tty/serial/8250/8250_early.c //early console 实现
drivers/tty/serial/8250/8250_fsl.c
drivers/tty/serial/8250/8250.c
drivers/tty/serial/8250/8250_port.c //端口相关的接口
drivers/tty/serial/earlycon.c //解析命令行参数,并提供注册 early con 接口
内核配置
Device Drivers --->
Character devices --->
Serial drivers --->
[*] 8250/16550 and compatible serial support
[ ] Support 8250_core.* kernel options (DEPRECATED)
[*] Console on 8250/16550 and compatible serial port 8250串口开启 console 功能
[ ] DMA support for 16550 compatible UART controllers
(5) Maximum number of 8250/16550 serial ports //一般填最大串口数
(5) Number of 8250/16550 serial ports to register at runtime //一般填最大串口数
[ ] Extended 8250/16550 serial driver options
[*] Support for Synopsys DesignWare 8250 quirks
关于 DMA 的使用
-
和中断传输模式相比,使用 DMA 并不一定能提高传输速度,相反可能略降低传输速度。 -
因为现在 CPU 的性能都很高,传输瓶颈在外设,而且启动 DMA 还会消耗额外的资源。 -
但整体上看中断模式会占用更多的 CPU 资源。只有传输数据量很大时,DMA 的使用对 CPU 负载的减轻效果才会比较明显。
使用 DMA 建议
-
如果外接的设备传输数据量不大,请使用默认的中断模式。 -
如果外接的设备传输数据量较大,可以使用 DMA。 -
如果串口没接自动流控脚,可以使用 DMA 作为 FIFO 缓冲,防止数据丢失
波特率
波特率 = 时钟源/16/DIV。(DIV 是分频系数)
9600、19200、38400、57600、115200、230400、460800、921600、1000000、1500000
cat /sys/kernel/debug/clk/clk_summary | grep uart
设置串口可唤醒系统
&uart0 {
wakeup-source; //使能串口唤醒功能,作用是待机时不去关闭串口,并把串口中断设置为唤醒源
status = "okay";
};
关掉串口打印功能
Device Drivers --->
Character devices --->
Serial drivers --->
[ ] Console on 8250/16550 and compatible serial port
4、tty 子系统
由于终端种类繁多,为了使其具有统一的上层接口函数,Linux 系统对终端设备进行了总结抽象,总结其共性,抽象出共用的上层接口函数,采用分层的设计思想,将 tty 设备分成三层: tty 核心层,tty 线路规程以及 tty 驱动层。

从图中可以看出用户程序通过 open 、 read 等函数调用核心层,核心层可通过线路规程与 tty 驱动通信。如果数据不需要处理加工,核心层也可直接与 tty 驱动层进行数据的传输。
tty 驱动程序将数据格式化为硬件理解的形式,然后才将数据发送到硬件设备。在用户程序进行终端设备操作时,要调用核心层操作函数 file operations,实现了所以终端设备的 API 函数,是核心层的主要数据结构。
在链路层主要通过 tty_regiser_driver()函数注册线路规程,是链路层的核心函数。终端设备的主要工作是实现 tty_driver 结构体成员的填充,实现其成员函数。




5、波形解析
示例 1
串口输入字符 1,即数据 0x31。
0x31 --> 00110001B --> LSB(低位先发) --> 10001100B

波形解析:
起始位 0
数据位 10001100
停止位 1
波特率计算
50us/div >6bit/div (图中所得)波特率= 6 /5010^6 ~115200 bps
https://blog.csdn.net/a371132/article/details/90727740
作者介绍