按键实现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");
