ARM Technical Support Knowledge Articles

MODIFY IRQ FLAG TO DISABLE/ENABLE INTERRUPTS

Applies to: RealView C Compiler

Answer


Information in this article applies to:


QUESTION

I would like to enable and disable interrupts in my application. However since the startup code puts the device into user mode, I cannot easily access the IRQ flag in the PSR register.

How can I modify the IRQ or FIQ flag to enable/disable interrupts?

ANSWER

When the device runs in user mode, accessing of the IRQ/FIQ flags in the PSR register is only possible when you execute a SWI function. The SWI instruction puts the device into the Supervisor mode that allows to access the PSR flags.

Before you investigate further you should consider:

The following modification to the SWI_Handler (provided in the folder ..ARMRV30ExamplesSWI) allows to set/clear the IRQ flag for global interrupt enable/disable.

SWI_Handler
                 :
                 :
                BICEQ   R12, R12, #0xFF000000  ; Extract SWI Number

; add code to enable/disable the global IRQ flag
                CMP     R12,#0xFE         ; disable IRQ implemented as __SWI 0xFE
                BEQ     disable_IRQ
                CMP     R12,#0xFF         ; enable IRQ implemented as __SWI 0xFF
                BEQ     enable_IRQ

                LDR     R8, SWI_Count
                 :
                 :
SWI_End

disable_IRQ
                LDMFD   SP!, {R8, R12}    ; Load R8, SPSR
                ORR     R12, R12, #0x80   ; Set IRQ flag to disable it
                MSR     SPSR_cxsf, R12    ; Set SPSR
                LDMFD   SP!, {R12, PC}^   ; Restore R12 and Return

enable_IRQ
                LDMFD   SP!, {R8, R12}    ; Load R8, SPSR
                BIC     R12, R12, #0x80   ; Set IRQ flag to disable it
                MSR     SPSR_cxsf, R12    ; Set SPSR
                LDMFD   SP!, {R12, PC}^   ; Restore R12 and Return

                END

From C source code you may use these functions in either CPU mode (ARM or Thumb) as shown below:

// function prototypes:
void __swi(0xFE) disable_isr (void);
void __swi(0xFF) enable_isr (void);

/*
 * Sample 'main' Function
 */

void main (void) {

  func_a();       // func_a executes with standard interrupt setting
  disable_isr (); // disable interrupts for the following function 
  func_b();       // func_b executes with disable interrupts
  enable_isr ();  // interrupts are now enabled again

}

For a complete example project showing this, download the attached files to this knowledge base article.

SEE ALSO

MORE INFORMATION

Article last edited on: 2007-01-15 11:50:17

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