嵌入式LINUX驱动学习之7中断相关(二)底半部机制之tasklet_struct
一、头文件、函数及说明
struct tasklet_struct
{
struct tasklet_struct *next;
unsigned long state;
atomic_t count;
void (*func)(unsigned long);
unsigned long data;
};
#define DECLARE_TASKLET(name, func, data) \
struct tasklet_struct name = { NULL, 0, ATOMIC_INIT(0), func, data }
struct tasklet_struct tasklet_init_s = {
.func = 延迟处理函数,
.data = 需要处理的数据
}
static inline void tasklet_schedule(struct tasklet_struct *t)
{
if (!test_and_set_bit(TASKLET_STATE_SCHED, &t->state))
__tasklet_schedule(t);
}
二、代码举例
#include <linux/init.h>
#include <linux/module.h>
#include <linux/gpio.h>
#include <cfg_type.h>
#include <linux/interrupt.h>
#include <linux/irqreturn.h>
struct btn_src {
char *name;
int gpio;
};
struct btn_src btn_info[] = {
{
.name = "LED1_BTN",
.gpio = PAD_GPIO_A +28
},
{
.name = "LED2_BTN",
.gpio = PAD_GPIO_B +30
},
{
.name = "LED3_BTN",
.gpio = PAD_GPIO_B +31
},
{
.name = "LED4_BTN",
.gpio = PAD_GPIO_B +9
}
};
struct led_src {
char *name;
int gpio ;
};
struct led_src led_info[] = {
{
.name = "LED1",
.gpio = PAD_GPIO_C +12,
},
{
.name = "LED2",
.gpio = PAD_GPIO_C +11,
},
{
.name = "LED3",
.gpio = PAD_GPIO_C +7,
},
{
.name = "LED4",
.gpio = PAD_GPIO_B +26,
},
};
struct led_src *g_led_irq;
unsigned long g_data = 255;
void tasklet_btn_led_func (unsigned long data){
printk("%s,%s状态为:%s,GPIO编号:%lu\n",__func__ , g_led_irq -> name ,\
gpio_get_value(g_led_irq->gpio) ? "关" : "开", \
g_data & g_led_irq -> gpio);
}
struct tasklet_struct tasklet_btn_led = {
.func = tasklet_btn_led_func,
.data = &g_data
};
static irqreturn_t irq_func(int irq,void * argv){
struct led_src *led_s = (struct led_src *) argv;
tasklet_schedule(&tasklet_btn_led);
gpio_set_value(led_s->gpio,(1 - gpio_get_value(led_s -> gpio)));
g_led_irq = argv;
return IRQ_HANDLED;
}
static int btn_led_init(void){
int i =0;
for(; i < ARRAY_SIZE(btn_info);i++){
gpio_request(btn_info[i].gpio,btn_info[i].name);
gpio_direction_input(btn_info[i].gpio);
request_irq(gpio_to_irq(btn_info[i].gpio),\
irq_func,IRQF_TRIGGER_LOW,
btn_info[i].name,&led_info[i]);
gpio_request(led_info[i].gpio,led_info[i].name);
gpio_direction_output(led_info[i].gpio,1);
}
return 0;
}
static void btn_led_exit(void){
int i = 0;
for(;i < ARRAY_SIZE(btn_info);i++){
free_irq(gpio_to_irq(btn_info[i].gpio),&led_info[i]);
gpio_free(btn_info[i].gpio);
gpio_set_value(led_info[i].gpio,1);
gpio_free(led_info[i].gpio);
}
}
module_init(btn_led_init);
module_exit(btn_led_exit);
MODULE_LICENSE("GPL");