目录
1.Linux驱动的分离与分层
1)驱动的分隔与分离
2)驱动的分层
2.platform平台驱动模型简介
1)platform总线
2)platform驱动
3)platform设备
3.试验程序编写
1)platform设备与驱动程序编写
2)测试APP编写
4.运行测试
1)编译驱动程序和测试APP
2)运行测试
5.设备树下的platform驱动简介
6.实验程序编写
1)修改设备树文件
2)platform驱动程序编写
7.运行测试
1)编译驱动程序和测试APP
2)运行测试
我们在前面几章编写的设备驱动都非常的简单,都是对IO进行最简单的读写操作。像I2C、SPI、
LCD等这些复杂外设的驱动就不能这么去写了,Linux系统要考虑到驱动的可重用性,因此提出了
驱动的分离与分层这样的软件思路,在这个思路下诞生了我们将来最常打交道的platform设备驱
动,也叫做平台设备驱动。本章我们就来学习一下Linux下的驱动分离与分层,以及platform框架下
的设备驱动该如何编写。
对于Linux这样一个成熟、庞大、复杂的操作系统,代码的重用性非常重要,否则的话就会在Linux
内核中存在大量无意义的重复代码。尤其是驱动程序,因为驱动程序占用了Linux内核代码量的大
头,如果不对驱动程序加以管理,任由重复的代码肆意增加,那么用不了多久Linux内核的文件数
量就庞大到无法接受的地步。假如现在有三个平台A、B和C,这三个平台(这里的平台说的是SOC)
上都有MPU6050这个I2C接口的六轴传感器,按照我们写裸机I2C驱动的时候的思路,每个平台都
有一个MPU6050的驱动,因此编写出来的最简单的驱动框架如图所示:
从图可以看出,每种平台下都有一个主机驱动和设备驱动,主机驱动肯定是必须要的,毕竟不同的
平台其I2C控制器不同。但是右侧的设备驱动就没必要每个平台都写一个,因为不管对于那个SOC
来说,MPU6050都是一样,通过I2C接口读写数据就行了,只需要一个MPU6050的驱动程序即
可。如果再来几个I2C设备,比如AT24C02、FT5206(电容触摸屏)等,如果按照图1中的写法,那
么设备端的驱动将会重复的编写好几次。显然在Linux驱动程序中这种写法是不推荐的,最好的做
法就是每个平台的I2C控制器都提供一个统一的接口(也叫做主机驱动),每个设备的话也只提供一
个驱动程序(设备驱动),每个设备通过统一的I2C接口驱动来访问,这样就可以大大简化驱动文
件,比如图中三种平台下的MPU6050驱动框架就可以简化为图所示:

实际的I2C驱动设备肯定有很多种,不止MPU6050这一个,那么实际的驱动架构如图所示:

