歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Unix知識 >> 關於Unix

外部中斷原理分析

linux 的外部中斷分為固定部分和可變部分,固定部分為0~~15號的系統本身定義的中斷,而可變部分則是提供給用戶自己定義設備驅動的中斷相應的,前兩天稍微寫了一點這方面的分析 MI LY: 宋體; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-famil       linux的外部中斷分為固定部分和可變部分,固定部分為0~~15號的系統本身定義的中斷,而可變部分則是提供給用戶自己定義設備驅動的中斷相應的,前兩天稍微寫了一點這方面的分析

MILY: 宋體; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">外部中斷可變部分描述:

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_idirqaction結構

(3)       如果找到這樣的結構,則將其從隊列上摘下,同時釋放其原本占用的內存空間

(4)       如果釋放後,irq_desc[irq]上已經沒有其他的irqaction結構,則釋放irq_desc[irq]上的相應域,關掉中斷

Copyright © Linux教程網 All Rights Reserved