驱动程序的分离其实就是把原来我们写的驱动程序进行分割,分割成为一个是基本不变的与硬件相关的drv程序和纯软件的dev程序。设备(dev),驱动(drv)两个模块分别编写驱动程序,在设备的.C文件中,负责定义驱动的设备IO地址等可变的信息,而在驱动的.C文件中负责统一的内存地址IOREMAP映射,注册设备等不变的代码。这样,当我们程序要修改时,比如说如果我们要将beep修改为led的话,那么就只需要将设备的.C文件中的地址修改过来就可以了,大大的增强了代码的可移植性。它的框图是这样的:
--------------------------------------------------
--------------------------------------------------
button.c
硬件相关
-----------------------------------------------
bus_drv_dev模型
1.把device放入bus的dev链表
2.从bus的drv链表取出每一个drv
用bus的match函数判断drv能否支持dev
3.若可以支持,调用drv的probe
-----------------------------------------------
usb_new_device /
usb_interface
-----------------------------------------------
platform_device
一、 设备Led_dev.c的实现
1.定义平台设备结构体
如图所示,在平台设备结构体,需要注意两个地方:
第一个是.name,它是用于保存在设备链中,利用它在驱动链中进行匹配,找到相应的驱动程序。
第二个是.resources,它是一个资源结构体,用于保存我们开发板的内存IO地址,当我们要更改硬件是,只需要修改资源结构体中的数据即可。简单的说,资源结构体主要的功能就是传递参数,将板子的内存地址传入Led_drv.c中,Led_drv.c只要通过platform_get_resource函数即可得到资源中保存的数据。
2.定义资源结构体
在Led_drv.c将这些数据获取,然后分别ioremap进行地址映射
3.接下来就是在分别在入口函数中申请平台设备,在出口函数中注销平台设备
4.注意:添加led_release()函数
没有添加led_release()函数时,会出现问题,需要定义一个led_release()函数,里面什么也不做。
二、 驱动Led_drv.c的实现
和上面差不多,此处我们先实现一个平台驱动的支持,也就是
①定义平台驱动结构体
②在入口函数中注册平台驱动
③在出口函数中卸载平台驱动
此处就不再详细将这个,见下图:
2.平台驱动探测函数probe实现
我们此处驱动程序的核心就是在probe这个函数。
当我们的驱动和设备匹配成功之后,就会调用probe函数,在此函数中可以干任何我们想干的事。
所以,我们呢,就利用此函数完成我们的硬件设备初始化的工作。
①
②将前面的资源中的地址,通过ioremap函数分别映射地址
③注册字符设备驱动,创建类,然后再类下面创建设备节点
如下图所示:
3.平台驱动释放函数remove实现
在remove函数中,自然就是将前面我们映射的地址取消映射,卸载字符设备驱动程序
如图所示:
4.实现file_opration结构体
前面注册字符设备时,
需要一个file_operation结构体,用于制定读写函数,如下图所示:
5.实现打开函数led_open
6.实现写函数led_write
通过前面的额正确配置GPIO,我们就已经可以正确的使用led了,接下来,我们通过写函数来将我们的数据传入内核,从而相应的led灯的亮和灭。
三 、应用程序led_test.c的实现
在测试程序中,我们只需要实现以下几步
①打开设备
②判断用户输入的命令
③根据用户的命令来相应的控制
当我们用户输入
./led_test on
./led_test off
四 、测试程序