这个就是驱动的分隔,也就是将主机驱动和设备驱动分隔开来,比如I2C、SPI等等都会采用驱动
分隔的方式来简化驱动的开发。在实际的驱动开发中,一般I2C主机控制器驱动已经由半导体厂家
编写好了,而设备驱动一般也由设备器件的厂家编写好了,我们只需要提供设备信息即可,比如
I2C设备的话提供设备连接到了哪个I2C接口上,I2C的速度是多少等等。相当于将设备信息从设备
驱动中剥离开来,驱动使用标准方法去获取到设备信息(比如从设备树中获取到设备信息),然后根
据获取到的设备信息来初始化设备。这样就相当于驱动只负责驱动,设备只负责设备,想办法将两
者进行匹配即可。这个就是Linux中的总线(bus)、驱动(driver)和设备(device)模型,也就是常说
的驱动分离。总线就是驱动和设备信息的月老,负责给两者牵线搭桥,如图所示:
当我们向系统注册一个驱动的时候,总线就会在右侧的设备中查找,看看有没有与之匹配的设备,
如果有的话就将两者联系起来。同样的,当向系统中注册一个设备的时候,总线就会在左侧的驱动
中查找看有没有与之匹配的设备,有的话也联系起来。Linux内核中大量的驱动程序都采用总线、
驱动和设备模式,我们一会要重点讲解的platform驱动就是这一思想下的产物。
上一小节讲了驱动的分隔与分离,本节我们来简单看一下驱动的分层,大家应该听说过网络的7层
模型,不同的层负责不同的内容。同样的,Linux下的驱动往往也是分层的,分层的目的也是为了
在不同的层处理不同的内容。以其他书籍或者资料常常使用到的input(输入子系统,后面会有专门
的章节详细的讲解)为例,简单介绍一下驱动的分层。input子系统负责管理所有跟输入有关的驱
动,包括键盘、鼠标、触摸等,最底层的就是设备原始驱动,负责获取输入设备的原始值,获取到
的输入事件上报给input核心层。input核心层会处理各种IO模型,并且提供file_operations操作集
合。我们在编写输入设备驱动的时候只需要处理好输入事件的上报即可,至于如何处理这些上报的
输入事件那是上层去考虑的,我们不用管。可以看出借助分层模型可以极大的简化我们的驱动编
写,对于驱动编写来说非常的友好。
前面我们讲了设备驱动的分离,并且引出了总线(bus)、驱动(driver)和设备(device)模型,比如
I2C、SPI、USB等总线。但是在SOC中有些外设是没有总线这个概念的,但是又要使用总线、驱
动和设备模型该怎么办呢?为了解决此问题,Linux提出了platform这个虚拟总线,相应的就有
platform_driver和platform_device。
Linux系统内核使用bus_type结构体表示总线,此结构体定义在文件include/linux/device.h,
bus_type结构体内容如下:
讯享网
第10行,match函数,此函数很重要,单词match的意思就是“匹配、相配”,因此此函数就是完成
设备和驱动之间匹配的,总线就是使用match函数来根据注册的设备来查找对应的驱动,或者根据
注册的驱动来查找相应的设备,因此每一条总线都必须实现此函数。match函数有两个参数:dev
和drv,这两个参数分别为device和device_driver类型,也就是设备和驱动。
platform总线是bus_type的一个具体实例,定义在文件drivers/base/platform.c,platform总线定义
如下:
讯享网
platform_bus_type就是platform平台总线,其中platform_match就是匹配函数。我们来看一下驱
动和设备是如何匹配的,platform_match()函数定义在文件drivers/base/platform.c中,函数内容
如下所示:
驱动和设备的匹配有四种方法,我们依次来看一下:
第11~12行,第一种匹配方式,OF类型的匹配,也就是设备树采用的匹配方式,
of_driver_match_device函数定义在文件include/linux/of_device.h中。device_driver结构体(表示设
备驱动)中有个名为of_match_table的成员变量,此成员变量保存着驱动的compatible匹配表,设备
树中的每个设备节点的compatible属性会和of_match_table表中的所有成员比较,查看是否有相同
的条目,如果有的话就表示设备和此驱动匹配,设备和驱动匹配成功以后probe函数就会执行。
第15~16行,第二种匹配方式,ACPI匹配方式。
第19~20行,第三种匹配方式,id_table匹配,每个platform_driver结构体有一个id_table成员变
量,顾名思义,保存了很多id信息。这些id信息存放着这个platformd驱动所支持的驱动类型。
第23行,第四种匹配方式,如果第三种匹配方式的id_table不存在的话就直接比较驱动和设备的
name字段,看看是不是相等,如果相等的话就匹配成功。
对于支持设备树的Linux版本号,一般设备驱动为了兼容性都支持设备树和无设备树两种匹配方
式。也就是第一种匹配方式一般都会存在,第三种和第四种只要存在一种就可以,一般用的最多的
还是第四种,也就是直接比较驱动和设备的name字段,毕竟这种方式最简单了。
platform_driver结构体表示platform驱动,此结构体定义在文件include/linux/platform_device.h
中,内容如下:
讯享网
第2行,probe函数,当驱动与设备匹配成功以后probe函数就会执行,非常重要的函数!!一般驱
动的提供者会编写,如果自己要编写一个全新的驱动,那么probe就需要自行实现。
第7行,driver成员,为device_driver结构体变量,Linux内核里面大量使用到了面向对象的思维,
device_driver相当于基类,提供了最基础的驱动框架。plaform_driver继承了这个基类,然后在此
基础上又添加了一些特有的成员变量。
第8行,id_table表,也就是我们上一小节讲解platform总线匹配驱动和设备的时候采用的第三种方
法,id_table是个表(也就是数组),每个元素的类型为platform_device_id,platform_device_id结构
体内容如下:
device_driver 结构体定义在 include/linux/device.h,device_driver结构体内容如下:
讯享网
第10行,of_match_table就是采用设备树的时候驱动使用的匹配表,同样是数组,每个匹配项都
为of_device_id结构体类型,此结构体定义在文件include/linux/mod_devicetable.h中,内容如下:
第4行的compatible非常重要,因为对于设备树而言,就是通过设备节点的compatible属性值和
of_match_table中每个项目的compatible成员变量进行比较,如果有相等的就表示设备和此驱动匹
配成功。
在编写platform驱动的时候,首先定义一个platform_driver结构体变量,然后实现结构体中的各

