Linux驱动开发|UART驱动

article/2025/10/12 23:56:42

UART驱动

串口是一个常用的外设,在 Linux 下通常通过串口和其他设备或传感器进行通信,根据电平的不同,串口分为 TTL 和 RS232。虽然接口电平不同,但其驱动程序都是一样的,通过外接 RS485芯片就可以将串口转换为 RS485 信号。本文介绍如何驱动 I.MX6U-ALPHA 开发板上的 UART3 串口

一、UART驱动框架

串口驱动没有主机端和设备端之分,就只有一个串口驱动,且驱动也已经由 NXP 官方已经编写好了,我们要做的就是在设备树中添加所要使用的串口节点信息。当系统启动以后串口驱动和设备匹配成功,相应的串口就会被驱动起来,生成/dev/ttymxcX(X=0….n)文件

1.1 uart_driver 注册与注销

虽然串口驱动不需要我们去写,但串口驱动框架还是需要了解的, uart_driver 结构体表示 UART 驱动, 其定义在 include/linux/serial_core.h 文件中

struct uart_driver {struct module *owner; 		/* 模块所属者 */const char *driver_name; 	/* 驱动名字 */const char *dev_name; 		/* 设备名字 */int major; 					/* 主设备号 */int minor; 					/* 次设备号 */int nr; 					/* 设备数 */struct console *cons; 		/* 控制台 *//** these are private; the low level driver should not* touch these; they should be initialised to NULL*/struct uart_state *state;struct tty_driver *tty_driver;
};

每个串口驱动都需要定义一个 uart_driver,加载驱动时向系统注册这个 uart_driver,注销驱动时注销掉注册的 uart_driver

/************ 注册uart_driver *************/
int uart_register_driver(struct uart_driver *drv)
//drv:要注册的 uart_driver
//返回值:0,成功;负值,失败
/************ 注销uart_driver *************/
void uart_unregister_driver(struct uart_driver *drv)
//drv:要注销的 uart_driver
1.2 uart_port 的添加与移除

uart_port 表示一个具体的 port, 其定义在 include/linux/serial_core.h 文件中

struct uart_port {spinlock_t lock; 				/* port lock */unsigned long iobase; 			/* in/out[bwl] */unsigned char __iomem *membase; /* read/write[bwl] */......const struct uart_ops *ops;		/* ops包含了串口的具体驱动函数 */unsigned int custom_divisor;unsigned int line; 				/* port index */unsigned int minor;resource_size_t mapbase; 		/* for ioremap */resource_size_t mapsize;struct device *dev; 			/* parent device */......
};

每个 UART 都有一个 uart_port,使用如下函数将 uart_port和 uart_driver 结合或者移除

/************ 将uart_port与相应的uart_driver结合 **************/
int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport)
//drv:此port对应的 uart_driver
//uport:要添加到uart_driver中的port
//返回值:0,成功;负值,失败
/************ 将uart_port从相应的uart_driver中移除 *************/
int uart_remove_one_port(struct uart_driver *drv, struct uart_port *uport)
//drv:要卸载的port所对应的uart_driver
//uport:要卸载的uart_port
//返回值:0,成功;负值,失败
1.3 uart_ops 实现

uart_port 中的成员变量 ops 包含了针对 UART 具体的驱动函数,Linux 系统收发数据最终调用的都是 ops 中的函数。ops 是 uart_ops类型的结构体指针变量,定义在 include/linux/serial_core.h 文件中

