AVR-LibC  2.2.0
Standard C library for AVR-GCC
 

AVR-LibC Documentation

Logo

AVR-LibC Development Pages

Main Page

User Manual

Library Reference

FAQ

Example Projects

File List

Loading...
Searching...
No Matches
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/** \file */
46/**@{*/
47
48
49/** \name Global manipulation of the interrupt flag
50
51 The global interrupt flag is maintained in the I bit of the status
52 register (SREG).
53
54 Handling interrupts frequently requires attention regarding atomic
55 access to objects that could be altered by code running within an
56 interrupt context, see <util/atomic.h>.
57
58 Frequently, interrupts are being disabled for periods of time in
59 order to perform certain operations without being disturbed; see
60 \ref optim_code_reorder for things to be taken into account with
61 respect to compiler optimizations.
62*/
63
64/** \def sei()
65 \ingroup avr_interrupts
66
67 Enables interrupts by setting the global interrupt mask. This function
68 actually compiles into a single line of assembly, so there is no function
69 call overhead. However, the macro also implies a <i>memory barrier</i>
70 which can cause additional loss of optimization.
71
72 In order to implement atomic access to multi-byte objects,
73 consider using the macros from <util/atomic.h>, rather than
74 implementing them manually with cli() and sei().
75*/
76# define sei() __asm__ __volatile__ ("sei" ::: "memory")
77
78/** \def cli()
79 \ingroup avr_interrupts
80
81 Disables all interrupts by clearing the global interrupt mask. This function
82 actually compiles into a single line of assembly, so there is no function
83 call overhead. However, the macro also implies a <i>memory barrier</i>
84 which can cause additional loss of optimization.
85
86 In order to implement atomic access to multi-byte objects,
87 consider using the macros from <util/atomic.h>, rather than
88 implementing them manually with cli() and sei().
89*/
90# define cli() __asm__ __volatile__ ("cli" ::: "memory")
91
92
93/** \name Macros for writing interrupt handler functions */
94
95
96#if defined(__DOXYGEN__)
97/** \def ISR(vector [, attributes])
98 \ingroup avr_interrupts
99
100 Introduces an interrupt handler function (interrupt service
101 routine) that runs with global interrupts initially disabled
102 by default with no attributes specified.
103
104 The attributes are optional and alter the behaviour and resultant
105 generated code of the interrupt routine. Multiple attributes may
106 be used for a single function, with a space seperating each
107 attribute.
108
109 Valid attributes are #ISR_BLOCK, #ISR_NOBLOCK, #ISR_NAKED,
110 #ISR_FLATTEN, #ISR_NOICF, #ISR_NOGCCISR and ISR_ALIASOF(vect).
111
112 \c vector must be one of the interrupt vector names that are
113 valid for the particular MCU type.
114*/
115# define ISR(vector, [attributes])
116#else /* real code */
117
118#if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)
119# define __INTR_ATTRS __used__, __externally_visible__
120#else /* GCC < 4.1 */
121# define __INTR_ATTRS __used__
122#endif
123
124#ifdef __cplusplus
125# define ISR(vector, ...) \
126 extern "C" void vector (void) __attribute__ ((__signal__,__INTR_ATTRS)) __VA_ARGS__; \
127 void vector (void)
128#else
129# define ISR(vector, ...) \
130 void vector (void) __attribute__ ((__signal__,__INTR_ATTRS)) __VA_ARGS__; \
131 void vector (void)
132#endif
133
134#endif /* DOXYGEN */
135
136#if defined(__DOXYGEN__)
137/** \def SIGNAL(vector)
138 \ingroup avr_interrupts
139
140 Introduces an interrupt handler function that runs with global interrupts
141 initially disabled.
142
143 This is the same as the ISR macro without optional attributes.
144 \deprecated Do not use SIGNAL() in new code. Use ISR() instead.
145*/
146# define SIGNAL(vector)
147#else /* real code */
148
149#ifdef __cplusplus
150# define SIGNAL(vector) \
151 extern "C" void vector(void) __attribute__ ((__signal__, __INTR_ATTRS)); \
152 void vector (void)
153#else
154# define SIGNAL(vector) \
155 void vector (void) __attribute__ ((__signal__, __INTR_ATTRS)); \
156 void vector (void)
157#endif
158
159#endif /* DOXYGEN */
160
161#if defined(__DOXYGEN__)
162/** \def EMPTY_INTERRUPT(vector)
163 \ingroup avr_interrupts
164
165 Defines an empty interrupt handler function. This will not generate
166 any prolog or epilog code and will only return from the #ISR. Do not
167 define a function body as this will define it for you.
168 Example:
169 \code EMPTY_INTERRUPT(ADC_vect);\endcode */
170# define EMPTY_INTERRUPT(vector)
171#else /* real code */
172
173#ifdef __cplusplus
174# define EMPTY_INTERRUPT(vector) \
175 extern "C" void vector(void) __attribute__ ((__signal__,__naked__,__INTR_ATTRS)); \
176 void vector (void) { __asm__ __volatile__ ("reti" ::: "memory"); }
177#else
178# define EMPTY_INTERRUPT(vector) \
179 void vector (void) __attribute__ ((__signal__,__naked__,__INTR_ATTRS)); \
180 void vector (void) { __asm__ __volatile__ ("reti" ::: "memory"); }
181#endif
182
183#endif /* DOXYGEN */
184
185#if defined(__DOXYGEN__)
186/** \def ISR_ALIAS(vector, target_vector)
187 \ingroup avr_interrupts
188
189 Aliases a given vector to another one in the same manner as the
190 ISR_ALIASOF attribute for the ISR() macro. Unlike the ISR_ALIASOF
191 attribute macro however, this is compatible for all versions of
192 GCC rather than just GCC version 4.2 onwards.
193
194 \note This macro creates a trampoline function for the aliased
195 macro. This will result in a two cycle penalty for the aliased
196 vector compared to the ISR the vector is aliased to, due to the
197 JMP/RJMP opcode used.
198
199 \deprecated
200 For new code, the use of ISR(..., ISR_ALIASOF(...)) is
201 recommended.
202
203 Example:
204 \code
205 ISR(INT0_vect)
206 {
207 PORTB = 42;
208 }
209
210 ISR_ALIAS(INT1_vect, INT0_vect);
211 \endcode
212
213*/
214# define ISR_ALIAS(vector, target_vector)
215#else /* real code */
216
217#ifdef __cplusplus
218# define ISR_ALIAS(vector, tgt) extern "C" void vector (void) \
219 __attribute__((__signal__, __naked__, __INTR_ATTRS)); \
220 void vector (void) { __asm__ __volatile__ ("%~jmp " __STRINGIFY(tgt) ::); }
221#else /* !__cplusplus */
222# define ISR_ALIAS(vector, tgt) void vector (void) \
223 __attribute__((__signal__, __naked__, __INTR_ATTRS)); \
224 void vector (void) { __asm__ __volatile__ ("%~jmp " __STRINGIFY(tgt) ::); }
225#endif /* __cplusplus */
226
227#endif /* DOXYGEN */
228
229/** \def reti()
230 \ingroup avr_interrupts
231
232 Returns from an interrupt routine, enabling global interrupts. This should
233 be the last command executed before leaving an #ISR defined with the
234 #ISR_NAKED attribute.
235
236 This macro actually compiles into a single line of assembly, so there is
237 no function call overhead.
238
239 \note According to the GCC documentation, the only code supported in
240 naked functions is \ref inline_asm "inline assembly".
241*/
242# define reti() __asm__ __volatile__ ("reti" ::: "memory")
243
244#if defined(__DOXYGEN__)
245/** \def BADISR_vect
246 \ingroup avr_interrupts
247
248 \code #include <avr/interrupt.h> \endcode
249
250 This is a vector which is aliased to __vector_default, the vector
251 executed when an IRQ fires with no accompanying ISR handler. This
252 may be used along with the ISR() macro to create a catch-all for
253 undefined but used ISRs for debugging purposes.
254*/
255# define BADISR_vect
256#else /* !DOXYGEN */
257# define BADISR_vect __vector_default
258#endif /* DOXYGEN */
259
260/** \name ISR attributes */
261
262#if defined(__DOXYGEN__)
263/** \def ISR_BLOCK
264 \ingroup avr_interrupts
265
266 Identical to an ISR with no attributes specified. Global
267 interrupts are initially disabled by the AVR hardware when
268 entering the ISR, without the compiler modifying this state.
269
270 Use this attribute in the attributes parameter of the #ISR macro.
271*/
272# define ISR_BLOCK
273
274/** \def ISR_NOBLOCK
275 \ingroup avr_interrupts
276
277 ISR runs with global interrupts initially enabled. The interrupt
278 enable flag is activated by the compiler as early as possible
279 within the ISR to ensure minimal processing delay for nested
280 interrupts.
281
282 This may be used to create nested ISRs, however care should be
283 taken to avoid stack overflows, or to avoid infinitely entering
284 the ISR for those cases where the AVR hardware does not clear the
285 respective interrupt flag before entering the ISR.
286
287 Use this attribute in the attributes parameter of the #ISR macro.
288*/
289# define ISR_NOBLOCK
290
291/** \def ISR_NAKED
292 \ingroup avr_interrupts
293
294 ISR is created with no prologue or epilogue code. The user code is
295 responsible for preservation of the machine state including the
296 SREG register, as well as placing a reti() at the end of the
297 interrupt routine.
298
299 Use this attribute in the attributes parameter of the #ISR macro.
300
301 \note According to GCC documentation, the only code supported in
302 naked functions is \ref inline_asm "inline assembly".
303*/
304# define ISR_NAKED
305
306/** \def ISR_FLATTEN
307 \ingroup avr_interrupts
308
309 The compiler will try to inline all called function into the ISR.
310 This has an effect with GCC 4.6 and newer only.
311
312 Use this attribute in the attributes parameter of the #ISR macro.
313*/
314# define ISR_FLATTEN
315
316/** \def ISR_NOICF
317 \ingroup avr_interrupts
318
319 Avoid identical-code-folding optimization against this ISR.
320 This has an effect with GCC 5 and newer only.
321
322 Use this attribute in the attributes parameter of the #ISR macro.
323*/
324# define ISR_NOICF
325
326/** \def ISR_NOGCCISR
327 \ingroup avr_interrupts
328
329 Do not generate
330 <a href="https://sourceware.org/binutils/docs/as/AVR-Pseudo-Instructions.html">\c __gcc_isr pseudo instructions</a>
331 for this ISR.
332 This has an effect with
333 <a href="https://gcc.gnu.org/gcc-8/changes.html#avr">GCC 8</a>
334 and newer only.
335
336 Use this attribute in the attributes parameter of the #ISR macro.
337*/
338# define ISR_NOGCCISR
339
340/** \def ISR_ALIASOF(target_vector)
341 \ingroup avr_interrupts
342
343 The ISR is linked to another ISR, specified by the vect parameter.
344 This is compatible with GCC 4.2 and greater only.
345
346 Use this attribute in the attributes parameter of the #ISR macro.
347 Example:
348 \code
349 ISR (INT0_vect)
350 {
351 PORTB = 42;
352 }
353
354 ISR (INT1_vect, ISR_ALIASOF (INT0_vect));
355 \endcode
356*/
357# define ISR_ALIASOF(target_vector)
358#else /* !DOXYGEN */
359# define ISR_BLOCK /* empty */
360/* FIXME: This won't work with older versions of avr-gcc as ISR_NOBLOCK
361 will use `signal' and `interrupt' at the same time. */
362# define ISR_NOBLOCK __attribute__((__interrupt__))
363# define ISR_NAKED __attribute__((__naked__))
364
365#if (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || (__GNUC__ >= 5)
366# define ISR_FLATTEN __attribute__((__flatten__))
367#else
368# define ISR_FLATTEN /* empty */
369#endif /* has flatten (GCC 4.6+) */
370
371#if defined (__has_attribute)
372#if __has_attribute (__no_icf__)
373# define ISR_NOICF __attribute__((__no_icf__))
374#else
375# define ISR_NOICF /* empty */
376#endif /* has no_icf */
377
378#if __has_attribute (__no_gccisr__)
379# define ISR_NOGCCISR __attribute__((__no_gccisr__))
380#else
381# define ISR_NOGCCISR /* empty */
382#endif /* has no_gccisr */
383#endif /* has __has_attribute (GCC 5+) */
384
385# define ISR_ALIASOF(v) __attribute__((__alias__(__STRINGIFY(v))))
386#endif /* DOXYGEN */
387
388/**@}*/
389
390#endif