Building Bare-Metal ARM Systems with GNU: Part 5
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.
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++
The compiler options controlling the C++ dialect discussed in the previous part of this article (the CPPFLAGS symbol) are closely related to 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 The mini_cpp.cpp module with non-throwing new and delete as well as dummy version of __aeabi_atexit().|
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
As mentioned in Part 1 of this article, placing strategic parts of the hot-spot code in RAM can significantly improve performance and reduce power dissipation of most ARM-based MCUs.
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
The provided code examples and the discussion should provide you with a head-start on any bare-metal ARM-based project with the GNU toolchain. Next in Part 6: ARM exceptions and interrupt handling.
To read Part 1, go to What's
need to get started.
To read Part 2, go to Startup code and the low level initialization
To read Part 3, go to The Linker Script.
To read Part 4, go to C and C++ compiler options
Miro Samek, Ph.D., is president of Quantum Leaps, LLC. He can be contacted at firstname.lastname@example.org.
 GNU Assembler (as) HTML documentation included in the CodeSourcery Toolchain for ARM.
 IAR Systems, "ARM IAR C/C++ Compiler Reference Guide for Advanced RISC Machines Ltd's ARM Cores", Part number: CARM-13, Thirteenth edition: June 2006. Included in the free EWARM KickStart edition
 Lewin A.R.W. Edwards, "Embedded System Design on a Shoestring", Elsevier 2003.
 ARM Projects.