如何指示avr-gcc优化volatile变量?

时间:2018-05-30 11:23:11

标签: gcc optimization microcontroller volatile avr-gcc

中断服务处理程序的代码:

volatile unsigned char x = 0;
void interruptHandler() __attribute__ ((signal));
void interruptHandler() {
    f();
    g();
}

呼叫:

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

因为x是一个易变量变量,所以每次使用它都会被读取和写入。中断处理程序的主体编译为(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

现在我可以手动内联函数并使用临时变量:

unsigned char y = x;
y ++;
y ++;
x = y;

或者我可以写:

x += 2;

两个示例都编译得更有效:

lds r24,x
subi r24,lo8(-(2))
sts x,r24

是否可以告诉avr-gcc优化对interruptHandler内部易变变量的访问,即自动进行手动优化?

毕竟,当interruptHandler正在运行时,全局中断被禁用,x无法更改。我不想手动优化代码,因此可能会创建重复的代码(如果在其他地方需要f()g())并引入错误。

2 个答案:

答案 0 :(得分:1)

  

是否可以告诉avr-gcc优化对interruptHandler内部的volatile变量的访问,即自动进行手动优化?

不,这在C语言中是不可能的。

  

毕竟,当interruptHandler正在运行时,全局中断被禁用

编译器知道这一点 - 你可以简单地将sei放入处理程序中以重新打开它们。

另请注意,硬件寄存器也被声明为volatile。其中一些 - 如UART数据寄存器 - 即使在读取时也会产生副作用。编译器不得删除任何读取或写入。

答案 1 :(得分:0)

如果您声明变量是易失性的,则对它的所有访问都是易失性的-编译器将按照源代码的说明准确地读写该变量,而无需组合它们或进行类似的优化。

因此,如果您要组合优化,则声明变量时不要使用“ volatile”-那么您将在中断代码中获得所需的内容。

然后从中断代码之外,您可以使用以下宏来强制进行易失性访问:

#define volatileAccess(v) *((volatile typeof((v)) *) &(v))

在中断代码外使用“ volatileAccess(x)”而不是“ x”。

别忘了“挥发”并不意味着“原子”!