ANALOG DEVICES EE-069 Service Manual

Engineer-to-Engineer Note EE-069
a
Technical notes on using Analog Devices DSPs, processors and development tools
Visit our Web resources http://www.analog.com/ee-notes and http://www.analog.com/processors or e-mail processor.support@analog.com or processor.tools.support@analog.com for technical support.
Understanding and Using Linker Description Files on SHARC® Processors
Contributed by Matt Walsh Rev 2 – January 17, 2007

Introduction

Often, a programmer wants to control where a particular piece of code or data resides in a SHARC® processor’s memory space. For example, on ADSP-2106x, ADSP-2116x, and ADSP-2137x processors, it is possible to execute from external memory; however, execution is performed at a reduced rate. In this case, the program will need to store and execute frequently used code internally and store rarely used code externally.
Regardless whether you want to relocate a C function or an assembly routine, the mechanism is the same. To map portions of code or data to specific memory sections, it is necessary to use the Linker Description File (referred to as the .LDF file). This EE-Note explains the functionality of the .LDF file and demonstrates its features through an example. The implementation details of specific applications that require relatively complex files (such as the external code-execution example previously mentioned) are beyond the scope of this document.
This EE-Note applies to all SHARC
L
The first step toward gaining an understanding of the .LDF file is to understand the makeup of the files involved in building a processor executable (.DXE).
processors.
.LDF

Source Files

Source files contain code written in C or assembly. The first step toward producing an executable is to compile and/or assemble these source files. The assembler outputs files called object files. (The compiler outputs assembly files that are then fed to the assembler.) The VisualDSP++® assembler produces object files that have a .DOJ extension.
Typically, these object files are
L
output to the ~/YourProject/debug directory.

Object Files

Object files produced by the compiler and assembler are divided into various sections (referred to as object sections). Each of these objects section holds a particular type of compiled source code. For example, an object section may hold program opcodes (48-bits wide) or data such as variables (16, 32, or 40 bits wide). Some object sections information not pertinent to this discussion (since the information is not important to the user, such as debug-information, and so on). Each object section has a different name that is specified in the source code. Depending on whether the source is C or assembly, a different convention is used to specify the object section name.
also hold
Copyright 2002-2007, Analog Devices, Inc. All rights reserved. Analog Devices assumes no responsibility for customer product design or the use or application of customers’ products or for any infringements of patents or rights of others which may result from Analog Devices assistance. All trademarks and logos are property of their respective holders. Information furnished by Analog Devices applications and development tools engineers is believed to be accurate and reliable, however no responsibility is assumed by Analog Devices regarding technical accuracy and topicality of the content provided in Analog Devices Engineer-to-Engineer Notes.
a
In an assembly source, the code and/or data is placed below the .SECTION segment_name.
Refer to the following e
.SECTION /dm seg_dmda .VAR foo[3];
.SECTION /pm seg_pmco r0 = 0x1234; r1 = 0x4567; r2 = r1 + r2;
In the example above, the seg_dmda object section would contain the foo array, and the three lines of code would be located in the
seg_pmco object section.
In a C source file, the programmer would use the
section("segment_name") directive, for
example:
section("ext_data") int temp; section("ext_code") void func1(void) { int x = 1; } void func2(void) { int i = 0; }
When the C file above is compiled, the code generated from func1 will be stored in its own separate object section of the of the .DOJ file named separately in ext_data.
So what happens to func2? If an object section name is not specified, the compiler will use a default name. In this case, the object file would hold the code from for program code with a default object section name of seg_pmco.
ext_code. The temp variable will reside
xample.
func2 in an object section
The way that these object sections and object section names relate memory will be illustrated later.
to code placement in

Executable Files

