linux串口驱动学习

整体框架

串口驱动隶属于linux tty驱动框架的一部分, 其整体框架可参考下图,方便有个直观印象。

前言

1、SPI,I2C驱动框架分为控制器驱动和设备驱动,然后芯片原厂负责编写控制器驱动和设备树,然后普通的驱动工程师编写/适配设备驱动和相应的设备树文件。

2、对于UART来说他没有所谓的设备驱动,只有控制器驱动,控制器驱动是由芯片原厂提供,如果不是在芯片原厂工作,一般需要编写uart驱动。如果是在芯片原厂需要编写uart驱动层,只需要编写uart硬件驱动层,Linux内核已经提供了串口核心层、tty层。

根据整体框架图。针对uart链路进行分析,以串口read和write为例,梳理整体流程如下

write流程

流程问题1:

为什么用户对文件操作后就是直接进入tty层,而不是直接进入到硬件驱动层呢?

tty文件存在其自身的字符接口:

复制代码
drivers/tty/tty_io.c文件
static const struct file_operations tty_fops 
static const struct file_operations console_fops
static const struct file_operations hung_up_tty_fops 

注册tty文件操作的接口函数为

复制代码
drivers/tty/tty_io.c文件
static int tty_cdev_add(struct tty_driver *driver, dev_t dev,
		unsigned int index, unsigned int count)

上一层调用该函数的接口只有两个

复制代码
drivers/tty/tty_io.c文件

struct device *tty_register_device_attr(struct tty_driver *driver,
				   unsigned index, struct device *device,
				   void *drvdata,
				   const struct attribute_group **attr_grp)

int tty_register_device(struct tty_driver *driver)

情况1 - tty_cdev_add直接调用

tty_cdev_add在tty_register_driver存在直接调用情况

tty_register_driver内部tty_cdev_add函数调用存在条件判断如下:

而flags值在uart_register_driver函数中的赋值情况如下,并不满足条件

因此,硬件驱动层tegra_uart_init函数调用的uart_register_driver并未完成对tty文件操作的注册。

总体调用关系如下

情况2 - tty_register_device_attr和tty_register_device间接调用

tty_register_device_attr函数在两处被调用:

tty_io.c----tty_register_device

tty_port.c---tty_port_register_device_attr

tty_io.c----tty_register_device也是因flags不满足条件在tty层tty_register_driver函数中未进行调用

流程可归纳为

tty_port.c---tty_port_register_device_attr则是在串口核心层uart_add_one_port中调用,层层追溯至硬件驱动层的tegra_uart_probe()函数中,该函数是在platform驱动框架下匹配设备树后执行。

调用流程归纳如下:

小结

1、用户对串口文件操作后直接进入tty层的原因在于驱动初始化时,将串口文件操作接口赋值为了tty文件操作函数,而不是不同的字符设备文件操作函数,使得打开串口文件时相当于打开了tty设备,所以直接进入到tty层。

2、在串口初始化时,文件操作接口赋值实际上有三次机会,但由于flags初值的原因,导致前两次在tty层并未直接完成赋值,这是因为串口属于硬件设备,需要等待硬件驱动完成后才能获得其文件节点,然后再进行文件操作接口赋值。

相关推荐
郝学胜-神的一滴8 小时前
Effective Python 第52条:用subprocess模块优雅管理子进程
linux·服务器·开发语言·python
晨枫阳9 小时前
不同语言数组详解
linux·服务器·windows
q***75189 小时前
Linux(CentOS)安装 MySQL
linux·mysql·centos
CS_浮鱼10 小时前
【Linux】线程
linux·c++·算法
q***133412 小时前
Linux(CentOS)安装 Nginx
linux·nginx·centos
摘星编程12 小时前
openGauss 快速上手:CentOS 环境下单机部署完整指南
linux·运维·centos
哈里谢顿17 小时前
使用kvm创建一台虚拟机
linux
hanyi_qwe18 小时前
文本三剑客--awk
linux·运维·服务器
Caven7718 小时前
【Linux 技巧】如何在登录时自动激活 Conda Base 环境
linux·运维·conda
凌寒1119 小时前
Linux(Debian)安装、卸载 MySQL
linux·运维·mysql·debian