【立创泰山派】Linux驱动之UART驱动程序


前言

提示:本章内容只介绍如何在泰山派上进行设备树配置以及串口应用移植
Linux串口驱动在Linux系统中具有广泛的应用,它主要用于控制和管理串口设备,使应用程序能够与这些设备进行通信,像printk就是基于串口驱动实现的。它可以分别实现以下功能:

1.串口通信
  • 串口通信是Linux串口驱动的核心应用。它允许Linux系统通过串口与其他设备(如传感器、显示屏、调制解调器等)进行通信。

  • 串口驱动提供了一系列函数和数据结构,使应用程序能够通过字符设备接口与串口设备进行交互

  • 串口驱动负责初始化串口硬件、处理串口中断、实现读写操作和控制命令等任务。

2.调试和测试
  • Linux串口驱动可用于系统开发和调试过程中的通信。例如,开发人员可以使用串口调试工具(如minicom、kermit等)通过串口与嵌入式系统或设备进行通信,以监控和调试系统状态。

  • 通过串口驱动,开发人员可以实时查看和修改系统参数、发送控制命令以及接收设备数据等。

3.性能分析
  • Linux串口驱动可以用于性能分析。通过在关键代码段插入串口输出语句(类似于printk),开发人员可以监控代码的执行流程和时间,从而找出性能瓶颈并进行优化。

  • printk是Linux内核中用于在控制台或系统日志中打印调试信息的函数。它允许开发人员选择不同的调试级别(如DEBUG、INFO、WARNING、ERROR等)以及定义输出的格式。

4.扩展串口功能
  • 开发人员可以通过自定义串口驱动模块来扩展Linux系统的串口功能,以满足特定应用需求。

  • 例如,对于使用RS-485通信协议的设备,开发人员可以编写一个基于tty驱动的485设备驱动程序,以实现对RTS和DTR信号线的控制。


提示:以下是本篇文章正文内容

一、基础知识

1.什么是串口

串口全称串行通信接口,是,种常用于电子设备之间通信的异步的全双工接口,典型的串口通信只需要三根线,分别是地线(GND),发送线(TX),接收线(RX)。如下图所示
在这里插入图片描述

1.1 波特率

串口的通信速率称为波特率(bandrate),波特率也可以称为码元速率,定义:单位时间内通过信道传输的码元个数就是波特率,单位:波特

在数字信号中,一个脉冲信号就是一个码元,码元速率指的是在1秒钟内能发送多少个码元,也就是说在数字信道中1秒钟内可以发送多少个脉冲信号。
在这里插入图片描述
注意:对于想要进行串口通信的双方,波特率必须一致!!

2.通信协议

UART是"Universal Asynchronous Receiver/Transmitter”,通用异步收发器的缩写。在19世纪60年代,为了解决计算机和电传打字机通信,Bel发明了 UART协议,将并行输入信号转换成串行输出信号。因为UART简单实用的特性,其已经成为一种使用非常广泛的通讯协议。我们日常接触到的串口,RS232,RS485等总线,内部使用的基本都是 UART协议
为了更好的理解和分析协议与总线的关系,我们通常把一个完整的通讯规范划分成物理层,协议层以及应用层。物理层只定义真实的信号特性(比如电压,电流,驱动能力等),以及电信号与逻辑信号0和1的对应关系;协议层不关心底层的0和1具体怎么实现,只规定逻辑信号的协议规范以及通讯过程(例如起始,数据以及结束等);应用层不关心数据是怎么获取的,只定义数据表示的意义,以及如何实现具体的业务逻辑。
在这里插入图片描述

2.1 UART帧结构

