自学linux驱动从入门到放弃(十三)中断上下文

        在中断中,分为中断上文和下文(tasklet),在request_irq中注册的函数为中断函数,一般是中断上文,中断下文一般用于处理一些复杂耗时间的程序。

1.中断上下文

1.1 tasklet结构体

struct tasklet_struct
{
	struct tasklet_struct *next;
	unsigned long state;
	atomic_t count;
	void (*func)(unsigned long);
	unsigned long data;
};
成员 描述
*next tasklet链表中下一个tasklet
state

tasklet 的状态

TASKLET_STATE_SCHED        已经被调度,将要运行

TASKLET_STATE_RUN        正在运行

count tasklet的引用计数,如果它不为0,则tasklet被禁止,不允许执行;只有当它为0时,tasklet才被激活,并且在被设置为挂起(TASKLET_STATE_SCHED)状态时,该tasklet才能够被执行。
 
(*func)(unsigned long) tasklet的处理函数
data tasklet fun的参数

1.2 tasklet 初始化

void tasklet_init(struct tasklet_struct *t,void (*func)(unsigned long), 
                    unsigned long data);
参数 描述
*t tasklet结构体指针
(*func)(unsigned long) tasklet处理函数
data tasklet参数

 1.3 tasklet 调度

static inline void tasklet_schedule(struct tasklet_struct *t)

1.4 调用过程

        1)定义tasklet结构体

        2)初始化tasklet

        3)编写tasklet function

        4)调度tasklet

        5)注销tasklet

1.5 伪代码

struct tasklet_struct key_task;

void key_task_fun(unsigned long data)    //tasklet function
{
    printk("key tasklet fun is action!\n");
}

irqreturn_t key_fun(int irq,void *args)    //interrupt function
{
	printk(KERN_ERR "test fun is action!!\n");
    tasklet_schedule(&key_task);    //开始调度tasklet
	return IRQ_HANDLED;
}

int led_probe(struct platform_device *pdev){

    int ret;
	gpio_res = gpiod_get_index(&pdev->dev,"key",0,GPIOD_OUT_LOW);	//获取名为key的gpio属性

    ret = gpiod_direction_input(gpio_res);		//将引脚设置为输入
	
	irq = of_irq_get(pdev->dev.of_node, 0);    //通过设备树结点获取中断信息

	ret = request_irq(irq, key_fun, IRQF_TRIGGER_RISING, "key_interrupt", NULL);	//申请中断号
    tasklet_init(&key_task,key_task_fun, 0);    //初始化tasklet
	
    //注册设备号
    //创建class
    //生成设备节点	
	return 0;
}

static void charDev_exit(void)
{

    //释放gpio
    tasklet_kill(&key_task);    //注销tasklet
    //释放irq
    //注销设备节点
    //注销类
    //注销设备号
		
}

 

上一篇:数据类型


下一篇:【C语言进阶剖析】2.C语言中的有符号数和无符号数