一个可移植性好的驱动程序,应该有三个部分组成
1、驱动框架程序(xxx_drv.c) — 对接应用层的 open read write 函数,不做GPIO具体操作
2、硬件操作程序(xxx_chip_gpio.c)— 执行具体的GPIO操作,初始化、读写
3、硬件资源定义程序(xxx_board.c,这在之后就过渡成了设备树)— 为第二层提供硬件资源,哪一组GPIO?第几个引脚?
经过分层之后,我们需要添加一个新的外设时,只需要做两个步骤:
(1)在 xxx_board.c 中添加硬件引脚资源
(2)在 xxx_chip_gpio.c 中添加具体的GPIO初始化、控制等操作
驱动层的 xxx_drv.c 根本不需要怎么修改
前几天自己总结了个图,也是帮助自己梳理思路
看上去有些乱,不过只要学过韦东山老师视频的
https://www.bilibili.com/video/BV1w4411B7a4?p=105&vd_source=fcd24cb292784bee4d86583df11ae49f
耐心看看应该会觉得思路清晰的
下图看不清楚,图片下载地址在这里
驱动分层框架图下载: 驱动分层框架图.jpg (图片有80多M,请耐心加载哦)
全部代码在我的 gitee 仓库中的 “09.led_platform_drv_chip_board_demo” 文件夹中,需要自取
gitee 仓库:https://gitee.com/chenshao777/imx6-ull_-drivers
粗略的解释一下流程,细说的话太麻烦了,这里主要介绍驱动分层思想的大概流程,也是为自己今后复习的时候帮助回忆
驱动分层思想
1、 首先是驱动程序(xxx_drv.c)的 file_operations 结构体,该结构体关联了应用层的文件IO函数与驱动层的函数
以led驱动为例
应用层 | 驱动层 |
---|---|
open | led_open |
read | led_read |
write | led_write |
2、 硬件操作程序(xxx_chip_gpio.c)中的 platform_driver 结构体,加载完ko文件后(即驱动文件),内核会自动帮它寻找 name 匹配的 platform_device 结构体,从其中获取到硬件资源,然后创建设备节点(/dev/ledx)
匹配到硬件资源层的 platform_device 结构体后,内核会自动调用其 probe 函数,在 probe 函数中创建设备节点
PS:创建设备节点需要驱动框架层的设备类对象,所以这里需要在设备框架层中为硬件操作层提供对应函数
3、硬件资源定义程序中的 platform_device 结构体,该结构体中定义了与硬件操作层中 platform_driver 对应的 name 成员和硬件引脚资源 resource 等
PS:注意要设置 dev 成员下的 release 属性,如果不加的话卸载驱动时会报警告
4、硬件资源层中硬件资源的定义,硬件资源有个特定的结构体 resource ,可以参照Linux内核中其他文件对其的定义来写。
PS:GPIO_PIN是一个宏,为了方便将GPIO组和是第几个引脚组合起来而定义
#define GPIO_PIN(g,p) ((g << 16) | p)
5、 更多的细节在图片中看吧,今天先写到这里,下一篇博客介绍设备树的使用。