Keil Logo

ARMCC: MODIFY IRQ FLAG TO DISABLE/ENABLE INTERRUPTS


Information in this article applies to:

  • RealView C Compiler Version 3

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:

  • A SWI function itself already is an atomic function that cannot be interrupted. Instead of enabling/disabling interrupts, you may just implement an SWI function that executes the function which should be protected from an interrupt.
  • Instead of enabling/disabling the IRQ/FIQ flags, the microcontroller itself may have an enable/disable flag in the interrupt controller. You should check the user's manual of the microcontroller before you proceed.

The following modification to the SWI_Handler (provided in the folder ..\ARM\RV30\Examples\SWI) 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

ATTACHED FILES

Request the files attached to this knowledgebase article.

FORUM THREADS

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

Last Reviewed: Monday, January 15, 2007


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.