Building Bare-Metal ARM Systems with GNU: Part 5 -

Building Bare-Metal ARM Systems with GNU: Part 5


Editor's note: Inthis series of ten articles Miro Samek of Quantum Leaps detailsdeveloping apps on the ARM processor using QNU, complete with sourcecode in C and C++.

Earlier in this series he provided the basics of the design: (Part1) on asimple LED blinker application; (Part2)  on the generic startup code and low levelinitialization; (Part3) on the linker script for the C/C++ ARM-9 basedBlinky application; and (Part4) on the C and C++ compiler options thatcauses four user LEDs to light up on the AtmelAT91SAM7S-EK.

In this part I describe the options for fine-tuning the application byselective ARM/Thumb compilation and by placing hot-spot parts of thecode in RAM. The code accompanyingthis article is available online at's Downloadable Code page .

ARM/THUMB compilation
The compiler options discussed in Part4 in this series (the CCFLAGS symbol) specifically do notinclude the instruction set option (-marm for ARM, and “mthumb forTHUMB). This option is selected individually for every module in theMakefile. For example, in the following example the modulelow_level_init.c is compiled to THUMB and module blinky.c is compiledto THUMB:


Reducing the Overhead of C++
The compiler options controlling the C++ dialect discussed in theprevious part of this article (the CPPFLAGS symbol) are closely relatedto reducing the overhead of C++.

However, disabling RTTI and exception handling at the compiler levelis still not enough to prevent the GNU linker from pulling in some 50KBof library code. This is because the standard new and delete operatorsthrow exceptions and therefore require the library support forexception handling.

(Note: The new and deleteoperators are used in the static constructor/destructor invocationcode, so are linked in even if you don't use the heap anywhere in yourapplication. )

Most low-end ARM-based MCUs cannot tolerate 50KB code overhead. Toeliminate that code you need to define your own, non-throwing versionsof global new and delete, which is done in the module mini_cpp.cpplocated in the directory cpp_blinky.

Listing1 The mini_cpp.cpp module with non-throwing new and delete as well asdummy version of __aeabi_atexit().

Listing 1 above shows theminimal C++ support that eliminates entirely the exception handlingcode. The highlights are as follows:

(1) The standard version ofthe operator new throws std::bad_alloc exception. This versionexplicitly throws no exceptions. This minimal implementation uses thestandard malloc().

(2) This minimalimplementation uses the standard free().

(3) The function__aeabi_atexit() handles the static destructors.

In a bare-metal system this function can be empty becauseapplication has no operating system to return to, and consequently thestatic 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 evenfurther. The module no_heap.cpp provides dummy empty definitions ofmalloc() and free():

Placing the Code in RAM
As mentioned in Part 1 of this article, placingstrategic parts of the hot-spot code in RAM can significantly improveperformance and reduce power dissipation of most ARM-based MCUs.

Thestartup code and the linker script discussed in Part2 and Part 3 of this series supportthe .fastcode section that is located in RAM, but is loaded to ROM andcopied to RAM upon startup.

You have two options to assign individual functions to the .fastcodesection:

1. Because each function islocated in a separate section (see the “ffunction-sections compileroption described in part 4), you can explicitly locate the code forevery function in the linker script for your applications. The linkerscripts blinky.ld for the Blinky application provide an example how tolocate the Blinky_shift() function in RAM.

2. You can assign anyfunction to the .fastcode.text section, by means of the __attribute__((section (“.text.fastcode”))) directive. The module blinky.c providesan example for the Blinky_flash() function.

Coming Up Next
The provided code examples and the discussion should provide you with ahead-start on any bare-metal ARM-based project with the GNU toolchain.Next in Part 6: ARM exceptions andinterrupt handling.

To read Part 1, go to What'sneed to get started.
To read Part 2, go to Startup code and the low level initialization
To read Part 3, go to TheLinker Script.
To read Part 4, go to  Cand C++ compiler options

To download the C and C++ sourcecode associated with this article series, go to's Downloadable Code page , or go to Blinky for C and Blinky for C++ to download theZipfiles.

MiroSamek, Ph.D., is president of QuantumLeaps, LLC. He can be contacted at

[1] GNU Assembler (as) HTMLdocumentation included in the CodeSourcery Toolchain for ARM .
[2] 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 thefree EWARM KickStart edition
[3] Lewin A.R.W. Edwards, “EmbeddedSystem Design on a Shoestring“, Elsevier 2003.
[4] ARMProjects.

[5] GNU ARMtoolchain.

1 thought on “Building Bare-Metal ARM Systems with GNU: Part 5

  1. “1. There should be “low_level_init.c is compiled to ARM” instead of “THUMB”n2. Why the paragraph “Reducing the Overhead of C++” is duplicated? It appeared in previous part as well.”

    Log in to Reply

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.