struct uart_ops {unsigned int (*tx_empty)(struct uart_port *);void (*set_mctrl)(struct uart_port *, unsigned int mctrl);unsigned int (*get_mctrl)(struct uart_port *);void (*stop_tx)(struct uart_port *);void (*start_tx)(struct uart_port *);void (*throttle)(struct uart_port *);void (*unthrottle)(struct uart_port *);void (*send_xchar)(struct uart_port *, char ch);void (*stop_rx)(struct uart_port *);void (*enable_ms)(struct uart_port *);void (*break_ctl)(struct uart_port *, int ctl);int (*startup)(struct uart_port *);void (*shutdown)(struct uart_port *);void (*flush_buffer)(struct uart_port *);void (*set_termios)(struct uart_port *, struct ktermios *new,struct ktermios *old);void (*set_ldisc)(struct uart_port *, struct ktermios *);void (*pm)(struct uart_port *, unsigned int state,unsigned int oldstate);/* Return a string describing the type of the port */const char *(*type)(struct uart_port *);/* Release IO and memory resources used by the port.* This includes iounmap if necessary. */void (*release_port)(struct uart_port *);/* Request IO and memory resources used by the port.* This includes iomapping the port if necessary. */int (*request_port)(struct uart_port *);void (*config_port)(struct uart_port *, int);int (*verify_port)(struct uart_port *, struct serial_struct *);int (*ioctl)(struct uart_port *, unsigned int, unsigned long);
#ifdef CONFIG_CONSOLE_POLLint (*poll_init)(struct uart_port *);void (*poll_put_char)(struct uart_port *, unsigned char);int (*poll_get_char)(struct uart_port *);
#endif
};

二、UART驱动实例

I.MX6U-ALPHA 开发板上 RS232、 RS485 和 GPS 这三个接口都连接到了 UART3 上。下面以RS232为例,介绍如何驱动开发板上的 UART3 接口。RS232的原理图如下图示:

在这里插入图片描述

2.1 RS232 驱动编写

IMX6U的 UART 驱动已经由 NXP 编写好了,因此要使用 UART3 接口,只需要在设备树中添加 UART3 对于的设备节点即可

  • 修改或添加pinctrl节点:在iomuxc中创建UART3对应的pinctrl子节点
pinctrl_uart3: uart3grp {fsl,pins = <MX6UL_PAD_UART3_TX_DATA__UART3_DCE_TX 	0X1b0b1MX6UL_PAD_UART3_RX_DATA__UART3_DCE_RX 	0X1b0b1>;
};
  • 添加子节点:添加UART3对应的子节点 uart3
&uart3 {pinctrl-names = "default";pinctrl-0 = <&pinctrl_uart3>;status = "okay";
};
  • 检查PIN是否冲突:检查pinctrl中设置以及设备节点中指定的引脚有没有被别的外设使用

保存修改后,在kernel主目录下使用“make dtbs”命令编译设备树,使用新的设备树文件启动Llinux系统

设备树修改成功的话,系统启动后会生成一个名为“/dev/ttymxc2”的设备文件,此文件就是 UART3 对应的设备文件,应用程序可以通过访问 ttymxc2 来实现对 UART3 的操作

2.2 RS232 驱动测试

参考开发板移植minicom一文将 minicom 移植到开发板中,这样就可以借助 minicom 对串口进行读写操作

  • RS232 连接:使用 USB转公头DB9数据线将开发板与电脑连接起来,电脑上串口助手波特率设为 115200

  • minicom 设置:开发板中使用“minicom -s”命令,打开配置界面,选中“Serial port setup”进行设置(如下图所设置)
    在这里插入图片描述

  • 设置完成后按回车键确认,退出配置界面后,minicom串口界面如下图示
    在这里插入图片描述

  • 依次按下"CTRL-A"和" Z " 进入帮助信息界面,按下"E"打开回显功能
    在这里插入图片描述

  • 发送测试:测试开发板通过 UART3 向电脑发送数据的功能
    在这里插入图片描述
    在这里插入图片描述

  • 接收测试:测试开发板的 UART3 接收功能
    在这里插入图片描述
    在这里插入图片描述


http://chatgpt.dhexx.cn/article/gqt6rbW1.shtml

相关文章

Linux驱动开发|WiFi驱动