个成员变量,重点是实现匹配方法以及probe函数。当驱动和设备匹配成功以后probe函数就会执
行,具体的驱动程序在probe函数里面编写,比如字符设备驱动等等。当我们定义并初始化好
platform_driver结构体变量以后,需要在驱动入口函数里面调用platform_driver_register()函数
向Linux内核注册一个platform驱动,platform_driver_register函数原型如下所示:
讯享网
函数参数和返回值含义如下:
driver:要注册的platform驱动。
返回值:负数,失败;0,成功。
还需要在驱动卸载函数中通过platform_driver_unregister函数卸载platform驱动,
platform_driver_unregister函数原型如下:
函数参数和返回值含义如下:
drv:要卸载的platform驱动。
返回值:无。
platform驱动框架如下所示:
讯享网
第1~27行,传统的字符设备驱动,所谓的platform驱动并不是独立于字符设备驱动、块设备驱动和
网络设备驱动之外的其他种类的驱动。platform只是为了驱动的分离与分层而提出来的一种框架,
其驱动的具体实现还是需要字符设备驱动、块设备驱动或网络设备驱动。
第33~39行,xxx_probe函数,当驱动和设备匹配成功以后此函数就会执行,以前在驱动入口init函
数里面编写的字符设备驱动程序就全部放到此probe函数里面。比如注册字符设备驱动、添加
cdev、创建类等等。
第41~47行,xxx_remove函数,platform_driver结构体中的remove成员变量,当关闭platfor备驱动
的时候此函数就会执行,以前在驱动卸载exit函数里面要做的事情就放到此函数中来。比如,使用
iounmap释放内存、删除cdev,注销设备号等等。
第50~53行,xxx_of_match匹配表,如果使用设备树的话将通过此匹配表进行驱动和设备的匹
配。
第51行设置了一个匹配项,此匹配项的compatible值为“xxx-gpio”,因此当设备树中设备节点的
compatible属性值为“xxx-gpio”的时候此设备就会与此驱动匹配。第52行是一个标记,of_device_id
表最后一个匹配项必须是空的。
第58~65行,定义一个platform_driver结构体变量xxx_driver,表示platform驱动,第59~62行设置
paltform_driver中的device_driver成员变量的name和of_match_table这两个属性。其中name属性
用于传统的驱动与设备匹配,也就是检查驱动和设备的name字段是不是相同。of_match_table属
性就是用于设备树下的驱动与设备检查。对于一个完整的驱动程序,必须提供有设备树和无设备树
两种匹配方法。最后63和64这两行设置probe和remove这两成员变量。
第68~71行,驱动入口函数,调用platform_driver_register函数向Linux内核注册一个platform驱
动,也就是上面定义的xxx_driver结构体变量。
第74~77行,驱动出口函数,调用platform_driver_unregister函数卸载前面注册的platform驱动。
总体来说,platform驱动还是传统的字符设备驱动、块设备驱动或网络设备驱动,只是套上了一张
“platform”的皮,目的是为了使用总线、驱动和设备这个驱动模型来实现驱动的分离与分层。
platform驱动已经准备好了,我们还需要platform设备,否则的话单单一个驱动也做不了什么。
platform_device这个结构体表示platform设备,这里我们要注意,如果内核支持设备树的话就不
要再使用platform_device来描述设备了,因为改用设备树去描述了。当然了,你如果一定要用
platform_device来描述设备信息的话也是可以的。platform_device结构体定义在文件
include/linux/platform_device.h中,结构体内容如下:
第23行,name表示设备名字,要和所使用的platform驱动的name字段相同,否则的话设备就无法
匹配到对应的驱动。比如对应的platform驱动的name字段为“xxx-gpio”,那么此name字段也要设置
为“xxx-gpio”。
第27行,num_resources表示资源数量,一般为第28行resource资源的大小。
第28行,resource表示资源,也就是设备信息,比如外设寄存器等。Linux内核使用resource结构
体表示资源,resource结构体内容如下:
讯享网
start和end分别表示资源的起始和终止信息,对于内存类的资源,就表示内存起始和终止地址,
name表示资源名字,flags表示资源类型,可选的资源类型都定义在了文件include/linux/ioport.h里
面,如下所示:
在以前不支持设备树的Linux版本中,用户需要编写platform_device变量来描述设备信息,然后使
用platform_device_register函数将设备信息注册到Linux内核中,此函数原型如下所示:
讯享网
函数参数和返回值含义如下:
pdev:要注册的platform设备。
返回值:负数,失败;0,成功。
如果不再使用platform的话可以通过platform_device_unregister函数注销掉相应的platform设
备,platform_device_unregister函数原型如下:
函数参数和返回值含义如下:
pdev:要注销的platform设备。
返回值:无。
platform设备信息框架如下所示:
讯享网
第7~18行,数组xxx_resources表示设备资源,一共有两个资源,分别为设备外设1和外设2的寄存
器信息。因此flags都为IORESOURCE_MEM,表示资源为内存类型的。
第21~26行,platform设备结构体变量,注意name字段要和所使用的驱动中的name字段一致,否
则驱动和设备无法匹配成功。num_resources表示资源大小,其实就是数组xxx_resources的元素
数量,这里用ARRAY_SIZE来测量一个数组的元素个数。
第29~32行,设备模块加载函数,在此函数中调用platform_device_register向Linux内核注册
platform设备。
第35~38行,设备模块卸载函数,在此函数中调用platform_device_unregister从Linux内核中卸载
platform设备。
以上代码主要是在不支持设备树的Linux版本中使用的,当Linux内核支持了设备树以后就不需要用
户手动去注册platform设备了。因为设备信息都放到了设备树中去描述,Linux内核启动的时候会从
设备树中读取设备信息,然后将其组织成platform_device形式,至于设备树到platform_device的具
体过程就不去详细的追究了,感兴趣的可以去看一下,网上也有很多博客详细的讲解了整个过程。
关于platform下的总线、驱动和设备就讲解到这里,我们接下来就使用platform驱动框架来编写一
个LED灯驱动,本章我们不使用设备树来描述设备信息,我们采用自定义platform_device这种“古
老”方式来编写LED的设备信息。下一章我们来编写设备树下的platform驱动,这样我们就掌握了无
设备树和有设备树这两种platform驱动的开发方式。
本章实验我们需要编写一个驱动模块和一个设备模块,其中驱动模块是platform驱动程序,设备模
块是platform的设备信息。当这两个模块都加载成功以后就会匹配成功,然后platform驱动模块中
的probe函数就会执行,probe函数中就是传统的字符设备驱动那一套。
新建名为“17_platform”的文件夹,然后在17_platform文件夹里面创建vscode工程,工作区命名为
“platform”。新建名为leddevice.c和leddriver.c这两个文件,这两个文件分别为LED灯的platform设
备文件和LED灯的platform的驱动文件。在leddevice.c中输入如下所示内容:
leddevice.c文件内容就是按照之前的示例代码的platform设备模板编写的。
第56~82行,led_resources数组,也就是设备资源,描述了LED所要使用到的寄存器信息,也就是
IORESOURCE_MEM资源。
第88~96,platform设备结构体变量leddevice,这里要注意name字段为“imx6ul-led”,所以稍后编
写platform驱动中的name字段也要为“imx6ul-led”,否则设备和驱动匹配失败。
第103~106行,设备模块加载函数,在此函数里面通过platform_device_register向Linux内核注册
leddevice这个platform设备。
第113~116行,设备模块卸载函数,在此函数里面通过platform_device_unregister从Linux内核中
删除掉leddevice这个platform设备。
leddevice.c文件编写完成以后就编写leddriver.c这个platform驱动文件,在leddriver.c里面输入如下
内容:
讯享网
leddriver.c文件内容就是按照之前示例的platform驱动模板编写的。
第34~122行,传统的字符设备驱动。
第130~206行,probe函数,当设备和驱动匹配以后此函数就会执行,当匹配成功以后会在终端上
输出“leddriveranddevicehasmatched!”这样语句。在probe函数里面初始化LED、注册字符设备驱
动。也就是将原来在驱动加载函数里面做的工作全部放到probe函数里面完成。
第213~226行,remove函数,当卸载platform驱动的时候此函数就会执行。在此函数里面释放内
存、注销字符设备等。也就是将原来驱动卸载函数里面的工作全部都放到remove函数中完成。
第229~235行,platform_driver驱动结构体,注意name字段为"imx6ul-led",和我们在leddevice.c
文件里面设置的设备name字段一致。第242~245行,驱动模块加载函数,在此函数里面通过
platform_driver_register向Linux内核注册led_driver驱动。
第252~255行,驱动模块卸载函数,在此函数里面通过platform_driver_unregister从Linux内核卸载
led_driver驱动。
测试APP的内容很简单,就是打开和关闭LED灯,新建ledApp.c这个文件,然后在里面输入如下内
容:
ledApp.c文件内容很简单,就是控制LED灯的亮灭,和第四十一章的测试APP基本一致,这里就不

