本文主要介绍了Linux驱动开发中一些常用的驱动框架,platform、input、iic、spi等,硬件平台使用的是正点原子的imx6ull开发板。
不管什么框架最后都是要追溯到配置IO的电气属性和复用功能
如果要使用外部中断,设备树节点中还需添加相关信息,什么边沿触发
1:module_init和module_exit,驱动的入口和出口
2:习惯性构建一个结构体来管理相关资源(主次设备号、cdev、class、device、设备节点等)
3:file_operations结构体里面包含了该设备驱动的操作函数集合,可以按需进行实现
file_operations结构体的原型,里面都是一些函数指针
驱动实现部分操作函数
4:init函数实现字符设备相关初始化
分配设备号、cdev_init、cdev_add、class_create、device_create
获取节点、获取gpio编号、申请gpio、设置输入输出模式
如果在某一过程申请资源失败要释放之前已经申请成功的资源
5:exit函数释放相关资源
定时器和中断在驱动设备中要添加的内容
定时器初始化
重新修改定时器计数,使得可以多次定时
外部中断
1:首先是module_init和module_exit,初始化一个platform_driver结构体,主要初始化匹配列表和probe、remove函数
驱动中对应的compatible字段
设备树中设备对应的compatible字段
当加载驱动后就会通过compatible字段查找,驱动和设备就可通过platform总线进行匹配。后面就和最简单没有总线的框架一样、其实就是套了一层皮。
大框架还是platform驱动框架,要添加一个miscdevice类型结构体
在probe中注册、remove中销毁,减少了分配设备号、cdev、class、device那繁琐的一套
设备结构体中要添加一个输入设备
在init中申请和注册、exit中取消注册和释放
设置事件和值(type、code、value)
使用input_event函数上报事件
上报的数据可以使用hexdump观察
应用层可以使用一个input_event结构体变量来接收上报的数据
首先module_init和module_exit,添加一个i2c_driver,对应init完成i2c_add_driver,exit中完成i2c_del_driver
同样的,设备和驱动匹配还是要靠compatible属性
当设备树节点和驱动文件匹配之后,执行probe函数,会传入i2c_client类型的一个结构体指针,可以使用一个指针变量保存下来,当在i2c读写寄存器的时候会用得到。
设备中定义一个指针进行保存
I2C读数据
I2C写数据
首先module_init和module_exit,创建一个spi_driver类型的结构体变量,init中spi_register_driver、exit中spi_unregister_driver
设备树相关信息
当执行到probe函数的时候会传入一个spi_device类型的结构体,像i2c驱动一样找一个变量存起来
设备中定义一个指针用来接收spi_device类型的指针
设置spi设备的工作模式
spi读写寄存器可以使用内核自带的spi_read和spi_write,其中都要传入类型为spi_device的参数,就是在调用probe传入的那个。
以上只是对学习驱动这段时间的一个梳理和回顾,想系统学习可以阅读正点的教程。