Embedded Systems Architecture
上QQ阅读APP看书,第一时间看更新

The cross-compiler

The cross-compiler distributed with a toolchain is in fact a variant of GCC, with the backend configured to build object files that contain machine code for a specific architecture. The output of the compilation are object files containing symbols that can only be interpreted by the specific target. arm-none-eabi-gcc is able to compile C code into machine instructions and CPU optimizations for several different targets.

The GCC backend for the ARM architecture supports a number of machine-specific options, to select the correct instruction set for the CPU, and the machine-specific optimization parameters.

The following table lists some of the ARM-specific machine options available on the GCC backend as -m flags:

Option Description
-marm / -mthumb Selects ARM or Thumb instruction set
-march=name Selects the architecture name within the family (for example, armv7)
-mtune=name Selects the CPU name for which GCC is optimized (for example, cortex-m3)
-mcpu=name Selects the CPU name for optimizations and architecture (can be used instead of -march and -mtune)

To compile code that is compatible with a generic ARM Cortex M4, the -mthumb and -mcpu=cortex-m4 options must be specified every time the compiler is invoked:

$ arm-none-eabi-gcc -c test.c -mthumb -mcpu=cortex-m4

The test.o file that is the result of this compile step is very different from the one that can be compiled, from the same source, using the host gcc. The difference can be better appreciated if instead of the two object files, the intermediate assembly code is compared. The compiler is in fact capable of creating intermediate assembly code files, instead of compiled and assembled objects, when it is invoked with the -S option.

Similarly to the host GCC compiler, there are different levels of possible optimization. In some cases, it makes sense to activate the size optimization to generate smaller object files. It is preferable, though, that the non-optimized image can fit the flash during the development, in order to facilitate the debugging procedures, as optimized code flow is more difficult to follow when the compiler may change the order of the execution of the code and hide away the content of some variables. The optimization parameter can be provided at the command line to select the desired optimization level:

Option Effect
-O0 Do not optimize—turn off optimizations
-O1 Optimize for performance
-O2 Optimize even more
-O3 Maximum level of performance optimization
-Os Optimize for size

Another generic GCC command-line option that is often used while debugging and prototyping is the -g flag, which instructs the compiler to keep the debugging-related data in the final object, in order to facilitate the access to functions' and variables' readable handles while running within the debugger.

To inform the compiler that we are running a bare-metal application, the -ffreestanding command-line option is used. In GCC jargon, a freestanding environment is defined by the possible lack of a standard library in the linking step, and most importantly, this option alerts the compiler that it should not expect to use the main function as the entry point of the program or provide any preamble code before the beginning of the execution. This option is required when compiling code for the embedded platforms, as it enables the boot mechanism described in Chapter 4, The Boot-up Procedure.

The GCC program supports many more command-line options than those quickly introduced here. For a more complete overview of the functionalities offered, please refer to the GNU GCC manual, available at https://gcc.gnu.org/onlinedocs/.

To integrate the cross-compiling toolchain in the automated build using Make, a few changes are required in the makefile.

Assuming that the toolchain is correctly installed on the development host and reachable in its executing path, it is sufficient to change the default compiler command using the CC Make variable in the makefile:

CC=arm-none-eabi-gcc

The custom command-line options required to run the compile options may be exported through the CFLAGS variable:

CFLAGS=-mthumb -mcpu=cortex-m4 -ffreestanding

Using default makefile variables, such as CC and CFLAGSenables implicit makefile rules, building object files from C sources with the same name and a custom compiler configuration.