重复讲解了。
1、编译驱动程序
编写Makefile文件,本章实验的Makefile文件和之前实验基本一样,只是将obj-m变量的值改为
“leddevice.oleddriver.o”,Makefile内容如下所示:
讯享网
第4行,设置obj-m变量的值为“leddevice.oleddriver.o”。
输入如下命令编译出驱动模块文件:
编译成功以后就会生成一个名为“leddevice.koleddriver.ko”的驱动模块文件。
2、编译测试APP
输入如下命令编译测试ledApp.c这个测试程序:
讯享网
编译成功以后就会生成ledApp这个应用程序。
将上一小节编译出来leddevice.ko、leddriver.ko和ledApp这两个文件拷贝到
rootfs/lib/modules/4.1.15目录中,重启开发板,进入到目录lib/modules/4.1.15中,输入如下命令加
载leddevice.ko设备模块和leddriver.ko这个驱动模块。
根文件系统中/sys/bus/platform/目录下保存着当前板子platform总线下的设备和驱动,其中devices
子目录为platform设备,drivers子目录为plartofm驱动。查看/sys/bus/platform/devices/目录,看看
我们的设备是否存在,我们在leddevice.c中设置leddevice(platform_device类型)的name字段为
“imx6ul-led”,也就是设备名字为imx6ul-led,因此肯定在/sys/bus/platform/devices/目录下存在一
个名字“imx6ul-led”的文件,否则说明我们的设备模块加载失败,结果如图所示:

