Special Considerations

This page covers a few special considerations to keep in mind when working with interrupts on AVR MCUs.

Sharing Data with the ISR

Variables shared between the ISR and the main program must be declared as volatile and be global in scope.

When compiling using the optimizer, in a loop like the following one:

the compiler will typically access "flag" only once, and optimize further accesses completely away, since its code path analysis shows that nothing inside the loop could change the value of "flag" anyway.

To tell the compiler that this variable could be changed outside the scope of its code path analysis (e.g., within an interrupt service routine), the variable needs to be declared like this:

When the variable is declared volatile as above, the compiler makes certain that wherever the variable is updated or read it will always write changes back to SRAM memory and read the variable from SRAM.

Atomic Data Operations

For an operation to be considered atomic, it must guarantee uninterrupted access of a given variable. Many assembly languages provide this at certain levels, i.e., bit test and set, however, there is no provision to automatically provide atomicity of all variable types in the ANSI C language.

ANSI-C expressions and statements are non-atomic.

This issue can be problematic (in certain situations) when multi-byte variables are shared with an ISR.

While declaring such a variable as volatile ensures that the compiler will not optimize accesses to it away, it does not guarantee atomic access to it. Consider the following code example:

There is a chance that the main context will exit its while( ) loop when the variable ctr just reaches the value 0x00FF. This happens because the compiler cannot natively access a 16-bit variable atomically in an 8-bit CPU. So, when ctr is for example at 0x0100, the compiler then tests the low byte for 0, which succeeds. It then proceeds to test the high byte, but that moment the ISR triggers, and the main context is interrupted. The ISR will decrement the variable from 0x0100 to 0x00FF, then the main context proceeds. It now tests the high byte of the variable which is (now) also 0, so it concludes the variable has reached 0, and terminates the loop.

Atomic Access Macros

The AVR-LIBC Atomic library provides the ATOMIC_BLOCK macros which insert the appropriate interrupt protection when atomic access is desired. These macros operate via automatic manipulation of the Global Interrupt Status (I) bit of the SREG register. Exit paths from both block types are all managed automatically without the need for special considerations, i. e. the interrupt status will be restored to the same value it has been when entering the respective block.

Using the macros from this header file, the above code can be rewritten like:

The ATOMIC_BLOCK macro will install the appropriate interrupt protection before accessing variable ctr, so it is guaranteed to be consistently tested.

In this case, the parameter ATOMIC_RESTORESTATE causes the ATOMIC_BLOCK to restore the previous state of the SREG register, saved before the Global Interrupt Status flag bit was disabled. The net effect of this is to make the ATOMIC_BLOCK's contents guaranteed atomic, without changing the state of the Global Interrupt Status flag when execution of the block completes.

 Learn More

megaAVR® Interrupt Overview
Learn more >
megaAVR® Interrupt Configuration
Learn more >
megaAVR® Interrupt Example
Learn more >
© 2024 Microchip Technology, Inc.
Notice: ARM and Cortex are the registered trademarks of ARM Limited in the EU and other countries.
Information contained on this site regarding device applications and the like is provided only for your convenience and may be superseded by updates. It is your responsibility to ensure that your application meets with your specifications. MICROCHIP MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND WHETHER EXPRESS OR IMPLIED, WRITTEN OR ORAL, STATUTORY OR OTHERWISE, RELATED TO THE INFORMATION, INCLUDING BUT NOT LIMITED TO ITS CONDITION, QUALITY, PERFORMANCE, MERCHANTABILITY OR FITNESS FOR PURPOSE. Microchip disclaims all liability arising from this information and its use. Use of Microchip devices in life support and/or safety applications is entirely at the buyer's risk, and the buyer agrees to defend, indemnify and hold harmless Microchip from any and all damages, claims, suits, or expenses resulting from such use. No licenses are conveyed, implicitly or otherwise, under any Microchip intellectual property rights.