Converting From Legacy Architecture
Files To Linker Description Files for
the ADSP-218x
Last modified: March 12, 2001
Introduction
This application note will explain how to describe
an ADSP-218x hardware memory architecture
using the latest version of the ADSP-218x
development tools, VisualDSP version 7.0. We
will go into excruciating detail to help explain
the differences between the use of linker
description files (.LDF) which are used by the
VisualDSP toolset to describe the system’s
hardware memory architecture, and the legacy
system (.SYS) and architecture (.ACH) files,
which were supported by the 5.x and 6.x ADSP2100 family development tools.
We’ll begin this engineering note with a generic
218x example, showing the differences between the
7.0 and the 5.x/6.x tools versions. We’ll then
provide another example showing how hardware
overlays are supported between the different tools
versions. The latest VisualDSP development tools
(7.0) provide enhanced support for hardware
memory overlays over the 5.x and 6.x development
tools. At the current time in which this engineering
note was written, the 7.0 tools version only supports
internal hardware overlays; support for software
overlays will be provided in an upcoming service
pack release. Please check our website at the
following address for development tools updates:
In the past (i.e. the 5.x and 6.x development tools
releases), life was pretty simple for the 218x when
declaring the memory used in your DSP system.
Only the internal memory of your processor was
declared. For processors with 16k/16k of PM and
DM or greater (ADSP-2187/2188/2189), no
additional on-chip hardware overlay memory
regions or external memory overlay regions were
declared. For processors with less than 16k/16k of
PM and DM respectively (ADSP-2184/2186), only
the proper amount of on-chip memory and overlay
memory regions were declared for your specific
processor was declared in your system file.
For example, if you were using an ADSP-2181 in
your system design, the following example is one
method to declare your DSP system file:
Example 2: Segmented Legacy System File (with vector table segment)
Here in example 2, we can see how the interrupt
vector table, ‘int_tbl’, is declared separately from
the rest of the internal PM region. Also, the mapping
of the PM/DM hardware overlay regions (both
Copyright 2001, 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 as sumed by Analog Devices
regarding the technical accuracy of the content provided in all Analog Devices’ Engineer-to-Engineer Notes.
internal and external) are declared. Using the 5.x
and 6.x tools, declaring a code or data module to a
specific memory region (which was declared in your
system file) was done by using the
“seg=segment_name” qualifier. For example, a code
module to place the interrupt vector table in the
memory segment “int_tbl” declared above would
look like the following:
Example 3: Legacy syntax to force a code module to a memory segment
The linker would use this “seg=” directive to
determine where in the DSP’s memory this code
segment should reside.
So if you’ve read this far, you’re probably
wondering where we’re going next, and when we’re
going to talk about using LDFs. Brace yourself for
some serious stuff below…
A Simple 2181 LDF Example (ASM only)
Example 4, titled “ADSP-2181 Assembly LDF
Example” in Appendix A, shows a basic LDF
example for a 2181 assembly system. We’ll start off
with just a simple example without any hardware
overlay declarations. (We’ll save the scary stuff for
later!)
From a first inspection of this example LDF, we see
that there are a few sections to this file. For the
MEMORY section of the LDF, things look
somewhat similar to the example 2 architecture file.
But there is also additional information in the LDF
which is used by the linker as well as the simulator
and emulator.
The first line of the LDF defines which specific
processor is being used in your system. The line,
ARCHITECTURE(ADSP-2181)
is analogous to the “.2181” processor type
declaration in the legacy architecture file.
The second line in this LDF example, is an LDF
macro which identifies the object and library files
generated by the assembler (from the source files) to
be used in their respective segments by the linker.
(FYI, all LDF macros are preceded by the dollar
sign “$”.)
The macro “$COMMAND_LINE_OBJECTS”
contains a listing of all of the object files (*.DOJ)
and library files (*.DLB) which are generated by the
assembler. This listing is then used by the
$OBJECTS macro, which is used by the linker to
perform specific placement of each object file to its
specific memory region. (The specific memory
region is defined by the user in the MEMORY
section of the LDF.)
The “MEMORY” section is the most familiar
section of the LDF for legacy 218x users. Here we
see how the different memory declarations are
performed.
Here we note that the start and end addresses of the
memory segment are declared in this portion of the
LDF. Also in an LDF file, there is a 5 hex digit field
for the address field. Veteran 21xx users are going
to say to themselves, “I thought that there were only
14 bits of addressing on the 218x? What’s up with
this 20-bit field?” For now all we’ll say is that the
most-significant hex digit represents the hardware
overlay region of the memory segment, also known
as the ‘live’ address of the memory overlay. We’ll
get into that later when we cover a hardware overlay
example for an ADSP-2189 processor.
We also see in the LDF that the data width for the
memory segment must also be declared in this
section. Program Memory segments must be
declared as 24 bits, using the “WIDTH(24)” LDF
command, and Data Memory segments must be
declared as 16 bits, using the “WIDTH(16)” LDF
command. Failure to declare these memory regions
with the proper data width will result in a linker
error.
EE-133 Page 2
Technical Notes on using Analog Devices’ DSP components and development tools
The “PROCESSOR” section is where the input
source files and output object files are used by the
linker to assign these objects to specific segments in
memory which were declared in the “MEMORY”
portion of the LDF. Since we’re only declaring a
single processor system, we only need one
“PROCESSOR” declaration in our LDF. (Note:
Since the linker is a shared resource between the
218x and 21xxx SHARC families, there is
multiprocessor support inherent to the LDF.
Multiple processor declarations are allowed for a
SHARC system, but they are not supported for a
218x LDF.) The name “p0” in this LDF example is
arbitrary; you can use any label or name for your
own LDF.
The first line in the ‘PROCESSOR’ section must
contain the following LDF command:
“OUTPUT(COMMAND_LINE_OUTPUT_FILE)”
Basically, this statement tells the linker to generate
an output file (*.DXE), which corresponds to the
name given in the project options page in the IDE or
by the name defined by the “-o” linker switch in a
DOS window.
The next section, titled “SECTIONS”, is where the
code objects are explicitly linked to their desired
memory locations. Let’s look at the interrupt vector
table section as an example.
The first heading “dxe_int_tbl” is actually an
intermediate label, which is used by the debugger,
simulator, and emulator utilities to allow them to
explicitly show the declared memory regions in their
respective disassembly windows.
The “INPUT_SECTIONS” command tells the linker
that the declared object files on this line will be
linked into the physical memory segment
“mem_int_tbl”, which we’ve declared in the
“MEMORY” section of the LDF. Here, the
“$OBJECTS” macro tells the linker to link in the
object file which contains the declaration:
.section/pm int_tbl;
This would be the first line of code in the source
code module which describes the interrupt vector
table. Here is what a 7.0 vector table declaration
might look like:
You can also explicitly define which object files get
linked to a specific section. For example, we may
wish to have two code objects named
“maincode.doj” and “function1.doj” reside in the
memory segment declared as “mem_int_pm”. This
would be implemented as shown in example 5
below:
The information described in this portion of the EE
note covers the 2189M assembly LDF example
included in Appendix A Example 6. (Due to the
sheer size of this example, it is more convenient to
include it in Appendix A and describe it in the
sections below.)
The first thing that you’ll notice when looking at
this LDF example is that there are a lot of memory
segments declared in the “MEMORY” section of the
LDF. The reason for this is simple: to define
hardware overlay regions for each hardware overlay,
you must declare a “live” and a “run” address.
Let’s look at the Program Memory overlay
declarations first. For the 2189M, internal Program
Memory occupies the address range 0x0000-0x1fff,
or 8k words of memory. All of the Program Memory
overlay regions occupy addresses 0x2000-0x3fff.
(Note: The PMOVLAY register determines which
overlay region is currently active, and determines
whether the active overlay is internal or external.
Please refer to the ADSP-218x Hardware Reference
Manual for more information on this register.)
Example 7: PM Overlay “Live/Run” memory declarations
From this LDF excerpt we can see that there are two
distinct sections to the Program Memory overlay
memory segment declarations. As mentioned above,
here is where we declare both the “live” and the
“run” memory segments for the hardware overlays.
The “run” segment corresponds to the physical
address of the 8k memory segment that the will be
the address of the instruction which is fetched and
executed by the Program Sequencer of the DSP,
addresses 0x2000-0x3fff. The “live” segment
declaration defines which physical hardware overlay
page the overlay memory region resides in.
(Note: For you legacy 218x users, the method of
defining the “live”overlay region was performed via
the “-po” and “-do” ld21 linker via the DOS
command line. The “run” address declarations
were done using a group file and the “-group”
linker command-line linker option.)
The segment declarations for the “live” addresses of
the overlay regions show an important feature of the
LDF. As mentioned earlier, you’ll notice that the
addresses are specified using 5 hex digits versus
using 4 hex digits. All of you hardcore 218x users
out there know that there’s only 14-bits of
addressing on the part, so what gives? The most
significant hex digit represents the hardware overlay
region (or the value of the PMOVLAY register) of
where the overlay region actually physically exists
on the DSP. For example the following LDF
statement, assigns the memory segment named
“mem_pmpage4” to Program Memory overlay four.
significant hex digit the value of four in our
eample.) The remaining 4 hex digits are used to
assign the 14-bit address of the overlay region, again
addresses 0x2000-0x3fff, as was done before in the
legacy architecture files.
For Data Memory overlay regions, basically things
are done in the same manner, except for the fact that
the Data Memory overlay regions are mapped to the
address range 0x0000-0x1fff. (Remember that the 32
memory-mapped control registers always reside in
the upper addresses of DM, 0x3fe0-0x3fff, so this is
an easy way to remember that this address range is
always internal Data Memory.)
EE-133 Page 4
Technical Notes on using Analog Devices’ DSP components and development tools
Example 9: DM Overlay “Live/Run” memory declarations
From example 9 above, we see again that there are
both “live” and “run” memory segments declared.
Here we’ve declared Data Memory hardware
overlay regions 0, 1, 2, 4, 5, 6, and 7. (FYI: Program
Memory Overlay 3 and Data Memory Overlay 3 are
not supported by the assembler.)
Again, from this excerpt from our example LDF, we
see how the Data Memory overlay regions are
mapped to their respective hardware overlay region.
As with the Program Memory overlays, the most
significant hex digit is used to define the hardware
page where the memory segment resides. For
example, the following line from the LDF example
assigns a memory segment named “mem_dmpage7”
to the hardware overlay region 7, which occupies
the address range 0x0000-0x1fff. Again, the
hardware page is defined by the most significant hex
digit (7 in this case), and the address range is
determined by the remaining 4 hex digits, which
represent the 14-bit address available on the 218x
family. (Please refer to example 10 below.)
Now that we’ve covered how to declare a hardware
overlay memory segment, it’s time to discuss how
we can now link an object module to one of these
specific memory regions.
Looking at the bottom of our 2189 LDF example
(line 67 to be specific), in the “SECTIONS” portion
of this file, you’ll see declarations for each overlay
region. Figure xx below is an example of how the
“run” segment for a Data Memory overlay is
declared.
From this excerpt, we see the declarations for two
Data Memory overlay regions, external regions 1
and 2, respectively. The PAGE_INPUT command
defines what information gets mapped to this
overlay segment by the linker. Simply put, all of the
information included between the curly braces of the
PAGE_INPUT declaration get linked in to this
specific overlay region.
The next LDF command, ALL_FIT, explicitly tells
the linker to include all of the declared objects
within the scope of the PAGE_INPUT command to
be placed into this overlay region. The
INPUT_SECTIONS command tells the linker which
objects are to be mapped into this overlay segment.
dxe_dmpage{
PAGE_INPUT{
ALGORITHM(ALL_FIT)
PAGE_OUTPUT(dm_page1.ovl)
INPUT_SECTIONS(DMOvly1.doj(dm_ovly_1))
}>mem_dmpage1 // assign to external DM overlay region #1
PAGE_INPUT{
ALGORITHM(ALL_FIT)
PAGE_OUTPUT(dm_page2.ovl)
INPUT_SECTIONS(DMOvly2.doj(dm_ovly_2))
}>mem_dmpage2 // assign to external DM overlay region #2
.
.
.
Example 11: Overlay Input & Output Sections
The last line within the scope of the PAGE_INPUT
section, is actually declared outside of the curly
braces of this section. This is where the explicit
assignment of the overlay segment to its actual
“live” memory region is defined.
EE-133 Page 5
Technical Notes on using Analog Devices’ DSP components and development tools
which assigns the overlay region to the “run”
segment for the overlay (for our example, DM
overlay region 2), which is declared in the
MEMORY section of the LDF.
Using LDFs With C
Now that we’ve discussed the “gory” details of the
LDF for an assembler example, let us now discuss
what is needed for C runtime support. First, we’ll
discuss how things worked in the past.
With the legacy 5.x and 6.x development tools, the
architecture file definitions were fairly simple. The
user was only responsible for declaring the actual
memory architecture of the specific processor that
they were using in their system. The heap and stack
segments were linked in automatically by the linker
(ld21.exe), and were not declared in the architecture
file. (If the legacy 218x user wished to modify the
length of the heap and stack memory segments, they
were required to edit and reassemble the files
heap.dsp and stack.dsp to reserve the desired
amount of Data Memory for these two memory
segments.)
With our LDF, the first thing that you’ll notice is
that there are explicit memory segment declarations
for both the heap and the stack, which again reside
in data memory. Changing the length of these two
segments is done by simply changing the address
range for each segment. These two segments must
be declared when using C.
For legacy users, the search path for the compiler to
locate library files was defined in your autoexec.bat
file with the “ADI_LIB” or “ADI_DSP”
environment variables. With our LDF, the following
line defines the search path for the compiler:
SEARCH_DIR($ADI_DSP\218x\lib)
Here, the LDF macro “$ADI_DSP” is assigned the
value of the directory path where the VisualDSP
development tools are installed. (By default, the
tools installation path is “C:\Program Files\Analog
Devices\VisualDSP”).
Another thing to notice is that the “$OBJECTS”
LDF macro has a lot more assigned to it. This macro
tells the linker that all of the objects listed on this
line are to be linked into the executable file
(*.DXE). Here is a brief description of what each
item on this line represents:
2189_int_tab.doj – This file is the interrupt vector
table which supports the C runtime environment.
Basically, it has C-style labels for each of the
interrupts in the interrupt vector table. This file is
analogous to the legacy file “2181_hdr.obj”.
218x_hdr.doj – This file contains the code for C
runtime environment initialization. For example,
this file is responsible for setting up the C runtime
stack and heap memory segments, assigning
appropriate values to the registers used by the
compiler, etc.
$COMMAND_LINE_OBJECTS – This LDF macro
is used to assign all of the user input object files (i.e.
all of your source modules) to the $OBJECTS LDF
macro in order for the linker to link in everything
into the executable.
Libio.dlb – This library file supports calls to the
stdio.h library.
Libc.dlb – This library file includes all of the C
runtime environment initialization library routines.
218x_exit.doj – This library file contains code
which is used upon exiting from the scope of main.
All of the files listed above must be included in your
LDF when using C.
EE-133 Page 6
Technical Notes on using Analog Devices’ DSP components and development tools