【发布时间】:2013-12-03 16:46:00
【问题描述】:
我正在使用 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);
}
}
从不从主函数调用测试函数(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
但如果我使用-Os(尺寸优化)或-O2,微控制器会运行test 函数而不是main 函数:LED 快速闪烁并且永不停止。
-Os 标志是否太危险而无法使用,是否应该避免使用?或者我可以在我的代码中改变什么来避免这种错误? ATtiny13a 只有 1K 的闪存,因此减小尺寸很重要。
编辑:正如 cmets 中所建议的,这是 -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:
这可能是这里的主要问题。经过进一步测试,我发现罪魁祸首是-freorder-functions 优化。有没有办法防止这种行为?
【问题讨论】:
-
也许考虑使用
-S选项进行编译,仅编译为程序集。您可以查看或发布-Os和-O2的程序集,也许会有一些明显的东西。 -
@Macattack:谢谢,你很可能为我指明了正确的方向。请参阅原始帖子中的编辑以了解差异。
-
这里有一些(nongnu 文档)[nongnu.org/avr-libc/user-manual/mem_sections.html] 提到
.text,但信息充其量是稀疏的。知道编译后的步骤中发生了什么吗?我对这些构建步骤知之甚少。 -
@DaniloBargen 您在差异中显示的代码在
-O1和-O2之间是相同的(仅更改标签名称)。相同的代码怎么会有不同的行为?
标签: c compiler-optimization avr-gcc