AVR-LibC  2.3.0git
Standard C library for AVR-GCC
 

AVR-LibC Documen­tation

AVR-LibC Development Pages

Main Page

User Manual

Library Refe­rence

FAQ

Example Projects

File List

Index

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#ifndef _AVR_INTERRUPT_H_
34#define _AVR_INTERRUPT_H_
35
36#include <avr/io.h>
37
38#if !defined(__DOXYGEN__) && !defined(__STRINGIFY)
39/* Auxiliary macro for ISR_ALIAS(). */
40#define __STRINGIFY(x) #x
41#endif /* !defined(__DOXYGEN__) */
42
43/** \file */
44/**@{*/
45
46
47/** \name Global manipulation of the interrupt flag
48
49 The global interrupt flag is maintained in the I bit of the status
50 register (SREG).
51
52 Handling interrupts frequently requires attention regarding atomic
53 access to objects that could be altered by code running within an
54 interrupt context, see <util/atomic.h>.
55
56 Frequently, interrupts are being disabled for periods of time in
57 order to perform certain operations without being disturbed; see
58 \ref optim_code_reorder for things to be taken into account with
59 respect to compiler optimizations.
60*/
61
62/** \def sei()
63 \ingroup avr_interrupts
64
65 Enables interrupts by setting the global interrupt mask. This function
66 actually compiles into a single line of assembly, so there is no function
67 call overhead. However, the macro also implies a <i>memory barrier</i>
68 which can cause additional loss of optimization.
69
70 In order to implement atomic access to multi-byte objects,
71 consider using the macros from <util/atomic.h>, rather than
72 implementing them manually with cli() and sei().
73*/
74# define sei() __asm__ __volatile__ ("sei" ::: "memory")
75
76/** \def cli()
77 \ingroup avr_interrupts
78
79 Disables all interrupts by clearing the global interrupt mask. This function
80 actually compiles into a single line of assembly, so there is no function
81 call overhead. However, the macro also implies a <i>memory barrier</i>
82 which can cause additional loss of optimization.
83
84 In order to implement atomic access to multi-byte objects,
85 consider using the macros from <util/atomic.h>, rather than
86 implementing them manually with cli() and sei().
87*/
88# define cli() __asm__ __volatile__ ("cli" ::: "memory")
89
90
91/** \name Macros for writing interrupt handler functions */
92
93
94#if defined(__DOXYGEN__)
95/** \def ISR(vector [, attributes])
96 \ingroup avr_interrupts
97
98 Introduces an interrupt handler function (interrupt service
99 routine) that runs with the \c SREG.I flag unchanged
100 by default with no attributes specified.
101 (On most devices this means that global interrupts are disabled
102 upon servicing the IRQ.)
103
104 The \c 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 separating 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
113 \ref avr_mcu_signames "interrupt vector names" that are
114 valid for the particular MCU type.
115
116 See also the #ISR_N macro for an alternative way to introduce an ISR.
117*/
118# define ISR(vector, [attributes])
119#else /* real code */
120
121#if defined (__clang__)
122# define __INTR_ATTRS __used__
123#elif (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)
124# define __INTR_ATTRS __used__, __externally_visible__
125#else /* GCC < 4.1 */
126# define __INTR_ATTRS __used__
127#endif
128
129#ifdef __cplusplus
130# define ISR(vector, ...) \
131 extern "C" void vector (void) __attribute__ ((__signal__,__INTR_ATTRS)) __VA_ARGS__; \
132 void vector (void)
133#else
134# define ISR(vector, ...) \
135 void vector (void) __attribute__ ((__signal__,__INTR_ATTRS)) __VA_ARGS__; \
136 void vector (void)
137#endif
138
139#endif /* DOXYGEN */
140
141#if defined(__DOXYGEN__)
142/** \def ISR_N(vector_num [, attributes])
143 \ingroup avr_interrupts
144
145 Introduces an interrupt handler function (interrupt service
146 routine) that runs with the \c SREG.I flag unchanged
147 by default with no attributes specified.
148 (On most devices this means that global interrupts are disabled
149 upon servicing the IRQ.)
150
151 \c vector_num must be a positive interrupt vector number that is
152 valid for the particular MCU type. For available vector numbers, see
153 for example the \ref avr_mcu_signames "MCU &rarr; Vector Names" table.
154
155 Contrary to the #ISR macro, #ISR_N does not provide a declarator for
156 the ISR. #ISR_N may be specified more than once, which can be used
157 to define aliases. For example, the following definition provides
158 an ISR for IRQ numbers 3 and 4 on an ATmega328:
159\code
160 ISR_N (PCINT0_vect_num)
161 ISR_N (PCINT1_vect_num)
162 static void my_isr_handler (void)
163 {
164 // Code
165 }
166\endcode
167 The \c attributes are optional and alter the behaviour and resultant
168 generated code of the interrupt routine. Multiple attributes may
169 be used for a single function, with a space separating each
170 attribute.
171
172 Valid attributes are #ISR_BLOCK, #ISR_NOBLOCK, #ISR_NAKED,
173 #ISR_FLATTEN, #ISR_NOICF and #ISR_NOGCCISR.
174
175\since AVR-LibC v2.3, <a href="https://gcc.gnu.org/gcc-15/changes.html#avr">GCC v15</a>
176*/
177# define ISR_N(vector_num, [attributes])
178#else /* real code */
179
180#if defined __HAVE_SIGNAL_N__
181/* Notice that "used" is implicit since v15, and that there is no requirement
182 that the handler function is externally visible. */
183#define ISR_N(N, ...) \
184 __attribute__((__signal__(N))) __VA_ARGS__
185#else /* HAVE_SIGNAL_N */
186/* When GCC does not support "signal(n)", which is the case up to v14,
187 then try to emit a helpful error message. */
188#define __ISR_N_error2(L) \
189 __attribute__((__used__,__error__( \
190 "ISR_N not supported by this version of the compiler"))) \
191 int AVR_LibC_show_error##L (int x) \
192 { \
193 __asm (".error \"ISR_N not supported by this version of the compiler\"");\
194 return x ? 1 : x * AVR_LibC_show_error##L (x - 1); \
195 }
196#define __ISR_N_error1(L) __ISR_N_error2(L)
197#define ISR_N(...) __ISR_N_error1(__LINE__)
198#endif /* HAVE_SIGNAL_N */
199#endif /* DOXYGEN ISR_N */
200
201#if defined(__DOXYGEN__)
202/** \def SIGNAL(vector)
203 \ingroup avr_interrupts
204
205 Introduces an interrupt handler function that runs with global interrupts
206 initially disabled.
207
208 This is the same as the ISR macro without optional attributes.
209 \deprecated Do not use SIGNAL() in new code. Use ISR() or ISR_N() instead.
210*/
211# define SIGNAL(vector)
212#else /* real code */
213
214#ifdef __cplusplus
215# define SIGNAL(vector) \
216 extern "C" void vector(void) __attribute__ ((__signal__, __INTR_ATTRS)); \
217 void vector (void)
218#else
219# define SIGNAL(vector) \
220 void vector (void) __attribute__ ((__signal__, __INTR_ATTRS)); \
221 void vector (void)
222#endif
223
224#endif /* DOXYGEN */
225
226#if defined(__DOXYGEN__)
227/** \def EMPTY_INTERRUPT(vector)
228 \ingroup avr_interrupts
229
230 Defines an empty interrupt handler function. This will not generate
231 any prolog or epilog code and will only return from the #ISR. Do not
232 define a function body as this will define it for you.
233 Example:
234 \code EMPTY_INTERRUPT(ADC_vect);\endcode */
235# define EMPTY_INTERRUPT(vector)
236#else /* real code */
237
238#ifdef __cplusplus
239# define EMPTY_INTERRUPT(vector) \
240 extern "C" void vector(void) __attribute__ ((__signal__,__naked__,__INTR_ATTRS)); \
241 void vector (void) { __asm__ __volatile__ ("reti" ::: "memory"); }
242#else
243# define EMPTY_INTERRUPT(vector) \
244 void vector (void) __attribute__ ((__signal__,__naked__,__INTR_ATTRS)); \
245 void vector (void) { __asm__ __volatile__ ("reti" ::: "memory"); }
246#endif
247
248#endif /* DOXYGEN */
249
250#if defined(__DOXYGEN__)
251/** \def ISR_ALIAS(vector, target_vector)
252 \ingroup avr_interrupts
253
254 Aliases a given vector to another one in the same manner as the
255 ISR_ALIASOF attribute for the ISR() macro. Unlike the ISR_ALIASOF
256 attribute macro however, this is compatible for all versions of
257 GCC rather than just GCC version 4.2 onwards.
258
259 \note This macro creates a trampoline function for the aliased
260 macro. This will result in a two cycle penalty for the aliased
261 vector compared to the ISR the vector is aliased to, due to the
262 JMP/RJMP opcode used.
263
264 \deprecated
265 For new code, the use of ISR(..., ISR_ALIASOF(...)) or #ISR_N is
266 recommended. Notice that using #ISR_N does \e not impose a
267 JMP/RJMP overhead.
268
269 Example:
270 \code
271 ISR (INT0_vect)
272 {
273 PORTB = 42;
274 }
275
276 ISR_ALIAS (INT1_vect, INT0_vect);
277
278 // Alternative using ISR_N
279
280 ISR_N (INT0_vect_num)
281 ISR_N (INT1_vect_num)
282 static void my_int01_handler (void)
283 {
284 PORTB = 42;
285 }
286
287 // or
288
289 ISR (INT0_vect,
290 [attributes]
291 ISR_N (INT1_vect_num))
292 {
293 PORTB = 42;
294 }
295 \endcode
296*/
297# define ISR_ALIAS(vector, target_vector)
298#else /* real code */
299
300#ifdef __cplusplus
301# define ISR_ALIAS(vector, tgt) extern "C" void vector (void) \
302 __attribute__((__signal__, __naked__, __INTR_ATTRS)); \
303 void vector (void) { __asm__ __volatile__ ("%~jmp " __STRINGIFY(tgt) ::); }
304#else /* !__cplusplus */
305# define ISR_ALIAS(vector, tgt) void vector (void) \
306 __attribute__((__signal__, __naked__, __INTR_ATTRS)); \
307 void vector (void) { __asm__ __volatile__ ("%~jmp " __STRINGIFY(tgt) ::); }
308#endif /* __cplusplus */
309
310#endif /* DOXYGEN */
311
312/** \def reti()
313 \ingroup avr_interrupts
314
315 Returns from an interrupt routine, enabling global interrupts. This should
316 be the last command executed before leaving an #ISR defined with the
317 #ISR_NAKED attribute.
318
319 This macro actually compiles into a single line of assembly, so there is
320 no function call overhead.
321
322 \note According to the GCC documentation, the only code supported in
323 naked functions is \ref inline_asm "inline assembly".
324*/
325# define reti() __asm__ __volatile__ ("reti" ::: "memory")
326
327#if defined(__DOXYGEN__)
328/** \def BADISR_vect
329 \ingroup avr_interrupts
330
331 \code #include <avr/interrupt.h> \endcode
332
333 This is a vector which is aliased to \c __vector_default, the vector
334 executed when an IRQ fires with no accompanying ISR handler. This
335 may be used along with the ISR() macro to create a catch-all for
336 undefined but used ISRs for debugging purposes. It cannot be used
337 with #ISR_N since there is no associated interrupt number. */
338# define BADISR_vect
339#else /* !DOXYGEN */
340# define BADISR_vect __vector_default
341#endif /* DOXYGEN */
342
343/** \name ISR attributes */
344
345#if defined(__DOXYGEN__)
346/** \def ISR_BLOCK
347 \ingroup avr_interrupts
348
349 Identical to an ISR with no attributes specified. Global
350 interrupts are initially disabled by the AVR hardware when
351 entering the ISR, without the compiler modifying this state.
352
353 Use this attribute in the \c attributes parameter of the #ISR
354 and #ISR_N macros.
355*/
356# define ISR_BLOCK
357
358/** \def ISR_NOBLOCK
359 \ingroup avr_interrupts
360
361 ISR runs with global interrupts initially enabled. The interrupt
362 enable flag is activated by the compiler as early as possible
363 within the ISR to ensure minimal processing delay for nested
364 interrupts.
365
366 This may be used to create nested ISRs, however care should be
367 taken to avoid stack overflows, or to avoid infinitely entering
368 the ISR for those cases where the AVR hardware does not clear the
369 respective interrupt flag before entering the ISR.
370
371 Use this attribute in the \c attributes parameter of the #ISR and
372 #ISR_N macros.
373*/
374# define ISR_NOBLOCK
375
376/** \def ISR_NAKED
377 \ingroup avr_interrupts
378
379 ISR is created with no prologue or epilogue code. The user code is
380 responsible for preservation of the machine state including the
381 SREG register, as well as placing a reti() at the end of the
382 interrupt routine.
383
384 Use this attribute in the \c attributes parameter of the #ISR and
385 #ISR_N macros.
386
387 \note According to GCC documentation, the only code supported in
388 naked functions is \ref inline_asm "inline assembly".
389*/
390# define ISR_NAKED
391
392/** \def ISR_FLATTEN
393 \ingroup avr_interrupts
394
395 The compiler will try to inline all called function into the ISR.
396 This has an effect with GCC 4.6 and newer only.
397
398 Use this attribute in the \c attributes parameter of the #ISR and
399 #ISR_N macros.
400*/
401# define ISR_FLATTEN
402
403/** \def ISR_NOICF
404 \ingroup avr_interrupts
405
406 Avoid identical-code-folding optimization against this ISR.
407 This has an effect with GCC 5 and newer only.
408
409 Use this attribute in the \c attributes parameter of the #ISR and
410 #ISR_N macros.
411*/
412# define ISR_NOICF
413
414/** \def ISR_NOGCCISR
415 \ingroup avr_interrupts
416
417 Do not generate
418 <a href="https://sourceware.org/binutils/docs/as/AVR-Pseudo-Instructions.html">\c __gcc_isr pseudo instructions</a>
419 for this ISR.
420 This has an effect with
421 <a href="https://gcc.gnu.org/gcc-8/changes.html#avr">GCC 8</a>
422 and newer only.
423
424 Use this attribute in the \c attributes parameter of the #ISR and
425 #ISR_N macros.
426*/
427# define ISR_NOGCCISR
428
429/** \def ISR_ALIASOF(target_vector)
430 \ingroup avr_interrupts
431
432 The ISR is linked to another ISR, specified by the vect parameter.
433 This is compatible with GCC 4.2 and greater only.
434
435 Use this attribute in the \c attributes parameter of the #ISR macro.
436 Example:
437 \code
438 ISR (INT0_vect)
439 {
440 PORTB = 42;
441 }
442
443 ISR (INT1_vect, ISR_ALIASOF (INT0_vect));
444 \endcode
445
446 Notice that the #ISR_ALIASOF macro implements its own IRQ handler that
447 jumps to the aliased ISR, which means there is a run-time overhead of
448 a JMP/RJMP instruction. For an alternative without overhead, see
449 the #ISR_N macro.
450*/
451# define ISR_ALIASOF(target_vector)
452#else /* !DOXYGEN */
453# define ISR_BLOCK /* empty */
454/* FIXME: This won't work with older versions of avr-gcc as ISR_NOBLOCK
455 will use `signal' and `interrupt' at the same time. */
456# ifdef __HAVE_SIGNAL_N__
457/* Use "noblock" if available. This works rather like a flag that can be
458 combined with "signal(n)" without imposing a specific function name,
459 like "interrupt" would do. */
460# define ISR_NOBLOCK __attribute__((__noblock__))
461# else
462# define ISR_NOBLOCK __attribute__((__interrupt__))
463# endif /* Have signal(n) and noblock */
464
465# define ISR_NAKED __attribute__((__naked__))
466
467#if (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || (__GNUC__ >= 5)
468# define ISR_FLATTEN __attribute__((__flatten__))
469#else
470# define ISR_FLATTEN /* empty */
471#endif /* has flatten (GCC 4.6+) */
472
473#if defined (__has_attribute)
474#if __has_attribute (__no_icf__)
475# define ISR_NOICF __attribute__((__no_icf__))
476#else
477# define ISR_NOICF /* empty */
478#endif /* has no_icf */
479
480#if __has_attribute (__no_gccisr__)
481# define ISR_NOGCCISR __attribute__((__no_gccisr__))
482#else
483# define ISR_NOGCCISR /* empty */
484#endif /* has no_gccisr */
485#endif /* has __has_attribute (GCC 5+) */
486
487# define ISR_ALIASOF(v) __attribute__((__alias__(__STRINGIFY(v))))
488#endif /* DOXYGEN */
489
490/**@}*/
491
492#endif