6.4.2.5 AVR Attributes

These attributes are supported by the AVR back end:

signal
interrupt

These attributes apply to functions.

They specify that the function is an interrupt service routine (ISR). The compiler generates function entry and exit sequences suitable for use in an interrupt handler when one of the attributes is present.

The AVR hardware globally disables interrupts when an interrupt is executed.

  • ISRs with the signal attribute do not re-enable interrupts. It is save to enable interrupts in a signal handler. This “save” only applies to the code generated by the compiler and not to the IRQ layout of the application which is responsibility of the application.
  • ISRs with the interrupt attribute re-enable interrupts. The first instruction of the routine is a SEI instruction to globally enable interrupts.

The recommended way to use these attributes is by means of the ISR macro provided by avr/interrupt.h from AVR-LibC:

#include <avr/interrupt.h>

ISR (INT0_vect) // Uses the "signal" attribute.
{
    // Code
}

ISR (ADC_vect, ISR_NOBLOCK) // Uses the "interrupt" attribute.
{
    // Code
}

When both signal and interrupt are specified for the same function, then signal is silently ignored.

signal(num)
interrupt(num)

These attributes apply to functions.

They are similar to the signal and interrupt attributes (respectively) without arguments, but the IRQ number is supplied as an argument num to the attribute, rather than providing the ISR name itself as the function name:

__attribute__((signal(1)))
static void my_handler (void)
{
   // Code for __vector_1
}

Notice that the handler function needs not to be externally visible. The recommended way to use these attributes is by means of the ISR_N macro provided by avr/interrupt.h from AVR-LibC:

#include <avr/interrupt.h>

ISR_N (PCINT0_vect_num)
static void my_pcint0_handler (void)
{
   // Code
}

ISR_N (ADC_vect_num, ISR_NOBLOCK)
static void my_adc_handler (void)
{
    // Code
}

ISR_N can be specified more than once, in which case several interrupt vectors are pointing to the same handler function. This is similar to the ISR_ALIASOF macro provided by AVR-LibC, but without the overhead introduced by ISR_ALIASOF.

noblock

This attribute applies to functions.

It can be used together with the signal attribute to indicate that an interrupt service routine should start with a SEI instruction to globally re-enable interrupts. Using attributes signal and noblock together has the same effect like using the interrupt attribute. Using the noblock attribute without signal has no effect.

no_gccisr

This attribute applies to functions.

It specifies that GCC should not use the __gcc_isr pseudo instruction in a function with the interrupt or signal attribute aka. interrupt service routine (ISR). Use this attribute if the preamble of the ISR prologue should always read

push  __zero_reg__
push  __tmp_reg__
in    __tmp_reg__, __SREG__
push  __tmp_reg__
clr   __zero_reg__

and accordingly for the postamble of the epilogue—no matter whether the mentioned registers are actually used in the ISR or not. Situations where you might want to use this attribute include:

  • Code that (effectively) clobbers bits of SREG other than the I-flag by writing to the memory location of SREG.
  • Code that uses inline assembler to jump to a different function which expects (parts of) the prologue code as outlined above to be present.

To disable __gcc_isr generation for the whole compilation unit, use option -mno-gas-isr-prologues, see AVR Options.

OS_main
OS_task

This attribute applies to functions.

On AVR, functions with the OS_main or OS_task attribute do not save/restore any call-saved register in their prologue/epilogue.

The OS_main attribute can be used when there is guarantee that interrupts are disabled at the time when the function is entered. This saves resources when the stack pointer has to be changed to set up a frame for local variables.

The OS_task attribute can be used when there is no guarantee that interrupts are disabled at that time when the function is entered like for, e.g. task functions in a multi-threading operating system. In that case, changing the stack pointer register is guarded by save/clear/restore of the global interrupt enable flag.

The differences to the naked function attribute are:

  • naked functions do not have a return instruction whereas OS_main and OS_task functions have a RET or RETI return instruction.
  • naked functions do not set up a frame for local variables or a frame pointer whereas OS_main and OS_task do this as needed.