Once the source files have been assembled and/or compiled into their respective object files, the linker combines these object files into one integrated executable, which has a .DXE extension.
Similar to object files, an executable is split into different sections. All .DXE files produced by the VisualDSP++ linker adhere to the splitting rules as dictated by the ELF (Executable and Linking Format) file standard. These sections are referred to as DXE sections, and have DXE
section names. DXE section names are completely independent
of object section names. They exist in different namespaces, which means that a DXE section name can be identical to an object section name. (Unfortunately, in most distributed examples, this is the case. Using the same name for different items, although valid, is poor programming style and makes the .LDF file look confusing.)
The .DXE file is not loaded into the processor, and it is not burned into an EPROM. A contains extra information (in addition to the raw code and data from the object files), which is used by down-stream tools such as the loader (to populate an EPROM) and the debugger (to simulate or emulate a processor) in locating code to the processor.
.DXE file
For the list of default object section names, refer to the VisualDSP++ C/C++ Compiler and Library Manual for SHARC Processors.
There are no default object section
L
Understanding and Using Linker Description Files (LDFs) on SHARC (EE-069) Page 2 of 7
names for assembly source files, and
.SECTION/ statements must be used.

.LDF Files vs. the Other Files

The linker’s job is reasonably straightforward. Based on commands in the .LDF file, the linker collects the object sections from the object files and combines them into a single executable
a
(.DXE) file using the memory model declared in
.LDF file.
the Let’s look at an example
.LDF file to understand
how this process works. We will examine an
.LDF file used to link assembly-only source code.
This is the simplest type of
.LDF file, because
C source code must be supported in the .LDF file with additional information about the C run-time header and other library information.
The following section of this document discusses
test.ldf (Listing 1). Each section below
includes a number that matches it to a corresponding portion of the
.LDF file, identified
with [#:] adjacent to the .LDF feature being described.

[1:] Memory{}

The first thing of interest in the .LDF file is the
Memory{} command, which defines the memory
model. It informs the linker as to the available
memory spaces and gives them names called memory space names. It’s important to
understand that the memory space names declared here have absolutely no relation to DXE object section names. The next notable feature of the .LDF file is used to bind (link) all of these various sections and name spaces together.
When the .DXE file created by the linker is loaded into the debugger or made ready for EPROM via the loader, each of these down­stream utilities will know where the different DXE sections reside on-chip.

[3:] $OBJECTS and $COMMAND_LINE_OBJECTS

A minor thing to note is that we have used
$OBJECTS interchangeably with $COMMAND_LINE_OBJECTS. This is because the $
symbol in the .LDF file is a macro definition. It works much like a #define statement in C.
These macro definitions, though unnecessary in this example, are quite useful when you have multiple object files. For instance, there are two options if you want to place all of the code portions (object sections) of multiple files into the same memory section. The first way is to explicitly list each object file, as follows:
seg_pmco { INPUT_SECTIONS( main.doj(seg_pmco) config.doj(seg_pmco) dsp.doj(seg_pmco) ) }> seg_pmco
The second way is to define a macro (as follows)

[2:] Sections{}

$OBJECTS = main.doj, config.doj, dsp.doj;
As mentioned, the second and perhaps most important piece of the
Sections{} portion, where the linker does the
.LDF file is the
and place the macro in the INPUT_SECTIONS{} portion of the .LDF file as follows:
real work. Based on three arguments to the
Sections{} command, the linker takes object
sections as inputs, places them in a DXE section, and then maps each DXE section to the specified memory space.
In test.ldf, for example, the first line in the
Sections{} command takes the object section
named seg_rth created in main.doj, places it in the DXE section named seg_rth, and maps that DXE section to the
Understanding and Using Linker Description Files (LDFs) on SHARC (EE-069) Page 3 of 7
seg_rth memory space.
seg_pmco { INPUT_SECTIONS( $OBJECTS (seg_pmco) ) } > seg_pmco
Both of these syntaxes are equivalent. They cause the linker to go through all of the object files listed, and if any object sections named
seg_pmco are found, it puts them into the same
DXE section (here
seg_pmco”), and then links
Loading...
+ 4 hidden pages