嵌入式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;