微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > arm linux 下中断流程简要分析初始化

arm linux 下中断流程简要分析初始化

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

esc = irq_esc + irq;/*获取保存该中断的中断描述符*/

spin_lock_irqsave(&desc->lock, flags);

irq_chip_set_defaults(chip); /*为chip设置一些默认的enable,disable函数*/

desc->chip = chip;/*为中断保存chip对象*/

/*

* For compatibility only:

*/

desc->chip = chip;

spin_unlock_irqrestore(&desc->lock, flags);

return 0;

}

为特定中断号初始化好chip对象,表示该中断号由这个chip控制,后面会调用到该中断号所属chip的相关函数,各个中断的chip是不同的,以IRQ_WDT为例,它的chip是s3c_irq_chip。

arch/arm/mach-s3c2410/Irq.c:

static struct irqchip s3c_irq_chip = {

.ack= s3c_irq_ack,

.mask= s3c_irq_mask,

.unmask= s3c_irq_unmask,

.set_wake= s3c_irq_wake

};

在看irq_chip_set_defaults

kernel/irq/Chip.c:

/*

* Fixup enable/disable function pointers

*/

void irq_chip_set_defaults(struct irq_chip *chip)

{

if (!chip->enable)

chip->enable = default_enable;

if (!chip->disable)

chip->disable = default_disable;

if (!chip->startup)

chip->startup = default_startup;

if (!chip->shutdown)

chip->shutdown = chip->disable;

if (!chip->name)

chip->name = chip->typename;

}

很显然,如果chip没有相应的操作函数,则就给chip赋默认的操作函数。

我们接着看set_irq_handler()

include/linux/Irq.h:

static inline void

set_irq_handler(unsigned int irq,

void fastcall (*handle)(unsigned int, struct irq_desc *,

struct pt_regs *))

{

__set_irq_handler(irq, handle, 0);

}

kernel/irq/Chip.c:

void

__set_irq_handler(unsigned int irq,

void fastcall (*handle)(unsigned int, irq_desc_t *,

struct pt_regs *),

int is_chained)

{

struct irq_desc *desc;

unsigned long flags;

if (irq >= NR_IRQS) { /*参数检查*/

printk(KERN_ERR

"Trying to install type control for IRQ%d/n", irq);

return;

}

desc = irq_desc + irq; /*获取中断描述符的存储地址*/

if (!handle)

handle = handle_bad_irq;/*赋默认的中断handle*/

if (desc->chip == &no_irq_chip) {

printk(KERN_WARNING "Trying to install %sinterrupt handler "

"for IRQ%d/n", is_chained ? "chained " : " ", irq);

/*

* Some ARM implementations install a handler for really dumb

* interrupt hardware without setting an irq_chip. This worked

* with the ARM no_irq_chip but the check in setup_irq would

* prevent us to setup the interrupt at all. Switch it to

* dummy_irq_chip for easy transition.

*/

desc->chip = &dummy_irq_chip;/*赋默认的chip*/

}

spin_lock_irqsave(&desc->lock, flags);

/* Uninstall? */

if (handle == handle_bad_irq) {

if (desc->chip != &no_irq_chip) {

desc->chip->mask(irq);

desc->chip->ack(irq);

}

desc->status |= IRQ_DISABLED;/*没有中断例程则disable掉该中断*/

desc->depth = 1;

}

desc->handle_irq = handle;/*保存中断例程,对于IRQ_WDT来说则是do_edge_IRQ */

/*由上面的调用可知,is_chained始终等于0*/

if (handle != handle_bad_irq && is_chained) {

desc->status &= ~IRQ_DISABLED;

desc->status |= IRQ_NOREQUEST | IRQ_NOPROBE;

desc->depth = 0;

desc->chip->unmask(irq);

}

spin_unlock_irqrestore(&desc->lock, flags);

}

上面这个函数就是为特定的中断设置好一个中断处理例程(这里的例程可不是我们request_irq注册的例程喔)。

接着看set_irq_flags()

arch/arm/kernel/Irq.c:

void set_irq_flags(unsigned int irq, unsigned int iflags)

{

struct irqdesc *desc;

unsigned long flags;

if (irq >= NR_IRQS) {

printk(KERN_ERR "Trying to set irq flags for IRQ%d/n", irq);

return;

}

desc = irq_desc + irq;

spin_lock_irqsave(&desc->lock, flags);

desc->status |= IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;

if (iflags & IRQF_VALID)

desc->status &= ~IRQ_NOREQUEST;/*清掉IRQ_NOREQUEST标记*/

if (iflags & IRQF_PROBE)

desc->status &= ~IRQ_NOPROBE;

if (!(iflags & IRQF_NOAUTOEN))

desc->status &= ~IRQ_NOAUTOEN;

spin_unlock_irqrestore(&desc->lock, flags);

}

该函数主要是为特定的中断设置相应的状态标记, 而这里我们调用它的目的就是清掉IRQ_NOREQUEST标记,告诉系统该中断已经可以被申请使用了,中断在申请的时候会查看是否有IRQ_NOREQUEST标记,如有则表面该中断还不能使用。而初始化的时候

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

网站地图

Top