arm 驱动linux内核驱动之中断下半部编程
func)
2.4.2将工作加入队列并调度(在中断上半部中调度)
int schedule_work(struct work_struct * work)
只要两步骤就完成,也不需要刷新,也不要销毁,因为这个工作队列是系统管理的,我们不用管
2.5:原理梳理:在工作队列中,有专门的工作者线程来处理加入到工作对列中的任务。工作对列对应的工作者线程可能不止一个,每个处理器有且仅有一个工作队列 对应的工作者线程,在内核中有一个默认的工作队列events,对于单处理器只有一个对应的工作者线程
3, 定时器timer编程方式:(以上两个下半部处理都是内核在一个特定的时候进行调度,时间不定,而timer可以指定某个时间点执行)
3.1, jiffies,表示从系统启动到当前的时间值,一般做加法(+5HZ(5s),)
3.2, 定义并初始化 timer_list对象
struct timer_list {
struct list_head entry; // 链表
unsigned long expires; // 过期时间。也及时在什么时候执行处理方法
struct tvec_base *base;
void (*function)(unsigned long); // 处理方法
unsigned long data; // 处理方法可以传递的参数
int slack;
};
静态初始化:TIMER_INITIALIZER(_function, _expires, _data)
动态初始化:void init_timer(timer)
参数:为一个指针,需要传递一个struct timer_list对象的地址
该函数只是初始化了timer_list对象的部分成员,还有以下成员是需要编程的:
struct timer_list mytimer;
init_timer(&mytimer);
mytimer.expires = jiffies + 2HZ
mytimer.fuction = my_timer_func; // 自己去实现
mytimer.data = (unsigned long)99; // 可以传递参数
3.3, 激活timer,开始计时 (一般也是放在中断上半部完成)
void add_timer(&mytimer);
3.4 计时结束是,也就是要执行处理函数时,执行函数中要下一次计时的话,必须修改timer
mod_timer(&my_timer, jiffies + 2*HZ);
// 2s之后再来,相当于如下:
my_timer.expires = jiffies + 2*HZ; //重新设定时间,在两秒后再执行
add_timer(&my_timer); //再次激活定时器
3.5 定时器的销毁
int del_timer(struct timer_list *timer) // 该函数用来删除还没超时的定时器
timer定时器的中断上下半部代码
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include arm/param.h>
#include
#include
#define VIRTUAL_MAJOR 250
int major = VIRTUAL_MAJOR;
struct myirq_desc{
int irq_id;
char *irq_name;
int irq_code;
};
struct myirq_desc myirq_descs[3]= {
{S3C2410_GPF0, "s2", KEY_A},
{S3C2410_GPF2, "s3", KEY_K},
{S3C2410_GPG3, "s4", KEY_Z},
};
struct VirtualDisk{
struct class *mycdevclass;//在/sys/class创建类
struct class_device *mycdevclassdevice;//在/dev下创建设备
struct cdev mycdev;//给设备添加相关的fileoption
struct timer_list mytimer;
};
struct VirtualDisk *myvirtualdisk;
static struct file_operations mydev_fops = {
.owner = THIS_MODULE,
};
static void mytimer_func(unsigned long fundata){
printk("*******%s********\n", __FUNCTION__);
struct VirtualDisk *myvirtualdisk_fun = (struct VirtualDisk *)(fundata);
myvirtualdisk_fun->mytimer.expires =jiffies + 2 * HZ;
add_timer(&myvirtualdisk_fun->mytimer);
printk("timer func happened!\n");
}
static irqreturn_t myirq_handle(int irq, void *dev_id){
struct myirq_desc *myirq_descone = (struct myirq_desc *)dev_id;
printk("*******%s********\n", __FUNCTION__);
printk("irq = %d, irq_id = %d,irq_name = %s, irq_code = %c\n", irq, myirq_descone->irq_id, myirq_descone->irq_name, myirq_descone->irq_code);
mod_timer(&myvirtualdisk->mytimer, jiffies + 2*HZ);
return IRQ_RETVAL(IRQ_HANDLED);
}
static int __init cdevtest_init(void){
dev_t mydev = MKDEV(major, 0);
int ret;
int i = 0;
printk("*******%s********\n", __FUNCTION__);
if(major){//注册proc/devices
ret = register_chrdev_region(mydev, 1, "mynewdriver");
}else{
ret = alloc_chrdev_region(&mydev, 0, 1, "mynewdriver");
major = MAJOR(mydev);
}
if(ret < 0){
printk(KERN_ERR "register_chrdev_region failed!\n");
ret = -EINVAL;
return ret;
}
myvirtualdisk = kmalloc(sizeof(struct VirtualDisk), GFP_KERNEL);
if(!myvirtualdisk){
ret = -ENOMEM;
printk(KERN_ERR "kmalloc myvirtualdisk failed!\n");
goto release_chrdev;
}
myvirtualdisk->mycdevclass = class_create(THIS_MODULE, "mynewdriver");
if(IS_ERR(myvirtualdisk->mycdevclass)){
ret = PTR_ERR(myvirtualdisk->mycdevclass);
printk(KERN_ERR "class_create failed!\n");
goto release_mem_malloc;
arm驱动linux内核驱动中断下半部编 相关文章:
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)