在串口通信中除了需要关注波特率以外,还需要关注数据流,一帧数据由11位组成,分别是1位起始位,8位数据位,1位奇偶校验位,1位停止位。
在这里插入图片描述

  • 起始位:数据线上空闲时为1,拉低代表开始传输数据。
  • 数据位:需要发送或者接收的数据。
  • 奇偶校验位:通过对数据中的1的个数(奇数/偶数)来校验数据传输是否准确。
  • 停止位:数据传输完成。数据线恢复成1的状态。
  • 流控:需要增加额外的线路。流控主要是为了解决两个设备之间的速度不一样的问题。(例如A设备发送的速度很快,B设备收不过来,此时如果有流控的话B设备就会告诉A设备:我现在收不过来了,你等一下在给我发。这个就是流控的作用)

2.2校验方式

  • 奇校验(odd parity):如果数据中有奇数个1,校验位为1,否则为0
  • 偶校验(even parily):如来数据中有偶数个 1,校验位为1,合则为0
  • 0校验(space parity):校验位恒为0,如果为1表述错误
  • 1校验(mark parity):检验位恒为1,如果为0表示错误

二、硬件接口

串口只对数据格式自定义,并没自规定接口的电气特性,如果用高电平代表1,用低电平代表0,那高电平是多少v?低电平又是多少v呢?所以串口的通信接口类型有很多。

在举个例子:
如果在串口通信中直接使用处理器引出的接口,电平是TTL电平。但是处理器的电平也有可能存在差异,所以某些情况下并不能直接连接。这时就要进行电平转换。TTL:ransistor transistor loglc

但是因为TTL的抗干扰能力比较弱,在数据传输的时候很容易出错,所以通信距离也短。往往只用在一个电板中的俩个不同的芯片通信。既然串口没有规定电平需特性,那是不是就可以通过电器特性来入手解决TTL的缺点呢?
在这里插入图片描述

1.基于TTL的UART通讯

为了增强驱动能力,以增加传输距离和可靠性,RS232总线采用了双极性电压信号来进行物理传输。信号在发送/接收之前,通过电平转换芯片实现内部信号和总线信号的互相转换。连接方式和TTL电平完全相同,整个物理层只是多了一层电平转换。
在这里插入图片描述
为了对比不同物理层实现的差别,我们可以观察发送相同数据时,不同物理层的实际信号有何不同。这里以发送字符D’为例,通过璞石示波器,直接观察TL实现传输的信号(探头接地端连接设备共地端,探头信号端连接上图蓝色信号线),可以获得如图 1-4所示的信号波形。从波形可以看出,当没有数据传输时,UART信号会一直保持在高电平(具体信号幅度由I/0的供电电压决定),数据传输时信号发生跳变,传输完成后信号重新回到空闲的高电平状态。
在这里插入图片描述

2.基于RS232的UART通讯

为了增强驱动能力,以增加传输距离和可靠性,RS232总线采用了双极性电压信号来进行物理传输。信号在发送/接收之前,通过电平转换芯片实现内部信号和总线信号的互相转换。连接方式和TTL电平完全相同,整个物理层只是多了一层电平转换。
在这里插入图片描述
同样以发送字符D为例,璞石示波器的探头连接到信号端,可以采集到如图 1-6所示的实际波形。可以看出,RS232波形在空闲时为负电压,当有数据传输时,信号开始在正负电压之间跳变,传输完成后重新回到空闲的负电压状态。
在这里插入图片描述

3.基于RS485的UART通讯

RS485为复杂的工业环境而设计,和其它UART协议的物理层相比,RS485总线最大的特点就是使用了差分信号传输。信号在发送之前,通过RS485的收发器把单端信号转换成差分信号,再发送到总线上进行传输;同样在接收之前,总线上的差分信号通过收发器的转换变成单端信号再送给UART控制器进行接收。在RS485总线上,如果希望进行全双工的双向通讯,需要两对差分信号线(即4根信号线)。如果只进行半双工的双向通讯,则仅需要一对差
分信号即可,
在这里插入图片描述
还是以发送字符D为例,使用璞石示波器2个通道的探头(共参考地),分别连接到其中一对差分信号的A/B端,可以采集到如图 1-8所示的实际波形。可以看出,A/B端的波形为互补关系。A端波形为正向逻辑(空闲时为正电压),B端波形为反向逻辑(空闲时为负电压)。
在这里插入图片描述

