File: interrupts.dox

package info (click to toggle)
avr-libc 1%3A1.4.5-2
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k
  • size: 7,324 kB
  • ctags: 25,560
  • sloc: ansic: 31,105; asm: 5,266; sh: 3,525; makefile: 1,837; pascal: 558; python: 45
file content (150 lines) | stat: -rw-r--r-- 6,601 bytes parent folder | download
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_").

*/