正文

外部中断原理分析2008-02-26 12:53:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/niao0311/32947.html

分享到:

linux的外部中断分为固定部分和可变部分,固定部分为0~~15号的系统本身定义的中断,而可变部分则是提供给用户自己定义设备驱动的中断相应的,前两天稍微写了一点这方面的分析 外部中断可变部分描述: 以irq_desc[]数组描述 Irq_desc_t: typedef struct {        unsigned int status;        /* IRQ status */        hw_irq_controller *handler;        struct irqaction *action;  /* IRQ action list */        unsigned int depth;        /* nested irq disables */        spinlock_t lock; } ____cacheline_aligned irq_desc_t;     Irq状态是由以下各标志组合的: unsigned int status;        /* IRQ status */: #define IRQ_INPROGRESS 1     /* IRQ handler active - do not enter! */ #define IRQ_DISABLED      2     /* IRQ disabled - do not enter! */ #define IRQ_PENDING       4     /* IRQ pending - replay on enable */ #define IRQ_REPLAY   8     /* IRQ has been replayed but not acked yet */ #define IRQ_AUTODETECT       16    /* IRQ is being autodetected */ #define IRQ_WAITING 32    /* IRQ not yet seen - for autodetection */ #define IRQ_LEVEL     64    /* IRQ level triggered */ #define IRQ_MASKED 128  /* IRQ masked - shouldn't be seen again */ #define IRQ_PER_CPU 256  /* IRQ is per CPU */   struct irqaction *action;  /* IRQ action list */: 描述外部中断的可变部分,对一个外部中断的所有处理将以irqaction结构挂在action队列上 Interrupt.hàirqaction: struct irqaction {        void (*handler)(int, void *, struct pt_regs *);        unsigned long flags;        unsigned long mask;        const char *name;        void *dev_id;        struct irqaction *next; }; Handler中断处理函数,dev_id设备标识,用于标记多个设备共享同一个irq   时间中断处理程序为timer_interrupt   外部设备的驱动程序在初始化时都要创建自己的irqaction结构 Irq.càrequest_irq: int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),                unsigned long irq_flags, const char * devname, void *dev_id) {        unsigned long retval;        struct irqaction *action;          if (irq >= NR_IRQS || !irq_desc[irq].valid || !handler ||            (irq_flags & SA_SHIRQ && !dev_id))               return -EINVAL;          action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL);        if (!action)               return -ENOMEM;          action->handler = handler;        action->flags = irq_flags;        action->mask = 0;        action->name = devname;        action->next = NULL;        action->dev_id = dev_id;          retval = setup_arm_irq(irq, action);          if (retval)               kfree(action);        return retval; }   调用setup_arm_irq向内存申请一块内存填写irqaction结构,返回irq号 该函数完成以下工作: (1)       在数组irq_desc[]中找到程序申请的irq号对应的action队列 (2)       如果该队列不为空,说明该irq号被多个设备共享,检查这种共享是否允许(由老的irqaction结构的flags标识),如果合法,则将新的irqaction结构插到对应的action队列的末尾 (3)       如果队列为空,则将irqaction结构插在对应action队列的头部,填写irq_desc[irq]的其他域   至此外部设备驱动向系统注册中断完成   中断释放: void free_irq(unsigned int irq, void *dev_id) 完成以下工作: (1)       检查irq的合法性 (2)       在action队列irq_desc[irq].action上,查找action->dev_id == dev_id的irqaction结构 (3)       如果找到这样的结构,则将其从队列上摘下,同时释放其原本占用的内存空间 (4)       如果释放后,irq_desc[irq]上已经没有其他的irqaction结构,则释放irq_desc[irq]上的相应域,关掉中断

阅读(1959) | 评论(0)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

暂无评论
您需要登录后才能评论,请 登录 或者 注册