ARM Technical Support Knowledge Articles

NESTING INTERRUPTS

Applies to: RealView C Compiler

Answer


Information in this article applies to:


QUESTION

The classic ARM architecture only provides two interrupts (IRQ and FIQ). The Vectored Interrupt Controller or Advanced Interrupt Controller provides interrupt priorities and interrupt nesting for the standard interrupt, but it requires that you set the I bit in the CPSR.

What is the best method to allow interrupt nesting with the RealView compiler?

ANSWER

It should be noted that good programming technique implies that you keep interrupt functions very short. When you are using short interrupt functions, interrupt nesting becomes unimportant. When you are using an Real-Time Operating System (such as the RTX Kernel), the stack usage of user tasks becomes unpredictable when you allow interrupt nesting.

However, if you still need interrupt nesting in your application, you may implement it using an assembly language wrapper function as described below:

Example:

Within the following __irq function you want to allow interrupt nesting:

void eint1_irq (void)  __irq  {   // C interrupt function
  EXTINT      = 2;                // Clear EINT1 interrupt flag
  delay ();                       // wait a long time
  ++intrp_count;                  // increment interrupt count
  VICVectAddr = 0;                // Acknowledge Interrupt
}

Change the interrupt function as shown below:

extern void eint1_irq (void);     // wrapper ASM interrupt function

void eint1_srv (void)  {          // C interrupt code
  EXTINT      = 2;                // Clear EINT1 interrupt flag
  delay ();                       // wait a long time
  ++intrp_count;                  // increment interrupt count
//VICVectAddr = 0;                // Acknowledge Interrupt
}

Add the following assembler wrapper (in a separate assembly module) to the interrupt function:

       PRESERVE8
       AREA    NEST_IRQ, CODE, READONLY
       ARM
       IMPORT  eint1_srv
       EXPORT  eint1_irq

eint1_irq

       PUSH    {R0-R3,R12,LR}          ; save register context
       MRS     LR, SPSR                ; Copy SPSR_irq to LR
       PUSH    {LR}                    ; Save SPSR_irq
       MSR     CPSR_c, #0x1F           ; Enable IRQ (Sys Mode)
       PUSH    {LR}                    ; Save LR

       BL      eint1_srv

       POP     {LR}                    ; Restore LR
       MSR     CPSR_c, #0x92           ; Disable IRQ (IRQ Mode)
       POP     {LR}                    ; Restore SPSR_irq to LR
       MSR     SPSR_cxsf, LR           ; Copy LR to SPSR_irq

;      VICVectAddr = 0;                ; Acknowledge Interrupt
       MOV     R0,#0
       STR     R0,[R0,#-0xFD0]

       POP     {R0-R3,R12,LR}          ; restore register context
       SUBS    R15,R14,#0x0004         ; return from interrupt


       END

Note:

MORE INFORMATION

SEE ALSO

ATTACHED FILES

Request the files attached to this knowledgebase article.

Article last edited on: 2010-03-23 09:15:02

Rate this article

[Bad]
|
|
[Good]
Disagree? Move your mouse over the bar and click

Did you find this article helpful? Yes No

How can we improve this article?

Link to this article
Copyright © 2011 ARM Limited. All rights reserved. External (Open), Non-Confidential