(九)添加虚拟设备节点以及驱动编写


添加虚拟设备结点

1.先了解设备驱动文件

设备某一类的设备驱动文件所在目录(这里的目录,下全是各类设备子目录):

cd /home/zhua/SDK/T113-i_v1.0/kernel/linux-5.4/drivers

在这里插入图片描述

比如在设备驱动目录下的,串口类驱动(tty),tty种类的设备目录里面还可以继续分类设备目录,如serial类的设备驱动目录:

cd /home/zhua/SDK/T113-i_v1.0/kernel/linux-5.4/drivers/tty/serial/

在这里插入图片描述

当然在serial设备驱动类目录下还有各类设备的区分,比如8250类设备。

在这里插入图片描述
驱动类文件,层层套娃,是有规律分类的。


这里要知道每一个类的设备驱动目录下面都有一个Kconfig和Makefile文件:

Kconfig是menuconfig来解析和配置的。

Makefile是内核编译链接,以及链接各种库,头文件,头文件路径等用的。

比如serial类设备目录下:

在这里插入图片描述


2.再看Kconfig被Menuconfig如何解析

首先利用menuconfig打开配置界面:

在目录:/home/zhua/SDK/T113-i_v1.0/kernel/linux-5.4 执行:

make menuconfig

进入 Device Drivers > Character devices > Serial drivers(先理解规则,最后一步步分析为什么是在这个菜单设备目录下)。
在这里插入图片描述

menuconfig工具配置以及使用可以参考:(二)编译原生SDK以及配置交叉编译链中的配置内核等选项等部分。


下面以串口类设备为例看Kconfig如何被解析的:

打开:/drivers/tty/serial/下的Kconfig,查看设备菜单名称以及设备名称。

注意:并不是每个Kconfig里面 都有menu这个生成Serial drivers设备菜单的指令,有的就没有,比如嵌套的8250的Kconfig就没有生成设备菜单目录,因此8250类设备里面的设备名称,直接生成在Serial drivers设备菜单目录下面。如果还有menu指令,那就在Serial drivers目录下在生成一层目录,如果目录下还有menu指令,则生成一层层的套娃目录。依此类推。

而且menu和endmenu是成对出现,并且包含在这俩句之间的才能包含在当前设备目录菜单内,否则就是和当前设备菜单是并行菜单。

另外:并不是设备名称一定是显示在menuconfig上面的,必须要满足depends on这个依赖,这个依赖其实,是因为一个设备树和驱动里面包含了各种平台,通过这个依赖进行区分哪个平台,比如A平台显示A的设备树名称和使用A的驱动,B平台显示就是B的设备树名称和使用B的驱动,以及设备是否支持这个总线,是否支持串口,是否支持iic啊等条件,支持就显示配置,不支持就不显示

比如Serial drivers设备菜单目录下面的config SERIAL_AMBA_PLP10这个设备 ,tristate后面的字符就是生成的设备名称,生成设备名称的前提是满足depends on ARM_AMBA,只有当这个设备在ARM_AMBA总线的支持情况才会在menuconfig上显示。如果没有依赖将直接显示,如果没有名称则肯定也是不显示的,比如第一个设备,config SERIAL_EARLYCON,bool后面就没有名称,因此不会显示。

在这里插入图片描述

这里看到生成了Serial drivers设备菜单目录。里面又嵌套一个8250类设备的Kconfig目录。

查看driver/tty/serial的子目录下/8250设备类目录的Kconfig

开头:
在这里插入图片描述
结尾:
在这里插入图片描述

可以看到并没有生成目录菜单,所以这个8250的设备没有自己的目录,直接就是在Serial drivers设备菜单目录内。

对应的menuconfig图形来查看:

在这里插入图片描述

大致的图形化理解:

Serial drivers
├── config SERIAL_EARLYCON (不显示名称,因为bool后面没有名称)
├── source "/serial/8250/Kconfig" (8250类设备,因为没有menu,里面的设备名称直接生成在Serial drivers下,如果有继续生成子目录)
└──"Non-8250 serial port support"(comment提示符)
├── config SERIAL_AMBA_PL010
│   └── tristate "ARM AMBA PL010 serial port support" (满足depends on ARM_AMBA时显示)
├── config SERIAL_AMBA_PL011
│   └── tristate "ARM AMBA PL011 serial port support" (满足depends on ARM_AMBA时显示)
└── menu "Other Serial Port Support"
├──.......

总结:

menuconfig根据Kconfig内容生成图像配置,如果有menu指令,则生成菜单目录。

包含在menu和endmenu之间的设备名称,如果在依赖满足的条件下,则生成设备名称在当前菜单目录下面。

包含在menu和endmenu之间有,source xx/Kconfig,这种嵌套其他目录Kconfig的指令,如果xx/Kconfig里面还有menu指令,则继续生成菜单目录,如果xx/Kconfig没有menu指令,当前设备在满足依赖的条件下,生成设备名称在包含source xx/Kconfig指令的菜单目录下。


最后解释为什么在Device Drivers > Character devices > Serial drivers目录下面:

从底往上推:
serial层菜单名称是 Serial drivers

在这里插入图片描述

再往上到tty层,发现tty层Kconfig并没有menu,没有生成目录,因为tty文件夹必然被其他的Kconfig包含。

