Linux驱动开发-7、中断分层机制_工作队列

中断分层机制_工作队列

1.工作队列概念:

a) 任务推后执行

b) 被推后的任务由“内核线程”执行

c) 允许重新调度和睡眠

d) 这些被推后的工作组成一个双向链表,既称为工作队列

2.运行机制

 

注释:

1.每个CPU都有独立的工作队列

2.每个工作队列形成一个双向链表

3.执行时由内核的一个线程去处理,执行的时机不确定;只有在线程觉得CPU有能 力处理时才去去工作队列的内容去执行

 

3.工作队列的相关结构

 

struct work_struct {

atomic_long_t data; /*原子类型数据*/

struct list_head entry; /*链表入口*/

work_func_t func; /*工作函数*/

#ifdef CONFIG_LOCKDEP

struct lockdep_map lockdep_map;

#endif

};

 

struct workqueue_struct/*好多成员*/

 

4.工作队列实现过程和相关函数:

 

 Linux驱动开发-7、中断分层机制_工作队列_第1张图片

法一:交给内核创建默认工作队列

a) 定义工作队列

struct work_struct xx_wq;

 

b) 定义工作函数

static work_func_t  work_fun(unsingend int xxx)

 

c) 初始化工作队列,将工作队列与处理函数绑定

INIT_WORK(&xx_wq, work_fun);

 

d) 提交工作到默认队列;既工作的创建由内核自行处理

schedule_work(&xx_wq);

 

法二:手工创建工作队列

e) 定义工作队列

struct work_struct  work; /*定义工作*/

workqueue_struct* wq; /*定义的队列*/

 

f) 定义工作函数

static work_func_t  work_fun(unsingend int xxx)

 

g) 创建名字为 “mywork” 的工作队列

wq = create_workqueue(“mywork”);

 

h) 初始化工作队列

INIT_WORK(&xx_wq, work_fun);

 

i) 提交工作队列

int queue_work(wq, $work);

 

 

5.工作队列在中断分层技术的应用

 

/*1.定义结构体*/

struct work_struct xx_wq;

 

/*2.编写底半部函数,既工作函数*/

void xxx_do_work(unsigned long x)

{

...

}

/*4.中断处理顶半部*/

static irqreturn_t xxx_interrupt(int irq, void *dev_id)

{

...

/*提交工作 并启动调度*/

schedule_work(&xx_wq);

...

}

/*5.模块加载*/

module_init(xxxx)

{

  .....

/*申请中断*/

 

/*初始化工作队列,将工作队列与处理函数绑定,这个可以在open 函数初始化*/

INIT_WORK(&xx_wq,xxx_do_work);

 

       ......

}

/*6.模块卸载*/

module_exit(yyyy)

{

/*释放中断*/

}

 

 

工作队列模块测试

/******************************************

author : hntea

date: 2016/3/14

function : key interrupt  work  test

******************************************/

 

#include<linux/module.h>

#include<linux/init.h>

#include<linux/miscdevice.h>

#include<linux/fs.h>

#include<linux/types.h>

#include<linux/io.h>

#include<linux/interrupt.h>

 

#define DEV_MINIR 11 /*自己随便取咯*/

#define DEV_NAME "key" /*自己随便取咯,该设备名会在 /dev目录下生成相应的设备文件*/

 

#define KEY_GPH0CON  0xE0200C00 /*key_1 /key_2 EXIT0/1*/

/*定义 work */

struct work_struct work1;

 

/******************************************

函数名: key_hardinit

函数功能:硬件初始化

******************************************/

void key_hardinit(void)

{

unsigned int *key_ioconfig = 0;

unsigned int *irq_mask = 0;

unsigned int *irq_enable = 0;

unsigned int temdata = 0;

/*GPIO初始化 32位寄存器*/

key_ioconfig = ioremap(KEY_GPH0CON,4);  /*按键12设置成外部中断*/

temdata = ioread32(key_ioconfig);

temdata &= (~0xff);

temdata |= 0xff;

iowrite32(temdata,key_ioconfig);

/*中断控制初始化*/

 

}

 

 

/******************************************

中断底半部用工作队列实现

******************************************/

 

/*定义服务函数,任务提交后只执行一次*/

static void my_work1(struct work_struct *work)

{

printk("I am work1\n");

printk("I am work1,extern interrupt rase!\n");

}

 

/******************************************

函数名: key_interrupt

函数功能:中断服务函数入口

******************************************/

static irqreturn_t key_interrupt (int irq, void *dev_id)

{

  /*1、顶部,硬件操作*/

  

  /*2、底部,交个工作队列来处理*/

schedule_work(&work1);

    return 0;

}

 

/******************************************

函数名: key_open

函数功能:文件操作

******************************************/

int  key_open(struct inode *inode, struct file *filp)

{

key_hardinit();

return 0;

}

 

/******************************************

函数名:

函数功能:文件操作

******************************************/

 

struct file_operations key_fop =

{

.open = key_open,

};

 

struct miscdevice key=

{

.minor = DEV_MINIR ,

.name = DEV_NAME,

.fops = &key_fop,

};

 

static int keyInit(void)

{

int ret = 0;

/*1、注册设备文件*/

ret = misc_register(&key);

/*2、注册中断号,IRQF_TRIGGER_FALLING中断号在

: linux/arch/arm/mach-s5pv210/include/mach/irqs.h文件中有定义*/

 

ret = request_irq(IRQ_EINT0,key_interrupt,IRQF_TRIGGER_FALLING, DEV_NAME, 0);

/*3.初始化工作*/

INIT_WORK(&work1,my_work1);

 

printk("ret val is:%d\n",ret);

if(ret < 0)

{

printk("EXINT0 request fail!\n");

}else{

printk("EXINT0 request sucess!\n");

}

return 0;

}

static void keyExit(void)

{

int ret = 0;

/*注销中断*/

free_irq(IRQ_EINT0, 0);

/*注销混杂设备*/

ret = misc_deregister(&key);

/*注销设备*/

}

 

MODULE_LICENSE("GPL");

MODULE_AUTHOR("Hntea");

 

module_init(keyInit);

module_exit(keyExit);

你可能感兴趣的:(linux,嵌入式,内核,TQ210,Linux驱动开发)