Keil Logo

ARMCC: NESTING INTERRUPTS


Information in this article applies to:

  • RealView Compiler Version 3.0 or higher

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:

  • The example above shows interrupt nesting with the NXP LPC2000 devices. It is important that you move the interrupt acknowledge sequence VICVectAddr = 0; to the assembly wrapper. Other ARM devices may require a different interrupt acknowledge sequence. Therefore consult the user's manual of the ARM device that you are using.

MORE INFORMATION

SEE ALSO

FORUM THREADS

The following Discussion Forum threads may provide information related to this topic.

Last Reviewed: Tuesday, March 23, 2010


Did this article provide the answer you needed?
 
Yes
No
Not Sure
 
  Arm logo
Important information

This site uses cookies to store information on your computer. By continuing to use our site, you consent to our cookies.

Change Settings

Privacy Policy Update

Arm’s Privacy Policy has been updated. By continuing to use our site, you consent to Arm’s Privacy Policy. Please review our Privacy Policy to learn more about our collection, use and transfers
of your data.