Keil Logo

Interrupt Functions

The 251 and its derivatives provide a number of hardware interrupts that may be used for counting, timing, detecting external events, and sending and receiving data using the serial interface. The standard interrupts found on an 80C251SB are listed in the following table:

Interrupt
Number
Description Address
0 EXTERNAL INT 0 FF:0003h
1 TIMER/COUNTER 0 FF:000Bh
2 EXTERNAL INT 1 FF:0013h
3 TIMER/COUNTER 1 FF:001Bh
4 SERIAL PORT FF:0023h
5 TIMER/COUNTER 2 FF:002Bh
6 PROG. COUNTER ARRAY (PCA) FF:0033h

As 251 vendors create new parts, more interrupts are added. The C251 Compiler supports interrupt functions for 32 interrupts (0-31). Use the interrupt vector address in the following table to determine the interrupt number.

Interrupt
Number
Address
0 FF:0003h
1 FF:000Bh
2 FF:0013h
3 FF:001Bh
4 FF:0023h
5 FF:002Bh
6 FF:0033h
7 FF:003Bh
8 FF:0043h
9 FF:004Bh
10 FF:0053h
11 FF:005Bh
12 FF:0063h
13 FF:006Bh
14 FF:0073h
15 FF:007Bh
  
Interrupt
Number
Address
16 FF:0083h
17 FF:008Bh
18 FF:0093h
19 FF:009Bh
20 FF:00A3h
21 FF:00ABh
22 FF:00B3h
23 FF:00BBh
24 FF:00C3h
25 FF:00CBh
26 FF:00D3h
27 FF:00DBh
28 FF:00E3h
29 FF:00EBh
30 FF:00F3h
31 FF:00FBh

The interrupt function attribute specifies that the associated function is an interrupt service routine. For example:

unsigned int  interruptcnt;
unsigned char data second;

void timer0 (void) interrupt 1 using 2  {
  if (++interruptcnt == 4000)  {    /* count to 4000 */
    second++;                       /* second counter    */
    interruptcnt = 0;               /* clear int counter */
  }
}

The interrupt attribute takes as an argument an integer constant in the 0 to 31 value range. Expressions with operators and the interrupt attribute are not allowed in function prototypes. The interrupt attribute affects the object code of the function as follows:

  • When required, the contents of ACC, B, DPH, DPL, PSW, and PSW1 are saved on the stack at function invocation time.
  • All working registers used in the interrupt function are stored on the stack if a register bank is not specified with the using attribute.
  • The working registers and special registers that were saved on the stack are restored before exiting the function.
  • The function is terminated by the RETI instruction.

In addition, the C251 Compiler generates the interrupt vector automatically.

The following example program demonstrates how to use the interrupt attribute. The program shows you what the code generated to enter and exit the interrupt function looks like. The using function attribute is used to select a register bank different from that of the non-interrupt program code. However, because no working registers are needed in this function, the code generated to switch the register bank is eliminated by the optimizer.

stmt level  source

   1        extern bit alarm;
   2        int alarm_count;
   3
   4        void falarm (void) interrupt 1 using 3  {
   5   1      alarm_count *= 10;
   6   1      alarm = 1;
   7   1      }


ASSEMBLY LISTING OF GENERATED OBJECT CODE

      ; FUNCTION falarm (BEGIN)
                                             ; SOURCE LINE # 4
000000 75D118         MOV      PSW1,#018H
                                             ; SOURCE LINE # 5
000003 7E24000A       MOV      WR4,#0AH
000007 7E3500      R  MOV      WR6,alarm_count
00000A AD32           MUL      WR6,WR4
00000C 7A3500      R  MOV      alarm_count,WR6
                                             ; SOURCE LINE # 6
00000F D200        E  SETB     alarm
                                             ; SOURCE LINE # 7
000011 32             RETI
;       FUNCTION falarm (END)

In the example above, note that the PSW1 register is already saved by the 251 hardware interrupt. Note also the RETI instruction generated to exit the interrupt.

The following rules apply to interrupt functions.

  • Parameter passing is not possible. The compiler emits an error message when the interrupt procedure contains any parameter declarations.
  • Interrupt function declarations may not include a return value. They must be declared as void (see the above examples). The compiler emits an error message if any attempt is made to define a return value for the interrupt function. The return type void should be applied to all interrupt procedure declarations. The implicit int return value, however, is ignored by the compiler.
  • The compiler recognizes direct calls to interrupt functions and rejects them. An interrupt procedure is exited with the RETI instruction. RETI restores the PSW1 value and affects the interrupt system of the 251. Because no interrupt request on the part of the hardware existed, the effect of this instruction is indeterminate and usually fatal. Do not call an interrupt function indirectly through a function pointer.
  • The compiler generates an interrupt vector for each interrupt function. The code generated for the vector is a jump to the beginning of the interrupt function. Generation of interrupt vectors can be suppressed by using the C251 directive NOINTVECTOR in the C251 command line. In this case, you must provide interrupt vectors from separate assembly modules. Refer to the INTVECTOR and INTERVAL control directives for more information about the interrupt vector table.
  • The C251 Compiler allows interrupt numbers within the 0-31 range. Refer to your 251 derivative document to determine which interrupts are available.
  • Since most of the C251 library functions are fully reentrant, there is no restriction for calling any of these functions. C251 uses reentrant code in the stack for automatic variables. Therefore, you may call any C251 function which is compiled with the reentrant attribute or which just uses registers during the function execution.
  • C251 never generates absolute addresses for register accesses. Each C251 function is independent from the actual registerbank in use. The NOAREGS directive known from the C51 Compiler is no longer required.

Note

  • It is sometimes more efficient to remove the using attribute and let the C251 compiler PUSH the used registers. This also saves the data memory required for the additional registerbank. You can compare the code generated with or without using attribute with the C251 CODE directive.
  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.