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