歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Unix知識 >> 關於Unix >> 外部中斷原理分析

外部中斷原理分析

日期:2017/3/6 15:18:26   编辑:關於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