首页 文章

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

提问于
浏览
-1

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

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 内部的volatile变量的访问,即自动进行手动优化?

毕竟,当 interruptHandler 正在运行时,全局中断被禁用, x 无法更改 . 我更喜欢不必手动优化代码,从而可能创建重复的代码(如果在别处需要 f()g() )并引入错误 .

2 回答

  • 1

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

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

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

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

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

  • 0

    如果将变量声明为volatile,则对它的所有访问都是易失性的 - 编译器将完全读取和写入源代码所说的次数,而不是将它们组合或进行类似的优化 .

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

    然后从中断代码外部,你可以使用像这样的宏来强制进行易失性访问:

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

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

    只是不要忘记“挥发性”并不意味着“原子”!

相关问题