在这里插入图片描述

并且再往上到drivers层,发现drivers层也没有加载tty文件夹的指令,此时看到drivers层生成了Device Drivers目录,并且包含了好多个不同目录的Kconfig,那就说明,tty被包含在drivers层包含的Kconfig里面了

在这里插入图片描述

直接在drivers目录下搜索 包含tty设备目录Kconfig 的文件所在。查找发现在drivers/char目录下面

grep -r "drivers/tty/Kconfig"

在这里插入图片描述

直接打开drivers/char目录下的Kconfig,可以发现里面包含 tty/Kconfig 和 serial/Kconfig,又因为当前目录生成了Character devices菜单,serial目录生成Serial drivers菜单,tty目录没有生成菜单,因此Character devices菜单下有Serial drivers菜单和tty/Kconfig内的设备。

在这里插入图片描述

在这里插入图片描述

大概结构:


Device Drivers
├──	Character devices
│	├── Serial drivers (from serial/Kconfig)
│	│   ├── [Serial driver options...]
│	│   
│	└── [Devices from tty/Kconfig]
│	    ├── tty devices 
│	    └── ...

3.最后看Makefile文件如何编写

最底层的Makefile(serial这一层)

所谓最底层(serial文件夹里)就是直接管理对应的驱动文件(如sunxi-uart.c)的那一层Makefile.(这里是因为我要用串口,驱动文件就在serial文件夹里面,所以这一层就是我认为的最底层,即要用的驱动代码所在的那一层,,,,当然serial下层也还是有8250类设备驱动文件夹)。

在这里插入图片描述

在这里插入图片描述

这一层的Makefile里面:

obj-$(CONFIG_SERIAL_SUNXI)      += sunxi-uart.o
其中:	
-$(CONFIG_SERIAL_SUNXI) 括号里面必须以大写CONFIG开头,后面的参数必须与Kconfig里面的保持一致,因为这个参数是可以通过图形界面配置的。
sunxi-uart.o 名称必须跟驱动文件sunxi-uart.c保持一致。

中间层的Makefile(tty以及除了顶层这一层)

不是顶层,就是下层还是有分类驱动设备文件夹,就比如tty这一层,它下层有serial类设备驱动文件夹(当然serial下层也还是有8250类设备驱动文件夹,也可以的哈,只是为了举例理解)。

那么这一层的Makefile就是管理serial这个文件夹了,而不是像直接管理sunxi-uart.c驱动文件一样的操作了。

一般Makefile管理,文件夹都是直接-y 直接编译进内核这个文件夹里面全部的驱动文件,当然也不一定比如上面说的管理8250文件夹的Makefile,它还是借助参数指定,通过图形界面配置的。

obj-y				+= serial/

这里段代码是直接将serial目录下全部驱动直接编译进内核。

在这里插入图片描述

为了消除顾虑,可以看到8250作为最底层,则上层Makefile管理8250文件夹,并且借助参数指定,通过图形界面配置。

在这里插入图片描述


顶层的Makefile(drivers层)

打开Makefile看到,顶层一般都是-y直接编译文件夹目录下全部驱动,不过也有通过参数指定,借助图形界面去设置,没有绝对的。这里也能看见 直接将tty目录下的全部驱动编译进内核。

obj-y				+= tty/

这里段代码是直接将tty目录下全部驱动直接编译进内核。虽然tty的设备目录 是在Character devices下面,但是所有的驱动是都要编译的。简单理解就目录排版随意,驱动代码必须全部编译。
在这里插入图片描述

至此Makefile和Kconfig文件全部理解完成。


4.在设备树直接添加虚拟设备节点

参考(八)简单修改设备树,直接添加一个设备节点。

	//测试节点
	myzhuazi{
   
		compatible = "allwinner,sun8iw20p1-zhuazii";
		status = "okay";
	};

在这里插入图片描述

注意这里一定要注意这个compatible关键字,后面的sun8iw20p1-zhuazi,就是设备节点和设备驱动匹配的关键依据,前面那个sun8iw20p1是芯片型号,其本质就是通过名称匹配的。如果不一致,设备驱动不能将设备成功加载,前面的myzhuazi可以随便取。

状态一定要使能。


5.书写虚拟设备节点驱动

整体完整代码

说明:

#define DRIVER_NAME “zhuazi” 这里只是用于标识模块和日志输出简单的作用而已,可以理解为一个模块的名字,只是名字方便辨认的作用,跟设备树里面的那个用于比较的名字不一样,但是最好还是相近相似,方便代码调试,日志输出,以及在出错时候快速定位哪个模块。

#define DEVICE_NAME “zhuazidev” 这个名称是生成/dev下面的文件目录 可以任意设定。

// 匹配Device Tree中的compatible属性
static const struct of_device_id zhuazi_of_match[] = {
   
    {
    .compatible = "allwinner,sun8iw20p1-zhuazi" },
    {
    /* sentinel */ }
};

代码 { .compatible = “allwinner,sun8iw20p1-zhuazi” },中的sun8iw20p1-zhuazi必须与前面添加的设备树那边的名称保持一致。

注释的函数暂时用不到,为了代码的完整性而已。

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/fs.h></
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小爪.exe

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值