I have installed WinARM, and compiled the AT91SAM7S64_Atmel_Interupt
project in the examples. And it runs. Excellent!
In the makefile, OPT=s (for smallest code size), FORMAT=binary. And it
creates a binary of 8196 bytes.
Doing the build of the Interupt demo project with the IAR compiler
yields a binary of only 2048 bytes.
I am hoping that I am just missing some step of the optimization or
stripping process. Why such the huge difference in filesize? I'd
expect some difference, but not a factor of 4!
- Joe
Joe Dupre wrote:
> I have installed WinARM, and compiled the AT91SAM7S64_Atmel_Interupt> project in the examples. And it runs. Excellent!>> In the makefile, OPT=s (for smallest code size), FORMAT=binary. And it> creates a binary of 8196 bytes.
This is because the "__inline" for the AT91-Library is not defined
correctly in this example so all functions from the library are linked
even if not needed. "__inline" should be defined as "static inline". As
can bee seen in the "newer" AT91SAM7S-examples in the WinARM-package or
from my "AT91-projects"-page. Sorry, I have forgotten to update the
example-code. I will upload an updated version to the web-server next
week. Please monitor the page:
http://www.siwawi.arubi.uni-kl.de/avr_projects/arm_projects/index_at91.html> Doing the build of the Interupt demo project with the IAR compiler> yields a binary of only 2048 bytes.
With the updated code and compiled with the tools from the WinARM
20060606-collection (arm-elf-gcc 4.1.1 etc.):
section size addr
.text 2084 1048576
.rodata 96 1050660
.bss 12 2097152
...
> I am hoping that I am just missing some step of the optimization or> stripping process. Why such the huge difference in filesize? I'd> expect some difference, but not a factor of 4!
Neither a problem with optimization nor with stipping (the binaries for
the target do not include debug-information), just my fault with the
__inline definition.
Martin Thomas
With my project which use libefsl and snprintf with float support, the
WinARM toolchain generates a binary file of 54276 bytes. In this case I
use the good __inline definition.
With the same project, the demo IAR toolchain generates a bin file of
31744 bytes.
So the file size has a factor of 1,70 between IAR and WinARM.
Does it seems ok for you? Or is it still possible de reduce the size?
Thank you.
Ralawa wrote:
> With my project which use libefsl and snprintf with float support, the> WinARM toolchain generates a binary file of 54276 bytes. In this case I> use the good __inline definition.> With the same project, the demo IAR toolchain generates a bin file of> 31744 bytes.>> So the file size has a factor of 1,70 between IAR and WinARM.>> Does it seems ok for you? Or is it still possible de reduce the size?
Yes it is kind of "ok". The stdio-functions in the newlib (the libc used
in the WinARM-collection and most of the other arm-elf-gcc collections)
need some memory esp. when using floating points.
Possibilities to reduce the size:
- convert the floating-points to strings or integers (int/frac
"Fixed-Point") with other methods/functions and use the
*iprinf-functions from the newlib. The integer-version have a smaller
memory-"footprint". You may even use something like "my_putstring" so
stdio is not needed at all. This is the method I usualy use. I have not
tried all following suggestions myself.
- try another libc like i.e. dietlibc. The stdio-functions in other
libraries have a smaller memory-demand. (Maybe a little difficult to
set-up)
- try replacement-functions like i.e. from the TRIO-library (
http://daniel.haxx.se/projects/trio/ ) or the contributed rprintf with
FP-support available at
http://www.siwawi.arubi.uni-kl.de/avr_projects/arm_projects/winarmtests/rprintf_fp_test.zip
- try/buy Rowley Crossworks. Rowley provides an "self-made" libc (not
newlibc, dietlibc,...) which may produce smaller binaries when using
stdio with FP
- stay with the IAR-tools and buy the full version.
Martin Thomas
Another reason why GCC often produces larger binaries than other
compilers is that unused functions are not removed. Since 4.0 the
compiler/linker can do this automatically if you add the following
options:
LDFLAGS:
-Wl,-Map=$(TARGET).map,--cref,--gc-section
CFLAGS:
-ffunction-sections -fdata-sections
@Martin: this should probably be included in the example Makefiles.
A "multi-reply" and some additional information which might be
interesting for all readers:
---
-> Andreas
Thanks for the reminder. A makefile with this settings has been on the
todo-list for some time.
---
I have modified an example from the LPC213x/4x "driver collection".
Download:
http://www.siwawi.arubi.uni-kl.de/avr_projects/arm_projects/lpc2k_bundle_port/index.html
So far only the example "uart_polled" integrates a modified makefile.
---
--> Ralawa
I have extended the example to use stdio-(i)printf and collected the
binary-sizes for several setups. The basic configuration creates
thumb/thumb-interwork binaries. All settings can be seen in the makefile
of the example. It seems that you compile a ARM-binary. Did you try to
build a thumb-binary so the "thumb-libc" gets linked? Does the
IAR-linker link with "thumb-libraries" or "ARM-libraries"?
---
For those who do not want to download the archive with the example a
copy of the table in uart_polled/main.c. It's not the best example for a
"size-benchmark" but should give an idea about the stdio-memory-usage.
/*
20060726 - mt
preserve MEMMAP and restore startup-value after memory-dump
20060727 - mt
- modified Makfile to enable gcc 4 "remove unused code"-feature
added (.bss.*) to linker-scripts
- demo for stdio: new file syscalls.c, USR stack-size had to be
increased for floating-points -> startup.S)
*/
/*
some "statistics" for this demo-application in revision 20060727 when
using the tools from WinARM 6/06 (gcc 4.1.1 et al)
r.u.c.(*) DEMO_STDIO DEMO_STDIO_FP .text .data .bss
[bytes]
no not defined not defined 2908 360 8
yes not defined not defined 2700 " "
diff: 208
no defined not defined 12156 2444 64
yes defined not defined 11976 " "
diff: 180
no defined defined 27172 2444 64
yes defined defined 26992 " " (#)
diff: 180
"OPT"-settings for configuration (#) (stdio/FP)
OPT .text .data .bss [bytes]
s 26992 2444 64
0 29108 " "
1 27296 " "
2 27272 " "
3 29360 " "
(*) r.u.c = remove unused code with -ffunction-sections -fdata-sections
for
the compilation and --gc-section for linking
yes : -ffunction-sections -fdata-sections used in CLFAGS
no : -ffunction-sections -fdata-sections not used in CFLAGS
*/
---
-> Jim Kaz wrote
> Any thoughts on what might I might be doing wrong?
Yes, at least an idea: please check your linker-script. The script from
the example mentioned above should give an idea. It should be rather
easy to port this to your AT91SAM7A linker-script.
---
Martin Thomas
I'm little confused about these flags.... In the GCC doc it says for
-ffunction-secionts and -fdata-sections:
Only use these options when there are significant benefits from doing
so. When
you specify these options, the assembler and linker will create larger
object and
executable files and will also be slower.
I must be misunderstanding this, because to me it sounds like the files
should be getting larger, where as in Martin's example they are clearly
getting smaller. Also, does anyone know how much of a performance hit
an application may take by doing this option? 1%, 50%? A broad range in
between that varies program to program that can only be checked by
myself? I'm figuring the third one, but I thought I'd ask just incase
:)
Oh, and the link to the zip file containing the examples is a dead link.
Jim Kaz wrote:
> I'm little confused about these flags.... In the GCC doc it says for> -ffunction-secionts and -fdata-sections:>> Only use these options when there are significant benefits from doing> so. When> you specify these options, the assembler and linker will create larger> object and> executable files and will also be slower.>> I must be misunderstanding this, because to me it sounds like the files> should be getting larger, where as in Martin's example they are clearly> getting smaller. Also, does anyone know how much of a performance hit> an application may take by doing this option? 1%, 50%? A broad range in> between that varies program to program that can only be checked by> myself? I'm figuring the third one, but I thought I'd ask just incase> :)>
I have not read enough of the documentation but this is how I understand
it so far: The idea behind these options (for compiler & linker) is to
eleminate unused code. I.e. if you have placed several functions in a
source-file which gets compiled to one object. The linking is normaly
(without the additional options) object-based so the complete object
gets linked even if only one of the functions in it is used by the
application. With the "new" options of GCC 4/binutils unused functions
are not linked even if they are in a object-file which contains a used
functions. The method seems to be: place every function in a an extra
section (which should lead to an inceased size of the object-code for
the additional information) and link "section-based" (not object-based).
I do not understand why this would lead to a "larger executable" too.
Maybe for an exectutable for a "real PC" which includes
debug-information. I think the "will be slower" is not ment for the code
of the target but for the build-process: The compiler, assembler and
linker have "more work to do" and will be slower.
As already written: my example is not a good "size benchmark". All
functions in the user code are rather small. So far I have not tried to
find which unused code has been removed. The c- and gcc-library should
be implemented as "one function per object" so only used functions of
the library get linked even when using the "old" method. This is why I
don't think the new options will lead to a decrease in the memory-demand
of functions from the library. But the libraries as in WinARM are not
compiled with the new options anyway, which would be needed to "measure"
this correctly.
> Oh, and the link to the zip file containing the examples is a dead link.
Sorry. The link has been fixed.
Martin Thomas
Martin Thomas wrote:
> --> Ralawa> I have extended the example to use stdio-(i)printf and collected the> binary-sizes for several setups. The basic configuration creates> thumb/thumb-interwork binaries. All settings can be seen in the makefile> of the example. It seems that you compile a ARM-binary. Did you try to> build a thumb-binary so the "thumb-libc" gets linked? Does the> IAR-linker link with "thumb-libraries" or "ARM-libraries"?
You are right, I did a mistake. libefsl was compiled with your makefile,
so it was compiled with the thumb mode, but my source code was not
compiled in thumb mode. I used SRCARM instead of SRC to compile.
I put all my C files in the SRC variable, also the interrupt services
routines. It works fine but I read that ISR should not be compiled in
ARM mode. Can you explain me why?
Know, the size of the binary file has been reduced by approximately 3kB
but it is still 1,6 bigger than the binary produced by the IAR compiler.
I am trying to use CFLAGS += -ffunction-sections -fdata-sections and
LDFLAGS = -nostartfiles -Wl,-Map=$(TARGET).map,--cref,--gc-sections to
reduce the binary size, but I have the following error:
Linking: main.elf
arm-elf-gcc -mthumb -mcpu=arm7tdmi -mthumb-interwork -I. -gdwarf-2
-DROM_RUN -D__WinARM__ -Os -Wall -Wcast-align -Wimplicit
-Wpointer-arith -Wswitch -Wredundant-decls -Wreturn-type -Wshadow
-Wunused -Wa,-adhlns=../compil/SrcWinARM/Cstartup.lst
-I../../efsl-0.2.7/conf -I../../efsl-0.2.7/inc -I../compil/SrcWinARM
-I../.. -ffunction-sections -fdata-sections -MD -MP -MF .dep/main.elf.d
../compil/SrcWinARM/Cstartup.o main.o ../compil/SrcWinARM/syscalls.o
uart0.o uart1.o commands.o one-wire.o nmea.o sdcard.o xmodem.o radars.o
s-cli.o clock.o ../../efsl-0.2.7/src/interfaces/at91_spi.o
../../efsl-0.2.7/src/interfaces/efsl_dbg_printf_arm.o
../../efsl-0.2.7/src/interfaces/sd.o ../../efsl-0.2.7/src/debug.o
../../efsl-0.2.7/src/dir.o ../../efsl-0.2.7/src/disc.o
../../efsl-0.2.7/src/efs.o ../../efsl-0.2.7/src/extract.o
../../efsl-0.2.7/src/fat.o ../../efsl-0.2.7/src/file.o
../../efsl-0.2.7/src/fs.o ../../efsl-0.2.7/src/ioman.o
../../efsl-0.2.7/src/ls.o ../../efsl-0.2.7/src/mkfs.o
../../efsl-0.2.7/src/partition.o ../../efsl-0.2.7/src/plibc.o
../../efsl-0.2.7/src/time.o ../../efsl-0.2.7/src/ui.o
../compil/SrcWinARM/Cstartup_SAM7.o --output main.elf -nostartfiles
-Wl,-Map=main.map,--cref,--gc-sections -lm -lc -lgcc
-T../compil/SrcWinARM/AT91SAM7S64-ROM.ld
c:/winarm/bin/../lib/gcc/arm-elf/4.1.1/../../../../arm-elf/bin/ld.exe:
internal error c:/winarms/binutils-060606/ld/ldlang.c 4260
collect2: ld returned 1 exit status
make.exe: *** [main.elf] Error 1
Do you have an idea about this error?
Thank you.
Ralawa wrote:
> I put all my C files in the SRC variable, also the interrupt services> routines. It works fine but I read that ISR should not be compiled in> ARM mode. Can you explain me why?
The core switches to ARM mode on excpetions (see the technical manual of
the used core-architecture). So the function to which a exception-vector
points to has to be build with ARM-instructions. When the
excpetion-vector entry does use the VIC (or AIC or ...) vector-address
directly the handlers have to be build in ARM-Mode. If you are using a
"wrapper" you can call functions build with thumb-instructions from
inside this wrapper (the wrapper itself has to be ARM-code). In most of
the codes which are based on the examples provided by Atmel a wrapper
written in Assembler is used (see *startup.S) so the "user functions"
can be compiled with thumb/thumb-iw.
> I am trying to use CFLAGS += -ffunction-sections -fdata-sections and> LDFLAGS = -nostartfiles -Wl,-Map=$(TARGET).map,--cref,--gc-sections to> reduce the binary size, but I have the following error:> Linking: main.elf> ...> c:/winarm/bin/../lib/gcc/arm-elf/4.1.1/../../../../arm-elf/bin/ld.exe:> internal error c:/winarms/binutils-060606/ld/ldlang.c 4260> collect2: ld returned 1 exit status> Do you have an idea about this error?
Please try to "rebuild": make clean; make all
Martin Thomas