Code for an interrupt service handler:
volatile unsigned char x = 0;
void interruptHandler() __attribute__ ((signal));
void interruptHandler() {
f();
g();
}
Calls:
void f() { x ++; } // could be more complex, could also be in a different file
void g() { x ++; } // as `f()`, this is just a very simple example
Because x
is a volatile variable, it is read and written every time it is used. The body of the interrupt handler compiles to (avr-gcc -g -c -Wa,-alh -mmcu=atmega328p -Ofast file.c
):
lds r24,x
subi r24,lo8(-(1))
sts x,r24
lds r24,x
subi r24,lo8(-(1))
sts x,r24
Now I can manually inline the functions and employ a temporary variable:
unsigned char y = x;
y ++;
y ++;
x = y;
Or I can just write:
x += 2;
Both examples compile to the much more efficient:
lds r24,x
subi r24,lo8(-(2))
sts x,r24
Is it possible to tell avr-gcc
to optimize access to volatile variables inside of interruptHandler
, i.e. to do my manual optimization automatically?
After all, while interruptHandler
is running, global interrupts are disabled, and it is impossible for x
to change. I prefer not having to hand optimize code, thereby possibly creating duplicate code (if f()
and g()
are needed elsewhere) and introducing errors.