ARM Technical Support Knowledge Articles

NESTING INTERRUPTS

Applies to: CARM 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.

In this context I have the following questions:

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 Advanced RTX), 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 as described below:

You may nest interrupts by using the macros IENABLE and IDISABLE at beginning and end of an interrupt service routine.

#define IENABLE                      /* Nested Interrupts Entry */    
  __asm { MRS     LR, SPSR      }    /* Copy SPSR_irq to LR     */    
  __asm { STMFD   SP!, {LR}     }    /* Save SPSR_irq           */    
  __asm { MSR     CPSR_c, #0x1F }    /* Enable IRQ (Sys Mode)   */    
  __asm { STMFD   SP!, {LR}     }    /* Save LR                 */    
#define IDISABLE                      /* Nested Interrupts Exit */    
  __asm { LDMFD   SP!, {LR}     }     /* Restore LR              */    
  __asm { MSR     CPSR_c, #0x92 }     /* Disable IRQ (IRQ Mode)  */    
  __asm { LDMFD   SP!, {LR}     }     /* Restore SPSR_irq to LR  */    
  __asm { MSR     SPSR_cxsf, LR }     /* Copy LR to SPSR_irq     */    

The usage is as shown below:

void interrupt_srv (void) __irq {
  IENABLE;                            // allow nested interrupts
  ... // interrupt code
  IDISABLE;                           // disable interrupt nesting
}

Depending on interrupt controller, it might be required to clear the interrupt source and acknowledge the interrupt. So in reality an implementation might look like the following example:

/* External Interrupt 1 Service */
void eint1_srv (void) __irq {
  EXTINT      = 2;                    // Clear EINT1 interrupt flag
  IENABLE;                            // allow nested interrupts
  delay ();
  ++intrp_count;                      // increment interrupt count
  IDISABLE;                           // disable interrupt nesting
  VICVectAddr = 0;                    // Acknowledge Interrupt
}

MORE INFORMATION

SEE ALSO

Article last edited on: 2005-03-31 08:57:42

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