PCI设备驱动开发详解

Linux下PCI设备驱动开发详解(三)

2023-12-13  本文已影响0人  北京不北

在进行PCIe实际软硬件开发之前,我们要先非常清晰几个概念,这些概念可以让我们高屋建瓴,了解整个PCIe软硬异构系统如何运行的,以及PCIe驱动和PCIe device处在整个系统的什么位置,非常关键。

一、PCIe软硬异构系统的概念

1. 应用程序、库、内核以及驱动程序

2. 设备类型

当前linux把所有的硬件设备分为3大类:字符设备、块设备、网络设备。

3. 设备文件、主设备号、从设备号

有了设备类型的划分,那么应用程序应该怎么访问具体的硬件设备?

答案:姓名,在linux中就是设备的文件名;

那么重名怎么办呢?

答案:身份证号,在linux中就是设备号(主、从);

设备文件:

在linux中,有一个约定成俗的说法,“一切皆文件”,应用程序使用设备文件节点对应的设备,linux下的各种硬件以文件的形式放在/dev目录下,linux把对硬件的操作全部抽象成对文件的操作(open、read、write、close)等;

在设备管理中,除了设备类型外,内核还需要一对主从设备号,才能唯一标识一个设备,类似于ID;

主设备号:用于标识驱动程序,相同的主设备号使用相同的驱动程序;

次设备号:用于标识同一驱动程序的不同硬件;

4. 驱动程序、应用程序

应用程序以main()开始,驱动程序没有main(),它以一个模块初始化函数作为入口;

应用程序从头到尾执行一个任务,驱动程序完成初始化之后不再运行,除非等待系统调用;

应用程序可以使用glibc等标准的c函数库,驱动程序不能使用标准c库;

5. 用户态、内核态

驱动程序是内核的一部分,工作在内核态;应用程序工作在用户态;

数据访问问题:

无法通过指针直接将二者的数据地址进行传递;系统提供了一系列函数完成数据空间的转换:

get_user、put_user、copy_from_user、copy_to_user

6. linux驱动程序功能

二、总线、设备和驱动

设备驱动离不开3部曲:总线、设备和驱动。

linux设备驱动模型,由总线(bus)、设备(device)、驱动(driver)三部分组成;总线是处理器和设备之间的通道,在设备模型中,所有的设备都是通过总线相连;总线作为linux设备驱动模型的核心架构,系统中设备都和驱动挂接在相应的总线上了,来完成各自的工作;

1. 总线、设备、驱动概述

2. 结合代码和实际分析三者关系

1702541057177.png

系统启动后,会调用buses_init()函数创建/sys/bus文件目录,这部分系统在开机是已经帮我们准备好了,接下去就是通过总线注册函数bus_register()进行总线注册,注册完成后,在/sys/bus目录下生成device文件夹和driver文件夹,最后分别通过device_register()以及driver_register()函数注册对应的设备和驱动。

2.1 总线初始化

系统启动后,会调用buses_init()函数创建/sys/bus这个文件目录,这部分操作在系统开机的时候帮我们准备好了。

2.2 总线注册

系统中不一定有你需要的总线,linux提供了一些函数来添加或注销总线,大部分情况下编写linux驱动模块时,内核已经为我们准备了大部分总线驱动,正常情况下我们一般不会去注册一个新的总线。

总线注册和注销的函数原型如下:

int bus_register(struct bus_type *bus)

当配对成功(match)后,内核就会调用指定驱动中的probe函数进行初始化。

以注册xbus总线为例:

创建/sys/bus/xbus目录,目录名xbus为我们新注册的总线名;
创建/sys/bus/xbus/devices目录,并创建属性文件;
创建/sys/bus/xbus/drivers目录,并创建属性文件;
初始化priv->klist_device链表头;
初始化priv->klist_driver链表头

下图是系统中注册的设备总线:

1702541284256.png

2.3 设备注册

添加设备,关联硬件相关代码:

int device_register(struct device *dev)
创建/sys/bus/xbus/devices/yyy目录;
加入bus->priv->devices_kset链表;
加入bus->priv->klist_devices链表;
加入bus->priv->klist_drivers,执行bus->match()寻找合适的drv;
dev关联driv,执行drv->probe()

下面就是实际的PCI设备:

1702541890192.png

2.4 驱动注册

添加驱动,关联软件相关代码:
int driver_register(struct device_driver *drv)
创建/sys/bus/xbus/driver/zzz目录;
加入bus->priv->driver_kset目录;
加入bus->priv->klist_driver链表;
遍历bus->priv->klist_device链表,执行bus->match()寻找合适的dev;
driv关联dev,执行drv->probe();

下面就是实际的PCI驱动:

1702542014807.png

三、总结

linux设备驱动模型,由总线(bus)、设备(device)、驱动(driver)三部分组成;总线是处理器与设备之间的通道,在设备模型中,所有的设备都是通过总线相连;总线作为linux设备驱动模型的核心架构,系统中的设备都和驱动挂接在相应的总线上,来完成各自的工作。

四、未完待续

Linux下PCI设备驱动开发详解(四),将会结合实际的PCI设备,讲解实际PCI设备驱动开发及其相关的知识。

五、参考资料

https://blog.csdn.net/pen_cil/article/details/79763106

上一篇下一篇

猜你喜欢

热点阅读