1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
|
/* Copyright (c) 1999, 2000, 2001, 2002, 2005 Rich Neswold
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE. */
/* $Id: interrupts.dox,v 1.9 2005/11/04 22:55:15 joerg_wunsch Exp $ */
/** \defgroup avr_interrupts <avr/interrupt.h>: Interrupts
\note This discussion of interrupts was originally taken from Rich Neswold's
document. See \ref acks.
<h3>Introduction to avr-libc's interrupt handling</h3>
It's nearly impossible to find compilers that agree on how to handle interrupt
code. Since the C language tries to stay away from machine dependent details,
each compiler writer is forced to design their method of support.
In the AVR-GCC environment, the vector table is predefined to point to
interrupt routines with predetermined names. By using the appropriate name,
your routine will be called when the corresponding interrupt occurs. The
device library provides a set of default interrupt routines, which will get
used if you don't define your own.
Patching into the vector table is only one part of the problem. The compiler
uses, by convention, a set of registers when it's normally executing
compiler-generated code. It's important that these registers, as well as the
status register, get saved and restored. The extra code needed to do this is
enabled by tagging the interrupt function with
<tt>__attribute__((signal))</tt>.
These details seem to make interrupt routines a little messy, but all these
details are handled by the Interrupt API. An interrupt routine is defined with
ISR(). This macro register and mark
the routine as an interrupt handler for the specified peripheral. The
following is an example definition of a handler for the ADC interrupt.
\code
#include <avr/interrupt.h>
ISR(ADC_vect)
{
// user code here
}
\endcode
Refer to the chapter explaining \ref ass_isr "assembler programming" for an
explanation about interrupt routines written solely in assembler language.
<h3>Catch-all interrupt vector</h3>
If an unexpected interrupt occurs (interrupt is enabled and no handler is
installed, which usually indicates a bug), then the default action is to reset
the device by jumping to the reset vector. You can override this by supplying
a function named \c __vector_default which should be defined with
ISR() as such.
\code
#include <avr/interrupt.h>
ISR(__vector_default)
{
// user code here
}
\endcode
<h3>Nested interrupts</h3>
The AVR hardware clears the global interrupt flag in SREG before
entering an interrupt vector. Thus, normally interrupts will remain
disabled inside the handler until the handler exits, where the RETI
instruction (that is emitted by the compiler as part of the normal
function epilogue for an interrupt handler) will eventually re-enable
further interrupts. For that reason, interrupt handlers normally do
not nest. For most interrupt handlers, this is the desired behaviour,
for some it is even required in order to prevent infinitely recursive
interrupts (like UART interrupts, or level-triggered external
interrupts). In rare circumstances though it might be desired to
re-enable the global interrupt flag as early as possible in the
interrupt handler, in order to not defer any other interrupt more than
absolutely needed. This could be done using an sei() instruction
right at the beginning of the interrupt handler, but this still leaves
few instructions inside the compiler-generated function prologue to
run with global interrupts disabled. The compiler can be instructed
to insert an SEI instruction right at the beginning of an interrupt
handler by declaring the handler the following way:
\anchor attr_interrupt
\code
void XXX_vect(void) __attribute__((interrupt));
void XXX_vect(void) {
...
}
\endcode
where \c XXX_vect is the name of a valid interrupt vector for the MCU
type in question, as explained below.
<h3>Chosing the vector: Interrupt vector names</h3>
The interrupt is chosen by supplying one of the symbols in following table.
There are currently two different styles present for naming the
vectors. One form uses names starting with \c SIG_, followed by
a relatively verbose but arbitrarily chosen name describing the
interrupt vector. This has been the only available style in
avr-libc up to version 1.2.x.
Starting with avr-libc version 1.4.0, a second style of interrupt
vector names has been added, where a short phrase for the vector
description is followed by \c _vect. The short phrase matches the
vector name as described in the datasheet of the respective device
(and in Atmel's XML files), with spaces replaced by an underscore
and other non-alphanumeric characters dropped. Using the suffix
\c _vect is intented to improve portability to other C compilers
available for the AVR that use a similar naming convention.
The historical naming style might become deprecated in a future
release, so it is not recommended for new projects.
\note The ISR() macro cannot really spell-check
the argument passed to them. Thus, by misspelling one of the names
below in a call to ISR(), a function will be created
that, while possibly being usable as an interrupt function, is not
actually wired into the interrupt vector table. The compiler will
generate a warning if it detects a suspiciously looking name of a
ISR() function (i.e. one that after macro replacement does not
start with "__vector_").
*/
|