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 three 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.
On address vector processors, the CS3 library provides an array
of pointers to interrupt handlers named
__cs3_interrupt_vector_
,
where form
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_
,
where name
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_
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.
name
To override an individual handler, provide your own definition
for the appropriate
__cs3_isr_
symbol. The definition need not be placed in any particular
object file section.
name
To override the entire interrupt vector, you can define
__cs3_interrupt_vector_
.
You must place this definition in a section named
form
.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_
occupies the proper section.
form
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[] = { ... };
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.