按键实现LED中断
#include <linux/init.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/gpio.h>
#include <linux/timer.h>
#include <linux/jiffies.h>
#include <linux/of_irq.h>
#include <linux/interrupt.h>
/*
myleds {
myled1 = <&gpioe 10 0>;
myled2 = <&gpiof 10 0>;
myled3 = <&gpioe 8 0>;
myled4 = <&gpioz 5 0>;
myled5 = <&gpioz 6 0>;
myled6 = <&gpioz 7 0>;
};
myirq{
interrupt-parent = <&gpiof>;
interrupts = <7 0>, <8 0>, <9 0>;//第一个成员指的是gpio编号,第二个成员表示触发方式,0表示默认属性
};*/
//定义指针指向获取的设备树节点信息空间
struct device_node *node_led;
struct device_node *node_irq;
struct gpio_desc * gpio1;
struct gpio_desc * gpio2;
struct gpio_desc * gpio3;
int ret;
unsigned int irq1;//用于接收软中断号
unsigned int irq2;
unsigned int irq3;
unsigned int count=0;//用于计数,中断发生一次,次数+1
//分配定时器对象
struct timer_list mytimer;
irqreturn_t irq_handler1(int irq1,void* dev)
{
count++;
gpiod_set_value(gpio1,!gpiod_get_value(gpio1));
return IRQ_HANDLED;
}
irqreturn_t irq_handler2(int irq2,void* dev)
{
count++;
gpiod_set_value(gpio2,!gpiod_get_value(gpio2));
return IRQ_HANDLED;
}
irqreturn_t irq_handler3(int irq3,void* dev)
{
count++;
gpiod_set_value(gpio3,!gpiod_get_value(gpio3));
return IRQ_HANDLED;
}
static int __init mycdev_init(void)
{
//通过名字获取设备树节点信息
node_led=of_find_node_by_name(NULL,"myleds");
if(node_led==NULL)
{
printk("通过名字解析设备树节点失败\n");
return -EFAULT;
}
node_irq=of_find_node_by_name(NULL,"myirq");
if(node_irq==NULL)
{
printk("通过名字解析设备树节点失败\n");
return -EFAULT;
}
printk("成功解析到设备树节点\n");
//获取中断号
irq1=irq_of_parse_and_map(node_irq,1);
if(0==irq1)
{
printk("获取中断号1失败\n");
return EINVAL;
}
printk("获取中断号1成功\n");
irq2=irq_of_parse_and_map(node_irq,2);
if(0==irq2)
{
printk("获取中断号2失败\n");
return EINVAL;
}
printk("获取中断号2成功\n");
irq3=irq_of_parse_and_map(node_irq,0);
if(0==irq3)
{
printk("获取中断号3失败\n");
return EINVAL;
}
printk("获取中断号3成功\n");
//获取并申请gpio编号
gpio1=gpiod_get_from_of_node(node_led,"myled1",0,GPIOD_OUT_LOW,NULL);
gpio2=gpiod_get_from_of_node(node_led,"myled2",0,GPIOD_OUT_LOW,NULL);
gpio3=gpiod_get_from_of_node(node_led,"myled3",0,GPIOD_OUT_LOW,NULL);
//将中断注册进内核
ret=request_irq(irq1,irq_handler1,IRQF_TRIGGER_FALLING,"key1_inte",NULL);
if(ret)
{
printk("注册中断1失败\n");
return ret;
}
printk("注册中断1成功\n");
ret=request_irq(irq2,irq_handler2,IRQF_TRIGGER_FALLING,"key2_inte",NULL);
if(ret)
{
printk("注册中断2失败\n");
return ret;
}
printk("注册中断2成功\n");
ret=request_irq(irq3,irq_handler3,IRQF_TRIGGER_FALLING,"key3_inte",NULL);
if(ret)
{
printk("注册中断3失败\n");
return ret;
}
printk("注册中断3成功\n");
return 0;
}
static void __exit mycdev_exit(void)
{
//卸载驱动前熄灭灯
gpiod_set_value(gpio1,0);
gpiod_set_value(gpio2,0);
gpiod_set_value(gpio3,0);
//释放申请得到的gpio编号
gpiod_put(gpio1);
gpiod_put(gpio2);
gpiod_put(gpio3);
//中断的注销
free_irq(irq1,NULL);
free_irq(irq2,NULL);
free_irq(irq3,NULL);
}
module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");