微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > arm 驱动linux内核驱动之中断下半部编程

arm 驱动linux内核驱动之中断下半部编程

时间:11-19 来源:互联网 点击:

static struct file_operations mydev_fops = {
.owner = THIS_MODULE,
};

static void mywork_func(struct work_struct *work){
printk("*******%s********\n", __FUNCTION__);
}
static void mytasklet_func(unsigned long fundata){
printk("*****%s******,date = %ld\n", __FUNCTION__, fundata);
}
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);
queue_work(myvirtualdisk->myworkqueue, &myvirtualdisk->mywork);
tasklet_schedule(&myvirtualdisk->mytasklet);//激发任务,将mytasklet_func加入系统任务
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;

}
myvirtualdisk->mycdevclassdevice = class_device_create(myvirtualdisk->mycdevclass, NULL, MKDEV(major, 0), NULL, "mynewdriver");
if(IS_ERR(myvirtualdisk->mycdevclassdevice)){
ret = PTR_ERR(myvirtualdisk->mycdevclassdevice);
printk(KERN_ERR "class_device_create failed!\n");
goto release_class_create;
}

//工作和工作队列
INIT_WORK(&myvirtualdisk->mywork, mywork_func);
myvirtualdisk->myworkqueue = create_workqueue("myworkqueue");
if (!myvirtualdisk->myworkqueue) {
ret = -ENOMEM;
goto release_class_create;
}

cdev_init(&(myvirtualdisk->mycdev), &mydev_fops);
myvirtualdisk->mycdev.owner = THIS_MODULE;
ret = cdev_add(&myvirtualdisk->mycdev, MKDEV(major, 0), 1);

//tasklet 任务调度
tasklet_init(&myvirtualdisk->mytasklet, mytasklet_func, (unsigned long) 90);

//这里把timer相关的放在irq前面,不然会有bug出现(当在insmod时候按下按钮就会出错)
init_timer(&myvirtualdisk->mytimer);
myvirtualdisk->mytimer.function = mytimer_func;
myvirtualdisk->mytimer.data = (unsigned long)myvirtualdisk;

if(ret < 0){
goto release_device_class_create;
}
for(i = 0; i < 3; i++)
{
ret = request_irq(gpio_to_irq(myirq_descs[i].irq_id), myirq_handle, IRQF_TRIGGER_FALLING, myirq_descs[i].irq_name, &myirq_descs[i]);
if(ret < 0){
printk(KERN_ERR "request irq failed!\n");
ret =-EFAULT;
goto release_cdevandtimer;
}
}

/*在模块注销的时候,销毁工作队列和工作对象
void flush_workqueue(struct workqueue_struct * wq)
该函数会一直等待,知道指定的等待队列中所有的任务都执行完毕并从等待队列中移除。
void destroy_workqueue(struct workqueue_struct * wq);
该函数是是创建等待队列的反操作,注销掉指定的等待队列。*/

return 0;
release_cdevandtimer:
tasklet_kill(&myvirtualdisk->mytasklet);//删除任务
del_timer(&myvirtualdisk->mytimer);
cdev_del(&myvirtualdisk->mycdev);
/*在模块注销的时候,销毁工作队列和工作对象
void flush_workqueue(struct workqueue_struct * wq)
该函数会一直等待,知道指定的等待队列中所有的任务都执行完毕并从等待队列中移除。
void destroy_workqueue(struct workqueue_struct * wq);
该函数是是创建等待队列的反操作,注销掉指定的等待队列。*/
flush_workqueue(myvirtualdisk->myworkqueue);
destroy_workqueue(myvirtualdisk->myworkqueue);
release_device_class_create:
class_device_unregister(myvirtualdisk->mycdevclassdevice);
release_class_create:
class_destroy(myvirtualdisk->mycdevclass);
release_mem_malloc:
kfree(myvirtualdisk);
release_chrdev:
unregister_chrdev_region(MKDEV(major, 0), 1);
return ret;
}

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top