avr-libc: interrupt.h Source File

avr-libc 2.0.0 Standard C library for AVR-GCC |

## AVR Libc Home Page |  | ## AVR Libc Development Pages
## Main Page | ## User Manual | ## Library Reference | ## FAQ | ## Example Projects

interrupt.h
Go to the documentation of this file.
1 /* Copyright (c) 2002,2005,2007 Marek Michalkiewicz
2 Copyright (c) 2007, Dean Camera
3
4 All rights reserved.
5
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions are met:
8
9 * Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11
12 * Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in
14 the documentation and/or other materials provided with the
15 distribution.
16
17 * Neither the name of the copyright holders nor the names of
18 contributors may be used to endorse or promote products derived
19 from this software without specific prior written permission.
20
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
25 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 POSSIBILITY OF SUCH DAMAGE. */
32
33 /* $Id$ */
34
35 #ifndef _AVR_INTERRUPT_H_
36 #define _AVR_INTERRUPT_H_
37
38 #include <avr/io.h>
39
40 #if !defined(__DOXYGEN__) && !defined(__STRINGIFY)
41 /* Auxiliary macro for ISR_ALIAS(). */
42 #define __STRINGIFY(x) #x
43 #endif /* !defined(__DOXYGEN__) */
44
45 /**
46 \file
47 \@{
48 */
49
50
51 /** \name Global manipulation of the interrupt flag
52
53 The global interrupt flag is maintained in the I bit of the status
54 register (SREG).
55
56 Handling interrupts frequently requires attention regarding atomic
57 access to objects that could be altered by code running within an
58 interrupt context, see <util/atomic.h>.
59
60 Frequently, interrupts are being disabled for periods of time in
61 order to perform certain operations without being disturbed; see
62 \ref optim_code_reorder for things to be taken into account with
63 respect to compiler optimizations.
64 */
65
66 #if defined(__DOXYGEN__)
67 /** \def sei()
68 \ingroup avr_interrupts
69
70 Enables interrupts by setting the global interrupt mask. This function
71 actually compiles into a single line of assembly, so there is no function
72 call overhead. However, the macro also implies a <i>memory barrier</i>
73 which can cause additional loss of optimization.
74
75 In order to implement atomic access to multi-byte objects,
76 consider using the macros from <util/atomic.h>, rather than
77 implementing them manually with cli() and sei().
78 */
79 #define sei()
80 #else /* !DOXYGEN */
81 # define sei() __asm__ __volatile__ ("sei" ::: "memory")
82 #endif /* DOXYGEN */
83
84 #if defined(__DOXYGEN__)
85 /** \def cli()
86 \ingroup avr_interrupts
87
88 Disables all interrupts by clearing the global interrupt mask. This function
89 actually compiles into a single line of assembly, so there is no function
90 call overhead. However, the macro also implies a <i>memory barrier</i>
91 which can cause additional loss of optimization.
92
93 In order to implement atomic access to multi-byte objects,
94 consider using the macros from <util/atomic.h>, rather than
95 implementing them manually with cli() and sei().
96 */
97 #define cli()
98 #else /* !DOXYGEN */
99 # define cli() __asm__ __volatile__ ("cli" ::: "memory")
100 #endif /* DOXYGEN */
101
102
103 /** \name Macros for writing interrupt handler functions */
104
105
106 #if defined(__DOXYGEN__)
107 /** \def ISR(vector [, attributes])
108 \ingroup avr_interrupts
109
110 Introduces an interrupt handler function (interrupt service
111 routine) that runs with global interrupts initially disabled
112 by default with no attributes specified.
113
114 The attributes are optional and alter the behaviour and resultant
115 generated code of the interrupt routine. Multiple attributes may
116 be used for a single function, with a space seperating each
117 attribute.
118
119 Valid attributes are ISR_BLOCK, ISR_NOBLOCK, ISR_NAKED and
120 ISR_ALIASOF(vect).
121
122 \c vector must be one of the interrupt vector names that are
123 valid for the particular MCU type.
124 */
125 # define ISR(vector, [attributes])
126 #else /* real code */
127
128 #if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)
129 # define __INTR_ATTRS used, externally_visible
130 #else /* GCC < 4.1 */
131 # define __INTR_ATTRS used
132 #endif
133
134 #ifdef __cplusplus
135 # define ISR(vector, ...) \
136 extern "C" void vector (void) __attribute__ ((signal,__INTR_ATTRS)) __VA_ARGS__; \
137 void vector (void)
138 #else
139 # define ISR(vector, ...) \
140 void vector (void) __attribute__ ((signal,__INTR_ATTRS)) __VA_ARGS__; \
141 void vector (void)
142 #endif
143
144 #endif /* DOXYGEN */
145
146 #if defined(__DOXYGEN__)
147 /** \def SIGNAL(vector)
148 \ingroup avr_interrupts
149
150 Introduces an interrupt handler function that runs with global interrupts
151 initially disabled.
152
153 This is the same as the ISR macro without optional attributes.
154 \deprecated Do not use SIGNAL() in new code. Use ISR() instead.
155 */
156 # define SIGNAL(vector)
157 #else /* real code */
158
159 #ifdef __cplusplus
160 # define SIGNAL(vector) \
161 extern "C" void vector(void) __attribute__ ((signal, __INTR_ATTRS)); \
162 void vector (void)
163 #else
164 # define SIGNAL(vector) \
165 void vector (void) __attribute__ ((signal, __INTR_ATTRS)); \
166 void vector (void)
167 #endif
168
169 #endif /* DOXYGEN */
170
171 #if defined(__DOXYGEN__)
172 /** \def EMPTY_INTERRUPT(vector)
173 \ingroup avr_interrupts
174
175 Defines an empty interrupt handler function. This will not generate
176 any prolog or epilog code and will only return from the ISR. Do not
177 define a function body as this will define it for you.
178 Example:
179 \code EMPTY_INTERRUPT(ADC_vect);\endcode */
180 # define EMPTY_INTERRUPT(vector)
181 #else /* real code */
182
183 #ifdef __cplusplus
184 # define EMPTY_INTERRUPT(vector) \
185 extern "C" void vector(void) __attribute__ ((signal,naked,__INTR_ATTRS)); \
186 void vector (void) { __asm__ __volatile__ ("reti" ::); }
187 #else
188 # define EMPTY_INTERRUPT(vector) \
189 void vector (void) __attribute__ ((signal,naked,__INTR_ATTRS)); \
190 void vector (void) { __asm__ __volatile__ ("reti" ::); }
191 #endif
192
193 #endif /* DOXYGEN */
194
195 #if defined(__DOXYGEN__)
196 /** \def ISR_ALIAS(vector, target_vector)
197 \ingroup avr_interrupts
198
199 Aliases a given vector to another one in the same manner as the
200 ISR_ALIASOF attribute for the ISR() macro. Unlike the ISR_ALIASOF
201 attribute macro however, this is compatible for all versions of
202 GCC rather than just GCC version 4.2 onwards.
203
204 \note This macro creates a trampoline function for the aliased
205 macro. This will result in a two cycle penalty for the aliased
206 vector compared to the ISR the vector is aliased to, due to the
207 JMP/RJMP opcode used.
208
209 \deprecated
210 For new code, the use of ISR(..., ISR_ALIASOF(...)) is
211 recommended.
212
213 Example:
214 \code
215 ISR(INT0_vect)
216 {
217 PORTB = 42;
218 }
219
220 ISR_ALIAS(INT1_vect, INT0_vect);
221 \endcode
222
223 */
224 # define ISR_ALIAS(vector, target_vector)
225 #else /* real code */
226
227 #ifdef __cplusplus
228 # if defined(__AVR_MEGA__) && __AVR_MEGA__
229 # define ISR_ALIAS(vector, tgt) extern "C" void vector (void) \
230 __attribute__((signal, naked, __INTR_ATTRS)); \
231 void vector (void) { asm volatile ("jmp " __STRINGIFY(tgt) ::); }
232 # else /* !__AVR_MEGA */
233 # define ISR_ALIAS(vector, tgt) extern "C" void vector (void) \
234 __attribute__((signal, naked, __INTR_ATTRS)); \
235 void vector (void) { asm volatile ("rjmp " __STRINGIFY(tgt) ::); }
236 # endif /* __AVR_MEGA__ */
237 #else /* !__cplusplus */
238 # if defined(__AVR_MEGA__) && __AVR_MEGA__
239 # define ISR_ALIAS(vector, tgt) void vector (void) \
240 __attribute__((signal, naked, __INTR_ATTRS)); \
241 void vector (void) { asm volatile ("jmp " __STRINGIFY(tgt) ::); }
242 # else /* !__AVR_MEGA */
243 # define ISR_ALIAS(vector, tgt) void vector (void) \
244 __attribute__((signal, naked, __INTR_ATTRS)); \
245 void vector (void) { asm volatile ("rjmp " __STRINGIFY(tgt) ::); }
246 # endif /* __AVR_MEGA__ */
247 #endif /* __cplusplus */
248
249 #endif /* DOXYGEN */
250
251 #if defined(__DOXYGEN__)
252 /** \def reti()
253 \ingroup avr_interrupts
254
255 Returns from an interrupt routine, enabling global interrupts. This should
256 be the last command executed before leaving an ISR defined with the ISR_NAKED
257 attribute.
258
259 This macro actually compiles into a single line of assembly, so there is
260 no function call overhead.
261 */
262 # define reti()
263 #else /* !DOXYGEN */
264 # define reti() __asm__ __volatile__ ("reti" ::)
265 #endif /* DOXYGEN */
266
267 #if defined(__DOXYGEN__)
268 /** \def BADISR_vect
269 \ingroup avr_interrupts
270
271 \code #include <avr/interrupt.h> \endcode
272
273 This is a vector which is aliased to __vector_default, the vector
274 executed when an ISR fires with no accompanying ISR handler. This
275 may be used along with the ISR() macro to create a catch-all for
276 undefined but used ISRs for debugging purposes.
277 */
278 # define BADISR_vect
279 #else /* !DOXYGEN */
280 # define BADISR_vect __vector_default
281 #endif /* DOXYGEN */
282
283 /** \name ISR attributes */
284
285 #if defined(__DOXYGEN__)
286 /** \def ISR_BLOCK
287 \ingroup avr_interrupts
288
289 Identical to an ISR with no attributes specified. Global
290 interrupts are initially disabled by the AVR hardware when
291 entering the ISR, without the compiler modifying this state.
292
293 Use this attribute in the attributes parameter of the ISR macro.
294 */
295 # define ISR_BLOCK
296
297 /** \def ISR_NOBLOCK
298 \ingroup avr_interrupts
299
300 ISR runs with global interrupts initially enabled. The interrupt
301 enable flag is activated by the compiler as early as possible
302 within the ISR to ensure minimal processing delay for nested
303 interrupts.
304
305 This may be used to create nested ISRs, however care should be
306 taken to avoid stack overflows, or to avoid infinitely entering
307 the ISR for those cases where the AVR hardware does not clear the
308 respective interrupt flag before entering the ISR.
309
310 Use this attribute in the attributes parameter of the ISR macro.
311 */
312 # define ISR_NOBLOCK
313
314 /** \def ISR_NAKED
315 \ingroup avr_interrupts
316
317 ISR is created with no prologue or epilogue code. The user code is
318 responsible for preservation of the machine state including the
319 SREG register, as well as placing a reti() at the end of the
320 interrupt routine.
321
322 Use this attribute in the attributes parameter of the ISR macro.
323 */
324 # define ISR_NAKED
325
326 /** \def ISR_ALIASOF(target_vector)
327 \ingroup avr_interrupts
328
329 The ISR is linked to another ISR, specified by the vect parameter.
330 This is compatible with GCC 4.2 and greater only.
331
332 Use this attribute in the attributes parameter of the ISR macro.
333 */
334 # define ISR_ALIASOF(target_vector)
335 #else /* !DOXYGEN */
336 # define ISR_BLOCK
337 # define ISR_NOBLOCK __attribute__((interrupt))
338 # define ISR_NAKED __attribute__((naked))
339 # define ISR_ALIASOF(v) __attribute__((alias(__STRINGIFY(v))))
340 #endif /* DOXYGEN */
341
342 /* \@} */
343
344 #endif
io.h