您的位置:首页 > 编程语言

ARM体系结构与编程学习(十三)

2011-05-01 18:55 393 查看
9.5 FIQ与IRQ异常中断处理程序

arm提供的FIQ与IRQ用于外部设备向CPU请求中断。

9.5.1 不可重入的IRQ/FIQ异常中断处理程序

;使用关键词_irq

__irq void IRQHandler (void)
{
volatile unsigned int *base = (unsigned int *) 0x80000000;

if (*base == 1) // which interrupt was it?
{
C_int_handler(); // process the interrupt
}
*(base+1) = 0; // clear the interrupt
}

;对应的汇编程序

IRQHandler PROC
STMFD sp!,{r0-r4,r12,lr}
MOV r4,#0x80000000
LDR r0,[r4,#0]
SUB sp,sp,#4
CMP r0,#1
BLEQ C_int_handler
MOV r0,#0
STR r0,[r4,#4]
ADD sp,sp,#4
LDMFD sp!,{r0-r4,r12,lr}
SUBS pc,lr,#4
ENDP

;不使用关键词_irq

void IRQHandler (void)
{
volatile unsigned int *base = (unsigned int *) 0x80000000;

if (*base == 1) // which interrupt was it?
{
C_int_handler(); // process the interrupt
}
*(base+1) = 0; // clear the interrupt
}

;对应的汇编程序

IRQHandler PROC
STMFD sp!,{r4,lr}
MOV r4,#0x80000000
LDR r0,[r4,#0]
CMP r0,#1
BLEQ C_int_handler
MOV r0,#0
STR r0,[r4,#4]
LDMFD sp!,{r4,pc}
END

可重入的IRQ/FIQ异常中断处理程序

1、将返回地址保存到IRQ的数据栈中

2、保存工作寄存器和SPSR_irq

3、清除中断标志位

4、将处理器切换到系统模式,重新使能IRQ/FIQ中断

5、保存用户模式的LR寄存器和被调用程序不保存的寄存器

6、调用C语言的IRQ/FIQ异常中断处理程序返回,恢复用户模式的寄存器,并禁止IRQ/FIQ

7、切换到IRQ模式,禁止中断

8、恢复工作组寄存器和寄存器LR_irq

9、从IRQ异常中断处理程序中返回

PRESERVE8

AREA INTERRUPT, CODE, READONLY
IMPORT C_irq_handler
IRQ
SUB lr, lr, #4 ; construct the return address
STMFD sp!, {lr} ; and push the adjusted lr_IRQ
MRS r14, SPSR ; copy spsr_IRQ to r14
STMFD sp!, {r12, r14} ; save work regs and spsr_IRQ

; Add instructions to clear the interrupt here
; then re-enable interrupts.

MSR CPSR_c, #0x1F ; switch to SYS mode, FIQ and IRQ
; enabled. USR mode registers
; are now current.
STMFD sp!, {r0-r3, lr} ; save lr_USR and non-callee
; saved registers
BL C_irq_handler ; branch to C IRQ handler.
LDMFD sp!, {r0-r3, lr} ; restore registers
MSR CPSR_c, #0x92 ; switch to IRQ mode and disable
; IRQs. FIQ is still enabled.

LDMFD sp!, {r12, r14} ; restore work regs and spsr_IRQ
MSR SPSR_cf, r14
LDMFD sp!, {pc}^ ; return from IRQ.
END

9.5.2 IRQ异常中断处理程序例程

;保存返回地址

SUB LR,LR #4

STMFD SP!,{LR}

;保存SPSR及工作组寄存器R12

MRS R14,SPSR

STMFD SP!,{R12,R14}

;读取中断控制器的基地址

MOV R12 , #IntBase

;读取优先级最高的中断源的优先级

LDR R12 ,[R12,#IntLevel]

;使能中断

MRS R14,CPSR

BIC R14,R14,#0X80

MSR CPSR_c ,R14

;跳转到优先级最高的中断对应的中断处理程序

LDR PC, [PC,R12,LSR #2]

;加入一条NOP指令,实现跳转表的地址计算方法

NOP

;中断处理程序地址表

;优先级为0的中断对应的中断处理程序地址

DCD Priority0Handler

;优先级为1的中断对应的中断处理程序地址

DCD Priority1Handler

;优先级为2的中断对应的中断处理程序地址

DCD Priority2Handler

;优先级为0的中断对应的中断处理程序

Priority0Handler

;保存工作寄存器

STMFD SP!,[R0-R11]

;这里为中断处理程序的程序体

;...

;恢复工作寄存器

LDMFD SP! ,{R0-R11}

;禁止中断

MRS R12,CPSR

ORR R12,R12

MSR CPSR_c, R12

;恢复SPSR和寄存器R12

LDMFD SP!, {R12,R14}

MSR SPSR_csxf, R14

;从优先级为0的中断程序返回

LDMFD SP!, {PC}^

;优先级为1的中断对应的中断处理程序地址

Priority1Handler

;...
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: