linux2.6.26内核中ARM中断实现详解
adds \irqnr, \irqnr, #IRQ_EINT0 @加上中断号的基准数值,得到最终的中断号,注意:此时没有考虑子中断的具体情况,(子中断的问题后面会有讲解)。IRQ_EINT0在 include/asm/arch-s3c2410/irqs.h中定义.从这里可以看出,中断号的具体值是有平台相关的代码决定的,和硬件中断挂起寄存器中的中断号是不等的。
1002:
@@ exit here, Z flag unset if IRQ
.endm
3.6 asm_do_IRQ实现过程,arch/arm/kernel/irq.c
asmlinkage void __exception asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
{
struct pt_regs *old_regs = set_irq_regs(regs);
struct irq_desc *desc = irq_desc + irq;//根据中断号找到对应的irq_desc
/*
* Some hardware gives randomly wrong interrupts. Rather
* than crashing, do something sensible.
*/
if (irq >= NR_IRQS)
desc = &bad_irq_desc;
irq_enter();//没做什么特别的工作,可以跳过不看
desc_handle_irq(irq, desc);// 根据中断号和desc进入中断处理
/* AT91 specific workaround */
irq_finish(irq);
irq_exit();
set_irq_regs(old_regs);
}
static inline void desc_handle_irq(unsigned int irq, struct irq_desc *desc)
{
desc->handle_irq(irq, desc);//中断处理
}
上述asmlinkage void __exception asm_do_IRQ(unsigned int irq, struct pt_regs *regs)使用了asmlinkage标识。那么这个标识的含义如何理解呢?
该符号定义在kernel/include/linux/linkage.h中,如下所示:
#include //各个具体处理器在此文件中定义asmlinkage
#ifdef __cplusplus
#define CPP_ASMLINKAGE extern "C"
#else
#define CPP_ASMLINKAGE
#endif
#ifndef asmlinkage//如果以前没有定义asmlinkage
#define asmlinkage CPP_ASMLINKAGE
#endif
对于ARM处理器的,没有定义asmlinkage,所以没有意义(不要以为参数是从堆栈传递的,对于ARM平台来说还是符合ATPCS过程调用标准,通过寄存器传递的)。
但对于X86处理器的中是这样定义的:
#define asmlinkage CPP_ASMLINKAGE __attribute__((regparm(0)))
表示函数的参数传递是通过堆栈完成的。
3.7 描述3.3节中的ret_to_user 中断返回过程,/arch/arm/kernel/entry-common.S
ENTRY(ret_to_user)
ret_slow_syscall:
disable_irq @ disable interrupts
ldr r1, [tsk, #TI_FLAGS]
tst r1, #_TIF_WORK_MASK
bne work_pending
no_work_pending:
/* perform architecture specific actions before user return */
arch_ret_to_user r1, lr
@ slow_restore_user_regs
ldr r1, [sp, #S_PSR] @ get calling cpsr
ldr lr, [sp, #S_PC]! @ get pc
msr spsr_cxsf, r1 @ save in spsr_svc
ldmdb sp, {r0 - lr}^ @ get calling r0 - lr
mov r0, r0
add sp, sp, #S_FRAME_SIZE - S_PC
movs pc, lr @ return & move spsr_svc into cpsr
第三章主要跟踪了从中断发生到调用到对应中断号的desc->handle_irq(irq, desc)中断函数的过程。后面的章节还会继续讲解后面的内容。
linux-2.6.26内核中ARM中断实现详解(3)
作者:刘洪涛,华清远见嵌入式学院金牌讲师。
四、中断处理模型
要想弄清楚desc->handle_irq(irq, desc)和我们注册的中断有什么关联,就要了解中断处理模型了。
4.1 中断处理模型结构
中断处理模型如下图所示,
其中NR_IRQS表示最大的中断号,在include/asm/arch/irq.h中定义。
irq_desc[]是一个指向irq_desc_t结构的数组, irq_desc_t结构是各个设备中断服务例程的描述符。Irq_desc_t结构体中的成员action指向该中断号对应的irqaction结构体链表。Irqaction结构体定义在include/linux/interrupt.h中,如下:
truct irqaction {
irq_handler_t handler; //中断处理函数,注册时提供
unsigned long flags; //中断标志,注册时提供
cpumask_t mask; //中断掩码
const char *name; //中断名称
void *dev_id; //设备id,本文后面部分介绍中断共享时会详细说明这个参数的作用
struct irqaction *next; //如果有中断共享,则继续执行,
int irq; //中断号,注册时提供
struct proc_dir_entry *dir; //指向IRQn相关的/proc/irq/n目录的描述符
};
在注册中断号为irq的中断服务程序时,系统会根据注册参数封装相应的irqaction结构体。并把中断号为irq的irqaction结构体写入 irq_desc [irq]->action。这样就把设备的中断请求号与该设备的中断服务例程irqaction联系在一起了。样当CPU接收到中断请求后,就可以根据中断号通过irq_desc []找到该设备的中断服务程序。
4.2 中断共享的处理模型
共享中断的不同设备
linux2 6 26内核ARM中断实 相关文章:
- Linux2.6.36移植到飞凌S3C6410开发板 步骤(11-23)
- Linux2.6.22内核移植(11-21)
- 基于3c2410的linux2.6.22移植(3)(11-20)
- 基于3c2410的linux2.6.22移植(2)(11-20)
- 基于3c2410的linux2.6.22移植(6)(11-20)
- 基于3c2410的linux2.6.22移植(5)(11-20)