Building Bare-Metal ARM Systems with GNU: Part 3

In this part I move on to describe the GNU linker script for abare-metal ARM project. The code accompanying this article is availableonline at the Embedded.com’s Downloadable Code page . Therecommended reading for this part includes “Embedded System Design on aShoestring” by Lewin Edwards [1] ,specifically section “Ld—GNU Linker” in Chapter 3.

Linker Script
The linker script must match the startup code described in Part 2 ofthis article for all the section names and other linker symbols. Thelinker script cannot be generic, because it must define the specificmemory map of the target device, as well as other application-specificinformation.

The linker script is therefore named here blinky.ld, whichcorresponds to the Blinky example application that blinks the 4 userLEDs of the AT91SAM7S-EK board. The C version of the example for thisarticle is located in the c_blinky directory, while the C++ version inthe cpp_blinky directory.


Listing1 Linker script for the Blinky example application (AT91SAM7S64 MCU).

Listing 1 above shows thelinker script for the Blinky example application. The script is almostidentical for C and C++ versions, with the minor differences discussedlater in this section. The highlights of the linker script are asfollows:

(1) The OUTPUT_FORMATdirective specifies the format of the output image (elf32,little-endian, ARM)

(2) OUTPUT_ARCH specifiesthe target machine architecture.

(3) ENTRY explicitlyspecifies the first instruction to execute in a program

(4) The MEMORY commanddescribes the location and size of blocks of memory in the target.

(5) The region ROMcorresponds to the on-chip flash of the AT91SAM7S64 device. It cancontain read-only and executable sections (rx), it starts at 0x00100000and is 64KB in size.

(6) The region RAMcorresponds to the on-chip SRAM of the AT91SAM7S64 device. It cancontain read-only, read-write and executable sections (rwx), it startsat 0x00200000 and is 16KB in size.

(7) The following symbolsdenote the sizes of the ARM stacks. You need to adjust the sizes foryour particular application. The C-stack cannot be zero.

(8) The SECTIONS commandopens the definition of all the sections for the linker.

(9) The .reset sectioncontains the startup code (including the ARM vectors) and must belocated as the first section in ROM.

(10) This line locates all.text sections from the startup.o object module.

(11) The section size isaligned to the 4-byte boundary

(12) This section is loadeddirectly to the ROM region defined in the MEMORY command.

(13) The .ramvect sectioncontains the RAM-based ARM vector table and the secondary jump tableand must be loaded as the first section in RAM

(14) The ARM vector tableand the secondary jump table have known size of 0x40 bytes. The currentlocation counter is simply incremented to reserve 0x40 bytes for thesection.

(15) The .ramvect sectiongoes into the RAM region.

(16) The .fastcode sectionis used for RAM-based code, which needs to be loaded to ROM, but copiedand executed from RAM.

(17) The .fastcode sectionhas different load memory address (LMA) than the virtual memory address(VMA). The symbol __fastcode_load corresponds to the LMA in ROM and isneeded by the startup code to copy the section from ROM to RAM.

(18) The __fastcode_startsymbol corresponds to the VMA of the .fastcode section and is needed bythe startup code to copy the section from ROM to RAM.

(19) The .glue_7t and.glue_7 sections are synthesized by the compiler when you specify theARM-THUMB interworking option. The sections contain the “call veneers”between THUMB and ARM code and are accessed frequently by every callbetween ARM and THUMB. It's typically advantageous to place this smallamount of hot-spot code in RAM.

(20) The .text.fastcodesection is assigned explicitly to individual functions in the C/C++code by means of the __attribute__ ((section (“.text.fastcode”)))command.

(21) The GNU compiler isalso capable of placing each function in the separate section namedafter the function (requires specifying the option-ffunction-sections). This allows you to be very selective and to placeindividual functions (e.g. the function Blinky_shift()) in RAM.

NOTE: The C++ compiler performsfunction name-mangling and you need to consult the map file to figureout the section name assigned to a given function. For example, theclass method Blinky::shift() is placed in the section.text._ZN6Blinky5shiftEv)

(22) You can place morehot-spot functions in RAM during the fine-tuning stage of the project.

(23) The .fastcode sectionis located in RAM, but is loaded at the ROM address.

(24) The .text section isfor code and read-only data accessed in place.

(25) If you repeat sectionsalready located in the .fastcode section, the earlier location willtake precedence. However, if you decide to remove these sections from.fastcode, they will be located per the second specification.

(26) The following sectionsare synthesized by the GNU C++ compiler and are used for staticconstructors and destructors.

(27) The section .rodata isused for read-only (constant) data, such as look-up tables. Just ascode, you might choose to place some frequently accessed constants inRAM by locating these sections in the .fastcode section.

(28) The .text section islocated and loaded to ROM.

(29) The .ARM.exidx sectionis used for C++ exception handling. It is located here forcompleteness. Bare-metal ARM projects typically cannot afford theoverhead associated with C++ exceptions handling.

(30) The .data sectioncontains initialized data.

(31) The .data section islocated in RAM, but is loaded to ROM and copied to RAM during startup.

(32) The .bss sectioncontains uninitialized data. The C/C++ standard requires that thissection must be cleared at startup.

(33) The .bss section islocated in RAM only.

(34) The .stack sectioncontains all the stacks. The section is initialized with a givenbit-pattern at startup.

(35) The ARM GNU toolsetuses full descending stack. Therefore the linker script provides onlythe top of stack symbols to initialize the various ARM stack pointers.In particular the C stack (SYS stack) is allocated at the end of the.stack section.

(36) The .stack section islocated in RAM.

(37) The symbols _end,__end, and end are used to set up the beginning of the heap, if theheap is used.

(38) The following sectionsare for the debugger only and are never loaded to the target.

Coming Up Next
Next in Part 4 , I'll describethe C and C++ compiler options as well as how to minimize the overheadof C++ using the GNU toolchain. Stay tuned.

To read Part 1, go to What'sneeded to get started.
To read Part 2, go to StartupCode and the Low-level Initialization.

To download the C and C++ sourcecode 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 theZipfiles.

MiroSamek, Ph.D., is president of QuantumLeaps, LLC. He can be contacted at miro@quantum-leaps.com.

References
[1] Lewin A.R.W. Edwards, “EmbeddedSystem Design on a Shoestring“, Elsevier 2003.
[2]  
GNU Linker (ld) HTML documentation included in the CodeSourceryToolchain for ARM..
[3] ARMProjects  

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

  1. “Aujourd'hui, je reu00e7u une montre. Le garu00e7on est pas mon pru00e9fu00e9ru00e9, juste le mettre comme un ami, un bon ami du bien. Il m'a envoyu00e9 une montre, j'ai u00e9tu00e9 rejetu00e9. Mais il a dit qu'il ne connaissait pas le sens de la

    Log in to Reply

Leave a Reply

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