三、软件框架

1.驱动子系统框架

![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/cade9dd0b237489bbb328aaf4a0420eb.png在这里插入图片描述

1.1 串口驱动程序位置

在 Linux 内核 4.19 中,串口驱动使用的是 8250 通用串口驱动,以下为主要驱动文件

- drivers/tty/serial/8250/8250 core.c//8250 串口驱动核心
- drivers/tty/serial/8250/8250_dw.c//synopsis DesignWare 8250 串口驱动
- drivers/tty/serial/8250/8250 dma.c//8250 串口 DMA 驱动
- drivers/tty/serial/8250/8250_port.c//8250串口端口操作
- drivers/tty/serial/8250/8250 early.c//8250 串口 early console 驱动

使用8250串口驱动的方法
在这里插入图片描述

1.2 使用8250驱动的方式

对于这个驱动的使用,首先uart3主节点,该节点已经由芯片原厂写好了,所以接下来我们只要打开就行。
另外,对于UART控制器的dts配置只有以下参数允许修改:

dma-namcs:

  • "tx’打开& txdma
  • "rx”打开区 rxdma
  • "!tx”关闭 txdma
  • "!rx”关闭 rxdma

pinctr-0:

  • &uart1m0_xfcr 配置tx和rx引脚为iomux group 0
  • &uart1m1_xfcr 配置tx和rx引脚为jomux group 1
  • &uart1m0_ctsn 和&uart1m0_rtsn 配置硬件自动流控 cts 和rts引脚为iomux group 0
  • &uart1m1_ctsn 和&uart1m1_rtsn 配置硬件自动流控 cts 和rts引脚为iomux group 1

status:

  • “okay” 打开
  • "disabled"关闭
uart3: serial@fe670000 {  
    compatible = "rockchip,rk3568-uart", "snps,dw-apb-uart"; // 指定设备的兼容性字符串    
    reg = <0x0 0xfe670000 0x0 0x100>; // 定义UART接口的物理地址和大小    
    interrupts = <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>; // 定义UART接口使用的中断信息    
    clocks = <&cru SCLK_UART3>, <&cru PCLK_UART3>; // 指定UART接口使用的时钟源    
    clock-names = "baudclk", "apb_pclk"; // 为上述的时钟源提供名称   
    reg-shift = <2>; // 地址偏移的位数    
    reg-io-width = <4>; // 每个寄存器的位宽  
    dmas = <&dmac0 6>, <&dmac0 7>; // 指定与UART接口关联的DMA通道  
    pinctrl-names = "default"; // 列出所有可能的引脚控制状态名称  
    pinctrl-0 = <&uart3m0_xfer>; // 指定默认状态下的引脚控制配置  
    status = "disabled"; // 表示UART接口的当前状态  
};

在设备树中选择复用管脚打开串口3。

//用户串口3
&uart3 {
	status = "okay";
	pinctrl-names = "default";
	pinctrl-0 = <&uart3m1_xfer>;
};

烧录设备树,即可在/dev/目录下看见新添加的串口设备。
在这里插入图片描述

1.3 串口设备的调试方法

对于创建的串口设备在Linux中有命令可以调试我们的tty设备,咱们主要通过stty命令进行配置

  • 查看串口参数:stty -F /dev/ttyS3 -a
    在这里插入图片描述
  • 设置串口参数:stty -F /dev/ttys3 115200 cs8 -cstopb -parenb -echo
    该命令将串口3(/dev/ttyS3 )设置成 115200 波特率,8位数据模式。一般情况下设置这两个参数就可以了如果显示数据乱码,可能还需要设置其它参数,使用–help查看stty其它设置选项。
  • 开启流控:stty -F /dev/ttyS3 crtscts
  • 关闭流控:stty -F /dev/ttyS3 -crtscts
  • 打印串口数据:cat /dev/ttyS3

2.注册流程分析

3.设备树配置

参考上面

3.串口应用编程

4.minicom移植

总结

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值