avr-libc  2.1.0
Standard C library for AVR-GCC

AVR Libc Home Page

AVRs

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: interrupt.h 2538 2017-06-11 15:16:05Z joerg_wunsch $ */
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" ::: "memory"); }
187 #else
188 # define EMPTY_INTERRUPT(vector) \
189  void vector (void) __attribute__ ((__signal__,__naked__,__INTR_ATTRS)); \
190  void vector (void) { __asm__ __volatile__ ("reti" ::: "memory"); }
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 # define ISR_ALIAS(vector, tgt) extern "C" void vector (void) \
229  __attribute__((__signal__, __naked__, __INTR_ATTRS)); \
230  void vector (void) { __asm__ __volatile__ ("%~jmp " __STRINGIFY(tgt) ::); }
231 #else /* !__cplusplus */
232 # define ISR_ALIAS(vector, tgt) void vector (void) \
233  __attribute__((__signal__, __naked__, __INTR_ATTRS)); \
234  void vector (void) { __asm__ __volatile__ ("%~jmp " __STRINGIFY(tgt) ::); }
235 #endif /* __cplusplus */
236 
237 #endif /* DOXYGEN */
238 
239 #if defined(__DOXYGEN__)
240 /** \def reti()
241  \ingroup avr_interrupts
242 
243  Returns from an interrupt routine, enabling global interrupts. This should
244  be the last command executed before leaving an ISR defined with the ISR_NAKED
245  attribute.
246 
247  This macro actually compiles into a single line of assembly, so there is
248  no function call overhead.
249 */
250 # define reti()
251 #else /* !DOXYGEN */
252 # define reti() __asm__ __volatile__ ("reti" ::: "memory")
253 #endif /* DOXYGEN */
254 
255 #if defined(__DOXYGEN__)
256 /** \def BADISR_vect
257  \ingroup avr_interrupts
258 
259  \code #include <avr/interrupt.h> \endcode
260 
261  This is a vector which is aliased to __vector_default, the vector
262  executed when an ISR fires with no accompanying ISR handler. This
263  may be used along with the ISR() macro to create a catch-all for
264  undefined but used ISRs for debugging purposes.
265 */
266 # define BADISR_vect
267 #else /* !DOXYGEN */
268 # define BADISR_vect __vector_default
269 #endif /* DOXYGEN */
270 
271 /** \name ISR attributes */
272 
273 #if defined(__DOXYGEN__)
274 /** \def ISR_BLOCK
275  \ingroup avr_interrupts
276 
277  Identical to an ISR with no attributes specified. Global
278  interrupts are initially disabled by the AVR hardware when
279  entering the ISR, without the compiler modifying this state.
280 
281  Use this attribute in the attributes parameter of the ISR macro.
282 */
283 # define ISR_BLOCK
284 
285 /** \def ISR_NOBLOCK
286  \ingroup avr_interrupts
287 
288  ISR runs with global interrupts initially enabled. The interrupt
289  enable flag is activated by the compiler as early as possible
290  within the ISR to ensure minimal processing delay for nested
291  interrupts.
292 
293  This may be used to create nested ISRs, however care should be
294  taken to avoid stack overflows, or to avoid infinitely entering
295  the ISR for those cases where the AVR hardware does not clear the
296  respective interrupt flag before entering the ISR.
297 
298  Use this attribute in the attributes parameter of the ISR macro.
299 */
300 # define ISR_NOBLOCK
301 
302 /** \def ISR_NAKED
303  \ingroup avr_interrupts
304 
305  ISR is created with no prologue or epilogue code. The user code is
306  responsible for preservation of the machine state including the
307  SREG register, as well as placing a reti() at the end of the
308  interrupt routine.
309 
310  Use this attribute in the attributes parameter of the ISR macro.
311 */
312 # define ISR_NAKED
313 
314 /** \def ISR_FLATTEN
315  \ingroup avr_interrupts
316 
317  The compiler will try to inline all called function into the ISR.
318  This has an effect with GCC 4.6 and newer only.
319 
320  Use this attribute in the attributes parameter of the ISR macro.
321 */
322 # define ISR_FLATTEN
323 
324 /** \def ISR_NOICF
325  \ingroup avr_interrupts
326 
327  Avoid identical-code-folding optimization against this ISR.
328  This has an effect with GCC 5 and newer only.
329 
330  Use this attribute in the attributes parameter of the ISR macro.
331 */
332 # define ISR_NOICF
333 
334 /** \def ISR_ALIASOF(target_vector)
335  \ingroup avr_interrupts
336 
337  The ISR is linked to another ISR, specified by the vect parameter.
338  This is compatible with GCC 4.2 and greater only.
339 
340  Use this attribute in the attributes parameter of the ISR macro.
341  Example:
342  \code
343  ISR (INT0_vect)
344  {
345  PORTB = 42;
346  }
347 
348  ISR (INT1_vect, ISR_ALIASOF (INT0_vect));
349  \endcode
350 */
351 # define ISR_ALIASOF(target_vector)
352 #else /* !DOXYGEN */
353 # define ISR_BLOCK /* empty */
354 /* FIXME: This won't work with older versions of avr-gcc as ISR_NOBLOCK
355  will use `signal' and `interrupt' at the same time. */
356 # define ISR_NOBLOCK __attribute__((__interrupt__))
357 # define ISR_NAKED __attribute__((__naked__))
358 
359 #if (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || (__GNUC__ >= 5)
360 # define ISR_FLATTEN __attribute__((__flatten__))
361 #else
362 # define ISR_FLATTEN /* empty */
363 #endif /* has flatten (GCC 4.6+) */
364 
365 #if defined (__has_attribute)
366 #if __has_attribute (__no_icf__)
367 # define ISR_NOICF __attribute__((__no_icf__))
368 #else
369 # define ISR_NOICF /* empty */
370 #endif /* has no_icf */
371 #endif /* has __has_attribute (GCC 5+) */
372 
373 # define ISR_ALIASOF(v) __attribute__((__alias__(__STRINGIFY(v))))
374 #endif /* DOXYGEN */
375 
376 /* \@} */
377 
378 #endif