progmem

This attribute applies to variables.

The progmem attribute is used on the AVR to place read-only data in the non-volatile program memory (flash). The progmem attribute accomplishes this by putting respective variables into a section whose name starts with .progmem.

This attribute works similar to the section attribute but adds additional checking.

• Ordinary AVR cores with 32 general purpose registers:

progmem affects the location of the data but not how this data is accessed. In order to read data located with the progmem attribute (inline) assembler must be used.

/* Use custom macros from AVR-LibC */
#include <avr/pgmspace.h>

/* Locate var in flash memory */
const int var[2] PROGMEM = { 1, 2 };

int read_var (int i)
{
    /* Access var[] by accessor macro from avr/pgmspace.h */
    return (int) pgm_read_word (& var[i]);
}

AVR is a Harvard architecture processor and data and read-only data normally resides in the data memory (RAM).

See also the AVR Named Address Spaces section for an alternate way to locate and access data in flash memory.

• AVR cores with flash memory visible in the RAM address range:

On such devices, there is no need for attribute progmem or __flash qualifier at all. Just use standard C / C++. The compiler will generate LD* instructions. As flash memory is visible in the RAM address range, and the default linker script does not locate .rodata in RAM, no special features are needed in order not to waste RAM for read-only data or to read from flash. You might even get slightly better performance by avoiding progmem and __flash. This applies to devices from families avrtiny and avrxmega3, see AVR Options for an overview.

• Reduced AVR Tiny cores like ATtiny40:

The compiler adds 0x4000 to the addresses of objects and declarations in progmem and locates the objects in flash memory, namely in section .progmem.data. The offset is needed because the flash memory is visible in the RAM address space starting at address 0x4000.

Data in progmem can be accessed by means of ordinary C code, no special functions or macros are needed.

/* var is located in flash memory */
extern const int var[2] __attribute__((progmem));

int read_var (int i)
{
    return var[i];
}

Please notice that on these devices, there is no need for progmem at all.

io
io (addr)

This attribute applies to variables.

Variables with the io attribute are used to address memory-mapped peripherals in the I/O address range. No memory is allocated. If an address is specified, the variable is assigned that address, and the value is interpreted as an address in the data address space. Example:

volatile int porta __attribute__((io (__AVR_SFR_OFFSET__ + 0x2)));

Otherwise, the variable is not assigned an address, but the compiler will still use in and out instructions where applicable, assuming some other module assigns an address in the I/O address range. Example:

extern volatile int porta __attribute__((io));
io_low
io_low (addr)

The io_low attribute applies to variables.

This is like the io attribute, but additionally it informs the compiler that the object lies in the lower half of the I/O area, allowing the use of cbi, sbi, sbic and sbis instructions.

address (addr)

This attribute applies to variables.

Variables with the address attribute can be used to address memory-mapped peripherals that may lie outside the I/O address range. Just like with the io and io_low attributes, no memory is allocated.

volatile int porta __attribute__((address (0x600)));

This attribute can also be used to define symbols in C/C++ code which otherwise would require assembly, a linker description file or command-line options like -Wl,--defsym,a_symbol=value. For example,

int a_symbol __attribute__((weak, address (1234)));

will be compiled to

.weak a_symbol
a_symbol = 1234
absdata

This attribute applies to variables.

Variables in static storage and with the absdata attribute can be accessed by the LDS and STS instructions which take absolute addresses.

  • This attribute is only supported for the reduced AVR Tiny core like ATtiny40.
  • You must make sure that respective data is located in the address range 0x400xbf accessible by LDS and STS. One way to achieve this as an appropriate linker description file.
  • If the location does not fit the address range of LDS and STS, there is currently (Binutils 2.26) just an unspecific warning like

    module.cc:(.text+0x1c): warning: internal error: out of range error

See also the -mabsdata command-line option.