同理,查看/sys/bus/platform/drivers/目录,看一下驱动是否存在,我们在leddriver.c中设置
led_driver(platform_driver类型)的name字段为“imx6ul-led”,因此会在/sys/bus/platform/drivers/目
录下存在名为“imx6ul-led”这个文件,结果如图所示:

驱动模块和设备模块加载成功以后platform总线就会进行匹配,当驱动和设备匹配成功以后就会输
出如图所示一行语句:

驱动和设备匹配成功以后就可以测试LED灯驱动了,输入如下命令打开LED灯:
讯享网
在输入如下命令关闭LED灯:
观察一下LED灯能否打开和关闭,如果可以的话就说明驱动工作正常,如果要卸载驱动的话输入如
下命令即可:
讯享网
上一章我们详细的讲解了Linux下的驱动分离与分层,以及总线、设备和驱动这样的驱动框架。基
于总线、设备和驱动这样的驱动框架,Linux内核提出来platform这个虚拟总线,相应的也有
platform设备和platform驱动。上一章我们讲解了传统的、未采用设备树的platform设备和驱动编写
方法。最新的Linux内核已经支持了设备树,因此在设备树下如何编写platform驱动就显得尤为重
要,本章我们就来学习一下如何在设备树下编写platform驱动。
platform驱动框架分为总线、设备和驱动,其中总线不需要我们这些驱动程序员去管理,这个是
Linux内核提供的,我们在编写驱动的时候只要关注于设备和驱动的具体实现即可。在没有设备树
的Linux内核下,我们需要分别编写并注册platform_device和platform_driver,分别代表设备和驱
动。在使用设备树的时候,设备的描述被放到了设备树中,因此platform_device就不需要我们去
编写了,我们只需要实现platform_driver即可。在编写基于设备树的platform驱动的时候我们需要
注意一下几点:
1、在设备树中创建设备节点
毫无疑问,肯定要先在设备树中创建设备节点来描述设备信息,重点是要设置好compatible属性的
值,因为platform总线需要通过设备节点的compatible属性值来匹配驱动!这点要切记。比如,
我们可以编写如下所示的设备节点来描述我们本章实验要用到的LED这个设备:
以上示例中的gpioled节点其实就是之前中创建的gpioled设备节点,我们可以直接拿过来用。注意
第4行的compatible属性值为“atkalpha-gpioled”,因此一会在编写platform驱动的时候
of_match_table属性表中要有“atkalpha-gpioled”。
2、编写platform驱动的时候要注意兼容属性
上一章已经详细的讲解过了,在使用设备树的时候platform驱动会通过of_match_table来保存兼容
性值,也就是表明此驱动兼容哪些设备。所以,of_match_table将会尤为重要,比如本例程的
platform驱动中platform_driver就可以按照如下所示设置:
讯享网
第1~4行,of_device_id表,也就是驱动的兼容表,是一个数组,每个数组元素为of_device_id类
型。每个数组元素都是一个兼容属性,表示兼容的设备,一个驱动可以跟多个设备匹配。这里我们
仅仅匹配了一个设备,那就是之前中创建的gpioled这个设备。第2行的compatible值为“atkalpha-
gpioled”,驱动中的compatible属性和设备中的compatible属性相匹配,因此驱动中对应的probe函
数就会执行。注意第3行是一个空元素,在编写of_device_id的时候最后一个元素一定要为空!
第6行,通过MODULE_DEVICE_TABLE声明一下leds_of_match这个设备匹配表。
第11行,设置platform_driver中的of_match_table匹配表为上面创建的leds_of_match,至此我们就
设置好了platform驱动的匹配表了。
3、编写platform驱动
基于设备树的platform驱动和上一章无设备树的platform驱动基本一样,都是当驱动和设备匹配成
功以后就会执行probe函数。我们需要在probe函数里面执行字符设备驱动那一套,当注销驱动模
块的时候remove函数就会执行,都是大同小异的。
本章实验我们编写基于设备树的platform驱动,所以需要在设备树中添加设备节点,然后我们只需
要编写platform驱动即可。
首先修改设备树文件,加上我们需要的设备信息,本章我们就使用到一个LED灯,因此可以直接使
用之前编写的gpioled子节点即可,不需要再重复添加。
新建名为leddriver.c的驱动文件,在leddriver.c中输入如下所示内容:
第33~112行,传统的字符设备驱动,没什么要说的。
第120~164行,platform驱动的probe函数,当设备树中的设备节点与驱动之间匹配成功以后此函数
就会执行,原来在驱动加载函数里面做的工作现在全部放到probe函数里面完成。
第171~180行,remobe函数,当卸载platform驱动的时候此函数就会执行。在此函数里面释放内
存、注销字符设备等,也就是将原来驱动卸载函数里面的工作全部都放到remove函数中完成。
第183~186行,匹配表,描述了此驱动都和什么样的设备匹配,第184行添加了一条值为"atkalpha-
gpioled"的compatible属性值,当设备树中某个设备节点的compatible属性值也为“atkalpha-
gpioled”的时候就会与此驱动匹配。
第189~196行,platform_driver驱动结构体,191行设置这个platform驱动的名字为“imx6ul-
led”,因此,当驱动加载成功以后就会在/sys/bus/platform/drivers/目录下存在一个名为“imx6u-
led”的文件。
第192行设置of_match_table为上面的led_of_match。
第203~206行,驱动模块加载函数,在此函数里面通过platform_driver_register向Linux内核注册
led_driver驱动。
第213~216行,驱动模块卸载函数,在此函数里面通过platform_driver_unregister从Linux内核卸载
led_driver驱动。
1、编译驱动程序
编写Makefile文件,本章实验的Makefile文件和之前实验基本一样,只是将obj-m变量的值改为
“leddriver.o”,Makefile内容如下所示:
讯享网
第4行,设置obj-m变量的值为“leddriver.o”。
输入如下命令编译出驱动模块文件:
编译成功以后就会生成一个名为“leddriver.o”的驱动模块文件。
2、编译测试APP
测试APP直接使用上一章的ledApp这个测试软件即可。
将上一小节编译出来leddriver.ko拷贝到rootfs/lib/modules/4.1.15目录中,重启开发板,进入到目录
lib/modules/4.1.15中,输入如下命令加载leddriver.ko这个驱动模块。
讯享网
驱动模块加载完成以后到/sys/bus/platform/drivers/目录下查看驱动是否存在,我们在leddriver.c中
设置led_driver(platform_driver类型)的name字段为“imx6ul-led”,因此会
在/sys/bus/platform/drivers/目录下存在名为“imx6ul-led”这个文件,结果如图所示:

同理,在/sys/bus/platform/devices/目录下也存在led的设备文件,也就是设备树中gpioled这个
节点,如图所示:

驱动和模块都存在,当驱动和设备匹配成功以后就会输出如图所示一行语句:

驱动和设备匹配成功以后就可以测试LED灯驱动了,输入如下命令打开LED灯:
在输入如下命令关闭LED灯:
讯享网
观察一下LED灯能否打开和关闭,如果可以的话就说明驱动工作正常,如果要卸载驱动的话输入如
下命令即可:

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/179950.html