WiFi驱动 一、WiFi驱动添加与编译 I.MX6U-ALPHA 开发板目前支持两种接口的 WIFI&#xff1a;USB 和 SDIO&#xff0c;其中 USB WIFI 使用的芯片为 RTL8188EUS 或 RTL8188CUS&#xff0c; SDIO 接口的 WIFI 使用的芯片为 RTL8189FS。这两个都是 realtek 公司出品的 WIFI 芯片。…

驱动开发:配置Visual Studio驱动开发环境

在正式开始驱动开发之前&#xff0c;需要自行搭建驱动开发的必要环境&#xff0c;首先我们需要安装Visual Studio 2013这款功能强大的程序开发工具&#xff0c;在课件内请双击ISO文件并运行内部的vs_ultimate.exe安装包&#xff0c;Visual Studio的安装非常的简单&#xff0c;您…

DDD领域驱动开发

文章目录 DDD&#xff08;Domain Driving Design&#xff09;领域驱动开发1、微服务设计为什么选择DDD1、架构对比2、微服务的问题3、战略设计&#xff08;业务层面-业务架构&#xff09;4、战术设计&#xff08;技术层面-系统架构&#xff09;&#xff1a;5、DDD和微服务 2、领…

Linux驱动开发|USB驱动

USB驱动 USB接口很复杂&#xff0c;不同的设备器协议也不同&#xff0c;因此本文仅介绍如何使能Linux内核自带的USB驱动&#xff0c;不涉及USB驱动开发 一、USB接口简介 1.1 USB介绍 USB&#xff08;Universal Serial Bus&#xff09;&#xff0c;即通用串行总线。由英特尔…

window10+vs2022配置window驱动开发环境

测试模式 开发的驱动程序没有官方数字签名&#xff0c;只能在测试模式下加载。 命令行键入以下命令&#xff0c;重启电脑后桌面右下角出现测试模式字样&#xff0c;说明进入了测试模式 bcdedit /set testsigning on 命令行键入以下命令&#xff0c;重启电脑后桌面右下角没有了测…

win10驱动开发——驱动签名

win1803开始直接禁用驱动强制签名的方式不行了 1.设置环境 bcdedit -set NOINTEGRITYCHECKS ON bcdedit -set TESTSIGNING ON bcdedit -set loadoptions DDISABLE_INTEGRITY_CHECKS2.配置环境变量 找到makecert.exe文件位置如【C:\Program Files (x86)\Windows Kits\10\bin\1…

Windows 10 驱动开发 及 驱动签名

记录下在公司开发驱动的一些注意事项, 驱动当前仅针对win10x64. 常识: 最早的驱动开发sdk是 ntddk, 类似于用户层的win32 api, 后面为了增加对pnp(Plug-and-Play, 即插即用)的支持, 迭代为 wdm. 后面因为wdm开发过于繁琐, 微软发布了 WDF 框架, 类似于 用户层的 …

Linux——驱动开发

一、驱动开发概述 1.1 驱动形式 驱动代码的形式一般可分为build-in和module两种形式&#xff0c;build-in是在编译linux同时将pcie的驱动代码编译到内核中&#xff0c;启动的时候就载入该驱动代码&#xff1b;module是在linux启动完成后通过终端输入命令insmod/remod进行载入…

Windows 驱动开发 新手入门(一)

Windows 驱动开发 新手入门&#xff08;一&#xff09; 引言驱动介绍Win10 WDK 建立一个驱动项目建立MyDriver.cpp理论知识驱动入口派遣函数 MajorFunctionDevice和SymbolicLinkDeviceExtensionIRP 引言 首先祝朋友们新年快乐&#xff0c;然后呢&#xff0c;因为无聊&#xff…

驱动开发学习

驱动 1、驱动开发环境 完成系统移植的三步&#xff1a;u-boot启动引导程序、内核镜像、文件系统&#xff0c;u-boot启动引导程序最好固化到开发板上&#xff0c;内核镜像通过tftp服务从ubuntu下载&#xff0c;文件系统通过nfs服务从ubuntu共享到开发板&#xff0c;开发板启动…

