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层并未直接完成赋值,这是因为串口属于硬件设备,需要等待硬件驱动完成后才能获得其文件节点,然后再进行文件操作接口赋值。

相关推荐
xuhe28 小时前
🛠️ 深度解析我的 Overleaf 私有化部署:一份稳定、高兼容性的 `docker-compose.yaml`
linux·docker·科研·overleaf
技术小白爱FPGA8 小时前
zynq7000- linux平台 PS读写PL测试
linux·fpga开发
BD_Marathon8 小时前
【Linux】awk命令
linux·运维·服务器
前端世界9 小时前
Linux 防火墙实战:用 firewalld 配置 External/Internal 区域,实现 NAT 内网共享上网
linux·服务器·网络
陌路209 小时前
操作系统(6)虚拟内存-缓存工具-页表(2)
linux
林一百二十八10 小时前
Win11配置VMware-workstation以及Ubuntu环境
linux·运维·ubuntu
铜豌豆_Y10 小时前
嵌入式Linux驱动开发之I2C子系统(3)--I2C子系统框架
linux·运维·驱动开发
LNN202211 小时前
Qt creator +Valgrind检测内存泄漏(linux)
linux·开发语言·qt
0wioiw011 小时前
Ubuntu(④Mysql)
linux·mysql·ubuntu
球求了11 小时前
Linux 系统入门:环境变量&&虚拟地址空间
linux·运维·服务器·1024程序员节