AVR Libc Home Page | AVR Libc Development Pages | ||||
Main Page | User Manual | Library Reference | FAQ | Alphabetical Index | Example Projects |
00001 /* Copyright (c) 2002,2005,2007 Marek Michalkiewicz 00002 Copyright (c) 2007, Dean Camera 00003 00004 All rights reserved. 00005 00006 Redistribution and use in source and binary forms, with or without 00007 modification, are permitted provided that the following conditions are met: 00008 00009 * Redistributions of source code must retain the above copyright 00010 notice, this list of conditions and the following disclaimer. 00011 00012 * Redistributions in binary form must reproduce the above copyright 00013 notice, this list of conditions and the following disclaimer in 00014 the documentation and/or other materials provided with the 00015 distribution. 00016 00017 * Neither the name of the copyright holders nor the names of 00018 contributors may be used to endorse or promote products derived 00019 from this software without specific prior written permission. 00020 00021 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00022 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00023 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00024 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 00025 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00026 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00027 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00028 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00029 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00030 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00031 POSSIBILITY OF SUCH DAMAGE. */ 00032 00033 /* $Id: interrupt.h 2158 2010-06-10 15:48:28Z joerg_wunsch $ */ 00034 00035 #ifndef _AVR_INTERRUPT_H_ 00036 #define _AVR_INTERRUPT_H_ 00037 00038 #include <avr/io.h> 00039 00040 #if !defined(__DOXYGEN__) && !defined(__STRINGIFY) 00041 /* Auxiliary macro for ISR_ALIAS(). */ 00042 #define __STRINGIFY(x) #x 00043 #endif /* !defined(__DOXYGEN__) */ 00044 00045 /** 00046 \file 00047 \@{ 00048 */ 00049 00050 00051 /** \name Global manipulation of the interrupt flag 00052 00053 The global interrupt flag is maintained in the I bit of the status 00054 register (SREG). 00055 00056 Handling interrupts frequently requires attention regarding atomic 00057 access to objects that could be altered by code running within an 00058 interrupt context, see <util/atomic.h>. 00059 00060 Frequently, interrupts are being disabled for periods of time in 00061 order to perform certain operations without being disturbed; see 00062 \ref optim_code_reorder for things to be taken into account with 00063 respect to compiler optimizations. 00064 */ 00065 00066 #if defined(__DOXYGEN__) 00067 /** \def sei() 00068 \ingroup avr_interrupts 00069 00070 \code #include <avr/interrupt.h> \endcode 00071 00072 Enables interrupts by setting the global interrupt mask. This function 00073 actually compiles into a single line of assembly, so there is no function 00074 call overhead. However, the macro also implies a <i>memory barrier</i> 00075 which can cause additional loss of optimization. 00076 00077 In order to implement atomic access to multi-byte objects, 00078 consider using the macros from <util/atomic.h>, rather than 00079 implementing them manually with cli() and sei(). 00080 */ 00081 #define sei() 00082 #else /* !DOXYGEN */ 00083 # define sei() __asm__ __volatile__ ("sei" ::: "memory") 00084 #endif /* DOXYGEN */ 00085 00086 #if defined(__DOXYGEN__) 00087 /** \def cli() 00088 \ingroup avr_interrupts 00089 00090 \code #include <avr/interrupt.h> \endcode 00091 00092 Disables all interrupts by clearing the global interrupt mask. This function 00093 actually compiles into a single line of assembly, so there is no function 00094 call overhead. However, the macro also implies a <i>memory barrier</i> 00095 which can cause additional loss of optimization. 00096 00097 In order to implement atomic access to multi-byte objects, 00098 consider using the macros from <util/atomic.h>, rather than 00099 implementing them manually with cli() and sei(). 00100 */ 00101 #define cli() 00102 #else /* !DOXYGEN */ 00103 # define cli() __asm__ __volatile__ ("cli" ::: "memory") 00104 #endif /* DOXYGEN */ 00105 00106 00107 /** \name Macros for writing interrupt handler functions */ 00108 00109 00110 #if defined(__DOXYGEN__) 00111 /** \def ISR(vector [, attributes]) 00112 \ingroup avr_interrupts 00113 00114 \code #include <avr/interrupt.h> \endcode 00115 00116 Introduces an interrupt handler function (interrupt service 00117 routine) that runs with global interrupts initially disabled 00118 by default with no attributes specified. 00119 00120 The attributes are optional and alter the behaviour and resultant 00121 generated code of the interrupt routine. Multiple attributes may 00122 be used for a single function, with a space seperating each 00123 attribute. 00124 00125 Valid attributes are ISR_BLOCK, ISR_NOBLOCK, ISR_NAKED and 00126 ISR_ALIASOF(vect). 00127 00128 \c vector must be one of the interrupt vector names that are 00129 valid for the particular MCU type. 00130 */ 00131 # define ISR(vector, [attributes]) 00132 #else /* real code */ 00133 00134 #if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4) 00135 # define __INTR_ATTRS used, externally_visible 00136 #else /* GCC < 4.1 */ 00137 # define __INTR_ATTRS used 00138 #endif 00139 00140 #ifdef __cplusplus 00141 # define ISR(vector, ...) \ 00142 extern "C" void vector (void) __attribute__ ((signal,__INTR_ATTRS)) __VA_ARGS__; \ 00143 void vector (void) 00144 #else 00145 # define ISR(vector, ...) \ 00146 void vector (void) __attribute__ ((signal,__INTR_ATTRS)) __VA_ARGS__; \ 00147 void vector (void) 00148 #endif 00149 00150 #endif /* DOXYGEN */ 00151 00152 #if defined(__DOXYGEN__) 00153 /** \def SIGNAL(vector) 00154 \ingroup avr_interrupts 00155 00156 \code #include <avr/interrupt.h> \endcode 00157 00158 Introduces an interrupt handler function that runs with global interrupts 00159 initially disabled. 00160 00161 This is the same as the ISR macro without optional attributes. 00162 \deprecated Do not use SIGNAL() in new code. Use ISR() instead. 00163 */ 00164 # define SIGNAL(vector) 00165 #else /* real code */ 00166 00167 #ifdef __cplusplus 00168 # define SIGNAL(vector) \ 00169 extern "C" void vector(void) __attribute__ ((signal, __INTR_ATTRS)); \ 00170 void vector (void) 00171 #else 00172 # define SIGNAL(vector) \ 00173 void vector (void) __attribute__ ((signal, __INTR_ATTRS)); \ 00174 void vector (void) 00175 #endif 00176 00177 #endif /* DOXYGEN */ 00178 00179 #if defined(__DOXYGEN__) 00180 /** \def EMPTY_INTERRUPT(vector) 00181 \ingroup avr_interrupts 00182 00183 \code #include <avr/interrupt.h> \endcode 00184 00185 Defines an empty interrupt handler function. This will not generate 00186 any prolog or epilog code and will only return from the ISR. Do not 00187 define a function body as this will define it for you. 00188 Example: 00189 \code EMPTY_INTERRUPT(ADC_vect);\endcode */ 00190 # define EMPTY_INTERRUPT(vector) 00191 #else /* real code */ 00192 00193 #ifdef __cplusplus 00194 # define EMPTY_INTERRUPT(vector) \ 00195 extern "C" void vector(void) __attribute__ ((signal,naked,__INTR_ATTRS)); \ 00196 void vector (void) { __asm__ __volatile__ ("reti" ::); } 00197 #else 00198 # define EMPTY_INTERRUPT(vector) \ 00199 void vector (void) __attribute__ ((signal,naked,__INTR_ATTRS)); \ 00200 void vector (void) { __asm__ __volatile__ ("reti" ::); } 00201 #endif 00202 00203 #endif /* DOXYGEN */ 00204 00205 #if defined(__DOXYGEN__) 00206 /** \def ISR_ALIAS(vector, target_vector) 00207 \ingroup avr_interrupts 00208 00209 \code #include <avr/interrupt.h> \endcode 00210 00211 Aliases a given vector to another one in the same manner as the 00212 ISR_ALIASOF attribute for the ISR() macro. Unlike the ISR_ALIASOF 00213 attribute macro however, this is compatible for all versions of 00214 GCC rather than just GCC version 4.2 onwards. 00215 00216 \note This macro creates a trampoline function for the aliased 00217 macro. This will result in a two cycle penalty for the aliased 00218 vector compared to the ISR the vector is aliased to, due to the 00219 JMP/RJMP opcode used. 00220 00221 \deprecated 00222 For new code, the use of ISR(..., ISR_ALIASOF(...)) is 00223 recommended. 00224 00225 Example: 00226 \code 00227 ISR(INT0_vect) 00228 { 00229 PORTB = 42; 00230 } 00231 00232 ISR_ALIAS(INT1_vect, INT0_vect); 00233 \endcode 00234 */ 00235 # define ISR_ALIAS(vector, target_vector) 00236 #else /* real code */ 00237 00238 #ifdef __cplusplus 00239 # if defined(__AVR_MEGA__) && __AVR_MEGA__ 00240 # define ISR_ALIAS(vector, tgt) extern "C" void vector (void) \ 00241 __attribute__((signal, naked, __INTR_ATTRS)); \ 00242 void vector (void) { asm volatile ("jmp " __STRINGIFY(tgt) ::); } 00243 # else /* !__AVR_MEGA */ 00244 # define ISR_ALIAS(vector, tgt) extern "C" void vector (void) \ 00245 __attribute__((signal, naked, __INTR_ATTRS)); \ 00246 void vector (void) { asm volatile ("rjmp " __STRINGIFY(tgt) ::); } 00247 # endif /* __AVR_MEGA__ */ 00248 #else /* !__cplusplus */ 00249 # if defined(__AVR_MEGA__) && __AVR_MEGA__ 00250 # define ISR_ALIAS(vector, tgt) void vector (void) \ 00251 __attribute__((signal, naked, __INTR_ATTRS)); \ 00252 void vector (void) { asm volatile ("jmp " __STRINGIFY(tgt) ::); } 00253 # else /* !__AVR_MEGA */ 00254 # define ISR_ALIAS(vector, tgt) void vector (void) \ 00255 __attribute__((signal, naked, __INTR_ATTRS)); \ 00256 void vector (void) { asm volatile ("rjmp " __STRINGIFY(tgt) ::); } 00257 # endif /* __AVR_MEGA__ */ 00258 #endif /* __cplusplus */ 00259 00260 #endif /* DOXYGEN */ 00261 00262 #if defined(__DOXYGEN__) 00263 /** \def reti() 00264 \ingroup avr_interrupts 00265 00266 \code #include <avr/interrupt.h> \endcode 00267 00268 Returns from an interrupt routine, enabling global interrupts. This should 00269 be the last command executed before leaving an ISR defined with the ISR_NAKED 00270 attribute. 00271 00272 This macro actually compiles into a single line of assembly, so there is 00273 no function call overhead. 00274 */ 00275 # define reti() 00276 #else /* !DOXYGEN */ 00277 # define reti() __asm__ __volatile__ ("reti" ::) 00278 #endif /* DOXYGEN */ 00279 00280 #if defined(__DOXYGEN__) 00281 /** \def BADISR_vect 00282 \ingroup avr_interrupts 00283 00284 \code #include <avr/interrupt.h> \endcode 00285 00286 This is a vector which is aliased to __vector_default, the vector 00287 executed when an ISR fires with no accompanying ISR handler. This 00288 may be used along with the ISR() macro to create a catch-all for 00289 undefined but used ISRs for debugging purposes. 00290 */ 00291 # define BADISR_vect 00292 #else /* !DOXYGEN */ 00293 # define BADISR_vect __vector_default 00294 #endif /* DOXYGEN */ 00295 00296 /** \name ISR attributes */ 00297 00298 #if defined(__DOXYGEN__) 00299 /** \def ISR_BLOCK 00300 \ingroup avr_interrupts 00301 00302 \code# include <avr/interrupt.h> \endcode 00303 00304 Identical to an ISR with no attributes specified. Global 00305 interrupts are initially disabled by the AVR hardware when 00306 entering the ISR, without the compiler modifying this state. 00307 00308 Use this attribute in the attributes parameter of the ISR macro. 00309 */ 00310 # define ISR_BLOCK 00311 00312 /** \def ISR_NOBLOCK 00313 \ingroup avr_interrupts 00314 00315 \code# include <avr/interrupt.h> \endcode 00316 00317 ISR runs with global interrupts initially enabled. The interrupt 00318 enable flag is activated by the compiler as early as possible 00319 within the ISR to ensure minimal processing delay for nested 00320 interrupts. 00321 00322 This may be used to create nested ISRs, however care should be 00323 taken to avoid stack overflows, or to avoid infinitely entering 00324 the ISR for those cases where the AVR hardware does not clear the 00325 respective interrupt flag before entering the ISR. 00326 00327 Use this attribute in the attributes parameter of the ISR macro. 00328 */ 00329 # define ISR_NOBLOCK 00330 00331 /** \def ISR_NAKED 00332 \ingroup avr_interrupts 00333 00334 \code# include <avr/interrupt.h> \endcode 00335 00336 ISR is created with no prologue or epilogue code. The user code is 00337 responsible for preservation of the machine state including the 00338 SREG register, as well as placing a reti() at the end of the 00339 interrupt routine. 00340 00341 Use this attribute in the attributes parameter of the ISR macro. 00342 */ 00343 # define ISR_NAKED 00344 00345 /** \def ISR_ALIASOF(target_vector) 00346 \ingroup avr_interrupts 00347 00348 \code#include <avr/interrupt.h>\endcode 00349 00350 The ISR is linked to another ISR, specified by the vect parameter. 00351 This is compatible with GCC 4.2 and greater only. 00352 00353 Use this attribute in the attributes parameter of the ISR macro. 00354 */ 00355 # define ISR_ALIASOF(target_vector) 00356 #else /* !DOXYGEN */ 00357 # define ISR_BLOCK 00358 # define ISR_NOBLOCK __attribute__((interrupt)) 00359 # define ISR_NAKED __attribute__((naked)) 00360 # define ISR_ALIASOF(v) __attribute__((alias(__STRINGIFY(v)))) 00361 #endif /* DOXYGEN */ 00362 00363 /* \@} */ 00364 00365 #endif