欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  网络运营

嵌入式LINUX驱动开发(中断处理函数)

程序员文章站 2022-03-13 21:19:13
嵌入式LINUX驱动学习之7中断相关(一)中断处理函数一、函数、头文件及说明二、编译举例:一、函数、头文件及说明//头文件位置:include/linux/interrupt.hextern int __must_checkrequest_threaded_irq(unsigned int irq, irq_handler_t handler,\ irq_handler_t thread_fn,\ unsigned...


嵌入式LINUX驱动学习之7中断相关(一)中断处理函数


一、函数、头文件及说明

//头文件位置:include/linux/interrupt.h extern int __must_check request_threaded_irq(unsigned int irq, irq_handler_t handler,\
                     irq_handler_t thread_fn,\ unsigned long flags, const char *name, void *dev); static inline int __must_check \ request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags, const char *name, void *dev) { return request_threaded_irq(irq, handler, NULL, flags, name, dev); } /*
参数:
irq : 中断号,获取外部中断号使用的函数 :
     static inline int gpio_to_irq(unsigned gpio);//头文件位置:include/linux/gpio.h
irq_handler_t : 中断处理函数 :
                typedef irqreturn_t (*irq_handler_t)(int, void *);
                使用方法:
                         static irqretrun_t irq_func(int args,void * argv);//args:全局的整数,argv:全局指针
flags:
      #define IRQF_TRIGGER_NONE       0x00000000             //没有中断
      #define IRQF_TRIGGER_RISING     0x00000001             //上升沿触发
      #define IRQF_TRIGGER_FALLING    0x00000002             //下降沿触发
      #define IRQF_TRIGGER_HIGH       0x00000004             //高电平触发
      #define IRQF_TRIGGER_LOW        0x00000008             //低电平触发
      #define IRQF_TRIGGER_MASK       (IRQF_TRIGGER_HIGH | IRQF_TRIGGER_LOW | \
                                      IRQF_TRIGGER_RISING |RQF_TRIGGER_FALLING)
      #define IRQF_TRIGGER_PROBE      0x00000010
 dev :向中断处理函数传递的参数     
*/ 

二、编译举例:

#include <linux/init.h> #include <linux/module.h> #include <linux/interrupt.h> #include <linux/gpio.h> #include <cfg_type.h> /*定义按键信息*/ struct btn_srouce{ char *name; int gpio ; }; struct btn_srouce btn_info[] = { { .name = "BTN1", .gpio = PAD_GPIO_A +28 }, { .name = "BTN2", .gpio = PAD_GPIO_B +30 }, { .name = "BTN3", .gpio = PAD_GPIO_B +31 }, { .name = "BTN4", .gpio = PAD_GPIO_B +9 } }; /*定义LED灯信息*/ struct led_source { char *name; int gpio ; }; struct led_source led_info[] = { { .name = "LED1", .gpio = PAD_GPIO_B +26 }, { .name = "LED2", .gpio = PAD_GPIO_C +12 }, { .name = "LED3", .gpio = PAD_GPIO_C +11 }, { .name = "LED4", .gpio = PAD_GPIO_C +7 } }; static int irq;//定义中断号变更  /*定义中断处理函数*/ static irqreturn_t irq_func(int args,void * argv){ struct led_source *led_num = (struct led_source *) argv;//保存传递来的的形参地址 gpio_set_value(led_num->gpio,(1 - gpio_get_value(led_num->gpio)));//获取当前灯的状态信息,当为0时,设置为1,当为1时设置为0;即开/关状态切换 printk("%s ,当前%s状态为%s\n",__func__,led_num->name,\ gpio_get_value(led_num->gpio) ? "关" :"开"); return IRQ_HANDLED; //返回值说明,见附A.1 } static int btn_led_init(void){ int i = 0; for(; i<ARRAY_SIZE(btn_info);i++){ /*LED灯初始化*/ gpio_request(led_info[i].gpio,led_info[i].name); gpio_direction_output(led_info[i].gpio,1); /*按键初始化*/ gpio_request(btn_info[i].gpio,btn_info[i].name); irq = gpio_to_irq(btn_info[i].gpio); request_irq(irq,irq_func,IRQF_TRIGGER_LOW,\
                    btn_info[i].name,&led_info[i]); } return 0; } static void btn_led_exit(void){ int i = 0; for(; i <ARRAY_SIZE(btn_info);i++){ /*释放LED灯占用的GPIO资源*/ gpio_set_value(led_info[i].gpio,1); gpio_free(led_info[i].gpio); /*释放按键占用的GPIO资源*/ irq = gpio_to_irq(btn_info[i].gpio); free_irq(irq,&led_info[i]); gpio_set_value(btn_info[i].gpio,1); gpio_free(btn_info[i].gpio); } } module_init(btn_led_init); module_exit(btn_led_exit); MODULE_LICENSE("GPL"); 

附 A.1

//源码位置:include/linux/irqreturn.h /**
 * enum irqreturn
 * @IRQ_NONE            interrupt was not from this device
 * @IRQ_HANDLED         interrupt was handled by this device
 * @IRQ_WAKE_THREAD     handler requests to wake the handler thread
 */ enum irqreturn { IRQ_NONE = (0 << 0), IRQ_HANDLED = (1 << 0), IRQ_WAKE_THREAD = (1 << 1), }; typedef enum irqreturn irqreturn_t; 

本文地址:https://blog.csdn.net/weixin_47273317/article/details/107908456