Keil™, An ARM® Company

CARM User's Guide

Discontinued

__irq: Interrupt

The CARM Compiler supports C interrupt functions and eliminates the need to write interrupt service routines in assembly language. Interrupt functions are defined using the __irq function attribute.

void funcname (void) __irq

Where:

funcnameis the name of the function.
__irqindicates the function is an interrupt function.

The __irq attribute affects the generated code of the function as follows:

  • The function is generated using ARM instructions even if the THUMB directive is specified.
  • On function entry, the registers R0-R12 (when modified) are saved on the stack.
  • When exiting the function, all register contents saved on the stack are restored.
  • The SUBS PC,R14,#4 instruction is used to return from the __irq function.

For ARM devices without a Vectored Interrupt Controller (VIC), when an interrupt is triggered, the ARM device jumps to the __irq vector location. On such devices, only one __irq function is possible. By default, the CPU startup code (STARTUP.S) jumps to the function named IRQ_Handler. So, if you name your __irq function IRQ_Handler, no changes to the STARTUP.S file are required.

For ARM devices with a Vectored Interrupt Controller (VIC), when an interrupt is triggered, the address of the __irq function is written into the interrupt vector register of the VIC. On such devices, seperate __irq functions for each interrupt source may be created.

The following example shows how to use the __irq attribute without a VIC. The code sequences generated are shown in the Assembler Listing.

stmt  level    source

   1          /*
   2           *  IRQ Handler for ADuC7000 Timer0 Interrupt
   3           */
   4
   5          #include <ADuC7024.H>
   6
   7          volatile int T0_ticks;
   8
   9          void IRQ_Handler (void)  __irq  {
  10   1        if (IRQSIG & 0x00000004)  {   // Timer0 Interrupt
  11   2          T0CLRI = 1;
  12   2          T0_ticks++;
  13   2        }
  14   1      }

ASSEMBLY LISTING OF GENERATED OBJECT CODE

*** PUBLICS:
 PUBLIC         IRQ_Handler?A
 PUBLIC         T0_ticks



*** DATA SEGMENT '?DT0?irq':
 00000000          T0_ticks:
 00000000            DS          4



*** CODE SEGMENT '?PR?IRQ_Handler?A?irq':
    9: void IRQ_Handler (void)  __irq  {
 00000000  E92D0003  STMDB       R13!,{R0-R1}
   10:   if (IRQSIG & 0x00000004)  {   // Timer0 Interrupt
 00000004  E5100000  LDR         R0,=0xFFFF0004
 00000008  E5900000  LDR         R0,[R0,#0x0]
 0000000C  E3A01004  MOV         R1,#0x4
 00000010  E1100001  TST         R0,R1
 00000014  0A000006  BEQ         L_1  ; Targ=0x34
   11:     T0CLRI = 1;
 00000018  E3A01001  MOV         R1,#0x1
 0000001C  E5100000  LDR         R0,=0xFFFF030C
 00000020  E5801000  STR         R1,[R0,#0x0]
   12:     T0_ticks++;
 00000024  E5100000  LDR         R0,=T0_ticks ; T0_ticks
 00000028  E5901000  LDR         R1,[R0,#0x0] ; T0_ticks
 0000002C  E2811001  ADD         R1,R1,#0x0001
 00000030  E5801000  STR         R1,[R0,#0x0] ; T0_ticks
   13:   }
 00000034          L_1:
 00000034  E8BD0003  LDMIA       R13!,{R0-R1}
 00000038  E25EF004  SUBS        R15,R14,#0x0004
 0000003C          ENDP ; 'IRQ_Handler?A'

Note

  • The __irq attribute is required when declaring or prototyping external functions. For example:
    extern void func (void) __irq;
    
  • Passing parameters to an interrupt function is not possible. Any attempt to define an interrupt function with arguments generates an error message.
  • Interrupt function declarations may not include a return value. They must be declared with a void return type. The compiler generates an error message if the return type is not void.
  • The CARM run-time library contains a default IRQ_Handler that generates an endless loop using the B $ instruction.