Writing Interrupt Handlers¶
Info
Refer the official GCC documentation page about ARC function attributes for details.
Overview¶
You can use interrupt GCC function attribute to declare a function as an
interrupt handler. Here is an example of declaring and defining a regular
interrupt handler for ARCv2 families:
/* Declaration */
void f () __attribute__ ((interrupt ("ilink")));
/* Definition */
void f() {
    ...
}
/* Declaration with a definition */
__attribute__ ((interrupt ("ilink"))) void f() {
    ...
}
A parameter for interrupt attribute stands for a type of an interrupt:
| Parameter | Type of an interrupt | 
|---|---|
ilink | 
A regular ARCv2 interrupt | 
firq | 
A fast ARCv2 interrupt | 
ilink1, ilink2 | 
ARC600/ARC700 interrupts | 
Example¶
The interrupt attribute only puts valid entry and exit code around a function
for an interrupt or exception handler. Also, it's necessary to do extra steps:
- Provide an interrupt vector table (IVT) with an array of pointers to handlers. By default, it's provided only for ARCv2 targets in Newlib.
 - Provide a valid value for 
INT_VECTOR_BASEauxiliary registers. It must contain a 1KB aligned address of IVT. 
Here is a simple implementation of a handler for EV_DivZero exception for
ARCv2. It prints a message and then exits:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define AUX_STATUS32_BCR 0x0A
#define AUX_STATUS32_DZ_OFFSET 13
/*
 * A helper for setting DZ flag - it enables EV_DivZero exceptions.
 */
void set_ev_divzero(bool on)
{
        unsigned int status32 = __builtin_arc_lr(AUX_STATUS32_BCR);
        unsigned int bit = (on ? 1 : 0) << AUX_STATUS32_DZ_OFFSET;
        status32 |= bit;
        __builtin_arc_flag(status32);
}
/*
 * Define an exception handler for EV_DivZero exception.
 * Note that it terminates the applications since EV_DivZero
 * returns to the same place in main function and the
 * exception is raised again.
 */
__attribute__ ((interrupt ("ilink"))) void EV_DivZero()
{
        printf("Divizion by zero is catched!\n");
        exit(1);
}
int main()
{
        /* Enable EV_DivZero exceptions */
        set_ev_divzero(true);
        /* Provoke EV_DivZero exception */
        int a = 5;
        int b = 0;
        int c = a / b;
        return 0;
}
Save it as main.c file and compile the application for ARC HS3x/4x families
using GNU toolchain:
Meaning of the options:
-Wl,-marcv2elf- a linker emulation which puts the IVT at0x0, this it's properly aligned.-specs=hl.specs- adds support of hostlink for nSIM simulator. It allows to use functions likeprintf.-mcpu=hs38 -O0- enable usingdivinstructions and ensure that it's not reduces since our application is too simple.
Run the application using nSIM (-p nsim_isa_intvbase_preset=0x0 is used to
ensure that INT_VECTOR_BASE is set to 0x0 by default):