免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 669 | 回复: 0
打印 上一主题 下一主题

Linux 中断学习笔记(五) [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-04-25 13:44 |只看该作者 |倒序浏览
编写自己的中断
申请和释放中断:
注册一个中断:request_irq()函数用来注册一个中断处理程序,这样做是因为真正的中断服务要等到具体设备的初始化程序将其中断服务程序通过该函数向系统注册后,并挂入某个中断请求队列中以后才可以真正的运行。源码如下:
               
               
               
536int request_irq(unsigned int irq, irq_handler_t handler,
537          unsigned long irqflags, const char *devname, void *dev_id)
538{
539        struct irqaction *action;/*创建一个此结构,并将其加入到相应irq号的struct irqaction队列中*/
540        int retval;/*返回值*/
541
//.....省略
554        if ((irqflags & IRQF_SHARED) && !dev_id)
555                return -EINVAL;
556        if (irq >= NR_IRQS)
557                return -EINVAL;
558        if (irq_desc[irq].status & IRQ_NOREQUEST)
559                return -EINVAL;
560        if (!handler)
561                return -EINVAL;
562
563        action = kmalloc(sizeof(struct irqaction), GFP_ATOMIC);
564        if (!action)
565                return -ENOMEM;
566
567        action->handler = handler;
568        action->flags = irqflags;
569        cpus_clear(action->mask);
570        action->name = devname;
571        action->next = NULL;
572        action->dev_id = dev_id;
573
574        select_smp_affinity(irq);
575
576#ifdef CONFIG_DEBUG_SHIRQ
577        if (irqflags & IRQF_SHARED) {
//....
584                unsigned long flags;
585
586                local_irq_save(flags);
587                handler(irq, dev_id);
588                local_irq_restore(flags);
589        }
590#endif
591
592        retval = setup_irq(irq, action);
593        if (retval)
594                kfree(action);
595
596        return retval;
597}
函数参数:
unsigned int irq:中断号,有些设备是预先指定的,大多数是自动检测获取或者动态确定。
handler:指向中断处理程序的指针,当相应的中断发生时,内核便会调用handler所指向处理程序。
irqflags:可以是0,或者是SA_INTERRUPT,SA_SAMPLE_RANDOM,SA_SHIRQ。
dev_name:产生中断的硬件的名字。
dev_id:该标志在共享中断号时用。
注意:使用此函数可能会睡眠,所以不能在中断上下文中用。
该函数相当于c++中的构造函数,成功返回0,否则返回非0。
前5个if语句是错误判断,作用依次为:
1 使用共享中断但没有提供dev_id则返回错误
2 中断号超出最大值
3 该中断号已被使用并且未共享
4 handler为空
5 未申请到内存
紧接着从566行开始根据函数传进来的相关参数初始化action结构,然后在调用setup_irq()注册该中断的irqaction结构体到irqactiona队列中。
释放void free()函数,原形:
void free_irq(unsigned int irq,void *dev_id);
释放时分两种情况:非共享时,将会在释放掉该处理程序的同时禁用该中断线。共享时,该函数将只会删除该中断线上由参数dev_id指定的那个中断处理程序。
注意:该函数应在进程上下文中调用。
当注册中断服务程序时,handler参数就是所要注册的中断服务程序,那么这个函数就是要自己编写的,定义如下:
static irqreturn_t my_handler(int irq,void *dev_id);
之所以将其定义为static是因为中断处理程序不会被其他文件中的代码直接调用。
然后再看返回值irqreturn_t,其实他就是int型,这样做为了和以前的版本兼容。
参数irq:中断线号,在没有dev_id之前,这个标志位很有用,现在只会在打印日志时用到他。
dev_id:设备唯一标识符,区分共享同一个中断处理程序的多个设备。
函数会返回两个值来通知用户是否真正处理了一个中断。分别是:
IRQ_NONE:当中断处理程序检测到一个中断后,发现该中断处理程序对应的设备并不是用request_irq()函数注册期间指定的那个设备时,则返回此值。
IRQ_HANDLER:当中断处理程序被正确调用,并且他检测到调用他的正是他所对应的那个设备时,则返回此值。
下面是一个例子:
#include linux/module.h>
#include linux/init.h>
#include linux/interrupt.h>
static int irq;
static char *interface;
module_param(interface,charp,0644); //2.6内核中的宏,表示这个参数要在插入模块时给出值
module_param(irq,int,0644);
int dev_id = 127;//设备id
static irqreturn_t myinterrupt(int irq, void *dev_id)//中断服务程序,自己所写
{
        static int count = 0;
        if (count  10) {
                printk("Interrupt %d, %d\n", irq, *(int *)dev_id);
                count++;
        }
        return IRQ_NONE;
}
static int __init myirqtest_init(void)
{
        printk ("My module worked!\n");
        if (request_irq(irq, &myinterrupt, IRQF_SHARED,interface, &dev_id)) {//注册中断,参数意义前面有讲
                printk(KERN_ERR "myirqtest: cannot register IRQ %d\n", irq);
                return -EIO;
        }
        printk("%s  Request on IRQ %d succeede dev_id is:%d\n",interface, irq, dev_id);
    return 0;
}
static void __exit myirqtest_exit(void)
{
    printk ("Unloading my module.\n");
    free_irq(irq, &irq);
    printk("Freeing IRQ %d\n", irq);
}
module_init(myirqtest_init);
module_exit(myirqtest_exit);
MODULE_LICENSE("GPL");
上面的例子牵扯到模块编程,可以参考这里:
http://www.kerneltravel.net/?page_id=8


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u2/74234/showart_1910550.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP