Provided by: avr-libc_2.2.1-1_all bug

NAME

       avr_interrupts - <avr/interrupt.h>: Interrupts

SYNOPSIS

   Global manipulation of the interrupt flag
       The global interrupt flag is maintained in the I bit of the status register (SREG).

       Handling interrupts frequently requires attention regarding atomic access to objects that could be
       altered by code running within an interrupt context, see <util/atomic.h>.

       Frequently, interrupts are being disabled for periods of time in order to perform certain operations
       without being disturbed; see Problems with reordering code for things to be taken into account with
       respect to compiler optimizations.
       #define sei()   __asm__ __volatile__ ('sei' ::: 'memory')
       #define cli()   __asm__ __volatile__ ('cli' ::: 'memory')

   Macros for writing interrupt handler functions
       #define ISR(vector,  attributes)
       #define SIGNAL(vector)
       #define EMPTY_INTERRUPT(vector)
       #define ISR_ALIAS(vector,  target_vector)
       #define reti()   __asm__ __volatile__ ('reti' ::: 'memory')
       #define BADISR_vect

   ISR attributes
       #define ISR_BLOCK
       #define ISR_NOBLOCK
       #define ISR_NAKED
       #define ISR_FLATTEN
       #define ISR_NOICF
       #define ISR_NOGCCISR
       #define ISR_ALIASOF(target_vector)

Detailed Description

       Note
           This discussion of interrupts was originally taken from Rich Neswold's document. See Acknowledgments.

   Introduction to AVR-LibC's interrupt handling
       It's nearly impossible to find compilers that agree on how to handle interrupt code. Since the C language
       tries to stay away from machine dependent details, each compiler writer is forced to design their method
       of support.

       In the AVR-GCC environment, the vector table is predefined to point to interrupt routines with
       predetermined names. By using the appropriate name, your routine will be called when the corresponding
       interrupt occurs. The device library provides a set of default interrupt routines, which will get used if
       you don't define your own.

       Patching into the vector table is only one part of the problem. The compiler uses, by convention, a set
       of registers when it's normally executing compiler-generated code. It's important that these registers,
       as well as the status register, get saved and restored.

       These details seem to make interrupt routines a little messy, but all these details are handled by the
       Interrupt API. An interrupt routine is defined with ISR(). This macro register and mark the routine as an
       interrupt handler for the specified peripheral. The following is an example definition of a handler for
       the ADC interrupt.

       #include <avr/interrupt.h>

       ISR(ADC_vect)
       {
           // user code here
       }

       Refer to the chapter explaining assembler programming for an explanation about interrupt routines written
       solely in assembly.

   Catch-all interrupt vector
       If an unexpected interrupt occurs (interrupt is enabled but no handler is installed, which usually
       indicates a bug), then the default action is to reset the device by jumping to the reset vector. You can
       override this by supplying a function named BADISR_vect which should be defined with ISR() as such. The
       name BADISR_vect is actually an alias for __vector_default. The latter must be used inside assembly code
       in case <avr/interrupt.h> is not included.

       #include <avr/interrupt.h>

       ISR(BADISR_vect)
       {
           // user code here
       }

   Nested interrupts
       The AVR hardware clears the global interrupt flag in SREG when an interrupt request is serviced. Thus,
       normally interrupts will remain disabled inside the handler until the handler exits, where the RETI
       instruction (that is emitted by the compiler as part of the normal function epilogue for an ISR) will
       eventually re-enable further interrupts. For that reason, interrupt handlers normally do not nest. For
       most interrupt handlers, this is the desired behaviour, for some it is even required in order to prevent
       infinitely recursive interrupts (like UART interrupts, or level-triggered external interrupts). In rare
       circumstances though it might be desired to re-enable the global interrupt flag as early as possible in
       the interrupt handler, in order to not defer any other interrupt more than absolutely needed. This could
       be done using an sei() instruction right at the beginning of the interrupt handler, but this still leaves
       few instructions inside the compiler-generated function prologue to run with global interrupts disabled.
       The compiler can be instructed to insert a SEI instruction right at the beginning of an interrupt handler
       by declaring the handler the following way:

       ISR(XXX_vect, ISR_NOBLOCK)
       {
         ...
       }

       where XXX_vect is the name of a valid interrupt vector for the MCU type in question, as explained below.

   Two vectors sharing the same code
       In some circumstances, the actions to be taken upon two different interrupts might be completely
       identical so a single implementation for the ISR would suffice. For example, pin-change interrupts
       arriving from two different ports could logically signal an event that is independent from the actual
       port (and thus interrupt vector) where it happened. Sharing interrupt vector code can be accomplished
       using the ISR_ALIASOF() attribute to the ISR macro:

       ISR(PCINT0_vect)
       {
         ...
         // Code to handle the event.
       }

       ISR(PCINT1_vect, ISR_ALIASOF(PCINT0_vect));

       Note
           There is no body to the aliased ISR.

       Note that the ISR_ALIASOF() feature requires GCC 4.2 or above (or a patched version of GCC 4.1.x). See
       the documentation of the ISR_ALIAS() macro for an implementation which is less elegant but could be
       applied to all compiler versions.

   Empty interrupt service routines
       In rare circumstances, in interrupt vector does not need any code to be implemented at all. The vector
       must be declared anyway, so when the interrupt triggers it won't execute the BADISR_vect code (which by
       default restarts the application).

       This could for example be the case for interrupts that are solely enabled for the purpose of getting the
       controller out of sleep_mode().

       A handler for such an interrupt vector can be declared using the EMPTY_INTERRUPT() macro:

       EMPTY_INTERRUPT(ADC_vect);

       Note
           There is no body to this macro.

   Manually defined ISRs
       In some circumstances, the compiler-generated prologue and epilogue of the ISR might not be optimal for
       the job, and a manually defined ISR could be considered particularly to speedup the interrupt handling.

       One solution to this could be to implement the entire ISR as manual assembly code in a separate
       (assembly) file. See Combining C and assembly source files for an example of how to implement it that
       way.

       Another solution is to still implement the ISR in C language but take over the compiler's job of
       generating the prologue and epilogue. This can be done using the ISR_NAKED attribute to the ISR() macro.
       Note that the compiler does not generate anything as prologue or epilogue, so the final reti() must be
       provided by the actual implementation. SREG must be manually saved if the ISR code modifies it, and the
       compiler-implied assumption of __zero_reg__ always being 0 could be wrong (e. g. when interrupting right
       after of a MUL instruction).

       Warning
           According to the GCC documentation, only inline assembly is supported in naked functions, like with
           ISR_NAKED.

       ISR(TIMER1_OVF_vect,  ISR_NAKED)
       {
         PORTB |= _BV(0);  // results in SBI which does not affect SREG
         reti();
       }

   Choosing the vector: Interrupt vector names
       The interrupt is chosen by supplying one of the vector names in the following table.

       There are currently two different styles present for naming the vectors.

       • Starting  with  AVR-LibC  v1.4,  the  style  of interrupt vector names is a short phrase for the vector
         description followed by _vect. The short phrase matches the vector name as described in  the  datasheet
         of  the  respective device (and in the hardware manufacturer's XML/ATDF files), with spaces replaced by
         an underscore and other non-alphanumeric characters dropped. Using the  suffix  _vect  is  intented  to
         improve portability to other C compilers available for the AVR that use a similar naming convention.

       • A  deprecated form that uses names starting with SIG_, followed by a relatively verbose but arbitrarily
         chosen name describing the interrupt vector. This has been the only available style in AVR-LibC  up  to
         version  1.2.x.  This  historical  naming  style  is not recommended for new projects, and some headers
         require that the macro __AVR_LIBC_DEPRECATED_ENABLE__ is defined so that the SIG_ names ISR  names  are
         available.

       Note
           The  ISR()  macro  cannot really spell-check the argument passed to them. Thus, by misspelling one of
           the names below used in ISR(), a function will be created that, while possibly  being  usable  as  an
           interrupt function, is not actually wired into the interrupt vector table. The compiler will generate
           a  warning  if it detects a suspiciously looking name of an ISR() function (i.e. one that after macro
           replacement does not start with '__vector_').

       Apart from the NAME_vect macros listed below, for each such ISR name there is also a macro  NAME_vect_num
       defined which resolves to the IRQ number. This is the index into the vector table, where indices start at
       index 0 (the reset vector).

       See  also  What  ISR  names  are available for my device? in the FAQ for how find all the IRQ names for a
       specific device.

        Vector Name Description Applicable for Device

       Note
           For the following devices, only the deprecated SIG_  names  are  available:  AT43USB320,  AT43USB355,
           AT76C711, AT90C8534, AT94K, M3000.

Macro Definition Documentation

   #define BADISR_vect
       #include <avr/interrupt.h>

       This  is  a  vector  which  is aliased to __vector_default, the vector executed when an IRQ fires with no
       accompanying ISR handler. This may be used along with the ISR() macro to create a catch-all for undefined
       but used ISRs for debugging purposes.

   #define cli()   __asm__ __volatile__ ('cli' ::: 'memory')
       Disables all interrupts by clearing the global interrupt mask. This function  actually  compiles  into  a
       single  line of assembly, so there is no function call overhead. However, the macro also implies a memory
       barrier which can cause additional loss of optimization.

       In  order  to  implement  atomic  access  to  multi-byte  objects,  consider  using   the   macros   from
       <util/atomic.h>, rather than implementing them manually with cli() and sei().

   #define EMPTY_INTERRUPT(vector)
       Defines  an  empty  interrupt handler function. This will not generate any prolog or epilog code and will
       only return from the ISR. Do not define a function body as this will define it for you. Example:

       EMPTY_INTERRUPT(ADC_vect);

   #define ISR(vector, attributes)
       Introduces an interrupt handler function (interrupt service routine) that  runs  with  global  interrupts
       initially disabled by default with no attributes specified.

       The  attributes  are  optional  and  alter  the  behaviour  and resultant generated code of the interrupt
       routine. Multiple attributes may be used for a single function, with a space seperating each attribute.

       Valid  attributes  are  ISR_BLOCK,  ISR_NOBLOCK,  ISR_NAKED,  ISR_FLATTEN,  ISR_NOICF,  ISR_NOGCCISR  and
       ISR_ALIASOF(vect).

       vector must be one of the interrupt vector names that are valid for the particular MCU type.

   #define ISR_ALIAS(vector, target_vector)
       Aliases  a  given  vector  to  another  one in the same manner as the ISR_ALIASOF attribute for the ISR()
       macro. Unlike the ISR_ALIASOF attribute macro however, this is compatible for all versions of GCC  rather
       than just GCC version 4.2 onwards.

       Note
           This  macro  creates  a  trampoline  function  for the aliased macro. This will result in a two cycle
           penalty for the aliased vector compared to the ISR the vector is aliased  to,  due  to  the  JMP/RJMP
           opcode used.

       Deprecated
           For new code, the use of ISR(..., ISR_ALIASOF(...)) is recommended.

       Example:

       ISR(INT0_vect)
       {
           PORTB = 42;
       }

       ISR_ALIAS(INT1_vect, INT0_vect);

   #define ISR_ALIASOF(target_vector)
       The  ISR  is  linked to another ISR, specified by the vect parameter. This is compatible with GCC 4.2 and
       greater only.

       Use this attribute in the attributes parameter of the ISR macro. Example:

       ISR (INT0_vect)
       {
           PORTB = 42;
       }

       ISR (INT1_vect, ISR_ALIASOF (INT0_vect));

   #define ISR_BLOCK
       Identical to an ISR with no attributes specified. Global interrupts are initially  disabled  by  the  AVR
       hardware when entering the ISR, without the compiler modifying this state.

       Use this attribute in the attributes parameter of the ISR macro.

   #define ISR_FLATTEN
       The  compiler  will  try  to inline all called function into the ISR. This has an effect with GCC 4.6 and
       newer only.

       Use this attribute in the attributes parameter of the ISR macro.

   #define ISR_NAKED
       ISR is created with no prologue or epilogue code. The user code is responsible for  preservation  of  the
       machine  state  including  the  SREG  register,  as  well as placing a reti() at the end of the interrupt
       routine.

       Use this attribute in the attributes parameter of the ISR macro.

       Note
           According to GCC documentation, the only code supported in naked functions is inline assembly.

   #define ISR_NOBLOCK
       ISR runs with global interrupts initially enabled. The interrupt enable flag is activated by the compiler
       as early as possible within the ISR to ensure minimal processing delay for nested interrupts.

       This may be used to create nested ISRs, however care should be taken to  avoid  stack  overflows,  or  to
       avoid  infinitely  entering  the ISR for those cases where the AVR hardware does not clear the respective
       interrupt flag before entering the ISR.

       Use this attribute in the attributes parameter of the ISR macro.

   #define ISR_NOGCCISR
       Do not generate __gcc_isr pseudo instructions for this ISR. This has an effect with GCC 8 and newer only.

       Use this attribute in the attributes parameter of the ISR macro.

   #define ISR_NOICF
       Avoid identical-code-folding optimization against this ISR. This has an effect with GCC 5 and newer only.

       Use this attribute in the attributes parameter of the ISR macro.

   #define reti()   __asm__ __volatile__ ('reti' ::: 'memory')
       Returns from an interrupt routine, enabling global interrupts. This should be the last  command  executed
       before leaving an ISR defined with the ISR_NAKED attribute.

       This macro actually compiles into a single line of assembly, so there is no function call overhead.

       Note
           According to the GCC documentation, the only code supported in naked functions is inline assembly.

   #define sei()   __asm__ __volatile__ ('sei' ::: 'memory')
       Enables  interrupts  by  setting the global interrupt mask. This function actually compiles into a single
       line of assembly, so there is no function call overhead. However, the macro also implies a memory barrier
       which can cause additional loss of optimization.

       In  order  to  implement  atomic  access  to  multi-byte  objects,  consider  using   the   macros   from
       <util/atomic.h>, rather than implementing them manually with cli() and sei().

   #define SIGNAL(vector)
       Introduces an interrupt handler function that runs with global interrupts initially disabled.

       This is the same as the ISR macro without optional attributes.

       Deprecated
           Do not use SIGNAL() in new code. Use ISR() instead.

Author

       Generated automatically by Doxygen for AVR-LibC from the source code.

AVR-LibC                                          Version 2.2.1                             avr_interrupts(3avr)