| using_tools(3avr) | using_tools(3avr) |
using_tools - Using the GNU tools
This is a short summary of the AVR-specific aspects of using the GNU tools. Normally, the generic documentation of these tools is fairly large and maintained in texinfo files. Command-line options are explained in detail in the manual page.
The following machine-specific options are recognized by the C compiler frontend. The preprocessor will define the macros __AVR and __AVR__ (to the value 1) when compiling for an AVR target. The macro AVR will be defined as well, except in strict ANSI mode.
There are many options supported by avr-gcc, which also depend on the compiler version. For a complete overview, please see the documentation of avr-gcc's command line options. Here are links to supported options of the respective release series:
Apart from the documentation of command line options, the linked pages also contain:
Since GCC v5, the compiler no more supports indivitual devices, instead the compiler comes with device specs files that describe which options to use with each sub-processes like pre-processor, compiler proper, assembler and linker.
The purpose of these specs files is to add support for AVR devices that the compiler does not yet support.
The easiest way to add support for an unsupported device is to use device support from an atpack archive as provided by the hardware manufacturer. Apart from the mcu specific specs file, it provides device headers io*.h, startup code crtmcu.o and device library libmcu.a.
The following general gcc options might be of some interest to AVR users.
-O0 reduces compilation time and makes debugging produce
the expected results. This is the default.
Turning off all optimizations will prevent some warnings from being issued
since the generation of those warnings depends on code analysis steps that
are only performed when optimizing (unreachable code, unused variables).
Moreover, the delay routines in <util/delay.h>
require optimization to be turned on.
-O2 optimizes for speed, but without enabling very expensive optimizations like -O3 does.
-Os turns on all -O2 optimizations except those that often increase code size. In most cases, this is the preferred optimization level for AVR programs.
-Og optimizes debugging experience. This should be the optimization level of choice for the standard edit-compile-debug cycle, offering a reasonable level of optimization while maintaining fast compilation and a good debugging experience.
-O3 attempts to inline all 'simple' functions and might unroll some loops. For the AVR target, this will normally constitute a large pessimization due to the code increasement.
-O is equivalent to -O1. The compiler tries to reduce code size and execution time, without performing any optimizations that take a great deal of compilation time.
See also the appropriate FAQ entry for issues regarding debugging optimized code.
For example, GCC does not recognize the .asm file extension as assembly source. With -x assembler-with-cpp file.asm, the compiler first runs the C preprocessor on file.asm (so that #include <avr/io.h> can be used in assembly), and then calls the assembler.
Another use case is to compile a C file that's read from standard input, which is specified as - (dash) instead of the name of a source file. As no source file name is specified, the compiler must be told which language to use: The command
$ echo '#include <avr/io.h>' | avr-gcc -xc - -mmcu=atmega8 -E -dM | grep _VECTOR
pre-processes the C file #include <avr/io.h> and writes all
macro definitions to stdout. The output is then filtered by grep to show
all possible ISR vector names for ATmega8.
-x none returns to the default for the following inputs, i.e. infer the respective source languages from the file extensions.
-dumpbase and -dumpdir can be used to adjust file names and locations.
With -fverbose-asm, the compiler adds the high level source code to the assembly output. Compiling without debugging information (-g0) improves legibility of the generated assembly.
The preprocessed files can be used to check if macro expansions work as expected. With -g3 or higher, the preprocessed files will also contain all macro definitions and indications where they are defined: Built-in, on the command line, or in some header file as indicated by #line notes.
Default linker scripts are stored in a system-specific location (e. g. under /usr/local/avr/lib/ldscripts on Unix systems), and consist of the AVR architecture name (avr2 through avrxmega7) with the suffix .x appended. They describe how the various memory sections will be linked together and which input sections go into them. Notice that the default linker scripts are part of the linker binary, changing them on file will have no effect.
For a simple linker script augmentation, see the avr-gcc Wiki on named address spaces.
Notice that parts of the startup code are provided by libgcc.a.
To get rid of that, one can -nostdlib or -nodefaultlibs; however that
also removes other code like functions required for arithmetic. To just get
rid of the startup bits, define the respective symbols, for example
-Wl,--defsym,__do_clear_bss=0 and similar for __do_copy_data,
__do_global_ctors and __do_global_dtors.
Note: Sinve GCC v4.9.2, tablejump code uses the ELPM instruction to read from jump tables. In older version, use the -fno-jump-tables switch when compiling a bootloader for devices with more than 64 KiB of code memory.
However, this option also turns off all optimizations normally done by the compiler which assume that functions known by a certain name behave as described by the standard. For example, applying the function strlen() to a literal string will normally cause the compiler to immediately replace that call by the actual length of the string, while with -ffreestanding, it will always call strlen() at run-time.
Note
$ avr-gcc -x assembler-with-cpp file.asm ...
This allows to use C preprocessor directives like
#include <avr/io.h>
in assembly sources.
The various sub-options can be combined into a single -a option list; =file must be the last one in that case.
Remember that assembler options can be passed from the C compiler frontend using -Wa (see gcc_minusW above), so in order to include the C source code into the assembler listing in file foo.lss, when compiling foo.c, the following compiler command-line can be used:
$ avr-gcc -mmcu=atmega8 -c foo.c -o foo.o -Wa,-ahls=foo.lss
In order to pass an assembler file through the C preprocessor first, and have the assembler generate line number debugging information for it, the following command can be used:
$ avr-gcc -c -x assembler-with-cpp -o foo.o foo.asm -Wa,--gstabs
Note that on Unix systems that have case-distinguishing file systems, specifying a file name with the suffix .S (upper-case letter S) will make the compiler automatically assume -x assembler-with-cpp, while using .s would pass the file directly to the assembler (no preprocessing done).
Note
A number of the standard options might be of interest to AVR users.
By default, all unknown non-option arguments on the avr-gcc command-line (i. e., all filename arguments that don't have a suffix that is handled by avr-gcc) are passed straight to the linker. Thus, all files ending in .o (object files) and .a (object libraries) are provided to the linker.
System libraries are usually not passed by their explicit filename but rather using the -l option which uses an abbreviated form of the archive filename (see above). AVR-LibC ships system libraries, libc.a, libm.a and libmcu.a. While the standard library libc.a will always be searched for unresolved references when the linker is started using the C compiler frontend (i. e., there's always at least one implied -lc option), the mathematics library libm.a is only automatically added in GCC v4.7 and above. On older versions, it needs to be explicitly requested using -lm.
Conventionally, Makefiles use the make macro LDLIBS to keep track of -l (and possibly -L) options that should only be appended to the C compiler command-line when linking the final binary. In contrast, the macro LDFLAGS is used to store other command-line options to the C compiler that should be passed as options during the linking stage. The difference is that options are placed early on the command-line, while libraries are put at the end since they are to be used to resolve global symbols that are still unresolved at this point.
Specific linker flags can be passed from the C compiler command-line using the -Wl compiler option, see gcc_minusW above. This option requires that there be no spaces in the appended linker option, while some of the linker options above (like -Map or --defsym) would require a space. In these situations, the space can be replaced by an equal sign as well. For example, the following command-line can be used to compile foo.c into an executable, and also produce a link map that contains a cross-reference list in the file foo.map:
$ avr-gcc -mmcu=atmega8 foo.c -o foo.elf -Wl,-Map,foo.map -Wl,--cref
Alternatively, a comma as a placeholder will be replaced by a space before passing the option to the linker. So for a device with external SRAM, the following command-line would cause the linker to place the data segment at address 0x2000 in the SRAM:
$ avr-gcc -mmcu=atmega128 foo.c -o foo.elf -Wl,-Tdata,0x802000
See the explanation of the data section for why 0x800000 needs to be added to the actual value. Note that the stack will still remain in internal RAM, through the symbol __stack that is provided by the run-time startup code. This is probably a good idea anyway (since internal RAM access is faster), and even required for some early devices that had hardware bugs preventing them from using a stack in external RAM. Note also that the heap for malloc() will still be placed after all the variables in the data section, so in this situation, no stack/heap collision can occur.
In order to relocate the stack from its default location at the top of interns RAM, the value of the symbol __stack can be changed on the linker command-line. As the linker is typically called from the compiler frontend, this can be achieved using a compiler option like
-Wl,--defsym=__stack=0x8003ff
The above will make the code use stack space from RAM address 0x3ff downwards. The amount of stack space available then depends on the bottom address of internal RAM for a particular device. It is the responsibility of the application to ensure the stack does not grow out of bounds, as well as to arrange for the stack to not collide with variable allocations made by the compiler (sections .data and .bss).
| Version 2.2.1 | AVR-LibC |