一、分析需求
1.看sch:怎么操作
2.规划驱动功能(不一定全都要实现)
APP open poll read
DRV drv_open drv_poll drv_read
例如 查询 、poll、休眠唤醒、异步通知等功能
3.写驱动/测试程序
在写驱动时可多参考源码里的驱动文件
二、构造设备树
1.可以先打开该目录下的dts文件作为参考
2.打开dts文件后,输入/gpio进行搜索
3.最终结果,将结果加入dts文件中,不是新加文件
sr501{
compatible = “100ask,sr501”;
gpios = <&gpio4 19 GPIO_ACTIVE_HIGH>;
};
在.dts文件的每个设备,都有一个compatible属性,compatible属性用户驱动和设备的绑定。
不同芯片的dts主要是gpios= <&gpio4 19 GPIO_ACTIVE_HIGH>;的写法不同,gpio-cells =2代表需要两个整形代表gpio口
三、实现驱动框架
1.平台DEV与平台DRV配对规则
嵌入式Linux应用开发完全手册V4.0_韦东山全系列视频文档-IMX6ULL开发板P 549,11.5节
2.参考以前程序,修改名称,删减程序
#include <linux/module.h>
#include <linux/poll.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/mutex.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/stat.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/tty.h>
#include <linux/kmod.h>
#include <linux/gfp.h>
#include <linux/gpio/consumer.h>
#include <linux/platform_device.h>
#include <linux/of_gpio.h>
#include <linux/of_irq.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/slab.h>
#include <linux/fcntl.h>
#include <linux/timer.h>
#include <linux/workqueue.h>
#include <asm/current.h>
struct gpio_key{
int gpio;
struct gpio_desc *gpiod;
int flag;
int irq;
struct timer_list key_timer;
struct tasklet_struct tasklet;
struct work_struct work;
} ;
static struct gpio_key *gpio_keys_100ask;
/* 主设备号 */
static int major = 0;
static struct class *gpio_key_class;
/* 环形缓冲区 */
#define BUF_LEN 128
static int g_keys[BUF_LEN];
static int r, w;
struct fasync_struct *button_fasync;
#define NEXT_POS(x) ((x+1) % BUF_LEN)
static int is_key_buf_empty(void)
{
return (r == w);
}
static int is_key_buf_full(void)
{
return (r == NEXT_POS(w));
}
static void put_key(int key)
{
if (!is_key_buf_full())
{
g_keys[w] = key;
w = NEXT_POS(w);
}
}
static int get_key(void)
{
int key = 0;
if (!is_key_buf_empty())
{
key = g_keys[r];
r = NEXT_POS(r);
}
return key;
}
static