Dan*_*gen 2 c compiler-optimization avr-gcc
我正在使用avr-gcc 4.8.2编程Atmel ATtiny13a微控制器.
这是我的c代码:
#include <avr/io.h>
#include <util/delay.h>
int main(void) {
DDRB = 1; // PB0 is output
for (uint8_t i = 0; i < 10; i++) {
PORTB = 1;
_delay_ms(500);
PORTB = 0;
_delay_ms(500);
}
while(1);
}
void test(void) {
DDRB = 1; // PB0 is output
for (uint8_t i = 0; i < 10; i++) {
PORTB = 1;
_delay_ms(100);
PORTB = 0;
_delay_ms(100);
}
}
Run Code Online (Sandbox Code Playgroud)
从不通过主功能调用测试功能(LED快速闪烁),因此控制器只应进入主功能(慢速闪烁).
当我编译代码时-O1,一切正常:
avr-gcc -std=gnu99 -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -mmcu=attiny13 -DF_CPU=1200000 -Wall -Wstrict-prototypes -Os -c test.c -o test.o
avr-gcc test.o -o test.elf
avr-objcopy -O ihex -R .eeprom -R .fuse -R .lock -R .signature test.elf test.hex
Run Code Online (Sandbox Code Playgroud)
但是如果我使用-Os(优化尺寸)或者-O2,微控制器运行test功能而不是main功能:LED快速闪烁并且永不停止.
-Os标志是否太危险而无法使用,是否应该避免?或者我的代码中是否可以更改某些内容以避免此类错误?ATtiny13a只有1K的闪光灯,因此尺寸减小很重要.
编辑:正如评论中所建议的,这里是汇编器差异-O1和-O2:http://www.diffchecker.com/3l9cdln6
在那里,您可以看到-O2将第一部分更改.text为.text.startup.
--- test.o1.txt 2013-12-03 19:10:43.874598682 +0100
+++ test.o2.txt 2013-12-03 19:10:50.574674155 +0100
@@ -3,7 +3,7 @@
__SREG__ = 0x3f
__tmp_reg__ = 0
__zero_reg__ = 1
- .text
+ .section .text.startup,"ax",@progbits
.global main
.type main, @function
main:
Run Code Online (Sandbox Code Playgroud)
这可能是这里的主要问题.经过一些进一步的测试后,我发现罪魁祸首就是-freorder-functions优化.有没有办法防止这种行为?
我做了一些进一步的调试,发现"罪魁祸首"是-freorder-functions优化.它在联机帮助页中记录如下:
-freorder-functions
Reorder functions in the object file in order to improve code locality.
This is implemented by using special subsections ".text.hot" for most
frequently executed functions and ".text.unlikely" for unlikely executed
functions. Reordering is done by the linker so object file format must
support named sections and linker must place them in a reasonable way.
Run Code Online (Sandbox Code Playgroud)
文档中的最后一行解释了我遇到的问题.如果我们再次查看原始问题的编译命令:
$ avr-gcc -std=gnu99 -funsigned-char -funsigned-bitfields -fpack-struct \
-fshort-enums -mmcu=attiny13 -DF_CPU=1200000 -Wall -Wstrict-prototypes \
-Os -c test.c -o test.o
$ avr-gcc test.o -o test.elf
Run Code Online (Sandbox Code Playgroud)
...我们看到我将优化标志传递给编译器,但没有传递给链接器.我假设CFLAGS唯一影响编译而不是链接,所以我没有将它们传递给链接器,但在那种情况下我错了.
结果:汇编代码由编译器重新排序(包括适当的标签),但链接器不考虑这些标签.并且因为函数由编译器test放在函数之前main而不是由链接器重新排列,这就是在微控制器上实际执行的代码.
所以解决方案结果是:编译器标志也应该传递给链接器!