AVR-LibC  2.3.0
Standard C library for AVR-GCC
 

AVR-LibC Manual

AVR-LibC Sources

Main Page

User Manual

Lib­rary Refe­rence

FAQ

Exam­ple Pro­jects

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.
256
257 \note This macro creates a trampoline function for the aliased
258 macro. This will result in a two cycle penalty for the aliased
259 vector compared to the ISR the vector is aliased to, due to the
260 JMP/RJMP opcode used.
261
262 \deprecated
263 For new code, the use of ISR(..., ISR_ALIASOF(...)) or #ISR_N is
264 recommended. Notice that using #ISR_N does \e not impose a
265 JMP/RJMP overhead.
266
267 Example:
268 \code
269 ISR (INT0_vect)
270 {
271 PORTB = 42;
272 }
273
274 ISR_ALIAS (INT1_vect, INT0_vect);
275
276 // Alternative using ISR_N
277
278 ISR_N (INT0_vect_num)
279 ISR_N (INT1_vect_num)
280 static void my_int01_handler (void)
281 {
282 PORTB = 42;
283 }
284
285 // or
286
287 ISR (INT0_vect,
288 [attributes]
289 ISR_N (INT1_vect_num))
290 {
291 PORTB = 42;
292 }
293 \endcode
294*/
295# define ISR_ALIAS(vector, target_vector)
296#else /* real code */
297
298#ifdef __cplusplus
299# define ISR_ALIAS(vector, tgt) extern "C" void vector (void) \
300 __attribute__((__signal__, __naked__, __INTR_ATTRS)); \
301 void vector (void) { __asm__ __volatile__ ("%~jmp " __STRINGIFY(tgt) ::); }
302#else /* !__cplusplus */
303# define ISR_ALIAS(vector, tgt) void vector (void) \
304 __attribute__((__signal__, __naked__, __INTR_ATTRS)); \
305 void vector (void) { __asm__ __volatile__ ("%~jmp " __STRINGIFY(tgt) ::); }
306#endif /* __cplusplus */
307
308#endif /* DOXYGEN */
309
310/** \def reti()
311 \ingroup avr_interrupts
312
313 Returns from an interrupt routine, enabling global interrupts. This should
314 be the last command executed before leaving an #ISR defined with the
315 #ISR_NAKED attribute.
316
317 This macro actually compiles into a single line of assembly, so there is
318 no function call overhead.
319
320 \note According to the GCC documentation, the only code supported in
321 naked functions is \ref inline_asm "inline assembly".
322*/
323# define reti() __asm__ __volatile__ ("reti" ::: "memory")
324
325#if defined(__DOXYGEN__)
326/** \def BADISR_vect
327 \ingroup avr_interrupts
328
329 \code #include <avr/interrupt.h> \endcode
330
331 This is a vector which is aliased to \c __vector_default, the vector
332 executed when an IRQ fires with no accompanying ISR handler. This
333 may be used along with the ISR() macro to create a catch-all for
334 undefined but used ISRs for debugging purposes. It cannot be used
335 with #ISR_N since there is no associated interrupt number. */
336# define BADISR_vect
337#else /* !DOXYGEN */
338# define BADISR_vect __vector_default
339#endif /* DOXYGEN */
340
341/** \name ISR attributes */
342
343#if defined(__DOXYGEN__)
344/** \def ISR_BLOCK
345 \ingroup avr_interrupts
346
347 Identical to an ISR with no attributes specified. Global
348 interrupts are initially disabled by the AVR hardware when
349 entering the ISR, without the compiler modifying this state.
350
351 Use this attribute in the \c attributes parameter of the #ISR
352 and #ISR_N macros.
353*/
354# define ISR_BLOCK
355
356/** \def ISR_NOBLOCK
357 \ingroup avr_interrupts
358
359 ISR runs with global interrupts initially enabled. The interrupt
360 enable flag is activated by the compiler as early as possible
361 within the ISR to ensure minimal processing delay for nested
362 interrupts.
363
364 This may be used to create nested ISRs, however care should be
365 taken to avoid stack overflows, or to avoid infinitely entering
366 the ISR for those cases where the AVR hardware does not clear the
367 respective interrupt flag before entering the ISR.
368
369 Use this attribute in the \c attributes parameter of the #ISR and
370 #ISR_N macros.
371*/
372# define ISR_NOBLOCK
373
374/** \def ISR_NAKED
375 \ingroup avr_interrupts
376
377 ISR is created with no prologue or epilogue code. The user code is
378 responsible for preservation of the machine state including the
379 SREG register, as well as placing a reti() at the end of the
380 interrupt routine.
381
382 Use this attribute in the \c attributes parameter of the #ISR and
383 #ISR_N macros.
384
385 \note According to GCC documentation, the only code supported in
386 naked functions is \ref inline_asm "inline assembly".
387*/
388# define ISR_NAKED
389
390/** \def ISR_FLATTEN
391 \ingroup avr_interrupts
392
393 The compiler will try to inline all called function into the ISR.
394
395 Use this attribute in the \c attributes parameter of the #ISR and
396 #ISR_N macros.
397*/
398# define ISR_FLATTEN
399
400/** \def ISR_NOICF
401 \ingroup avr_interrupts
402
403 Avoid identical-code-folding optimization against this ISR.
404 This has an effect with GCC 5 and newer only.
405
406 Use this attribute in the \c attributes parameter of the #ISR and
407 #ISR_N macros.
408*/
409# define ISR_NOICF
410
411/** \def ISR_NOGCCISR
412 \ingroup avr_interrupts
413
414 Do not generate
415 <a href="https://sourceware.org/binutils/docs/as/AVR-Pseudo-Instructions.html">\c __gcc_isr pseudo instructions</a>
416 for this ISR.
417 This has an effect with
418 <a href="https://gcc.gnu.org/gcc-8/changes.html#avr">GCC 8</a>
419 and newer only.
420
421 Use this attribute in the \c attributes parameter of the #ISR and
422 #ISR_N macros.
423*/
424# define ISR_NOGCCISR
425
426/** \def ISR_ALIASOF(target_vector)
427 \ingroup avr_interrupts
428
429 The ISR is linked to another ISR, specified by the vect parameter.
430
431 Use this attribute in the \c attributes parameter of the #ISR macro.
432 Example:
433 \code
434 ISR (INT0_vect)
435 {
436 PORTB = 42;
437 }
438
439 ISR (INT1_vect, ISR_ALIASOF (INT0_vect));
440 \endcode
441
442 Notice that the #ISR_ALIASOF macro implements its own IRQ handler that
443 jumps to the aliased ISR, which means there is a run-time overhead of
444 a JMP/RJMP instruction. For an alternative without overhead, see
445 the #ISR_N macro.
446*/
447# define ISR_ALIASOF(target_vector)
448#else /* !DOXYGEN */
449# define ISR_BLOCK /* empty */
450/* FIXME: This won't work with older versions of avr-gcc as ISR_NOBLOCK
451 will use `signal' and `interrupt' at the same time. */
452# ifdef __HAVE_SIGNAL_N__
453/* Use "noblock" if available. This works rather like a flag that can be
454 combined with "signal(n)" without imposing a specific function name,
455 like "interrupt" would do. */
456# define ISR_NOBLOCK __attribute__((__noblock__))
457# else
458# define ISR_NOBLOCK __attribute__((__interrupt__))
459# endif /* Have signal(n) and noblock */
460
461# define ISR_NAKED __attribute__((__naked__))
462
463#if (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || (__GNUC__ >= 5)
464# define ISR_FLATTEN __attribute__((__flatten__))
465#else
466# define ISR_FLATTEN /* empty */
467#endif /* has flatten (GCC 4.6+) */
468
469#if defined (__has_attribute)
470#if __has_attribute (__no_icf__)
471# define ISR_NOICF __attribute__((__no_icf__))
472#else
473# define ISR_NOICF /* empty */
474#endif /* has no_icf */
475
476#if __has_attribute (__no_gccisr__)
477# define ISR_NOGCCISR __attribute__((__no_gccisr__))
478#else
479# define ISR_NOGCCISR /* empty */
480#endif /* has no_gccisr */
481#endif /* has __has_attribute (GCC 5+) */
482
483# define ISR_ALIASOF(v) __attribute__((__alias__(__STRINGIFY(v))))
484#endif /* DOXYGEN */
485
486/**@}*/
487
488#endif