Embedded LINUX driver learning 7 interrupt related (1) interrupt processing function

Embedded LINUX driver learning 7 interrupt related (1) interrupt processing function

1. Functions, header files and descriptions

//头文件位置: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 :向中断处理函数传递的参数     
*/

Two, compilation example:

#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");

Attachment 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;

Guess you like

Origin blog.csdn.net/weixin_47273317/article/details/107908456