根据上一个帖子的分析,想要实现按键中断,首先得知道引脚对应的中断号,LRADC0对应的中断编号#define SUNXI_IRQ_LRADC (SUNXI_GIC_START + 30) /* 62*/
通过static inline int gpio_to_irq(SUNXI_IRQ_LRADC)这个函数确定这个IO上的外部中断编号
程序流程,当引脚电平发生变化触发中断,进入中断函数把按键状态更新,此时在应用程序读相应设备,则可以知道引脚状态
驱动程序框架
#define BTN_MAJOR 255
static struct miscdevice misc = {
.minor = BTN_MAJOR, //次设备号
.name = DEVICE_BUTTON,//设备名
.fops = &dev_fops, //文件操作方法
};
//按键标志,'0'表示没有按键,'1'表示按下了
static char keybuf[1] = {‘0’};
//中断处理函数声明
irqreturn_t key_isr(int irq, void* dev);
//读函数,读取引脚状态
static ssize_t btn_read (struct file *flp, char __user *buff, size_t count, loff_t * off);
//file_operations结构体
static const struct file_operations dev_fops = {
.read = btn_read ,
.owner = THIS_MODULE,
};
//初始化函数
static int __init btn_init(void);
//注销函数
static void __exit btn_exit(void);
首先先看初始化函数static int __init btn_init(void);
static int __init btn_init(void)
{
int ret;
int irq;//中断号
int flags; //触发标志
flags = IRQ_TYPE_EDGE_BOTH; //设置为双边触发
//得到中断号
irq = gpio_to_irq(SUNXI_IRQ_LRADC);
//注册中断
ret = request_irq(irq,key_isr, flags, “key”, NULL);
if(ret < 0)
break;
//如果不是成功,注销已经注册的中断
if(ret < 0) {
irq = gpio_to_irq(SUNXI_IRQ_LRADC);
disable_irq(irq);
free_irq(irq, NULL);
return ret;
}
//注册杂项设备
ret = misc_register(&misc);
printk(KERN_EMERG " Device registered n ");
return ret;
}
注销函数 static void __exit btn_exit(void);
static void __exit btn_exit(void)
{
int irq;
//注销中断
irq = gpio_to_irq(SUNXI_IRQ_LRADC);
disable_irq(irq);
free_irq(irq, NULL);
//注销杂项设备
misc_deregister(&misc);
printk(KERN_EMERG " Equipment logged out n");
}
读函数,读取引脚状态 static ssize_t btn_read (struct file *flp, char __user *buff, size_t count, loff_t * off);
static ssize_t tiny4412_read (struct file *flp, char __user *buff, size_t count, loff_t * off)
{
int ret ;
//count为0,直接返回
if(!count) {
return 0;
}
//复制数据到用户空间
ret = copy_to_user(buff, keybuf, count);
if(ret) {
printk("error:copy_to_userrn");
return -EFAULT;
}
return count;
}
中断服务函数irqreturn_t key_isr1(int irq, void* dev)
irqreturn_t key_isr1(int irq, void* dev)
{
//存放按键状态
int btn = 0;
btn= !gpio_get_value(SUNXI_IRQ_LRADC );
//把按键状态更新到对应的按缓冲中
keybuf[0] = dn + '0';
//输出按键提示
printk("key %srn", dn ? "down" : "up");
return IRQ_HANDLED;//目前只是实现一个按键的,这个是共享中断的情况才用到, 在中断到来时,会遍历共享此中断的所有中断处理程序, 直到某一个中断服务函数时返回 IRQ_HANDLED。
}
未完待续... ....
|