如何防止 GCC 优化繁忙的等待循环? [英] How to prevent GCC from optimizing out a busy wait loop?
问题描述
我想为 Atmel AVR 微控制器编写 C 代码固件.我将使用 GCC 编译它.另外,我想启用编译器优化(-Os
或 -O2
),因为我认为没有理由不启用它们,它们可能会更快地生成更好的汇编方式而不是手动编写程序集.
I want to write a C code firmware for Atmel AVR microcontrollers. I will compile it using GCC. Also, I want to enable compiler optimizations (-Os
or -O2
), as I see no reason to not enable them, and they will probably generate a better assembly way faster than writing assembly manually.
但我想要一小段未优化的代码.我想将函数的执行延迟一段时间,因此我想编写一个什么都不做的循环来浪费一些时间.无需精确,只需等待一段时间.
But I want a small piece of code not optimized. I want to delay the execution of a function by some time, and thus I wanted to write a do-nothing loop just to waste some time. No need to be precise, just wait some time.
/* How to NOT optimize this, while optimizing other code? */
unsigned char i, j;
j = 0;
while(--j) {
i = 0;
while(--i);
}
由于 AVR 中的内存访问要慢很多,我希望 i
和 j
保存在 CPU 寄存器中.
Since memory access in AVR is a lot slower, I want i
and j
to be kept in CPU registers.
更新:我刚刚找到了 util/delay.h和 util/delay_basic.h 来自 AVR Libc.尽管大多数时候使用这些函数可能是一个更好的主意,但这个问题仍然有效且有趣.
Update: I just found util/delay.h and util/delay_basic.h from AVR Libc. Although most times it might be a better idea to use those functions, this question remains valid and interesting.
相关问题:
推荐答案
我在访问 dmckee 的答案,但它采用的方法与他/她的答案不同.
I developed this answer after following a link from dmckee's answer, but it takes a different approach than his/her answer.
Function Attributes 来自 GCC 的文档提到:
Function Attributes documentation from GCC mentions:
noinline
此函数属性可防止考虑内联函数.如果函数没有副作用,除了内联之外还有其他优化会导致函数调用被优化掉,尽管函数调用是实时的.为避免此类调用被优化掉,请将 asm ("");
noinline
This function attribute prevents a function from being considered for inlining. If the function does not have side-effects, there are optimizations other than inlining that causes function calls to be optimized away, although the function call is live. To keep such calls from being optimized away, putasm ("");
这给了我一个有趣的想法......我没有在内部循环中添加 nop
指令,而是尝试在其中添加一个空的汇编代码,如下所示:
This gave me an interesting idea... Instead of adding a nop
instruction at the inner loop, I tried adding an empty assembly code in there, like this:
unsigned char i, j;
j = 0;
while(--j) {
i = 0;
while(--i)
asm("");
}
它奏效了!该循环没有被优化掉,也没有插入额外的 nop
指令.
And it worked! That loop has not been optimized-out, and no extra nop
instructions were inserted.
更重要的是,如果你使用volatile
,gcc会将这些变量存储在RAM中并添加一堆ldd
和std
来复制它们到临时寄存器.另一方面,这种方法不使用 volatile
并且不会产生这样的开销.
What's more, if you use volatile
, gcc will store those variables in RAM and add a bunch of ldd
and std
to copy them to temporary registers. This approach, on the other hand, doesn't use volatile
and generates no such overhead.
更新: 如果您使用 -ansi
或 -std
编译代码,则必须替换 asm
带有 __asm__
的关键字,如 在 GCC 文档中所述.
Update: If you are compiling code using -ansi
or -std
, you must replace the asm
keyword with __asm__
, as described in GCC documentation.
此外,如果您的 HOWTO.html#ss5.4" rel="noreferrer">汇编语句必须在我们放置它的地方执行,(即不能作为优化从循环中移出).
In addition, you can also use __asm__ __volatile__("")
if your assembly statement must execute where we put it, (i.e. must not be moved out of a loop as an optimization).
这篇关于如何防止 GCC 优化繁忙的等待循环?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!