微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > ARM Linux中断机制之中断处理

ARM Linux中断机制之中断处理

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

0是作为堆栈的sp在使用的。

//它的值是指向中断前r0的值在堆栈中存放的位置。在寄存器结构体pt_regs在堆栈中的位置上面。

ldmiar0, {r1 - r3}

//S_PC即是pt_regs中的PC寄存器位置,让r0指向该位置。虽然S_PC还没有存入堆栈但它在堆栈中的位置存在
addr0, sp, #S_PC

movr4, #-1//在r4中放入一个无效值。

strr1, [sp]//r1中存放的是中断前r0的值,此时将该值存入堆栈,上面已解释过在堆栈中流出r0的位置的问题。

//此时r2-r4存放的是中断前的lr, spsr的值和无效之。

//此时将这些值存入pt_regs中寄存器在堆栈中对应的位置,即此时将中断前的lr, spsr的值和无效之

//存入寄存器结构体pt_regs的ARM_pc,ARM_cpsr,ARM_ORIG_r0中。
stmiar0, {r2 - r4}
stmdbr0, {sp, lr}^//stmdb是递减取值,将ARM_lr,ARM_sp存入lr,sp中。

alignment_trap r0

//宏zero_fp在文件arch/arm/kernel/entry-header.S中定义,清零fp。
zero_fp
.endm

上面的提到的struct pt_regs,在include/asm/ptrace.h中定义

struct pt_regs {
long uregs[18];
};

#define ARM_cpsruregs[16]
#define ARM_pcuregs[15]
#define ARM_lruregs[14]
#define ARM_spuregs[13]
#define ARM_ipuregs[12]
#define ARM_fpuregs[11]
#define ARM_r10uregs[10]
#define ARM_r9uregs[9]
#define ARM_r8uregs[8]
#define ARM_r7uregs[7]
#define ARM_r6uregs[6]
#define ARM_r5uregs[5]
#define ARM_r4uregs[4]
#define ARM_r3uregs[3]
#define ARM_r2uregs[2]
#define ARM_r1uregs[1]
#define ARM_r0uregs[0]
#define ARM_ORIG_r0uregs[17]

(2)

//宏macroget_thread_info在文件arch/arm/kernel/entry-header.S中定义。用来获取当前线程的地址。

/*

include/linux/sched.h中:

union thread_union {

struct thread_info thread_info; // 线程属性

unsigned long stack[THREAD_SIZE/sizeof(long)]; // 栈

};

由它定义的线程是8K字节对齐的, 并且在这8K的最低地址处存放的就是thread_info对象,即该栈拥有者线程的对象,而get_thread_info就是通过把sp低13位清0(8K边 界)来获取当前thread_info对象的地址。

THREAD_SIZE在文件arch/arm/include/asm/thread_info.h中定义:#define THREAD_SIZE8192

*/

.macroget_thread_info, rd
mov\rd, sp, lsr #13
mov\rd, \rd, lsl #13
.endm

(3)

//宏irq_handler文件arch/arm/kernel/entry-armv.S中定义:

.macroirq_handler

//宏get_irqnr_preamble是一个空操作,在文件 arch/arm/mach-s3c2410/include/mach/entry-macro.S中定义
get_irqnr_preamble r5, lr

//宏get_irqnr_and_base通过读取寄存器INTPND来获得中断号。在该宏中获取的一些参量将存于这些寄存器中r0, r6, r5, lr。

//宏get_irqnr_and_base定义在文件 arch/arm/mach-s3c2410/include/mach/entry-macro.S,这个宏后续讲到。
1:get_irqnr_and_base r0, r6, r5, lr
movner1, sp
@
@ routine called with r0 = irq number, r1 = struct pt_regs *
@
adrnelr, 1b

/*

// 通过上面的宏get_irqnr_and_base为调用asm_do_IRQ准备了参数中断号。

于是调用asm_do_IRQ来处理中断。函数asm_do_IRQ()是中断处理函数的C语言入口。此函数将在后续讨论。

函数asm_do_IRQ()在文件linux/arch/arm/kernel/irq.c中实现。

*/
bneasm_do_IRQ

#ifdef CONFIG_SMP
。。。。。。

#endif

.endm

get_irqnr_and_base是平台相关的,这个宏查询ISPR(IRQ挂起中断服务寄存器,当有需要处理的中断时,这个寄存器的相应位会置位,任意时刻,最多一个位会置位),计算出的中断号放在irqnr指定的寄存器中;这个宏在不同的ARM芯片上是不一样的,这个宏主要作用在于就是获得发生中断的中断号,对于s3c2440,代码在arch/arm/mach-s3c2410/include/entry-macro.S里,该宏处理完后,r0 = 中断号。

.macroget_irqnr_and_base, irqnr, irqstat, base, tmp

mov\base, #S3C24XX_VA_IRQ

@@ try the interrupt offset register, since it is there

ldr\irqstat, [ \base, #INTPND ]
teq\irqstat, #0
beq1002f
ldr\irqnr, [ \base, #INTOFFSET ]
mov\tmp, #1
tst\irqstat, \tmp, lsl \irqnr
bne1001f

@@ the number specified is not a valid irq, so try
@@ and work it out for ourselves

mov\irqnr, #0@@ start here

@@ work out which irq (if any) we got

movs\tmp, \irqstat, lsl#16
addeq\irqnr, \irqnr, #16
moveq\irqstat, \irqstat, lsr#16
tst\irqstat, #0xff
addeq\irqnr, \irqnr, #8
moveq\irqstat, \irqstat, lsr#8
tst\irqstat, #0xf
addeq\irqnr, \irqnr, #4
moveq\irqstat, \irqstat, lsr#4
tst\irqstat, #0x3
addeq\irqnr, \irqnr, #2
moveq\irqstat, \irqstat, lsr#2
tst\irqstat, #0x1
addeq\irqnr, \irqnr, #1

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

网站地图

Top