Linux设备驱动开发详解

Linux设备驱动开发详解 Linux设备驱动开发详解Linux设备驱动开发Linux设备驱动开发详解1. linux设备驱动概述及开发环境搭建2. 驱动设计的硬件基础3. linux内核及内核编程4. linux内核模块5. linux文件系统与设备文件6. 字符设备驱动7. linux设备驱动中的并发控制8. linux设备驱…

QT部件基类——QWidget与QDialog

一、默认基类 QT提供的默认部件基类包括QMainWindow、QWidget、和QDialog这三种&#xff0c;这三个部件基类也是用的最多的。 QWidget类是所有部件对象的基类&#xff0c;被称为基础窗口部件&#xff0c;继承关系详看QWidget类关系图。QWidget提供自我绘制和处理用户输入等基本…

qt 中 qwidget 嵌入 qml

以上是效果图&#xff0c; 整个窗口是 qml 窗口 核心代码 #ifndef WIDGETANCHOR_H #define WIDGETANCHOR_H#include <QObject> #include <QQuickItem> #include <QWidget> #include <QQmlApplicationEngine> #include <QQmlContext>class WgtAn…

QWidget尺寸限定

1、控件只能在最小和最大之间进行调整&#xff0c;不能超过范围。 ①直接宽高同时设置 window.setMinimumSize(200, 200)&#xff1b; window.setMaximumSize(500, 500) app QApplication(sys.argv)window QWidget()window.setWindowTitle("最小最大窗口")windo…

QWidget居中显示

须知 以下函数只要继承QWidget都可以使用.例如 QDialog, QPushButton( -v- 一个居中的”引爆按钮”)关于坐标问题: qt窗口坐标原点是在”左上角”的. 如图, (x2, y2)是我窗口的分辨率的一半无论目前我的窗口在什么位置,我只要把窗口原点设置为(x1, y1)就行了.所以目前我要获得…

QWidget事件消息

1、用户操作界面时会产生特定的事件消息。 API&#xff1a;显示和关闭事件、移动事件、调整大小、鼠标事件、键盘事件、焦点事件、拖拽事件、绘制事件、改变事件、右键菜单、输入法。 应用场景&#xff1a;当一个控件被触发了一个特定的行为时&#xff0c;就会调用特定的方法…

QWidget的isHidden和isVisible

文章目录 问题的出现QWidget的show()函数QWidget的isVisible和isHidden源码追溯 QWidget的isHidden和isVisible 问题的出现 最近在写代码的时候&#xff0c;出现了一个问题&#xff0c;我新建了两个类&#xff0c;分别是Chapter2和ConsecutiveCurtain // ConsecutiveCurta…

QWidget鼠标操作

1、设置鼠标形状&#xff1a;鼠标放置在不同控件上&#xff08;有不同功能时&#xff09;鼠标的形状是不一样的。 鼠标跟踪&#xff1a;鼠标在某一个控件上移动&#xff0c;则会向对应的控件对象发送一个消息&#xff0c;去调用具体的某一个方法&#xff0c;可以在方法里面监听…

QWidget旋转方法

参考链接&#xff1a;https://stackoverflow.com/questions/43388464/rotate-whole-qwidget-by-angle 说明&#xff1a; 本文实现方法本质是使用QGraphics三件套&#xff0c;即View、Scene、Item&#xff0c;将QWidget控件作为Item显示&#xff0c;从而实现角度控制的目的&…

QWidget设置背景图及圆角

在Qt开发过程中&#xff0c;QWidget是经常作为主窗体的父窗口&#xff0c;有时我们需要对主窗口设置背景&#xff0c;设置圆角以达到美观的效果&#xff0c;通常的有以下三种方法&#xff1a;qss, QPalette设置以及paintEvent绘制。下面介绍这三种方法。 背景设置介绍 方法一&a…