5.4. Interrupt Vectors and Handlers
Prev | Chapter 5. CS3™: The CodeSourcery Common Startup Code Sequence | Next

## 5.4. Interrupt Vectors and Handlers

CS3 provides standard handlers for interrupts, exceptions and traps, but also allows you to define your own handlers as needed. In this section, we use the term interrupt as a generic term for this entire class of events.

Different processors handle interrupts in various ways, but there are two general approaches:

- Some processors fetch an address from an array indexed by the interrupt number, and jump to that address. We call these address vector processors.

- Others multiply the interrupt number by some constant factor, add a base address, and jump directly to that address. Here, the interrupt vector consists of blocks of code, so we call these code vector processors.

- Still other processors use a more complicated descriptor mechanism for the interrupt table.

M-profile processors like the Cortex-M3 use the address vector model. Classic ARM processors (including ARM7/ARM9 as well as Cortex-A/R series processors) are technically code vector processors. However, each vector slot only holds a single instruction. CS3 emulates the address vector model on these processors by placing an indirect branch instruction in each slot of the real exception vector. The remainder of this section assumes that you have some understanding of the specific requirements for your target; refer to the architecture manuals if necessary.

### 5.4.1. ARM EABI Interrupt Vector Implementation

On address vector processors, the CS3 library provides an array of pointers to interrupt handlers named `__cs3_interrupt_vector_`form``, where `form` identifies the particular processor variant the vector is appropriate for. Each entry in the vector holds a reference to a symbol named `__cs3_isr_`name``, where `name` is the customary name of that interrupt on the processor, or a number if there is no consistently used name. You can find the interrupt vector details in Section 5.6, “Interrupt Vector Tables”. The particular vector used by a given CS3-supported board is documented in the tables in Section 5.5, “Supported Boards for ARM EABI”.

CS3 provides a reasonable default definition for each `__cs3_isr_`name`` handler. Many of these symbols are aliased to a common handler routine. If your program stops at a default interrupt handler, its name as shown in backtraces may therefore not correctly reflect which interrupt occurred.

To override an individual handler, provide your own definition for the appropriate `__cs3_isr_`name`` symbol. The definition need not be placed in any particular object file section.

To override the entire interrupt vector, you can define `__cs3_interrupt_vector_`form``. You must place this definition in a section named `.cs3.interrupt_vector`. The linker script reports an error if the `.cs3.interrupt_vector` section is empty, to ensure that the definition of `__cs3_interrupt_vector_`form`` occupies the proper section.

You may define the vector in C with an array of pointers using the `section` attribute to place it in the appropriate section. For example, to override the interrupt vector on Altera Cyclone III Cortex-M1 boards, make the following definition:

    typedef void handler(void);
    handler *__attribute__((section (".cs3.interrupt_vector")))
      __cs3_interrupt_vector_micro[] =
    { ... };

### 5.4.2. Writing Interrupt Handlers

Interrupt handlers typically require special call/return and register usage conventions that are target-specific and beyond the scope of this document. In many cases, normal C functions cannot be used as interrupt handlers. For example, the EABI requires that the stack be 8-byte aligned, but on some ARMv7-M processors, only 4-byte stack alignment is guaranteed when calling an interrupt vector. This can cause subtle runtime failures, usually when 8-byte types are used.

As an alternative to writing interrupt handlers in assembly language, on ARM targets they may be written in C using the `interrupt` attribute. This tells the compiler to generate appropriate function entry and exit sequences for an interrupt handler. For example, to override the `__cs3_isr_nmi` handler, use the following definition:

    void __attribute__ ((interrupt)) __cs3_isr_nmi (void)
    {
      ... custom handler code ...
    }

On ARM targets, the `interrupt` attribute also takes an optional parameter to specify the type of interrupt. Refer to the GCC manual for more details about attribute syntax and usage.

Prev | Up | Next
5.3. Memory Layout | Home | 5.5. Supported Boards for ARM EABI