这个优化方法必须对makefile作修改,无法直接在avr studio中设置,所以新手慎用。 这几天avrfreaks上有个优化的讨论贴(我也顺便插了一脚^_^),EW大大推荐了一对优化参数 -combine -fwhole-program (这位EW大大就是winavr的工程管理者Eric Weddington,sf上的用户名是arcanum, 在avrfreaks上比较活跃的。顺便插播个新闻,他在某个帖子中说,他在这2个月内[最快这几天]打算发布新版的winavr, 增加对xmega的ATxmega128A1,ATxmega64A1,及ATmega32C1, ATmega32M1, ATmega32U4,ATtiny167等新mcu的支持, 当然也包括了gcc 4.3.0) 适用版本为winavr 20071221, 注意,20070525使用该参数是有bug的,会导致中断向量表无法和代码里的中断函数地址关联起来(向量表会全为默认地址) 先来看下我手头一个工程优化的效果对比(128的): -0s avrstudio的自动生成的makefile编译结果 Program: 40508 bytes (30.9% Full) (.text + .data + .bootloader) Data: 2519 bytes (61.5% Full) (.data + .bss + .noinit) 然后是-combine -fwhole-program Program: 35694 bytes (27.2% Full) (.text + .data + .bootloader) Data: 2160 bytes (52.7% Full) (.data + .bss + .noinit) 代码部分相差约4%,数据部分差约9%! 连data和bss段都被优化了?! 不过优化后的代码我还没有用实物实测过(手头暂时没有板子) 以下是这2个参数的解释(来自gcc 4.1.2文档): -combine : If you are compiling multiple source files, this option tells the driver to pass all the source files to the compiler at once (for those languages for which the compiler can handle this). This will allow intermodule analysis (IMA) to be performed by the compiler. Currently the only language for which this is supported is C. If you pass source files for multiple languages to the driver, using this option, the driver will invoke the compiler(s) that support IMA once each, passing each compiler all the source files appropriate for it. For those languages that do not support IMA this option will be ignored, and the compiler will be invoked once for each source file in that language. If you use this option in conjunction with ‘-save-temps’, the compiler will generate multiple pre-processed files (one for each source file), but only one (combined) ‘.o’ or ‘.s’ file. -fwhole-program : Assume that the current compilation unit represents whole program being compiled. All public functions and variables with the exception of main and those merged by attribute externally_visible become static functions and in a affect gets more aggressively optimized by interprocedural optimizers. While this option is equivalent to proper use of static keyword for programs consisting of single file, in combination with option ‘--combine’ this flag can be used to compile most of smaller scale C programs since the functions and variables become local for the whole combined compilation unit, not for the single source file itself. 简单的说,-combine会把所有指定的源代码文件一起传递给gcc(就类似把代码都写在一个c文件里),使得-fwhole-program能让gcc使用“模块互调分析”(IMA) (目前该分析功能只支持c语言,另外这个词的中文译文是我自己翻的^_^),对同一类语言的代码所有文件作为整体来分析其结构。 而-fwhole-program则会把除了main和externally_visible属性定义的变量或函数外的所有公共函数、变量做静态处理,成为内部的变量、函数。 要注意的事项: 1. -fwhole-program会导致目标文件中所有没有用externally_visible属性定义的变量或函数对外部不可见,所以库的编译一般不用这个参数 2. -fwhole-program应当是对整个工程代码为目标的做优化的,而不是单个源代码文件(那就完全失去全局性优化的意义,而且会因为上面说的不可见性,导致其它文件中无法调用该文件里的函数或变量) 3. 在极少数情况下,它可能会反而增加编译后的大小。 4. 要注意不能用20070525版编译。 5. 建议在一般-0s优化编译完成,并确认程序运行正常后,再使用该参数重新编译测试,不要在开发中就使用(因为使用了后,map文件里就看不到变量的地址分配了)。 设置方法: 这里我以avrstudio自动生成的makefile为基础来修改, 先找到OBJECTS的设置,比如我这里是这样的: ## Objects that must be built in order to link OBJECTS = exmem.o func.o init.o main.o timer.o twi_master_drv.o uart.o 等号后面的全部删除(我不需要编译出obj文件,只需要直接产生elf),变成这样: ## Objects that must be built in order to link OBJECTS = 然后找到## Compile,可以看到一长排这样的语句(每个c文件对应一个) ## Compile main.o: ../src/main.c $(CC) $(INCLUDES) $(CFLAGS) -c $< ... ##Link 把## Compile和##Link之间的全部删除, 再修改TARGET的规则: ##Link $(TARGET): $(OBJECTS) $(CC) $(LDFLAGS) $(OBJECTS) $(LINKONLYOBJECTS) $(LIBDIRS) $(LIBS) -o $(TARGET) 改为 ##Link $(TARGET): $(CC) $(INCLUDES) $(CFLAGS) $(wildcard ../src/*.c) $(LDFLAGS) $(LINKONLYOBJECTS) $(LIBDIRS) $(LIBS) -o $(TARGET) 我的c文件都在"../src/"这个目录下的,所以直接用wildcard函数。$(CFLAGS)里不要用-c参数。 最后,加入这2个参数: CFLAGS += -combine -fwhole-program OK,另存,接下来只要在avrstudio里选择使用这个外部makefile,rebuild all,就行了(别忘记测试下,我还没运行测试过(-_-;)。 至于倒底gcc如何在-0s基础上再优化的,有兴趣的网友可以去研究研究(我目前没空去比较了^_^) 其它优化参数还可以看一下我以前的帖子: 不链接未调用函数和用rjmp替换jmp实现方法 http://www.ouravr.com/bbs/bbs_content.jsp?bbs_sn=838274 另外,20070525如果要使用这对参数,需要使用自己根据中断函数改写的start file(比如改写avr-libc的gcrt1.S)来链接,而不能用gcc默认的启动代码。 本贴被 yyccaa 编辑过,最后修改时间:2008-03-27,13:37:06.