Engineer To Engineer Note EE-69
Notes on using Analog Devices’ DSP’s, audio, & video components from the Computer Products Division
Phone: (800) ANALOG-D , FAX: (781) 461-3010, EMAIL: dsp.support@analog.com
Understanding and Using
Linker Description Files (LDFs)
There are a number of cases in which a programmer
would like to control where a particular piece of code
or data resides in a 2106x’s memory space.
For example, on the 21065L it is possible to execute
from external memory, however this execution is
performed at a reduced rate. In this case, the
programmer will want to store and execute frequently
used code internally and rarely used code externally.
Regardless of if one wishes to relocate a C-function
or an assembly routine, the mechanism is the same.
To map portions of code or data to specific memory
segments, it is necessary to use the Linker
Description File (referred to as the LDF).
This application note will explain the functionality of
the LDF and demonstrate it’s features through an
example. The implementation details of specific
applications that require relatively complex LDF files
(such as the external code-execution example
previously mentioned) are beyond the scope of this
document.
_____________________________
The first step towards gaining an understanding of
the LDF is to first understand the makeup of the files
involved in building a DSP executable.
- Source Files -
At the beginning of it all, we have the source files.
These files contain code written in either C or
Assembly. The first step towards producing an
executable is to compile and/or assemble these
sources. The assembler outputs files called “object
files”. (The compiler outputs assembly files that are
then fed to the assembler.) VisualDSP produces
object files that have the extension .DOJ.
(Note: these object files are typically output to the
~/YourProject/debug directory.)
- Object Files -
The object files produced by the compiler and
assembler are divided up into various “sections” or
“segments” (referred to as Object Segments). Each
of these Object Segments is used to hold a particular
type of compiled source code. For example, such an
Object Segment may hold program op-codes (48-bits
wide) or data such as variables (16, 32 or 40-bits
wide). Some of these Object Segments also hold
information not pertinent to this discussion (since the
information isn’t important to the user - such as
debug-information, etc.).
Each of these different Object Segments has a
different name that is specified in the source code.
Depending on whether the source is C or assembly,
there is a different convention for specifying this
Object Segment Name.
In an assembly source, the code and/or data is placed
between the “.segment SegName” and the
“.endseg” statements will then be found in the
Object Segment called “SegName”. Here is an
example:
.segment /dm asmdata
.var foo[3];
.endseg
.segment /pm asmcode
r0 = 0x1234;
r1 = 0x4567;
r2 = r1 + r2;
.endsegment
Here, the Object Segment “asmdata” would contain
the array foo, and the 3-lines of code would be
located in the Object Segment “asmcode”.
In a C source the programmer would use the
segment(“seg_name”) directive. Here is an
example:
segment(“ext_data”) int temp;
a
segment("extern") void func1(void)
{
int x = 1;
}
void func2(void)
{
int i = 0;
}
When this C-file is compiled, the code generated from
func1 will be stored in its own separate Object
Segment of the of the .DOJ file named “extern”. The
variable “temp” will reside seperately in the
“ext_data”.
So what happens to func2? If an Object segment
Name isn’t specified, the compiler will use a set of
default names. So in this case, the object file would
hold the code from func2 in an Object Segment for
program code which happens to have a default Object
Segment Name of “seg_pmco”.
Page 2-60 of the “C Compiler Guide & Reference for the ADSP-2106x
Family DSPs” lists the default Object Segment Names.
(Note: there are no default Object Segment Names
for assembly source files, and the .segment/
.endseg statements MUST be used.)
How these Object Segments and Object Segment
Names relate to code placement in memory will be
illustrated later.
- Executable Files -
Once all of the source files have been assembled
and/or compiled into their respective object files, it is
then the job of the linker to combine all of these
object files into one integrated executable which has
the extension .DXE.
Just like the object file, the executable is broken up
into different “segments”. (As dictated by the ELF
[Executable and Linking Format] file standard that’s conformed
to by the .DXEs produced by Visual DSP.) These segments
are referred to as DXE Segments, and as you may
suspect, the segments have DXE Segment Names.
It is absolutely crucial to understand that these DXE
Segment Names are completely independent of the
Object Segment Names. They exist in different
name-spaces, which means that you can actually have
a DXE Segment Name that is exactly the same as an
Object Segment Name. (Unfortunately, in most
distributed examples, this is the case. This use of the
same name for different items, although legal, is poor
programming style and makes for a confusing LDF).
It is also important to understand the function of the
.DXE. The .DXE is not what is loaded into the DSP,
and it is not what is burned into an EPROM. This is
because the DXE contains “extra” information (in
addition to the raw code and data from the object
files.) This data is used by “down stream tools” such
as the Loader (used to create an EPROM) and the
Debugger (used for simulation/emulation), to
properly locate code in the DSP.
So How Does the LDF Relate to All of These
Different Files?
The linker’s job in all of this is reasonably
straightforward. Based on commands in the LDF
file, the linker takes all of the Object Segments from
all the object files, and using the memory model
declared in the LDF file, combines them all into a
single executable .DXE file.
So let’s look at an example LDF file to understand
how this process works! We will examine an LDF
that’s used to link assembly-only source code. This
is the simplest type of LDF because C-source code
needs to be supported in the LDF with additional
information about the C-run-time-header and other
such library information.
The remainder of this application-note will discuss Code
Listing 1 - test.ldf. Each numbered section below
describes a feature in the LDF file. The section number
corresponds to a number in the LDF file that we’ve added
(using the [#:] format) beside the LDF feature in question.
1) The first thing of interest in the LDF is the
Memory{} command. This defines the memory
model. It tells the linker what Memory Spaces are
available and gives them names called Memory Space
EE-69 Page 2
Notes on using Analog Devices’ DSP, audio, & video components from the Computer Products Division
Phone: (800) ANALOG-D or (617) 461-3881, FAX: (617) 461-3010, EMAIL: dsp.support@analog.com