费尽九牛二虎之力,终于在ADS下调正常了PXA270的中断, 得益于网上的 嵌入式开发要点,发觉英文文档的阅读能力真是至关重要,而且要养成好的工作习惯,比如,在用ADS开发程序时,完全应该把ADS开发手册看一遍的,正所谓磨刀不误砍柴工。基于此考虑,以后作工作的时候利用课余时间多多翻译一下相关权威资料,既练英文,又学技术,岂不美哉!
抽空,将ADS开发手册关于_irq的部分翻译一下。
5.5.1 Simple interrupt handlers in C
You can write simple C interrupt handlers by using the __irq function declaration
keyword. You can use the __irq keyword both for simple one-level interrupt handlers,
and interrupt handlers that call subroutines. However, you cannot use the __irq keyword
for reentrant interrupt handlers, because it does not cause the SPSR to be saved or
restored. In this context, reentrant means that the handler re-enables interrupts, and may
itself be interrupted. See Reentrant interrupt handlers on page 5-26 for more
information.
The __irq keyword:
• preserves all ATPCS corruptible registers
• preserves all other registers (excluding the floating-point registers) used by the
function
• exits the function by setting the program counter to (lr – 4) and restoring the
CPSR to its original value.
If the function calls a subroutine, __irq preserves the link register for the interrupt mode
in addition to preserving the other corruptible registers. See Calling subroutines from
interrupt handlers for more information.
Note
C interrupt handlers cannot be produced in this way using tcc. The __irq keyword is
faulted by tcc because tcc can only produce Thumb code, and the processor is always
switched to ARM state when an interrupt, or any other exception, occurs.
However, the subroutine called by an __irq function can be compiled for Thumb, with
interworking enabled. See Chapter 3 Interworking ARM and Thumb for more
information on interworking.
Calling subroutines from interrupt handlers
If you call subroutines from your top-level interrupt handler, the __irq keyword also
restores the value of lr_IRQ from the stack so that it can be used by a SUBS instruction to
return to the correct address after the interrupt has been handled.
Example 5-13 on page 5-25 shows how this works. The top level interrupt handler reads
the value of a memory-mapped interrupt controller base address at 0x80000000. If the
value of the address is 1, the top-level handler branches to a handler written in C.
Handling Processor Exceptions
ARM DUI 0056D Copyright © 1999-2001 ARM Limited. All rights reserved. 5-25
Example 5-13
__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
}
Compiled with armcc, Example 5-13 produces the following code:
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
Compare this with the result when the __irq keyword is not used:
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}
ENDP