Building Bare-Metal ARM Systems with GNU: Part 5 - Fine-tuning the Application
(07/23/07, 01:15:00 H EDT)
Editor's note: In this series of ten articles Miro Samek of Quantum Leaps details developing apps on the ARM processor using QNU, complete with source code in C and C++.
Earlier in this series he provided the basics of the design: (Part 1) on a simple LED blinker application; (Part 2) on the generic startup code and low level initialization; (Part 3) on the linker script for the C/C++ ARM-9 based Blinky application; and (Part 4) on the C and C++ compiler options that causes four user LEDs to light up on the Atmel AT91SAM7S-EK. In this part I describe the options for fine-tuning the application by selective ARM/Thumb compilation and by placing hot-spot parts of the code in RAM. The code accompanying this article is available online at Embedded.com's Downloadable Code page. ARM/THUMB compilation The compiler options discussed in Part 4 in this series (the CCFLAGS symbol) specifically do not include the instruction set option (-marm for ARM, and "mthumb for THUMB). This option is selected individually for every module in the Makefile. For example, in the following example the module low_level_init.c is compiled to THUMB and module blinky.c is compiled to THUMB: Reducing the Overhead of C++ However, disabling RTTI and exception handling at the compiler level is still not enough to prevent the GNU linker from pulling in some 50KB of library code. This is because the standard new and delete operators throw exceptions and therefore require the library support for exception handling. (Note: The new and delete operators are used in the static constructor/destructor invocation code, so are linked in even if you don't use the heap anywhere in your application.) Most low-end ARM-based MCUs cannot tolerate 50KB code overhead. To eliminate that code you need to define your own, non-throwing versions of global new and delete, which is done in the module mini_cpp.cpp located in the directory cpp_blinky.
Listing 1 above shows the minimal C++ support that eliminates entirely the exception handling code. The highlights are as follows: (1) The standard version of the operator new throws std::bad_alloc exception. This version explicitly throws no exceptions. This minimal implementation uses the standard malloc(). (2) This minimal implementation uses the standard free(). (3) The function __aeabi_atexit() handles the static destructors. In a bare-metal system this function can be empty because application has no operating system to return to, and consequently the static destructors are never called. Finally, if you don't use the heap, which you shouldn't in robust, deterministic applications, you can reduce the C++ overhead even further. The module no_heap.cpp provides dummy empty definitions of malloc() and free():
Placing the Code in RAM The startup code and the linker script discussed in Part 2 and Part 3 of this series support the .fastcode section that is located in RAM, but is loaded to ROM and copied to RAM upon startup. You have two options to assign individual functions to the .fastcode section: 1. Because each function is located in a separate section (see the "ffunction-sections compiler option described in part 4), you can explicitly locate the code for every function in the linker script for your applications. The linker scripts blinky.ld for the Blinky application provide an example how to locate the Blinky_shift() function in RAM. 2. You can assign any function to the .fastcode.text section, by means of the __attribute__ ((section (".text.fastcode"))) directive. The module blinky.c provides an example for the Blinky_flash() function.
Coming Up Next To read Part 1, go to What's need to get started. To download the C and C++ source code associated with this article series, go to Embedded.com's Downloadable Code page, or go to Blinky for C and Blinky for C++ to download the Zip files. Miro Samek, Ph.D., is president of Quantum Leaps, LLC. He can be contacted at miro@. References |
|
来自: lao_o > 《Embedded》