USRGUIDE
USRGUIDE
Development Toolkit
Version 2.50
User Guide
Release Information
Change History
Proprietary Notice
ARM, Thumb, StrongARM, and the ARM Powered logo are registered trademarks of ARM Limited.
Angel, ARMulator, EmbeddedICE, Multi-ICE, ARM7TDMI, ARM9TDMI, and TDMI are trademarks of
ARM Limited.
All other products or services mentioned herein may be trademarks of their respective owners.
Neither the whole nor any part of the information contained in, or the product described in, this document
may be adapted or reproduced in any material form except with the prior written permission of the copyright
holder.
The product described in this document is subject to continuous developments and improvements. All
particulars of the product and its use contained in this document are given by ARM in good faith. However,
all warranties implied or expressed, including but not limited to implied warranties of merchantability, or
fitness for purpose, are excluded.
This document is intended only to assist the reader in the use of the product. ARM Limited shall not be liable
for any loss or damage arising from the use of any information in this document, or any error or omission in
such information, or any incorrect use of the product.
ii Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Preface
This preface introduces the ARM Software Development Toolkit and its user
documentation. It contains the following sections:
• About this book on page iv
• Further reading on page vi
• Typographical conventions on page viii
• Feedback on page ix.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. iii
Preface
Organization
This book is organized into the following chapters:
Chapter 1 Introduction
Read this chapter for an introduction to the ARM Software Development
Toolkit version 2.5, and details of the changes that have been made since
version 2.11a.
iv Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Preface
Chapter 12 ARMulator
Read this chapter for an introduction to the ARM processor emulator.
Chapter 13 Angel
Read this chapter for a description of how to use the Angel debug
monitor. This chapter also provides information on porting Angel to your
own hardware.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. v
Preface
Further reading
This section lists publications from both ARM Limited and third parties that provide
additional information on developing for the ARM processor, and general information
on related topics such as C and C++ development.
ARM publications
This book contains reference information that is specific to the ARM Software
Development Toolkit. For additional information, refer to the following ARM
publications:
• ARM Software Development Toolkit Reference Guide (ARM DUI 0041)
• ARM Architectural Reference Manual (ARM DUI 0100)
• ARM Reference Peripheral Specification (ARM DDI 0062)
• ARM Target Development System User Guide (ARM DUI 0061)
• the ARM datasheet for your hardware device.
Other publications
This book is not intended to be an introduction to the C or C++ programming languages,
It does not try to teach programming in C or C++, and it is not a reference manual for
the C or C++ standards. The following texts provide general information:
ARM architecture
• Furber, S., ARM System Architecture (1996). Addison Wesley Longman, Harlow,
England. ISBN 0-201-40352-8.
vi Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Preface
• Ellis, M.A. and Stroustrup, B., The Annotated C++ Reference Manual (1990).
Addison-Wesley Publishing Company, Reading, Massachusetts. ISBN
0-201-51459-1.
This is a reference guide to C++.
C programming guides
• Kernighan, B.W. and Ritchie, D.M., The C Programming Language (2nd edition,
1988). Prentice-Hall, Englewood Cliffs, NJ, USA. ISBN 0-13-110362-8.
This is the original C bible, updated to cover the essentials of ANSI C.
• Harbison, S.P. and Steele, G.L., A C Reference Manual (second edition, 1987).
Prentice-Hall, Englewood Cliffs, NJ, USA. ISBN 0-13-109802-0.
This is a very thorough reference guide to C, including useful information on
ANSI C.
ANSI C reference
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. vii
Preface
Typographical conventions
The following typographical conventions are used in this book:
typewriter Denotes text that may be entered at the keyboard, such as commands, file
and program names, and source code.
typewriter Denotes a permitted abbreviation for a command or option. The
underlined text may be entered instead of the full command or option
name.
typewriter italic
Denotes arguments to commands and functions where the argument is to
be replaced by a specific value.
bold Highlights interface elements, such as menu names. Also used for
emphasis in descriptive lists, where appropriate, and for ARM processor
signal names.
typewriter bold
Denotes language keywords when used outside example code.
viii Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Preface
Feedback
ARM Limited welcomes feedback on both the Software Development Toolkit, and the
documentation.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. ix
Preface
x Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Contents
User Guide
Preface
About this book ...............................................................................................iv
Further reading ...............................................................................................vi
Typographical conventions ........................................................................... viii
Feedback ........................................................................................................ix
Chapter 1 Introduction
1.1 About the ARM Software Development Toolkit ............................................ 1-2
1.2 Supported platforms ..................................................................................... 1-5
1.3 What is new? ............................................................................................... 1-6
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. xi
Chapter 4 Command-Line Development
4.1 The hello world example .............................................................................. 4-2
4.2 armsd ........................................................................................................... 4-6
xii Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
9.12 System mode ............................................................................................. 9-46
Chapter 12 ARMulator
12.1 About the ARMulator .................................................................................. 12-2
12.2 ARMulator models ..................................................................................... 12-3
12.3 Tracer ......................................................................................................... 12-6
12.4 Profiler ...................................................................................................... 12-12
12.5 Windows Hourglass ................................................................................. 12-13
12.6 Watchpoints ............................................................................................. 12-14
12.7 Page table manager ................................................................................. 12-15
12.8 armflat ...................................................................................................... 12-19
12.9 armfast ..................................................................................................... 12-20
12.10 armmap .................................................................................................... 12-21
12.11 Dummy MMU ........................................................................................... 12-24
12.12 Angel ........................................................................................................ 12-25
12.13 Controlling the ARMulator using the debugger ........................................ 12-27
12.14 A sample memory model ......................................................................... 12-29
12.15 Rebuilding the ARMulator ........................................................................ 12-32
12.16 Configuring ARMulator to use the example ............................................. 12-34
Chapter 13 Angel
13.1 About Angel ............................................................................................... 13-2
13.2 Developing applications with Angel .......................................................... 13-10
13.3 Angel in operation .................................................................................... 13-27
13.4 Porting Angel to new hardware ................................................................ 13-41
13.5 Configuring Angel .................................................................................... 13-67
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. xiii
13.6 Angel communications architecture ......................................................... 13-71
13.7 Angel C library support SWIs .................................................................. 13-77
13.8 Angel debug agent interaction SWIs ....................................................... 13-92
13.9 The Fusion IP stack for Angel ................................................................. 13-96
xiv Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Chapter 1
Introduction
This chapter introduces the ARM Software Development Toolkit version 2.50 and
describes the changes that have been made since SDT version 2.11a. It contains the
following sections:
• About the ARM Software Development Toolkit on page 1-2
• Supported platforms on page 1-5
• What is new? on page 1-6.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 1-1
Introduction
You can use the SDT to develop, build, and debug C, C++, or ARM assembly language
programs.
The ARM Software Development Toolkit consists of the following major components:
• command-line development tools
• Windows development tools
• utilities
• supporting software.
armcc The ARM C compiler. The compiler is tested against the Plum Hall C
Validation Suite for ANSI conformance. It compiles ANSI or PCC source
into 32-bit ARM code.
tcc The Thumb C compiler. The compiler is tested against the Plum Hall C
Validation Suite for ANSI conformance. It compiles ANSI or PCC source
into 16-bit Thumb code.
armasm The ARM and Thumb assembler. This assembles both ARM assembly
language and Thumb assembly language source.
armlink The ARM linker. This combines the contents of one or more object files
with selected parts of one or more object libraries to produce an
executable program. The ARM linker creates ELF executable images.
armsd The ARM and Thumb symbolic debugger. This enables source level
debugging of programs. You can single step through C or assembly
language source, set breakpoints and watchpoints, and examine program
variables or memory.
1-2 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Introduction
ADW The ARM Debugger for Windows. This provides a full Windows
environment for debugging your C, C++, and assembly language source.
APM The ARM Project Manager. This is a graphical user interface tool that
automates the routine operations of managing source files and building
your software development projects. APM helps you to construct the
environment, and specify the procedures needed to build your software.
Utilities
The following utility tools are provided to support the main development tools:
fromELF The ARM image conversion utility. This accepts ELF format input files
and converts them to a variety of output formats, including AIF, plain
binary, Extended Intellec Hex (IHF) format, Motorola 32-bit S record
format, and Intel Hex 32 format.
armlib The ARM librarian enables sets of AOF files to be collected together and
maintained in libraries. You can pass such a library to the linker in place
of several AOF files.
decaof The ARM Object Format decoder decodes AOF files such as those
produced by armasm and armcc.
decaxf The ARM Executable Format decoder decodes executable files such as
those produced by armlink.
topcc The ANSI to PCC C Translator helps to translate C programs and headers
from ANSI C into PCC C, primarily by rewriting top-level function
prototypes.
topcc is available for UNIX platforms only, not for Windows.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 1-3
Introduction
Supporting software
The following support software is provided to enable you to debug your programs,
either under emulation, or on ARM-based hardware.
ARMulator The ARM core emulator. This provides instruction accurate emulation of
ARM processors, and enables ARM and Thumb executable programs to
be run on non-native hardware. The ARMulator is integrated with the
ARM debuggers.
Angel The ARM debug monitor. Angel runs on target development hardware
and enables you to develop and debug applications running on
ARM-based hardware. Angel can debug applications running in either
ARM state or Thumb state.
ARM C++ is not part of the base Software Development Toolkit. It is available
separately. Contact your distributor or ARM Limited if you want to purchase ARM
C++.
armcpp This is the ARM C++ compiler. It compiles draft-conforming C++ source
into 32-bit ARM code.
support software
The ARM C++ release provides a number of additional components to
enable support for C++ in the ARM Debuggers, and the ARM Project
Manager.
Note
The ARM C++ compilers, libraries, and enhancements to the ARM Project Manager
and ARM Debuggers are described in the appropriate sections of the ARM Software
Development Toolkit User Guide and Reference Guide.
1-4 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Introduction
The Windows development tools (ADW and APM) are supported on IBM compatible
PCs running Windows 95, Windows 98, and Windows NT 4.
• Windows NT 3.51
• SunOS 4.1.3
• HP-UX 9
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 1-5
Introduction
The preferred and default debug table format for the SDT is now DWARF 2. The ASD
debug table format is supported for this release, but its use is deprecated and support for
it will be withdrawn in future ARM software development tools.
The preferred and default executable image format is now ELF. Refer to the ELF
description in c:\ARM250\PDF\specs for details of the ARM implementation of
standard ELF format.
Demon-based C libraries are no longer included in the toolkit release, and RDP is no
longer supported as a remote debug protocol.
1-6 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Introduction
Compiling for debug (-g), and the optimization level (-O), have been made orthogonal
in the compilers.
-O0 Turns off all optimization, except some simple source transformations.
The -O0 option gives the best debug view, but with the least optimized code.
The -O1 option gives a satisfactory debug view, with good code density. By default no
debug data is emitted for inline functions, so they cannot be debugged. With DWARF1
debug tables (-dwarf1 command-line option), variables local to a function are not
visible, and it is not possible to get a stack backtrace.
The -O2 option emits fully optimized code that is still acceptable to the debugger.
However, the correct values of variables are not always displayed, and the mapping of
object code to source code is not always clear, because of code re-ordering.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 1-7
Introduction
A new pragma has been introduced to specify that debug data is to be emitted for inline
functions. The pragma is #pragma [no]debug_inlines. You can use this pragma to
bracket any number of inline functions. It can be used regardless of the level of
optimization chosen.
Impact
Any existing makefiles or APM projects that use –g+ –gxo will now get the behavior
defined by –g+ -O1. The SDT 2.11a option -g+ -gxr is still supported by SDT 2.50,
and has the same functionality as in SDT 2.11a, but will not be supported by future
releases.
Instruction scheduling is of benefit to code for the StrongARM1 and ARM9 processor
families:
• if the -processor option specifies any processor other than the StrongARM1,
instruction scheduling suitable for the ARM 9 is performed
By default, instruction scheduling is turned on. It can be turned off with the
-zpno_optimize_scheduling command-line option.
In SDT 2.50 and C++ 1.10, the compilers generate one set of debug areas for each input
file, including header files. The linker is able to detect multiple copies of the set of
debug areas corresponding to an input file that is included more than once, and emits
only one such set of debug areas in the final image. This can result in a considerable
reduction in image size. This improvement is not available when ASD debug data is
generated.
In SDT 2.11a and C++ 1.01 images compiled and linked for debug could be
considerably larger than expected, because debug data was generated separately for
each compilation unit. The linker emitted all the debug areas, because it was unable to
identify multiple copies of debug data belonging to header files that were included more
than once.
1-8 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Introduction
Impact
Existing makefiles and APM projects generate smaller debug images, and therefore the
images load more quickly into the debugger. This feature cannot be disabled.
These processor names (and those of all other released ARM processors) are now
permitted as arguments to the –processor command-line option of the compilers and
assembler.
ADW enhancements
• The command-line options supported by armsd that are suitable for a GUI
debugger are now understood on the ADW command line. This enables you, for
example, always to start ADW in remote debug mode. The available
command-line options are:
• -symbols
• -li, -bi
• -armul
• -adp –linespeed baudrate -port
[s=serial_port[,p=parallel_port]] |
[e=ethernet_address]
• Save and restore all window formats. Windows retain the format they were given.
• Breakpoints can be set as 16-bit or 32-bit. The dialog box for setting a breakpoint
has been modified to enable breakpoints to be set either as ARM or Thumb
breakpoints, or for the choice to be left to the debugger.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 1-9
Introduction
• The Memory window now has halfword and byte added to its display formats.
• Value fields in editable windows (for example, Variable windows and Memory
windows) are now edit in place, rather than using a separate dialog box for
entering new values.
The compilers in SDT 2.50 and C++ 1.10 have been enhanced to provide an assembly
language listing, annotated with the original C or C++ source that produced the
assembly language. Use the command-line options -S –fs to get interleaved source
and assembly language.
This facility is not available if ASD debug tables are requested (-g+ -asd).
This facility is only easily accessible from the command line, and is not integrated with
APM.
The SDT 2.11a assemblers (armasm and tasm) have been merged into a single
assembler, called armasm, that supports both ARM code and Thumb code. In addition,
it provides functionality previously supported only by tasm, such as the CODE16 and
CODE32 directives, and the -16 and -32 command-line options. The assembler starts in
ARM state by default. A tasm binary is shipped with SDT 2.50 for compatibility
reasons, however this binary only invokes armasm –16.
1-10 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Introduction
In the C and C++ compilers, the implementation of the long long data type has been
optimized to inline most operators. This results in smaller and faster code. In particular:
long long res = (long long) x * (long long) y;
Angel enhancements
ARMulator enhancements
• Wait states and true idle cycles are counted separately if a map file is used.
• Verbose statistics are enabled by the line Counters=True in the armul.cnf file.
For cached cores, this adds counters for TLB misses, write buffer stalls, and cache
misses.
• The instruction tracer now supports both Thumb and ARM instructions.
• A new fast memory model is supplied, that enables fast emulation without cycle
counting. This is enabled using Default=Fast in the armul.cnf file.
• Trace output can be sent to a file or appended to the RDI log window.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 1-11
Introduction
The fromELF translation utility is a new tool in SDT 2.50. It can translate an ELF
executable file into the following formats:
• AIF family
• Plain binary
• Extended Intellec Hex (IHF) format
• Motorola 32 bit S record format
• Intel Hex 32 format
• Textual Information.
This tool does not have a GUI integrated with APM. It can be called directly from the
command line, or by editing your APM project to call fromELF after it calls the linker.
Each selectable option on the dialog boxes now has a tool tip that displays the
command-line equivalent for the option.
The changes that have been made to the default behavior of the SDT are described in:
• Stack disciplines on page 1-12
• Default Procedure Call Standard (APCS and TPCS) on page 1-13
• Default debug table format on page 1-13
• Default image file format on page 1-14
• Default processor in the compilers and assembler on page 1-14
• RDI 1.0 and RDI 1.5 support on page 1-14
• Register names permitted by the assembler on page 1-15.
Stack disciplines
The ARM and Thumb compilers now adjust the stack pointer only on function entry and
exit. In previous toolkits they adjusted the stack pointer on block entry and exit. The
new scheme gives improved code size.
1-12 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Introduction
The default Procedure Call Standard (PCS) for the ARM and Thumb compilers, and
the assembler in SDT 2.50 and C++ 1.10 is now:
-apcs 3/32/nofp/noswst/narrow/softfp
Note
The new default PCS will not perform software stack checking and does not use a frame
pointer register. This generates more efficient and smaller code for use in embedded
systems.
The default procedure call standard for the ARM (not Thumb) compiler in SDT 2.11a
was -apcs 3/32/fp/swst/wide/softfp.
The default procedure call standard for the ARM (not Thumb) assembler in SDT 2.11a
was -apcs 3/32/fp/swst.
Impact
Existing makefiles and APM project files where the PCS was not specified will generate
code that does not perform software stack checking and does not use a frame pointer
register. This will result in smaller and faster code, because the default for previous
compilers was to emit function entry code that checked for stack overflow and set up a
frame pointer register.
In SDT 2.50 and C++ 1.10 the default debug table format is DWARF 2. DWARF 2 is
required to support debugging C++, and to support the improvements in debugging
optimized code.
The default debug table format emitted by the SDT 2.11a compilers and assemblers was
ASD.
If DWARF debug table format was chosen, the SDT 2.11a compilers and assemblers
emitted DWARF 1.0.3.
Impact
Existing makefiles and APM project files where debugging information was requested
will now result in DWARF 2 debug data being included in the executable image file.
Previous behavior can be obtained from the command line by specifying -g+ -asd or
-g+ -dwarf1, or by choosing these from the appropriate Tool Configuration dialog
boxes in APM.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 1-13
Introduction
The default image file format emitted by the linker has changed from AIF to ELF.
Impact
Existing makefiles in which no linker output format was chosen, and existing APM
project files in which the Absolute AIF format was chosen, will now generate an ELF
image. If you require an AIF format image, use -aif on your armlink command line,
or choose Absolute AIF on the Output tab of the APM Linker options dialog box. This
will then generate a warning from the linker. AIF images can also be created using the
new fromELF tool.
Note
When the ARM debuggers load an executable AIF image they switch the processor
mode to User32. For ELF, and any format other than executable AIF, the debuggers
switch the processor mode to SVC32. This means that, by default, images now start
running in SVC32 mode rather than User32 mode. This better reflects how the ARM
core behaves at reset.
C code that performs inline SWIs must be compiled with the -fz option to ensure that
the SVC mode link register is preserved when the SWI is handled.
The default processor for the SDT 2.11a ARM (not Thumb) compilers was ARM6. In
SDT 2.50 and C++ 1.10 this has been changed to ARM7TDMI. The default processor
for the assembler has changed from -cpu generic –arch 3 to -cpu ARM7TDMI.
Impact
Existing makefiles and APM project files where the processor was not specified (with
the -processor option) will generate code that uses halfword loads and stores
(LDRH/STRH) where appropriate, whereas such instructions would not previously have
been generated. Specifying -arch 3 on the command line prevents the compilers from
generating halfword loads and stores.
A new variant of the Remote Debug Interface (RDI 1.5) is introduced in SDT 2.50. The
version used in SDT 2.11a was 1.0.
The debugger has been modified so that it will function with either RDI 1.0 or RDI 1.5
client DLLs.
1-14 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Introduction
Impact
Third party DLLs written using RDI 1.0 will continue to work with the versions of
ADW and armsd shipped with SDT 2.50.
In SDT 2.50, the assembler pre-declares all PCS register names, but also allows them
to be declared explicitly through an RN directive.
In SDT 2.11a the procedure call standard (PCS) register names that the assembler would
pre-declare were restricted by the variant of the PCS chosen by the -apcs option. For
example, -apcs /noswst would disallow use of sl as a register name.
Impact
Any source files that declared PCS register names explicitly will continue to assemble
without fault, despite the change to the default PCS.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 1-15
Introduction
The features listed below are either obsolete or deprecated. Obsolete features are
identified explicitly. Their use is faulted in SDT 2.50. Deprecated features will be made
obsolete in future ARM toolkit releases. Their use is warned about in SDT 2.50. These
features are described in:
• AIF, Binary AIF, IHF and Plain Binary Image formats on page 1-16
• Shared library support on page 1-17
• Overlay support on page 1-17
• Frame pointer calling standard on page 1-17
• Reentrant code on page 1-18
• ARM Symbolic Debug Table format (ASD) on page 1-18
• Demon debug monitor and libraries on page 1-18
• Angel as a linkable library, and ADP over JTAG on page 1-18
• ROOT, ROOT-DATA and OVERLAY keywords in scatter load description on page
1-19
• Automatically inserted ARM/Thumb interworking veneers on page 1-19
• Deprecated PSR field specifications on page 1-19
• ORG no longer supported in the assembler on page 1-19.
Because the preferred (and default) image format for the SDT is now ELF, the linker
emits a warning when instructed to generate an AIF image, a binary AIF image, an IHF
image or a plain binary image.
Impact
Any makefiles with a link step of -aif, -aif -bin, -ihf, or -bin now produce a
warning from the linker. For existing APM projects where an Absolute AIF image has
been requested on the Linker configuration Output tab, there will be no warning.
However, an ELF image is created instead, because this is the new default for the linker.
Future release
In a future release of the linker, these formats will be obsolete, and their use will be
faulted.
1-16 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Introduction
This feature is obsolete. The Shared Library support provided by previous versions of
the SDT has been removed for SDT 2.50. The linker faults the use of the -shl
command-line option.
Impact
Any makefile or APM project file that uses the Shared Library mechanism will now
generate an error from the linker. The SDT 2.11a linker can be used if this facility is
required.
Future release
A new Shared Library mechanism will be introduced in a future release of the linker.
Overlay support
Use of the -overlay option to the linker and use of the OVERLAY keyword in a scatter
load description file are now warned against by the linker.
Impact
Any makefile, APM project file, or scatter load description file that uses the overlay
mechanism will now generate a warning from the linker.
Future release
A future release of the linker will subsume the overlay functionality into the scatter
loading mechanism.
Use of a frame pointer call standard when compiling C or C++ code is warned against
in the SDT 2.50 and ARM C++ 1.10 versions of the compilers.
Impact
Any makefile or APM project file that uses a frame pointer call standard ( -apcs /fp)
will now generate a warning from the compilers.
Future release
A new procedure call standard will be introduced with a future release of the compilers.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 1-17
Introduction
Reentrant code
Use of the reentrant procedure call standard when compiling C or C++ code is warned
against in the SDT 2.50 and ARM C++ 1.10 versions of the compilers.
Impact
Any makefile or APM project file that uses the reentrant procedure call standard (-apcs
/reent) will now generate a warning from the compilers.
Future release
A new procedure call standard will be introduced with a future release of the compilers.
Because the preferred (and default) debug table format is now DWARF 2, the compilers
and assembler will warn when asked to generate ASD debug tables.
Impact
Any makefiles with a compiler or assembler command-line option of -g+ –asd will
now produce a warning. For existing APM projects in which debugging information has
been requested, there will be no warning and DWARF 2 debug tables will be emitted
instead, because this is the new default for the compilers and assembler.
Future release
In a future release of the compilers and assembler, ASD will be made obsolete, and its
use will be faulted.
This feature is obsolete. The Demon Debug monitor is now obsolete and support for it
has been removed from the SDT. There is no longer a remote_d.dll selectable as a
remote debug connection in ADW, and Demon C libraries are not supplied with SDT
2.50.
This feature is obsolete. Full Angel is no longer available as a library to be linked with
a client application. The version of Angel that runs on an EmbeddedICE and acts as an
ADP debug monitor (adpjtag.rom) is also no longer available.
1-18 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Introduction
In the SDT 2.11 manuals, use of the ROOT, ROOT-DATA and OVERLAY keywords in a
scatter load description file was documented, and a later Application Note warned
against its use. The linker now warns against use of these keywords.
Impact
Any existing scatter load descriptions that use ROOT, ROOT-DATA or OVERLAY
keywords will now generate a warning, but the behavior will be as expected.
Future release
In a future release of the linker, use of ROOT, ROOT-DATA and OVERLAY will be faulted.
In SDT 2.11a, the linker warned of calls made from ARM code to Thumb code or from
Thumb code to ARM code (interworking calls) when the destination of the call was not
compiled for interworking with the -apcs /interwork option. In spite of the
warning, an interworking return veneer was inserted.
In SDT 2.50, the linker faults inter-working calls to code that cannot return directly to
the instruction set state of the caller, and creates no executable image.
Impact
Existing code that caused the interworking warning in SDT 2.11a is now faulted
because the return veneers inserted by the SDT 2.11a linker can cause incorrect program
behavior in obscure circumstances.
The assembler now warns about the use of the deprecated field specifiers CPSR,
CPSR_flg, CPSR_ctl, CPSR_all, SPSR, SPSR_flg, SPSR_ctl, and SPSR_all.
The ORG directive is no longer supported in the assembler. Its use conflicts with the
scatter loading mechanism supported by the linker.
Impact
Existing assembly language sources that use the ORG directive will no longer assemble.
The effect of the ORG directive can be obtained by using the scatter loading facility of
the linker.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 1-19
Introduction
1-20 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Chapter 2
ARM Project Manager
This chapter describes the ARM Project Manager, and contains the following sections:
• About the ARM Project Manager on page 2-2
• Getting started on page 2-4
• The APM desktop on page 2-16
• Additional APM functions on page 2-21
• Setting preferences on page 2-32
• Working with source files on page 2-35
• Viewing object and executable files on page 2-38
• Working with project templates on page 2-40
• Build step patterns on page 2-48
• Using APM with C++ on page 2-53.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 2-1
ARM Project Manager
APM helps you to construct the environment and specify the procedures necessary to
build your software. APM builds derived files as directed by your choice of project
template but you have full control over the options passed to the build tools.
APM schedules the calling of development tools such as compilers, linkers, and your
own custom tools. This is particularly helpful when you need to perform a sequence of
operations frequently and consistently.
APM uses the concept of a project to maintain information about the system you are
building. You specify what to build and how to build it. When you have described your
system as a project, you can build all of it or just part of it. If the project output is an
image, you can execute it or debug it by calling the ARM Debugger for Windows
(ADW), or a third party debugger such as XRAY, directly from APM.
When you create a project with APM, all the tools you need for your work are accessible
through the APM graphical interface (the APM desktop).
When you have started APM, you can display online help giving details relevant to your
current situation, or navigate your way to any other page of APM online help.
F1 key Press the F1 key on your keyboard to display help, if available, on the
currently active window.
Help button Many APM windows contain a Help button. Click this button to display
help on the currently active window.
Help menu Select Contents from the Help menu to display a Help Topics screen
with Contents, Index, and Find tabs. The tab you used last is selected.
Click either of the other tabs to select it instead.
Select Search from the Help menu to display the Help Topics screen with
the Index tab selected.
Under Contents, click on a closed book to open it and see a list of the
topics it contains. Click on an open book to close it. Select a topic and
click the Display button to display online help.
2-2 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARM Project Manager
Under Index, either scroll through the list of entries or start typing an
entry to bring into view the index entry you want. Select an index entry
and click the Display button to display online help.
Under Find, follow the instructions to search all the available online help
text for any keywords you specify. The first time you undertake a Find
operation a suitable database file is constructed, and is then available for
any later Find operations.
Select Using Help from the Help menu to display a guide to the use of
on-screen help.
Hypertext links
Most pages of online help include highlighted text that you can click on
to display other relevant online help. Clicking on highlighted text
underscored with a broken line displays a popup box. Clicking on
highlighted text underscored with a solid line jumps to another page of
help.
Browse buttons
Most pages of online help include a pair of browse buttons that enable
you to step through a sequence of related help pages.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 2-3
ARM Project Manager
When APM starts, the last file or project you accessed is loaded.
Select Exit from the File menu to stop APM. The source files and projects you currently
have open will be re-opened the next time you start APM.
An APM project is a description of how you build something, such as an image or object
library, and a list of the files you need, such as source files, include files, and any
sub-projects.
APM describes what you are building and how you build it by means of a project
template. A template consists of a series of build step patterns that define the build steps
used to construct the output of your project.
A sub-project is simply an APM project that has been added to another project. For
example if you have a project that builds a library, it could become a sub-project of
another project that makes an image using routines from that library.
2-4 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARM Project Manager
Project files
A project manages source files, and derived files created from source files by the build
tools.
Source files form the basis of a project. Symbols in the Project window indicate various
types of source file, as shown in the following list. The source file types recognized by
the standard templates are:
C or C++ source file
ARM assembly language file
include file
sub-project (this is also a type of source file, contributing its own project
output to the current project)
file of a type unknown to APM.
When you add a source file to a project, it is not copied or moved from its original
location in the file system. Its location is referenced from the project file. Whenever
possible APM refers to files relative to the project directory structure rather than
absolutely. You can set the variable $$DepthOfDotAPJBelowProjectRoot to
increase the scope of the directories that are considered a part of the project. Refer to
Variables on page 2-27 for more information.
Note
If you move a project, you must keep the directory structure containing its files the
same. If you change the directory structure, the files required to build the project will
not be found.
Derived files are created as the result of a build step, such as a compile or a link.
An object file
A library
An ARM executable image.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 2-5
ARM Project Manager
1. Select New from the File menu or click the New button. The New dialog is
displayed (Figure 2-1).
4. Select the template Type that you want to use for the project. The template
description is displayed. For this example select ARM Executable Image.
2-6 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARM Project Manager
5. Enter a Project name, such as hello. This is used for the project file and the
project output.
7. Click OK.
If you have specified a directory that does not currently exist, you are prompted
to confirm that you want a new project directory created. The new project file is
created in the project directory and the Project window is displayed.
For the hello project you created in the previous section, follow these steps to create
a new source file from within APM:
1. Click the New button or select New from the File menu. The New dialog appears.
4. Enter the following code, deliberately omitting the semicolon at the end of the
printf() function call:
#include <stdio.h>
int main(void)
{
printf("Hello World\n")
return 0;
}
5. Save the code in a source file by selecting Save or Save As... from the File menu
or by clicking the Save button. Enter hello.c when you are prompted for a
filename.
6. Close the Edit window by selecting Close from the File menu. You are now
returned to the Project window with the hello project loaded.
The source files and files inferred by the build steps are organized in a project using
partitions (as described under Partitions on page 2-25). APM uses variants to create
different versions of your project output. By default the following variants are defined:
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 2-7
ARM Project Manager
DebugRel This variant is designed for projects where you intend to release the same
code that you are debugging. It provides an adequate debug view,
together with good optimization. This variant sets the debug and
optimization command-line options to -g+ -O1.
Debug This variant is designed for projects where you intend to have separate
debug and release builds of your code. It contains the debug version of
your project and provides maximum debug information at the expense of
optimization. This variant sets the debug and optimization command-line
options to -g+ -O0.
Release This variant is designed for projects where you intend to have separate
debug and release builds of your code. It contains the release version of
your project. It provides maximum optimization at the expense of debug
information. This variant turns off debug table generation and sets the
optimization command-line option to -O2.
Follow these steps to add the newly created file to your project:
Note
If the project directory is still your current directory, that is where the source file is
stored by default. You can, however, store source files in any accessible directory, and
add source files from any directory to a project.
2-8 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARM Project Manager
When you have added files to your project, you may want to view the project in more
detail. To expand a level of the project hierarchy, click on the plus (+) symbol next to
that level. Figure 2-3 shows how the Project View looks if you expand the first three
levels of hello.apj.
You can see that hello.c, the file you added to the project, is now in the Sources
partition. The files hello.o and hello.axf have been added to the Objects and
Image partitions. These are the derived files that are the anticipated output of the project
build steps. The work in progress symbol indicates that they have not yet been built.
Other options for viewing a project are discussed in Changing the way a project is
displayed on page 2-18.
Note
APM displays nested source dependencies only if the compiler and assembler are
invoked with the -MD- command-line option. This option instructs the assembler and
compiler to output source dependencies to the Project Manager. The project templates
shipped with APM specify this option in the build step pattern.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 2-9
ARM Project Manager
2.2.3 Build
Either a build or a force build processes the source files of a selected variant through the
defined build steps to create the project output. A build executes a build step only if
some input to it is newer than its outputs. A force build executes all build steps.
The actions performed in the various build steps and the type of project output are
determined by the project template. The project template also partially determines the
build order to ensure, for example, that compilation takes place before linking.
When you have added the necessary files to a project, you can build that project. As
your project is being built, the progress indicator at the bottom of the project window is
updated and any diagnostic information generated is displayed in the build log.
The simplest way to turn source files into project output is to build the entire project.
You can also process a single source file, force build an entire project, or select multiple
variants to be built.
Building a project
After you have added the example source files to your project you can build it. Click
the Build button or select Build project-name from the Project menu. When you start
the build, the button in the status area changes to Stop Build, and a build status indicator
appears next to the button. Messages from the build tools are displayed in the build log.
The build log is opened by APM if it is not already open. Figure 2-4 on page 2-11 shows
the APM desktop when the build is complete.
2-10 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARM Project Manager
You can see from the messages in the build log that the build was not successful. The
red X next to hello.c in the Project view indicates that there is an error in the
hello.c source file. The section headed Correcting problems on page 2-13 explains
how APM can help you to resolve problems in building your project.
You can perform a build step from a single source file if the file is associated with a
project and has been opened as a part of a project. If the file can be processed (compiled
or assembled, for example), the appropriate menu item in the Project menu is enabled
and labeled with the name of the build step pattern that is used to perform the build step.
If the project template does not define a build step for the selected file type, the Build
menu item and the Build button are disabled.
APM performs the actions associated with the build step and displays the results in the
build log pane.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 2-11
ARM Project Manager
Select Force Build to build all of the output files in your project for the selected variant,
regardless of whether they have been changed since the last build. If you first select
APM... from the Tools menu and check-mark the Build also builds sub-projects
option, Force Build also builds any associated sub-projects (see APM preferences on
page 2-32).
Note
If you move your project to a new location, you must rebuild it using Force Build.
Building variants
When you build a project only the selected variant is built. To build all variants of your
project, select Build Variants from the Project menu.
Build steps
A build step is a step in the build process that contributes to the project output. Usually,
a build step generates one file or a group of related files.
The actions performed in a build step are defined by a build step pattern within the
project template. The build step pattern also defines what type of source file each build
step acts upon. Typical build steps include:
• compiling or assembling source files
• linking object files and libraries
• building sub-projects.
2-12 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARM Project Manager
Stopping a build
You can stop a build at the end of its current step by clicking the Stop build toolbar
button or by clicking the Stop Build variant button in the status area at the bottom of
the Project Window.
When you build your project, you may find errors and problems. As the build
progresses, messages are written to the build log (see Project window on page 2-16) that
appears in the lower pane of the Project window. These may be informational messages
or diagnostic messages from the tools that are invoked by the project template.
When the build is complete, you can double click on any error message that relates to
an editable source file (such as a compile error with a file line tag) and APM takes you
to the location where the error was detected. In the case of a compile error, this is the
line of code listed in the log. If a line relates to a sub-project, the project is loaded into
the Project Window. You can also locate errors by selecting Next Error and Previous
Error from the View menu.
To find and correct the problem in the hello.c source file in your sample project, and
rebuild the project:
1. Double click on the serious error line, indicated by a solid red exclamation mark,
in the build log. The Edit window displays the appropriate source file, with the
line that was being processed when the error was detected highlighted.
2. In this case, the error is due to the missing semicolon at the end of the previous
line:
printf("Hello World\n")
should read
printf("Hello World\n");
Note
Often an error in a line is detected only when the next line is being processed.
3. Correct the error and click the Build button. When you rebuild the project:
• APM prompts you to save the file if you have not already done so
• the Project window becomes the current window
• the build takes place and messages are written to the build log.
Figure 2-5 on page 2-14 shows the APM Desktop when the build is complete.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 2-13
ARM Project Manager
Blue checkmarks appear by all three files and an informational message in the
build log shows that the project is up to date. This means that the project was built
successfully and that the output of every project build step involved was created
after the most recent change to any of its inputs. You can now execute or debug
your project.
The output of a project is typically a single file or a closely related group of files, such
as a program image or an object library.
The output is determined by one or more of the build step patterns in the project
template. A different version of the project output is created for each variant built. For
example, output can be built for a debug-and-release version, a debug version, and a
release version.
When your project has been successfully built, you can either execute or debug it to see
how it works. Use the ARM Debugger for Windows (see ARM Debuggers for Windows
and UNIX on page 3-1 for more information).
2-14 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARM Project Manager
Executing an image
Click the Execute button or select Execute project.apj from the Project menu, to load
the image in to the ARM Debugger for Windows and commence execution. If you
execute the hello.apj project, ‘Hello World’ appears in the Console Window.
Select Exit from the File menu when you have finished executing the image.
Debugging an image
When you click the Debug button or select Debug project.apj from the Project menu,
again the image is loaded into the ARM Debugger for Windows, but the debugger is
halted at the start of the program. You can then debug the image as necessary, using the
features of the Debugger.
Note
Whether you Execute or Debug your image, if the project output is older than its source,
it is rebuilt before it is sent to the Debugger.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 2-15
ARM Project Manager
The Project window contains a pane showing the project view, a pane showing the build
log, and a status area. Figure 2-6 shows an example of the project window. The
following sections describe the parts of the project window.
2-16 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARM Project Manager
Project view
The project view occupies the upper pane and displays the project hierarchy. The
following symbols are used to denote variants and partitions. File symbols are defined
in Project files on page 2-5:
variant
partition.
You can use the project view to examine various aspects of your project and select
elements for action. For example, you can select a partition in which you want to add a
file, or select a source file for a build.
Build log
The build log occupies the lower pane and is displayed each time you perform a build.
The build log contains messages from the tools used to build your project. You can
double click on many of these messages to display the line where an error was detected.
The following symbols in the build log indicate the type of diagnostic message:
Informational (blue)
Warning (blue)
Error (red)
Status area
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 2-17
ARM Project Manager
You can change the level of detail displayed in the Project Window in several ways:
• Click the View Dependencies button to show or hide the lower level dependency
files. These are indicated by a plus sign (+) next to the source filename.
• Click the View Build Log button to toggle the display of the build log in the lower
pane of the Project window. The build log is always displayed by APM when you
build from a single source or build an entire project.
• Hold the Tab key and click the mouse on a point in the project view where you
want to set a tab to control the spacing of the project hierarchy. All levels of the
hierarchy are spaced evenly based on the position you have selected.
• Select Variants from the View menu to toggle the display of the project variants.
When you do so, partitions and their files are still displayed.
• Select Toolbar or Status Bar from the View menu to toggle the display of the
toolbar and status bar.
When you display the contents and structure of a project, various arrow keys and
numeric keypad keys act as shortcut keys. Shortcut keys enable you to expand or
collapse your view of the levels of the project. See Table 2-1 for a list of shortcut keys.
2-18 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARM Project Manager
Use the Edit window to create or modify a source file, such as a code file or an include
file. This window is opened when you:
• double click on a code or include file in the Project View
• open an existing code or include file
• select New from the File menu and create a source or include file.
Figure 2-7 shows an example of the Edit window. The Edit window provides a fully
functional editor in which you can copy, paste, search, and replace using the appropriate
toolbar buttons or the menu selections in the Edit menu.
If you are editing a source file as a component of a project, you can perform a build
using that source file from the Edit window by clicking the Perform Build Step button.
You are prompted to save the file if you have not already done so. The Project window
is displayed and the results of the build appear in the build log.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 2-19
ARM Project Manager
Note
To build from a single source file, you must access the file as part of a project because
APM uses the project template to determine how to process the file.
The View window is used to display the contents of a binary file, such as an object,
library or image file, using a utility such as decaof, decaxf, or armlib. Figure 2-8 shows
an example of the View window.
2-20 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARM Project Manager
You can change how a tool, such as a compiler or assembler, is executed by changing
its configuration within the Project Manager. You can change either the system-wide
configuration (see Making system-wide configuration changes on page 2-23), or
project-specific configuration (see Making project-specific configuration changes on
page 2-23).
When a tool configuration is associated with a file, it is associated with that file as an
input to a build step, not with that file as an output from a build step. For example, if
you select an image you can change the debugger configuration but not the linker
configuration. Linker configuration is associated with object files.
The appearance of the Tool Configuration dialog varies with the tool you are
configuring. Tools that are APM compliant, such as armcc, tcc, armcpp, tcpp, armasm,
and armlink, respond by displaying their configuration interface. For most ARM tools
this consists of sets of property sheets. Figure 2-9 on page 2-22 shows the configuration
dialog for the ARM C compiler.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 2-21
ARM Project Manager
When you change the settings, the modifications are reflected in the Equivalent
Command Line box near the bottom of the dialog.
Note
If a tool DLL is not in the directories searched by Windows, or if a found tool is not a
DLL with APM compliant entry points, an error will be reported because the tool cannot
be configured graphically. You can take any of the following actions:
• install the product containing the missing APM compliant tool DLL (for example
C++ projects will need armcpp.dll which is part of C++ 1.10 for SDT 2.50)
• specify command-line options in the command-line box in the Failed to Locate
the Tool dialog
• select Edit Project Template… Project menu and enter the command-line
options in the Command Lines field of the appropriate Build step pattern (see
Working with project templates on page 2-40)
• use the Edit Paths dialog to specify the correct location of the tool DLL (see
Editing a path on page 2-44).
2-22 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARM Project Manager
System-wide configuration changes to a tool affect all projects that invoke the tool.
1. Select Configure from the Tools menu, and select the tool to configure. You are
given a warning message about the effects of such a configuration change.
2. Confirm that you want to proceed. The appropriate Tool Configuration dialog is
displayed, showing current settings.
1. Click on one or more entities, such as the Debug variant in the Project window, to
specify the scope of a configuration change. Hold down the Shift or Ctrl keys
while clicking to select several entities or a range of entities.
2. Select Tool Configuration for from the Project menu to display a submenu of
the tools used.
3. Select the tool you want to configure. The Tool Configuration submenu is
displayed.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 2-23
ARM Project Manager
You can return the configuration of a tool to the settings of its parent (see Project
hierarchy on page 2-26) as follows:
1. Click on one or more entities, for example the Debug variant, in the Project
window to select the scope for the configuration change.
2. Select Tool Configuration for from the Project menu, then select the tool to be
configured. The Tool Configuration submenu is displayed. If there is a
configuration setting for the selected scope, the Unset menu item is enabled.
3. Select Unset to reset the configuration to the settings of that tool at the next higher
level of hierarchy.
There are two options that allow you to read additional command-line options from a
file. These options must be specified on the Extra command line arguments text box of
the Configuration Dialog:
-via filename
Opens a file and reads additional command-line options from it. For
example:
armcpp -via input.txt options source.c
The options specified in filename are read at the same time as any other
command-line options are parsed. If -via is specified in the Extra
command line arguments text box of the APM Compiler Configuration
dialog, the command-line options are immediately read into the tool
configuration settings.
You can nest -via calls within -via files.
-latevia filename
This option is similar to -via. In the case of -latevia the file is read
immediately before compilation begins, not when other command-line
options are parsed.
If -latevia is specified, the command-line options are not read in until
the compiler is executed. This means that files specified with the
-latevia option stay in the text box, and can be changed more easily
than files specified with the -via option.
Calls to -latevia files cannot be nested. If -latevia is specified
within a -latevia file, it is ignored. However, you can nest -via
options within -latevia files.
2-24 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARM Project Manager
2.4.2 Partitions
Partitions enable you to organize the various files that make up your project in a similar
way to placing them in a directory structure. Partitions exist only within APM, as an
organizational convenience. Your files are not copied or moved when you add them to
a partition. They remain where you normally keep them.
Partitions help to control the effect of adding a file to a project. The partitions created
for a project are determined by the project template. The partitions used by standard
APM templates include:
Sources Contains source files used to build the project output. Other source
partitions may be added depending on the template, such as Thumb-C,
ARM-C, ASM-Sources.
IncludedFiles
Contains any files included by the sources used by the project.
SubProjects Contains other projects that are to be used in the construction of the
project output. If the project output from a sub-project is a library, the
library file is built in the Libraries partition.
Image Contains the project output of your build as specified in the project
template.
Note
You can use other names for partitions, this list is only an example.
A project template defines how to build a particular type of project output. In a project
template, build step patterns describe the necessary processes, their input files, and their
output files.
Project templates give you great flexibility when you build your project output. You can
select a template from those supplied with APM or you can construct your own. You
can modify a project template by adding tools and changing the way they are executed
while building the project. You can modify variables at any level in the project hierarchy
to change the way specific files are handled. You can also create additional variants.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 2-25
ARM Project Manager
APM includes standard templates that you can copy and modify to suit your own needs.
If you have installed the ARM C++ Compiler you will have some additional templates
that you can use (see Using APM with C++ on page 2-53).
• A project template. A blank template becomes a project template when you create
a new project based on the template, and add files to it.
Normally you have one blank template for each type of project that you might want to
create, and you accumulate an increasing number of project templates. Each project
template is based on one of the blank templates, but now uniquely defines the build steps
for one particular project.
In most of this chapter, editing a template or any of its elements (details, variables,
paths, build steps) implies editing a project template, not editing one of the blank
templates. Creating a new template on page 2-46 describes how to create and edit new
blank templates.
When you build a project using different tool configurations or variable values, project
settings take precedence over system-wide settings, variant settings take precedence
over project settings, partition settings take precedence over variant settings, and file
settings take precedence over partition settings.
2-26 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARM Project Manager
2.4.5 Variables
A variable holds a value used either by APM or by a build step pattern to specify a
changeable aspect of your project, such as a filename or directory path.
A variable prefixed with $ is read-only, a variable prefixed with $$ can affect the actions
of APM. A variable containing a $, such as path$Debug, has a standard purpose
defined by APM.
You can set variables for any level of the project hierarchy.
$$DepthOfDotAPJBelowProjectRoot
Affects how the location of a file is resolved in the directory structure of
the project.
$$ProjectName
When you create a project, this variable is set to "" and the name of the
project is contained in $projectname. When you change the value of
this variable, $projectname is set to the new value.
$projectname
You cannot change the value of this variable directly. It contains the name
of the project as assigned when you created the project or whenever it is
saved. This value is also changed if the variable $$ProjectName is set
to a non-empty value.
path$variant
The path specifying the directory of a variant, created as a sub-directory
below the directory that holds the project file. You can change the value
of this variable if necessary.
config$tool
This variable stores an encoding of the configuration of a tool, or the
command-line arguments for a tool that is not configurable.
Note
User-defined variables cannot begin with $
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 2-27
ARM Project Manager
2.4.6 Variants
You can use variants to create different versions of your project output from the same
source files. Typically you use variants to create a debug-release version, or separate
debug and release versions of your project output.
You can change variant level variables to control how the project output for the variant
is built. The derived files for each variant, such as object files and project output, are
created in a subdirectory of the project directory. You specify the project directory when
you create the project.
Note
You cannot add a source file to only one variant of your project.
1. Select Add Variant from the Project menu. The Add Variant dialog is displayed
(Figure 2-10).
2. Select a variant from the Add Variant Like list. The files and variable values
from the original are assigned to the new template.
3. Enter a new variant name. The variant name cannot contain spaces.
4. Click OK.
2-28 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARM Project Manager
1. Select Build Variants from the Project menu. The Build Variants dialog is
displayed (Figure 2-11).
2. Select one or more variants from the Select Variants to build box.
3. If you want to force build the selected variants, check Force build regardless of
timestamps.
Follow these steps to change the name of the project output only:
1. Select Edit Variables for projectname.apj from the Project menu. The Edit
Variables dialog is displayed (Figure 2-12 on page 2-30).
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 2-29
ARM Project Manager
Changing the names of both the project file and the project output
Follow these steps to change the name of both the project file and the project output:
1. Select Save As from the File menu. The Save As dialog is displayed.
Note
The value of $$ProjectName must be "" otherwise the project output retains the name
stored in that variable.
The value of $projectname is updated by APM. See Variables on page 2-27 for more
information on variables.
2-30 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARM Project Manager
If you open a project that was created with an earlier version of the ARM Project
Manager, you are asked to confirm that you want to convert the project to the current
format. After you convert a project file to a later format, you can no longer read it with
the earlier version of APM.
1. Open the project. The Project Conversion Wizard starts (Figure 2-13).
2. Confirm that the conversion should proceed, and that the old file can be
overwritten.
4. Examine, and change if necessary, the project name and directory, then click the
Next button.
5. Verify the source files that are to be added to the project, and click the Next
button. By default all files belonging to the original project are carried over to the
new project file.
6. Confirm that you want to proceed with the conversion by clicking the Finish
button. If you elected to overwrite the existing file, the conversion cannot be
reversed.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 2-31
ARM Project Manager
1. Select APM... from the Tools menu. The APM Preferences dialog is displayed
(Figure 2-14).
2. Select the preferences you require. An item is check-marked when selected. The
options are:
2-32 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARM Project Manager
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 2-33
ARM Project Manager
The Editor Preferences dialog allows you to choose which editor to use when you edit
source and include files, and to modify the behavior of that editor.
1. Select Editor... from the Tools menu to display the Editor Preferences dialog
(Figure 2-15).
2-34 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARM Project Manager
If you have selected the file from the Project View, you can build the output from your
source file from within the editor. Any messages from the build tool are written to the
build log. You can edit files that are not associated with a project, but until they are
added to a project, APM has no information on how the file should be processed.
1. Select New from the File menu or click the New button. The New dialog is
displayed (Figure 2-16).
2. Select the New file type, for example C/C++ source or C/C++ include file, from
the scroll box.
3. Click OK.
Note
If you create a new source file and at the same time you have an open project, the source
file is not automatically added to the open project.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 2-35
ARM Project Manager
If the file type is associated with tools in multiple partitions, the Files Matched Multiple
Partitions dialog is displayed (Figure 2-17).
2. Select the file or files to add to the selected partition from the Files Matched
Multiple Partitions dialog.
3. Click Add.
Note
You can use the Retain partition selection settings on the APM Preferences dialog to
keep the default partition set to the one last used.
Project templates supplied with APM have a Miscellanea partition, where files of types
not associated with other partitions are placed. If the Miscellanea partition does not
exist when you add a file not associated with a partition, the Unable to Add Files
message box appears. To add the file to the project, you must associate the file type with
a partition.
If you have a file type that is associated with more that one partition, you can select the
partition to receive the file before you add the file to the project. Follow these steps to
select the partition:
2-36 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARM Project Manager
3. Select the files to be added to the project using the Add Files to partition dialog.
4. Click OK.
You can process and generate output from a single file if it is associated with a project
and if the file has been opened as a part of that project. If a build step can be performed
on the file (if it can be compiled or assembled, for example) the appropriate menu item
in the Project menu is enabled and labeled with the name of the build step pattern for
the build step. If the project template does not define a build step for the selected file
type, the menu item and the button are disabled.
For example, if you have several source files in your hello project, and select
hello.c from the Release variant, the item on the Project menu would read:
Note
Compile is a term specified within the template. Any build type tool can be used to build
an output file from a source file. See Adding a build step pattern on page 2-52 for more
information on assigning tools to a template.
2. Click the Perform Build Step button (the tool tip reflects which build step is
executed) or select Compile hello.c "Release" from the Project menu.
3. The actions associated with the Compile build step are executed and the results
are displayed in the build log pane.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 2-37
ARM Project Manager
2. Select Contents hello.o from the View menu. The appropriate Viewing dialog for
the translator is displayed (Figure 2-18).
4. Click OK. The information is displayed in the specified format in a View window
(Figure 2-19).
2-38 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARM Project Manager
2.7.1 decaof
The ARM Object Format (AOF) file decoder, decaof, decodes AOF files such as those
produced by armasm and armcc.
For a full specification of AOF and a full description of decaof, refer to the ARM
Software Development Toolkit Reference Guide.
2.7.2 decaxf
The ARM Executable Format (AXF) file decoder, decaxf, decodes executable files such
as those produced by armlink.
For a full description of decaxf, refer to the ARM Software Development Toolkit
Reference Guide.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 2-39
ARM Project Manager
Tools Tools are the programs used by a build step pattern to transform a source
file into a derived file. Tool configuration is discussed in Configuring
tools on page 2-21.
Partitions Partitions are a construct of APM used to organize the source and derived
files in your project, in the same way that you might use a directory
structure. The partitions used by your project are determined by the build
step patterns.
Variants Variants define different versions of the project output created from the
same set of source files. Variants are discussed in Adding a new variant
to a project on page 2-28.
2-40 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARM Project Manager
Variables Variables are used within the definition of build steps to change how a
tool is used in the various levels of a project hierarchy. For example, you
could use a variable to change the configuration settings for armcc, so
that a single source, or a particular set of sources in a separate partition,
is compiled in one way and the rest of the source is compiled in another.
See Editing a variable on page 2-43.
To create a new project, select an existing blank template that defines the tools to be
used, the organization of project files into partitions, and the variants that can be built.
Add your source files to the blank template and save it as the new project template. A
project template helps you to build your project output repeatedly and consistently.
You can modify a project template after the project has been created or you can create
your own blank templates.
After creating a project you can add new tools, remove unused tools, and edit the build
step patterns to suit your needs. These changes have a global effect across your project,
but do not affect the blank template you used when you created your project.
If you need finer control, for example to compile a subset of your sources in a particular
way, you can use tool configuration settings and/or variables to change the handling of
a single source or a group of sources. For example, you could create an additional
source partition. You could then configure the tool used on source files differently,
depending on the partition used. You could even use a different compiler.
Finally, to create a number of projects that require a framework that is not supported by
the supplied blank templates, you can create your own blanks. To create a blank
template, take an existing blank template, save it to a new file in the Templates
directory, then make the required changes. The new template appears in the list
presented when you create a new project.
Note
You are advised to create new templates based on the current APM templates, rather
than modifying the blank templates supplied with APM.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 2-41
ARM Project Manager
You can use the following APM templates to create both executable images and ARM
libraries:
Blank template
A blank template from which to make your own templates. Change the
description using the Details dialog (Editing project template details on
page 2-47). This template defines DebugRel, Debug, and Release
variants and the Miscellanea partition.
2-42 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARM Project Manager
A variable holds a value used by either APM or by a build step pattern to specify a
changeable aspect of your project, such as a filename or directory path. You can set
variables for any level of the project hierarchy. For example, you could set the variable
specifying the C compiler (cc) to be one tool for the entire project (cc=armcc) and
create a special configuration for a particular source file (cc=tcc).
Follow these steps to edit the variables for a particular level of the project hierarchy:
1. Select an element from the Project view (for example the Debug variant).
2. Select Edit Variable from the Project menu. The Edit Variables dialog is
displayed (Figure 2-20). The title of the dialog box reflects the scope of the
changes that are being made.
3. Select a variable from the scroll box or type the variable name.
5. If you have additional variables to modify, click Apply to save the change and
modify another variable.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 2-43
ARM Project Manager
Follow these steps to use a tool in your project that is not on the Windows search path:
1. Select Edit Paths from the Project menu. The Edit Paths dialog is displayed
(Figure 2-21).
4. If you have additional tool paths to modify, click Apply to save the change and
go on to modify another path.
Note
Do not edit paths if your tools are on your Windows search path. Editing paths can make
your project difficult to use on another machine or with other versions of the software.
The Windows search path is the preferred method for locating tool DLLs. The primary
reason to edit a path is to experiment with a different version of a tool DLL.
2-44 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARM Project Manager
When you edit a project template, you change the options used by APM when it builds
the project.
1. Select Edit Project Template from the Project menu. The Project Template
Editor dialog is displayed (Figure 2-22).
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 2-45
ARM Project Manager
If you have a number of similar project outputs to produce that do not fit the templates
provided with the ARM Project Manager, you can create your own blank template to
use as a basis for new project templates. You can use an existing blank template or
project template as a basis for your new blank template.
3. Click the Edit Details button and modify the Title and the Description of the
template (see Editing project template details on page 2-47).
4. Select Save as Template from the File menu. The Save As... dialog is displayed.
5. Locate the file in the directory specified in the APM Preferences dialog (Setting
preferences on page 2-32) and give it a unique name.
6. Click Save. The new project has now been created and is the currently active
project.
7. Modify the build step patterns listed for the template, adding or deleting build step
patterns as necessary (see Editing a build step pattern on page 2-50).
9. Edit any tool paths as necessary (see Editing a path on page 2-44).
The new template is displayed (sorted by filename) in the Type list of the New Project
dialog the next time you create a new project.
2-46 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARM Project Manager
Project template details consist of a short project name (for example, ARM Executable
Image) and a description providing more details of the project.
1. Select Edit Project Template from the Project menu. The Project Template
Editor is displayed.
2. Click Edit Details. The Edit Template Details dialog is displayed (Figure 2-23).
4. Click OK.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 2-47
ARM Project Manager
When you add a file to a project, APM searches for an input pattern expression to match
the filename. If a match is found, the pattern variables used in the input pattern become
defined and are used to generate output filenames. When the project is built, the same
pattern variables are used to generate command-lines for the tools invoked by the build
step pattern.
Conditional literal
written as <name|literal> that either:
• matches and <name> takes on the value of the literal
• fails to match and <name> takes on the value "" (null).
Patterns match from right to left, and / in a pattern matches / or \ in the filename.
2-48 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARM Project Manager
path = ""
slash = ""
file = "myfile"
and the same input pattern element supplied with the string:
c:\projdir\myproj\myfile.c
Note
An input pattern element <path>\<file>.c does not recognize the string
myfile.c because the string does not contain the specified literal \.
For example, the output pattern element <path|-I><path> consists of the pattern
variable and conditional literal -I (defined only if the pattern variable <path> is
non-empty) followed by the pattern variable <path> value.
When given with the filename myfile.c this expression resolves to "" (a null string).
When given with the fully qualified filename -I c:\projdir\myproj\myfile.c
the expression resolves to -Ic:\projdir\myproj because in the first case the input
pattern variable <path> is set to "", so the output pattern element <path|-I><path>
becomes:
<""|-I>""
which produces:
""""
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 2-49
ARM Project Manager
In the case of the fully qualified filename, the input pattern variable <path> is set to
"c:\projdir\myproj", so the output pattern element <path|-I><path> becomes:
<"c:\projdir\myproj"|-I>"c:\projdir\myproj"
Outputs and command-lines can refer to variables not used in an input pattern. A typical
example is:
<tool> -o <file>.o ... <TOOLFLAGS> ...
If the variable <TOOLFLAGS> is defined within the project, its value is used, otherwise
it is ignored.
Note
The first variable on a command-line is treated differently. Its default value is its name.
APM insists that the name of a tool must be a variable. So, if you want to call armcc,
you must enter <armcc>.
Note
A build step pattern can use one or more tools, process one or more input files, and can
produce one or more outputs.
1. Select the Build Step Pattern from the Project Template Editor dialog.
2. Click Edit. The Build Step Pattern dialog is displayed (Figure 2-24 on page 2-51).
2-50 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARM Project Manager
3. Edit the build step pattern as required, possibly deleting, editing, or adding
input/output patterns, as follows:
Deleting an input/output pattern
a. Select the pattern line from the list in the Input or Output Partition box.
The selected pattern is loaded on the edit line.
b. Click Delete to remove the pattern.
Editing an input/output pattern
a. Select the pattern line from the list in the Input or Output Partition box.
The selected pattern is loaded on the edit line.
b. Edit the pattern as required (see Specifying input and output patterns in a
build step pattern on page 2-48).
c. Click Replace to change the pattern.
Adding a new input/output pattern
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 2-51
ARM Project Manager
Note
If you do not click Add, Replace or Delete in step 3, you are prompted to save or cancel
your changes before exiting this dialog.
You can have more than one Edit Build Step Pattern dialog open at one time, so that you
can copy from one build step pattern to another easily using Ctrl+Insert (to copy text)
and Shift+Insert (to paste text).
2. Click New.
4. Click OK. The Edit Build Step Pattern dialog is displayed (see Edit Build Step
Pattern dialog on page 2-51).
8. Click Add.
If you are debugging with ADW or ADU, you can use the -args option in a
command-line to introduce any arguments you may want to supply to the program you
are about to debug. For example:
launch <adw> -exec <any>.asf -args ex0.eqn
See Writing Code for ROM on page 10-1 for an example showing how to add a
FromELF build step pattern.
2-52 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARM Project Manager
ARM C++ provides additional project templates to enable you to build C++ projects in
APM. The C++ project templates are based on the corresponding C project templates
for the Software Development Toolkit. The templates provide options for producing
C++ executable images and object libraries from within APM.
By default, the templates are installed in the \template directory of your SDT
installation directory. If you installed SDT in the default location, this will be
c:\arm250\template.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 2-53
ARM Project Manager
The APM C++ templates provide a number of options for creating C++ source files,
header files, and projects.
This section describes how to create new projects based on the C++ project templates.
The following general points apply to the templates:
• All templates that produce ARM executable images or ARM object libraries are
configured to use armcpp to compile C++ source files.
• All templates that produce Thumb executable images or Thumb object libraries
are configured to use tcpp to compile C++ source files.
• All templates that produce executable images use the ARM Debugger for
Windows (ADW) as their debugger.
1. Select New... from the File menu. The New dialog is displayed (Figure 2-25).
2. Select Project from the list of options and click OK. The New Project dialog is
displayed (Figure 2-26 on page 2-55).
2-54 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARM Project Manager
3. Select the type of project you want to create. In addition to the standard options
available in SDT 2.50, you can create a project based on the new C++ templates.
These are:
• ARM C++ Executable Image
• Thumb C++ Executable Image
• ARM C++ Object Library
• Thumb C++ Object Library
• Thumb/ARM C++ Interworking Image.
4. Enter a project name and project directory for the new project.
5. Click OK. A new project is created for the type of image or library you have
chosen.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 2-55
ARM Project Manager
2-56 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Chapter 3
ARM Debuggers for Windows and UNIX
This chapter describes the ARM Debugger for Windows (ADW) and ARM Debugger for
UNIX (ADU). These are two versions of the same debugger, adapted to run under
Windows and UNIX respectively. ADW is part of the ARM Software Development
Toolkit. ADU is an extra-cost addition that requires SDT 2.11a or greater.
ADW and ADU screens differ slightly in appearance. Your screens might look different
from the figures in this chapter.
If you have purchased the ARM C++ compiler, the C++ installation process adds extra
features to the ARM Debuggers to support debugging C++. Refer to ARM Debugger
with C++ on page 3-62 for details.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 3-1
ARM Debuggers for Windows and UNIX
You can also use the ARM Debugger to benchmark your application.
Refer to the documentation supplied with your target board for specific information on
setting up your system to work with the ARM Software Development Toolkit, and the
EmbeddedICE interface, Angel, and so on.
Most of this chapter applies to both the Windows and the UNIX version of the ARM
Debugger. The term ARM Debugger refers to whichever version you are using,
depending on your operating system. If a section applies to one version only, that is
indicated in the text or in the section heading.
When you have started ADW or ADU, you can display online help giving details
relevant to your current situation, or navigate your way to any other page of ADW/ADU
online help.
F1 key Press the F1 key on your keyboard to display help, if available, on the
currently active window.
Help button Many APM windows contain a Help button. Click this button to display
help on the currently active window.
Help menu Select Contents from the Help menu to display a Help Topics screen
with Contents, Index, and Find tabs. The tab you used last is selected.
Click either of the other tabs to select it instead.
Select Search from the Help menu to display the Help Topics screen with
the Index tab selected.
Under Contents, click on a closed book to open it and see a list of the
topics it contains. Click on an open book to close it. Select a topic and
click the Display button to display online help.
Under Index, either scroll through the list of entries or start typing an
entry to bring into view the index entry you want. Select an index entry
and click the Display button to display online help.
Under Find, follow the instructions to search all the available online help
text for any keywords you specify. The first time you undertake a Find
operation a database file is constructed, and is then available for any later
Find operations.
3-2 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARM Debuggers for Windows and UNIX
Select Using Help from the Help menu to display a guide to the use of
on-screen help.
Hypertext links
Most pages of online help include highlighted text that you can click on
to display other relevant online help. Clicking on highlighted text
underscored with a broken line displays a popup box. Clicking on
highlighted text underscored with a solid line jumps to another page of
help.
Browse buttons
Most pages of online help include a pair of browse buttons that enable
you to step through a sequence of related help pages.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 3-3
ARM Debuggers for Windows and UNIX
The ARM Debuggers work in conjunction with either a hardware or a software target
system. An ARM Development Board, communicating through an EmbeddedICE
interface, Multi-ICE, or Angel, is an example of a hardware target system. The
ARMulator is an example of a software target system.
You debug your application using a number of windows that give you various views on
the application you are debugging.
3-4 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARM Debuggers for Windows and UNIX
The following debugging systems are available for applications developed to run on an
ARM core:
• the ARMulator
• the EmbeddedICE interface or Multi-ICE
• the Angel Debug Monitor.
The ARMulator
The ARMulator is a collection of programs that emulate the instruction sets and
architecture of various ARM processors. The ARMulator:
• provides an environment for the development of ARM-targeted software on the
supported host systems
• enables benchmarking of ARM-targeted software.
EmbeddedICE and Multi-ICE also enable the embedded microprocessor to access host
system peripherals, such as screen display, keyboard input, and disk drive storage.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 3-5
ARM Debuggers for Windows and UNIX
Angel
Angel is a debug monitor that allows rapid development and debugging of applications
running on ARM-based hardware. Angel can debug applications running in either ARM
state or Thumb state on target hardware. Angel runs alongside the application being
debugged on the target platform.
You can use Angel to debug an application on an ARM Development Board or on your
own custom hardware. See Chapter 13 Angel for more information.
This section introduces some of the concepts of that you need to be aware when
debugging program images.
Debug agent
A debug agent is the entity that performs the actions requested by the debugger, such as
setting breakpoints, reading from memory, or writing to memory. It is not the program
being debugged, or the ARM Debugger itself. Examples of debug agents include the
EmbeddedICE interface, Multi-ICE, the ARMulator, and the Angel Debug Monitor.
The Remote Debug Interface (RDI) is a procedural interface between a debugger and
the image being debugged, through a debug monitor or controlling debug agent. RDI
gives the debugger core a uniform way to communicate with:
• a controlling debug agent or debug monitor linked with the debugger
• a debug agent executing in a separate operating system process
• a debug monitor running on ARM-based hardware accessed through a
communication link
• a debug agent controlling an ARM processor through hardware debug support.
3-6 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARM Debuggers for Windows and UNIX
Figure 3-2 on page 3-8 shows the ARM Debugger with the Execution, Console, Globals
and Locals windows, in the process of debugging the sample image DHRY.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 3-7
ARM Debuggers for Windows and UNIX
The menu bar is at the top of the ARM Debugger desktop. Click on a menu name to
display the pull down menu.
If you have installed the ARM C++ compiler, a C++ menu appears between the View
and Execute menus that provides options relevant only to C++ program debugging .
C++ also adds its own mini toolbar. See ARM Debugger with C++ on page 3-62 for
more information.
Underneath the menu bar is the toolbar. Position the cursor over an icon and a brief
description is displayed. A processor-specific mini toolbar is also displayed. The
menus, the toolbar, and the mini toolbar are described in greater detail in the online help.
At the bottom of the desktop is the status bar. This provides current status information
or describes the currently selected user interface component.
3-8 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARM Debuggers for Windows and UNIX
Start the ARM Debugger for Windows (ADW) in any of the following ways:
• if you are running Windows 95 or Windows 98, click on the ARM Debugger for
Windows icon in the ARM SDT v2.50 Program folder
• if you are running Windows NT4, double click on the ARM Debugger for
Windows icon in the ARM SDT v2.50 Program group or select Start →
Programs →ARM SDT v2.50 →ARM Debugger for Windows
• if you are working in the ARM Program Manager, click the ARM Debugger
button or select Debug project from the Project menu
• launch ADW from the DOS command-line, optionally with arguments.
Start the ARM Debugger for UNIX (ADU) in either of the following ways:
• from any directory type the full path and name of the debugger, for example,
/opt/arm/adu
• change to the directory containing the debugger and type its name, for example,
./adu
The possible arguments (which must be in lower case) for both ADW and ADU are:
-debug ImageName
Load ImageName for debugging.
-exec ImageName
Load and run ImageName.
-nomainbreak
Do not set a breakpoint on main() on loading image.
-script ScriptName
Obey the ScriptName on startup. This is the equivalent of typing obey
ScriptName as soon as the debugger starts up.
-symbols Load only the symbols of the specified image. This is equivalent to
selecting Load Symbols only… from the File menu.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 3-9
ARM Debuggers for Windows and UNIX
For example, to launch ADW from the command-line and load sorts.axf for
debugging, but without setting a breakpoint on main(), type:
adw -debug sorts.axf -nomainbreak
To launch ADW (with arguments) from APM, select Project →Edit Variables →adw
and enter the arguments after adw in the Value box. Refer to Specifying command-line
arguments for your program on page 3-46 for more information on specifying
command-line options.
When you start the ARM Debugger, the windows you were using last time are again
displayed. These usually include the Console, Command, and Execution windows, and
you can load your executable image.
Select Exit from the File menu to close down the ARM Debugger.
You must load a program image before you can execute it or step through it.
Loading an image
1. Select Load Image from the File menu or click the Open File button. The Open
File dialog is displayed.
3-10 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARM Debuggers for Windows and UNIX
If you have recently loaded your required image, your file appears as a recently used file
on the File menu. If you load your image from the recently used file list, the ARM
Debugger loads the image using the command-line arguments you specified in the
previous run.
Reloading an image
After you have executed an image you must reload it before you can execute it again.
To reload an executable image, select Reload Current image from the File menu or
click the Reload button on the toolbar.
Executing an image
To run your program in the ARM Debugger, select Go from the Execute menu or click
the Go button to execute the entire program. Execution continues until:
• a breakpoint halts the program at a specified point
• a watchpoint halts the program when a specified variable or register changes
• you stop the program by clicking the Stop button.
Alternatively, select Step from the Execute menu or click the Step button to step
through the code a line at a time. Refer to Stepping through an image on page 3-34 for
more information on stepping through code.
To continue execution from the point where the program stopped use Go or Step.
Note
If you want to execute your program again, you must reload it first.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 3-11
ARM Debuggers for Windows and UNIX
You can use the ARM Debugger to display and modify the contents of the variables and
registers used by your executable image. You can also examine the contents of memory.
Variables
You can display and modify both local and global variables. Follow these steps to
display and modify a variable:
a. Select View →Variables →Local or click the Locals button on the toolbar
to display a list of local variables.
b. Select View →Variables →Global to display a list of global variables.
2. Double click on the value you want to change in the right pane of the window. The
Memory window is displayed, showing the area around your selected location.
4. Press Return when you have set the variable to the required value.
Registers
To display a list of registers for the current processor mode, click the Current
Registers button on the toolbar. Follow these steps to display and modify registers for
a selected processor mode:
2. Select the required processor mode from the Registers submenu. The registers
are displayed in the appropriate Registers window.
3. Double click on the register you want to modify. The Memory window is
displayed, showing the area around your selected location.
5. Press Return when you have set the variable to the required value.
3-12 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARM Debuggers for Windows and UNIX
Memory
1. Select Memory from the View menu or click on the Memory button. The
Memory Address dialog is displayed.
1. Select Goto from the Search menu or select Goto Address from the Memory
Window menu. The Goto Address dialog is displayed.
3. Click OK.
See Saving or changing an area of memory on page 3-44 for more information on
working with areas of memory.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 3-13
ARM Debuggers for Windows and UNIX
The following additional windows are available from the View menu:
• Backtrace window
• Breakpoints window
• Debugger Internals window
• Disassembly window
• Expression window
• Function Names window
• Locals/Globals window
• Low Level Symbols window
• Memory window
• Registers window
• RDI Log window
• Search Paths window
• Source Files List window
• Source File window
• Watchpoints window.
Some windows become available only after you have loaded an image.
You may change the format of displayed windows, and the format of each window is
automatically saved for future use. Whatever arrangement of windows you have when
you quit the Debugger is displayed again the next time you start the Debugger.
3-14 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARM Debuggers for Windows and UNIX
Execution window
The Execution window (Figure 3-3) displays the source code of the program that is
currently executing.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 3-15
ARM Debuggers for Windows and UNIX
Console window
The Console window (Figure 3-4) allows you to interact with the executing program.
Anything printed by the program, for example a prompt for user input, is displayed in
this window and any input required by the program must be entered here.
Information remains in the window until you select Clear from the Console window
menu. You can also save the contents of the Console window to disk, by selecting Save
from the Console window menu.
Initially the Console window displays the startup messages of your target processor, for
example the ARMulator or ARM Development board.
Note
When input is required from the debugger keyboard by your executable image, most
ARM Debugger functions are disabled until the required information has been entered.
3-16 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARM Debuggers for Windows and UNIX
Command window
Use the Command window (Figure 3-5) to enter armsd instructions when you are
debugging an image.
See Using command-line debugger instructions on page 3-46 for further details about
the use of the Command window. Type help at the Debug prompt for information on
the available commands or refer to Chapter 7 ARM Symbolic Debugger in the ARM
Software Development Toolkit Reference Guide.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 3-17
ARM Debuggers for Windows and UNIX
The windows described in this section are all available by selecting appropriate options
in the View menu.
Backtrace window
The Backtrace window displays current backtrace information about your program. Use
the Backtrace window to:
• show disassembled code for the current procedure
• show a list of local variables for the current procedure
• set or remove breakpoints.
Breakpoints window
The Breakpoints window displays a list of all breakpoints set in your image. The actual
breakpoint is displayed in the right-hand pane. If the breakpoint is on a line of code, the
relevant source file is shown in the left-hand pane.
The Debugger Internals window displays some of the internal variables used by the
ARM Debugger. You can use this window to examine the values of the following
variables, and to change the values of those not marked read-only:
$cmdline Contains the argument string for the image being debugged.
$echo Non-zero if commands from obeyed files should be echoed (initially set
to 0).
Obeyed files are text files that contain lists of armsd commands. Refer to
the description of the obey command in Chapter 7 ARM Symbolic
Debugger in the ARM Software Development Toolkit Reference Guide for
more information.
3-18 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARM Debuggers for Windows and UNIX
$examine_lines
Contains the default number of lines for the examine command (initially
set to 8).
$int_format
Contains the default format for displaying integer values.
$uint_format
Contains the default format for displaying unsigned integer values.
$float_format
Contains the default format for displaying floating-point values.
$sbyte_format
Contains the default format for displaying signed byte values.
$ubyte_format
Contains the default format for displaying unsigned byte values.
$string_format
Contains the default format for displaying string values.
$complex_format
Contains the default format for displaying complex values.
$fpresult Contains the floating-point value returned by last called function (junk if
none, or if a floating-point value was not returned). $fpresult returns
a result only if the image has been build for hardware floating-point. If
the image is built for software floating-point, it returns zero. This variable
is read-only.
$inputbase Contains the base for input of integer constants (initially set to 10).
$list_lines
Contains the default number of lines for the list command (initially set
to 16).
$pr_linelength
Contains the default number of characters displayed on a single line
(initially set to 72).
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 3-19
ARM Debuggers for Windows and UNIX
0 0 Off
0 1 RDI on
You can set these bits of the $rdi_log internal variable from the
Debugger Internals window. For more information see RDI Log window
on page 3-24 and Remote debug information on page 3-41.
$result Contains the integer result returned by last called function (junk if none,
or if an integer result was not returned). This variable is read-only.
$sourcedir Contains the directory name of the directory containing source code for
the program being debugged.
$statistics
Contains any statistics that the ARMulator has been keeping. You can
examine the contents of this variable by clicking on statistics in the
Debugger Internals window. This variable is read-only.
$statistics_inc
Not available in the debugger internals window. This variable can be used
in the command window.
$statistics_inc_w
Similar to $statistics, but outputs the difference between the current
statistics and the point at which you asked for the $statistics_inc_w
window. To create a $statistics_inc_w window, select this item,
right click to display the pop-up menu, and select Indirect through item.
This variable is read-only and is not available in the command window.
$top_of_memory
If you are using an EmbeddedICE interface, set this variable to the total
amount of memory normally on your development board. If you add
more memory to the board, change this variable to reflect the new amount
of memory.
3-20 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARM Debuggers for Windows and UNIX
$type_lines
Contains the default number of lines for the type command (initially set
to 10).
$vector_catch
Applies to ARMulator and EmbeddedICE only. It sets the exceptions that
result in control passing back to the debugger. The default value is
%RUsPDAifE. An uppercase letter indicates an exception is intercepted:
R reset
U undefined instruction
S SWI
P prefetch abort
D data abort
A address
I normal interrupt request (IRQ)
F fast interrupt request (FIQ)
E unused
Disassembly window
The Disassembly window displays disassembled code interpreted from a specified area
of memory. Memory addresses are listed in the left-hand pane and disassembled code
is displayed in the right-hand pane. You can view ARM code, Thumb code, or both.
Note
More than one Disassembly window can be active at a time.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 3-21
ARM Debuggers for Windows and UNIX
Expression window
The Expression window displays the values of selected variables and/or registers.
For more information on displaying variable information, see Working with variables
on page 3-37.
The Function Names window lists the functions that are part of your program.
Locals/Globals window
The Locals window (Figure 3-6) displays a list of variables currently in scope. The
Globals window displays a list of global variables. The variable name is displayed in
the left-hand pane, the value is displayed in the right-hand pane.
3-22 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARM Debuggers for Windows and UNIX
As you step through the program, the variable values are updated.
For more information on displaying variable information, see Working with variables
on page 3-37.
The Low Level Symbols window displays a list of all the low level symbols in your
program.
You can display the low level symbols in either name or address order. Right click in
the window to display the Low Level Symbols window menu and select Sort Symbols
by… to toggle between the two settings.
Memory window
The Memory window displays the contents of memory at a specified address. Addresses
are listed in the left-hand pane, and the memory content is displayed in the right-hand
pane.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 3-23
ARM Debuggers for Windows and UNIX
Registers window
The Registers window displays the registers corresponding to the mode named at the
top of the window, with the contents displayed in the right-hand pane. You can double
click on an item to modify the value in the register.
Note
Multiple register mode windows can be open at any one time, but you cannot open more
than one window for each processor mode. For example, you can open no more than
one FIQ register window at a time.
The RDI Log window displays the low level communication messages between the
ARM Debugger and the target processor.
Note
This facility is not normally enabled. It must be specifically enabled when the RDI is
compiled. In addition, the debugger internal variable $rdi_log must be non-zero.
For more information on RDI, see Remote debug information on page 3-41.
The Search Paths window displays the search paths of the image currently being
debugged. You can remove a search path from this window using the Delete key.
The Source Files List window displays a list of all source files that are part of the loaded
image.
Use the Source Files List window to select a source file that is displayed in its own
Source File window.
3-24 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARM Debuggers for Windows and UNIX
The Source File window displays the contents of the source file named at the top of the
window. Line numbers are displayed in the left-hand pane, code in the right-hand pane.
For more information on displaying source files, see Working with source files on page
3-36.
Watchpoints window
Window-specific menus
Each of the ARM Debugger desktop windows displays a window-specific menu when
you click the secondary mouse button over the window. The secondary button is
typically the right mouse button. Item-specific options require that you position the
cursor over an item in the window before they are activated.
Each of the window-specific menus is described in the online help for that window.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 3-25
ARM Debuggers for Windows and UNIX
A breakpoint is a point in the code where your program is halted by the ARM Debugger.
When you set a breakpoint it is marked in red in the left pane of the breakpoints window.
You can set a breakpoint at a point in the source, or in the disassembled code if it is
currently being displayed. To display the disassembled code, either:
• select Toggle Interleaving from the Options menu to display interleaved source
and assembly language in the Execution window
• select Disassembly... from the View menu to display the Disassembly window.
You can also set breakpoints on individual statements on a line, if that line contains
more than one statement.
3-26 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARM Debuggers for Windows and UNIX
There are two methods you can use to set a simple breakpoint:
Method 1
1. Double click on the line where you want to set the breakpoint.
Method 2
1. Position the cursor in the line where you want to set the breakpoint.
A new breakpoint is displayed as a red marker in the left pane of the Execution window,
the Disassembly window, or the Source File window.
In a line with several statements you can set a breakpoint on an individual statement, as
demonstrated in the following example:
int main()
{
hello(); world();
.
.
.
return 0;
}
If you position the cursor on the word world and click the Toggle breakpoint button,
hello() is executed, and execution halts before world() is executed.
To see all the breakpoints set in your executable image select Breakpoints from the
View menu.
2. Select Toggle Breakpoint from the Function Names window menu or click the
Toggle breakpoint button.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 3-27
ARM Debuggers for Windows and UNIX
The breakpoint is set at the first statement of the function. This method also works for
the Low Level Symbols window, but the breakpoint is set to the first machine instruction
of the function, that is, at the beginning of its entry sequence.
Method 1
Method 2
Method 3
2. Click the Toggle breakpoint button in the toolbar, or press the F9 key.
Method 4
1. Select Breakpoints from the View menu to display a list of breakpoints in the
Breakpoint window.
Method 5
1. Select Delete All Breakpoints from the Execute menu to delete all breakpoints
that are set in the currently selected image. Delete All Breakpoints is also
available in relevant window menus.
3-28 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARM Debuggers for Windows and UNIX
In its simplest form, a watchpoint halts a program when a specified register or variable
is changed. The watchpoint halts the program at the next statement or machine
instruction after the one that triggered the watchpoint.
Note
If you set a watchpoint on a local variable, you lose the watchpoint as soon as you leave
the function that uses the local variable.
Select Watchpoints from the View menu to see all the watchpoints set in your
executable image.
Method 1
1. Select Watchpoints from the View menu to display a list of watchpoints in the
Watchpoint window.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 3-29
ARM Debuggers for Windows and UNIX
Method 2
Note
If you set a watchpoint on a local variable, you lose the watchpoint as soon as you leave
the function that uses the local variable.
When you set a complex breakpoint, you specify additional conditions in the form of
expressions entered in the Set or Edit Breakpoint dialog (Figure 3-7).
File The source file that contains the breakpoint. This field is read-only.
Location The position of the breakpoint within the source file. This position is a
hexadecimal address for assembler code. For C or C++ code, it is shown
as a function name, followed by a line number, and if the line contains
multiple statements, a column position. This field is read-only.
Expression An expression that must be true for the program to halt, in addition to any
other breakpoint conditions. Use C-like operators such as:
i < 10
i != j
i != j + k
3-30 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARM Debuggers for Windows and UNIX
Count The program halts when all the breakpoint conditions apply for the nth
time.
Breakpoint Size
You can set breakpoints to be 32-bit (ARM) or 16-bit (Thumb) size, or
allow the debugger to make the appropriate setting. A checkbox allows to
make your selection the default setting.
1. Double click on the line where you want to set a breakpoint, or on an existing
breakpoint position. The Set or Edit Breakpoint dialog is displayed.
3. Click OK. The breakpoint is displayed as a red marker in the left-hand pane of
the Execution, Source File, or Disassembly window. If the line in which the
breakpoint is set contains several functions, the breakpoint is set on the function
that you selected in step 1.
2. Select Set or Edit Breakpoint from the Function Names window menu.
3. The Set or Edit Breakpoint dialog is displayed. Complete or alter the details of the
breakpoint.
4. Click OK.
4. Click OK.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 3-31
ARM Debuggers for Windows and UNIX
When you set a complex watchpoint, you specify additional conditions in the form of
expressions entered in the Set or Edit Watchpoint dialog.
Target Value The value of the variable or register that is to halt the program. If this
value is not specified, any change in the value of the item halts the
program, dependent on the other watchpoint conditions.
Expression Any expression that must be true for the program to halt, in addition to
any other watchpoint conditions. As with breakpoints, use C-like
operators such as:
i < 10
i != j
i != j + k
Count The program halts when all the watchpoint conditions apply for the nth
time.
2. Select Set or Edit Watchpoint from the Execute menu. The Set or Edit
Watchpoint dialog is displayed.
4. Click OK.
3-32 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARM Debuggers for Windows and UNIX
4. Click OK.
3.4.5 Backtrace
The following example shows the backtrace information for a program compiled with
debug information and linked with the C library:
#DHRY_2:Proc_6 line 42
#DHRY_1:Proc_1 line 315
#DHRY_1:main line 170
PC = 0x0000eb38 (_main + 0x5e0)
PC = 0x0000ae60 (__entry + 0x34)
Lines 1-3 The first line indicates the function that is currently executing. The
second line indicates the source code line from which this function was
called, and the third line indicates the call to the second function.
Lines 4-5 Line 4 shows the position of the call to the C library in the main procedure
of your program, and the final line shows the entry point in your program
made by the call to the C library.
Note
A simple assembly language program assembled without debug information and not
linked to a C library would show only the pc values.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 3-33
ARM Debuggers for Windows and UNIX
Step to the the next line of code in either of the following ways:
• select Step from the Execute menu
• click the Step button.
The program moves to the next line of code, which is highlighted in the Execution
window. Function calls are treated as one statement.
If only C code is displayed, Step moves to the next line of C. If disassembled code is
shown (possibly interleaved with C source), Step moves to the next line of disassembled
code.
The program moves to the next line of code. If the code is in a called function, the
function source appears in the Execution window, with the current line highlighted.
The program completes execution of the function and halts at the line immediately
following the function call.
Follow these steps to execute your program to a specific line in the source code:
2. Select Run to Cursor from the Execute menu or click the Run to Cursor button.
This executes the code between the current execution and the position of the cursor.
3-34 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARM Debuggers for Windows and UNIX
Note
Be sure that the execution path includes the statement selected with the cursor.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 3-35
ARM Debuggers for Windows and UNIX
Search paths
To view the source for your program image during the debugging session, you must
specify the location of the files. A search path points to a directory or set of directories
that are used to locate files whose location is not referenced absolutely.
If you use the ARM command-line tools to build your project, you may need to edit the
search paths for your image manually, depending on the options you chose when you
built it.
If you move the source files after building an image, use the Search Paths window to
change the search paths set up in the ARM Debugger (see Search paths on page 3-36).
3-36 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARM Debuggers for Windows and UNIX
To display source file search paths select Search Paths from the View menu. The
current search paths are displayed in the Search Paths window.
1. Select Add a Search Path from the Options menu. The Browse for Folder dialog
is displayed.
2. Browse for the directory you want to add and highlight it.
3. Click OK.
1. Select Search Paths from the View menu. The Search Paths window is displayed.
Follow these steps to examine the source files of the current program:
1. Display the list of source files by selecting Source Files from the View menu. The
Source Files List window is displayed.
2. Select a source file to examine by double clicking on its name. The file is opened
in its own Source File window.
Note
You can have more than one source file open at a time.
To display a list of local or global variables, select the appropriate item from the View
menu. A Locals/Globals window is displayed. You can also display the value of a single
variable, or you can display additional variable information from the Locals/Globals
window.
3. Click OK. The variable and its value are displayed in the Expression window.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 3-37
ARM Debuggers for Windows and UNIX
Alternatively:
Note
If you select a local variable that is not in the current context, an error message is
displayed.
1. Right click on the variable and select the Change line format from the Locals or
Globals window menu. The Display Format dialog is displayed.
2. Enter the display format. Use the same syntax as a printf() format string in C.
Table 3-2 lists the valid format descriptors.
3. Click OK.
int Only use this if the expression being printed yields an integer:
%u Unsigned integer
char Only use this if the expression being printed yields a char:
%c Character
3-38 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARM Debuggers for Windows and UNIX
Note
If you change a single line, that line is not affected by global changes.
Leave the Display Format dialog empty and click OK to restore the default display
format. Use this method to revert a line format change to the global format.
The initial display format of a variable declared as char[]= is special. The whole string
is displayed, whereas normally arrays are displayed as ellipses (…). If the format is
changed it reverts to the standard array representation.
Variable properties
If you have a list of variables displayed in a Locals/Globals window, you can display
additional information on a variable by selecting Properties from the window-specific
menu (see Figure 3-9). To display the window-specific menu, right click on an item.
The information is displayed in a dialog.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 3-39
ARM Debuggers for Windows and UNIX
Indirection
Select Indirect through item from the Variables menu to display other areas of
memory.
If you select a variable of integer type, the value is converted to a pointer. Sign
extension is used if applicable, and the memory at that location is displayed. If you
select a pointer variable, the memory at the location pointed to is displayed. You cannot
select a void pointer for indirection.
You can display disassembled code in the Execution window or in the Disassembly
window. Select Disassembly from the View menu to display the Disassembly window.
You can also choose the type of disassembled code to display by selecting the
Disassembly mode submenu from the Options menu. ARM code, Thumb code, or both
can be displayed, depending on your image.
1. Select Toggle Interleaving from the Options menu to display interleaved source
and assembly language in the Execution window. Disassembled code is displayed
in grey. The C or C++ code is displayed in black.
1. Select Disassembly from the View menu, or click the Display Disassembly
button. The Disassembly Address dialog is displayed.
2. Enter an address.
3. Click OK. The Disassembly window displays the assembler instructions derived
from the code held in the specified area of memory. Use the scroll bars to display
the content of another memory area, or:
3-40 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARM Debuggers for Windows and UNIX
The ARM debugger tries to display disassembled code as ARM code or Thumb code,
as appropriate. Sometimes, however, the type of code required cannot be determined.
This can happen, for example, if you have copied the contents of a disk file into
memory.
When you display disassembled code in the Execution window you can choose to
display ARM code, Thumb code, or both. To specify the type of code displayed, select
Disassembly mode from the Options menu.
The RDI Log window displays the low level communication messages between the
debugger and the target processor.
This facility is not normally enabled. It must be specially turned on when the RDI is
compiled.
To display remote debug information (RDI) select RDI Protocol Log from the View
menu. The RDI Log window is displayed.
Use the RDI Log Level dialog, obtained by selecting Set RDI Log Level from the
Options menu, to select the information to be shown in the RDI Log window:
Warning
The RDI log level is used internally within ARM to assist with debugging. This level
should be changed only if you have been requested to do so by ARM.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 3-41
ARM Debuggers for Windows and UNIX
Regular expressions are the means by which you specify and match strings. A regular
expression is either:
• a single extended ASCII character (other than the special characters described
below)
• a regular expression modified by one of the special characters.
You can include low level symbols or high level symbols in a regular expression (see
High level and low level symbols on page 3-43 for more information.)
Pattern matching is done following the UNIX regexp(5) format, but without the
special symbols, ^ and $.
The following special characters modify the meaning of the previous regular
expression, and work only if such regular expression is given:
* Zero or more of the preceding regular expressions. For example, A*B
would match B, AB, and AAB.
[ ] A set of characters, any one of which can appear in the search match. For
example, the expression r[23] would match strings r2 and r3. The
expression [a-z] would match all characters between a and z.
3-42 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARM Debuggers for Windows and UNIX
A high level symbol for a procedure refers to the address of the first instruction that has
been generated within the procedure, and is denoted by the function name shown in the
Function Names window.
A low level symbol for a procedure refers to the address that is the target for a branch
instruction when execution of the procedure is required.
The low level and high level symbols can refer to the same address. Any code between
the addresses referred to by the low level and high level symbols generally concerns the
stack backtrace structure in procedures that conform to the appropriate variants of the
ARM Procedure Call Standard (APCS), or argument lists in other procedures. You can
display a list of the low level symbols in your program in the Low Level Symbols
window.
In a regular expression, indicate high level and low level symbols as follows:
• precede the symbol with @ to indicate a low level symbol
• precede the symbol with ^ to indicate a high level symbol.
3.5.7 Profiling
Profiling involves sampling the pc at specific time intervals. This information is used to
build up a picture of the percentage of time spent in each procedure. Using the armprof
command-line program on the data generated by either armsd or the ARM Debugger,
you see where effort can be most effectively spent to make the program more efficient.
Note
Profiling is supported by ARMulator, but not by the EmbeddedICE interface or by
Multi-ICE. Profiling is also supported by Angel, except when used with StrongARM.
6. Click Save.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 3-43
ARM Debuggers for Windows and UNIX
Note
You cannot display profiling information from within the ARM Debugger. You must
capture the data using the Profiling functions on the Options menu, then use the
armprof command-line tool.
After you have started program execution you cannot turn profile collection on.
However, if you want to collect information on only a certain part of the execution, you
can initiate collection before executing the program, clear the information collected up
to a certain point, such as a breakpoint, by selecting Options →Profiling →
Clear Collected, then execute the remainder of your program.
1. Select Put File from the File menu to display the Put file dialog (Figure 3-10).
4. Click Save.
3-44 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARM Debuggers for Windows and UNIX
1. Select Get File from the File menu to display the Get file dialog (Figure 3-11).
4. Click Open.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 3-45
ARM Debuggers for Windows and UNIX
Follow these steps to specify the command-line arguments for your program:
1. Select Set Command Line Args from the Options menu. The Command Line
Arguments dialog (Figure 3-12) is displayed.
3. Click OK.
Refer to Starting and closing the debugger on page 3-9 for a list of valid command-line
options.
Note
You can also specify command-line arguments when you load your program in the
Open File dialog or by changing the Debugger internal variable, $cmdline.
If you are familiar with the ARM symbolic debugger (armsd) you may prefer to use
almost the same set of commands from the Command window.
The armsd commands Pause and Quit are unavailable in the Command window.
Follow these steps to use all other armsd commands from within ADW or ADU:
1. Select Command from the View menu to open the Command window.
The Command window displays a Debug: command-line.
2. Enter ARM command-line debug commands at this prompt. The syntax used is
the same as that used for armsd. Type help for information on the available
commands.
3-46 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARM Debuggers for Windows and UNIX
You can use the Command window to enter a command that reads data from, or writes
data to memory. You must, however, be aware of the default width of data read or
written, and how to change it if necessary. By default, a read from or write to memory
in armsd, ADW, or ADU transfers a word value. For example:
let 0x8000 = 0x01
transfers 4 bytes to memory starting at address 0x8000. In this example the bytes at
0x8001, 0x8002 and 0x8003 are all zero-filled.
and to read a single byte from memory, use an instruction of the form:
print /%x *(char *) 0xaddress
You can also read and write halfword short values in a similar way, for example:
let *(short *) 0xaddress = value
print /%x *(short *) 0xaddress
You can also select View →Variables →Expression to open the View Expression
window, and use that to specify bytes or shorts for displaying memory. For example, for
bytes, enter *(char *) 0xaddress in the View Expression box, and for shorts, enter
*(short *) 0xaddress in the View Expression box. To display in hexadecimal,
click the right mouse button on the Expression window, select Change Window
Format and enter %x.
Note
Changes to window formats are saved. Changes to line formats are not saved. If you
select Change Window Format and leave the format field blank, the setting defaults to
the original setting.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 3-47
ARM Debuggers for Windows and UNIX
Use the Flash Download dialog (Figure 3-13) to write an image to the Flash memory
chip on an ARM Development Board or any suitably equipped hardware.
Arguments / Image
Specifies the arguments or image to write to Flash. Use the Browse
button to select the image.
For more information about writing to Flash memory, including details of how to build
your own Flash image, refer to the Target Development System User Guide.
3-48 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARM Debuggers for Windows and UNIX
Note
The ARM Debugger for UNIX does not support the use of Channel Viewers.
To select a Channel Viewer when running the ARM Debugger for Windows:
4. Select the Channel Viewer Enabled option. The Add and Remove buttons are
activated.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 3-49
ARM Debuggers for Windows and UNIX
The window has a dockable dialog bar at the bottom that is used to send information
down the channel. Typing information in the edit box and clicking the Send button will
store the information in a buffer. The information is sent when requested by the target.
The Left to send counter displays the number of bytes that are left in the buffer.
Sending information
To send information to the target, type a string into the edit box on the dialog bar and
click the Send button. The information is sent when requested by the target, in ASCII
character codes.
Receiving information
The information that is received by the channel viewer is converted into ASCII
character codes and displayed in the window, if the channel viewers are active.
However, if 0xffffffff is received, the following word is treated and displayed as a
number.
3-50 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARM Debuggers for Windows and UNIX
3.7 Configurations
You can examine and change the configuration of the:
• ARMulator
• EmbeddedICE or Multi-ICE.
These are described below. Select Configure Debugger from the Options menu to
open the Debugger Configuration dialog.
Target environment
1. Click the Target tab of the Debugger Configuration dialog (Figure 3-15 on page
3-52).
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 3-51
ARM Debuggers for Windows and UNIX
Target Environment
The target environment for the image being debugged.
Note
Apply is disabled for the Target page because a successful RDI connection must be
made first. When you click OK an attempt is made to make your selected RDI
connection. If this does not succeed, the ARMulate setting is restored.
3-52 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARM Debuggers for Windows and UNIX
Debugger
1. Click the Debugger tab of the Debugger Configuration dialog (Figure 3-16)
Profile Interval
This is the time between pc sampling in microseconds. It is applicable
to ARMulator and Angel only. Lower values have a higher
performance overhead, and slow down execution. Higher values are
not as accurate as lower values.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 3-53
ARM Debuggers for Windows and UNIX
Note
When you make changes to the Debugger configuration the current execution is ended
and your program is reloaded.
Memory Maps
1. Click the Memory Maps tab of the Debugger Configuration dialog (Figure 3-17).
3-54 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARM Debuggers for Windows and UNIX
Memory Map
This allows you to specify a memory map file, containing information
about a simulated memory map that the ARMulator uses. It is
applicable to ARMulator only. The file includes details of the databus
widths and access times for each memory region in the simulated
system. See Chapter 12 ARMulator for more information.
You can select one of three Memory Map options:
• do not use a memory map
• use a global memory map, which means using the specified
memory map for every image that is loaded during the current
debug session
• use a local memory map, which means using a memory map that
is local to a project.
The three Memory Map options are explained in greater detail as follows:
No Map File
Select this Memory Map option to use the ARMulator default memory
map. This is a flat 4GB bank of ideal 32-bit memory, having no wait
states.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 3-55
ARM Debuggers for Windows and UNIX
Note
Map files are used only at re-initialization, not when a program is loaded. When
you select the Local Map File option, the map file in the working directory of the
current image is used. If you load a new image, the same map file is used. To use
a map file that is associated with the new image, you must re-initialize the
debugger by selecting Configure Debugger… from the Options menu and
clicking OK.
3-56 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARM Debuggers for Windows and UNIX
Use the Armulator Configuration dialog to change configuration settings for the
ARMulator.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 3-57
ARM Debuggers for Windows and UNIX
Floating-point emulation
Toggles floating-point emulation on and off.
If you are using the software floating-point C libraries, ensure that this
option is off (blank). The option should be on (checked) only if you are
using the floating-point emulator (FPE).
3-58 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARM Debuggers for Windows and UNIX
If you are using Angel or EmbeddedICE, use the Angel Remote Configuration dialog
to configure the settings for the remote connection you are using to debug your
application.
3. Select Remote_A in the Target Environment field to select ADP (Angel Debug
Protocol).
Remote Connection
Chooses either Serial or Serial/Parallel depending on the connections.
For Ethernet, enter either an IP address or the hostname of the target
board.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 3-59
ARM Debuggers for Windows and UNIX
Heartbeat
Ensures reliable transmission by sending heartbeat messages. If not
enabled, there is a danger that the host and the target can get into a
deadlock situation, with both waiting for a packet.
Ports Allows the correct serial and parallel devices to be chosen for the
debug connection.
Channel Viewers
Channel viewers are not supported by the ARM Debugger for UNIX
(ADU).
In the ARM Debugger for Windows (ADW) you can enable or disable
the selected channel viewer DLL. See ThumbCV channel viewer on
page 3-49 for more information.
Click the Add... button to add a channel viewer DLL to the displayed
list.
Click the Remove... button to remove the currently selected channel
viewer DLL from the displayed list.
Use the EmbeddedICE Configuration dialog to select the settings for an EmbeddedICE
target. This option is enabled only if you have EmbeddedICE connected to your
machine.
3-60 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARM Debuggers for Windows and UNIX
Load Agent
Specify a new EmbeddedICE ROM image file, download it to your
board, and run it. Use this for major updates to the ROM.
Load Config
Specify an EmbeddedICE configuration file to be loaded. Click OK to
run. Use this for minor updates.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 3-61
ARM Debuggers for Windows and UNIX
ARM C++ provides additions to ADW and ADU to support C++ debugging. A dynamic
link library (adw_cpp.dll ) is installed in the same directory as adw.exe. The
adw_cpp.dll adds:
• A C++ menu between the View and Execute menus in the main menu bar
• Five new buttons in the ADW/ADU toolbar:
Evaluate Expression
View Classes
Show Watches
Hide Watches
Recalculate Watches
Figure 3-21 on page 3-63 shows an example of the ARM Debugger C++ debug
interface and the C++ menu.
3-62 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARM Debuggers for Windows and UNIX
The menu items in the C++ menu give access to three new debugger windows:
• The Class View window. This window displays the class hierarchy of a C++
program in outline format.
• The Watch View window. This window displays a list of watches. It enables you
to add and remove variables and expressions to be watched, and change the
contents of watched variables.
• The Evaluate Expression window. This window enables you to enter an
expression to be evaluated, and to add that expression to the Watch window.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 3-63
ARM Debuggers for Windows and UNIX
You can use the Class View window to view the class structure of your C++ program.
Classes are displayed in an outline format that allows you to navigate through the
hierarchy to display the member functions for each class. A special branch of the
hierarchy called Global displays global functions.
You can also use the Class View window to view function code and set breakpoints for
a class.
1. Select View Classes from the C++ menu, or click on the View Classes button in
the toolbar. A Class View window is displayed that shows the class hierarchy of
your C++ program. Figure 3-22 shows an example of the Class View window.
3-64 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARM Debuggers for Windows and UNIX
2. Click the right mouse button on a member function. A Class View window menu
is displayed (Figure 3-23).
3. Select View Source from the Class View window menu to display the source code
for the function.
Note
You can also double click the left mouse button on a member function to display
the function source.
4. Select Set or Edit Breakpoint... from the Execute menu if you want to add a
breakpoint within the code you are viewing. Refer to the next section for
information on how to set a breakpoint at function entry.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 3-65
ARM Debuggers for Windows and UNIX
Follow these steps to toggle a breakpoint that will halt the program when the source for
a class or function is entered:
2. Click the right mouse button on a member function. A Class View window menu
is displayed (Figure 3-23 on page 3-65).
3. Select Toggle Breakpoint from the Class View window menu to set a breakpoint,
or unset an existing breakpoint. Breakpoints are indicated by a red dot to the left
of the function in the Class View window.
The Watch window allows you to set watches on variables and expressions. The Watch
window provides similar functionality to the debugger Local and Global windows. In
addition, it provides a C++ interpretation of the data being displayed.
Note
The Watch window is not used to set watchpoints. Select Set or Edit Watchpoint...
from the Execute menu to set watchpoints. Refer to Simple watchpoints on page 3-29
and Complex watchpoints on page 3-32 for more information.
Evaluation of function pointers and member functions is not available in this version of
ADW or ADU.
You can specify the contents and format of the Watch window using the Watch window
menu. The following sections describe how to:
• view the Watch window
• display the Watch window menu
• delete and add watch items
• format watch items
• change the contents of watched items
• recalculate watches.
1. Select Show Watch Window from the C++ menu or click on the Show Watches
button in the toolbar. The Watch window displays a list of watched variables and
expressions. Figure 3-24 on page 3-67 shows an example.
3-66 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARM Debuggers for Windows and UNIX
Note
You can also open the Watch window from the Evaluate Expression window. Refer to
Evaluating expressions and adding watches on page 3-71 for more information.
The Watch window menu enables you to add and delete watches, to change the display
format of watches, and to change the contents of watched variables. Follow these steps
to display the Watch window menu:
2. Click the right mouse button in the Watch window. The Watch window menu is
displayed. This menu is context sensitive. The menu items that it contains will
depend on:
• whether or not you have clicked on an existing watch item
• the type of watch item you have clicked on.
For example, Figure 3-25 on page 3-68 shows the Watch window menu that is
displayed when the right mouse button is clicked on the character array buf.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 3-67
ARM Debuggers for Windows and UNIX
Follow these steps to delete a watch item from the Watch window:
2. Either:
• click the right mouse button on the item you want to delete and select
Delete Item from the Watch window menu
• click on the item you want to delete and press the Delete key.
2. Either:
• click the right mouse button in the Watch window to display the Watch
window menu and select Add Item from the Watch window menu
• press the Insert key.
A Watch Control window is displayed (Figure 3-26 on page 3-69).
3-68 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARM Debuggers for Windows and UNIX
3. Enter an expression to add to the Watch window and click OK. Refer to
Evaluating expressions and adding watches on page 3-71 for more information
on the types of expression you can add to the Watch window.
Note
You can also add an expression to the Watch window directly from the Evaluate
Expression window. Refer to Evaluating expressions and adding watches on page 3-71
for more information.
Follow these steps to change the formatting of values displayed in the Watch window:
2. Click the right mouse button in the Watch window to display the Watch window
menu.
3. Select Format Window to format all items in the window. The Display Format
window is displayed (Figure 3-27).
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 3-69
ARM Debuggers for Windows and UNIX
4. Enter a format string for the item, or items in the window. You can enter any single
print conversion specifier that is acceptable as an argument to ANSI C
sprintf() as a format string, except that * cannot be used as a precision. For
example, enter %x to format values in hexadecimal, or %f to format values as a
character string.
Follow these steps to change the contents of items in the Watch window:
2. Click the right mouse button in the Watch window to display the Watch window
menu.
3. Select Edit value from the Watch window menu. The Modify Item window is
displayed (Figure 3-28).
Recalculating watches
Select Recalculate Watches from the C++ menu or click on the Recalculate Watches
button in the toolbar to reinitialize the Watch window to its original state, with all
structures and classes expanded by one level. This menu item can be used if the value
of any variable may have been changed by external hardware while the debugger is not
stepping through code.
3-70 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARM Debuggers for Windows and UNIX
The Evaluate Expression window allows you to enter a simple C++ expression to be
evaluated. The Evaluate Expression window provides similar functionality to the
debugger Expression window, with a C++ interpretation of the data being displayed.
1. Select Evaluate Expressions from the C++ menu or click on the Evaluate
Expression button in the toolbar. The Evaluate Expression window is displayed
(Figure 3-29).
2. Enter the expression to be evaluated and press the Enter key, or click on the
Calculate button. The value of the expression is displayed:
• If the expression is a variable, the value of the variable is displayed.
• If the expression is a logical expression, the window displays ‘1’ if the
expression evaluates to true, or ‘0’ if the expression evaluates to false.
• If the expression is a function, the value of the function is displayed.
Member functions of C++ classes cannot be evaluated.
3. Click on the Add Watch button to add the expression to the Watch window.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 3-71
ARM Debuggers for Windows and UNIX
Note
The following guidelines apply to all areas of ADW or ADU where an expression can
be used, including setting watchpoints and breakpoints, and evaluating expressions in
the Watch window.
3-72 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARM Debuggers for Windows and UNIX
If you are in method do_sth() you can access the member variables A, name,
and B through the this pointer. For example, this->name returns the name
defined in class Derived.
To access name in class Base, the standard C++ notation is:
void Derived::do_sth()
{
Base::name="value"; // sets name in the base class
// to "value"
}
However, the expression evaluation window does not accept
this->Base::name because ADW and ADU do not understand the scope
operator. You can access this value with:
this->::Base.name
• private, public, and protected attributes are not recognized by the ADW or
ADU Evaluate Expression window. This means that private and protected
member variables can be accessed in the Evaluate Expression window because
ADW and ADU treat them as public.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 3-73
ARM Debuggers for Windows and UNIX
This section provides information about the debug table formats that can be generated
by the ARM C++ compilers. It also describes how to change the format of the debug
tables generated.
The ARM C++ compiler provides a number of options for building debug images. You
can use the Compiler Configuration window in APM to set these options. Figure 3-30
shows an example of the Compiler Configuration window.
By default, the C++ compiler produces DWARF2 format debug tables. The available
formats are:
dwarf 2 This is the default format produced by APM for C++ projects. You should
use this format unless you have specific reasons for using DWARF1.
3-74 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARM Debuggers for Windows and UNIX
dwarf 1 You should use this format only if you have specific reasons for doing so.
For example, you may want to use a debugger that does not support
DWARF2.
asd Do not use this format for C++. The ASD format cannot represent some
C++ constructs, such as pointers to member functions. Using ASD will
produce unpredictable results.
DWARF1 limitations
The DWARF1 debug table format has limitations that introduce severe restrictions to
debugging C++ code. These include:
• DWARF1 is less descriptive than DWARF2, and therefore has limited potential
for building optimized debug images and objects.
For these reasons, it is recommended that you use the DWARF2 debug table format.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 3-75
ARM Debuggers for Windows and UNIX
3-76 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Chapter 4
Command-Line Development
This chapter gives a brief overview of using the command-line tools. It contains the
following sections:
• The hello world example on page 4-2
• armsd on page 4-6.
Refer to the ARM Software Development Toolkit Reference Guide for more information
on the command-line tools.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 4-1
Command-Line Development
armcc
compile
.o
.c
C source module(s) link executable
C library
Follow these steps to create, compile, link, and run a simple C program:
int main(void)
{
printf("Hello World\n");
return 0;
}
4. Enter armsd hello to execute the code under software emulation. armsd starts,
loads the file, and displays the armsd: prompt.
4-2 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Command-Line Development
5. Enter go and press Return. The debugger responds with Hello World, followed
by a message indicating that the program terminated normally.
6. To reload and run the program again enter: reload and then go at the armsd
prompt.
To quit the debugger, enter: quit.
5. You can enter debugging commands to examine register contents and source
code:
• To display the contents of the registers enter: reg.
• To list the C source, enter: type.
This displays the whole source file. The type command can also display
sections of code. For example, enter: type 1,6 to display lines 1 to 6 of
the source.
• To list the assembly code enter: list
The assembly code around the current position in the program is shown. You can
also list memory at a given address, for example: list 0x8080
Refer to armsd on page 4-6 or the ARM Software Development Toolkit Reference Guide
for more information on using the command-line debugger.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 4-3
Command-Line Development
3. Enter armlink hello.o -o hello3 to link the object file with a library and
generate an executable program.
3. Display the file hello.s on screen using the appropriate operating system
command, or load it into a text editor. Example 4-1 on page 4-5 shows the
assembly language generated for hello.c.
Note
Your code may differ slightly from Example 4-1, depending on the version of
compiler you are using.
4-4 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Command-Line Development
Example 4-1
|x$codeseg| DATA
For a description of the ARM C compiler options and the ARM linker options, see the
ARM Software Development Toolkit Reference Guide.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 4-5
Command-Line Development
4.2 armsd
The ARM command-line debugger, armsd, enables you to debug your ARM targeted
image using any of the debugging systems described in Debugging systems on page 3-5.
This section describes how to carry out basic tasks such as loading a C language based
image into armsd and setting simple breakpoints. Refer to the ARM Software
Development Toolkit Reference Guide for more detailed instructions on how to use
armsd.
To start armsd and load the image you want to debug, enter the command:
armsd {options} imagename {arguments}
If you regularly issue the same set of armsd commands, you can run these automatically
by adding them to a text file called armsd.ini. This file must be in the current
directory, or the directory specified by the environment variable HOME. The commands
are run whenever you start armsd.
4-6 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Command-Line Development
• To list all the current breakpoints and their corresponding numbers, enter break
without any arguments.
unbreak #n
to delete breakpoint number n
unbreak function_name
to delete a breakpoint on the first statement of function
function_name.
You can use any of these methods to remove a breakpoint, regardless of the way
in which the breakpoint was set.
• To list all the current watchpoints and their corresponding numbers enter: watch
without any arguments.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 4-7
Command-Line Development
• To step out of a function to the line that immediately follows the call to that
function enter: step out.
This command is useful if step in has been used too often.
4-8 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Command-Line Development
To exit the debugger type quit. You are returned to the command-line.
The following commands enable you to view and set program variables:
• To list all the variables defined within the current context, enter: symbols
• To view the contents of a variable enter: print variable
• To set the value of a variable use the command: let variable = expression
symbols can be abbreviated to sy, print can be abbreviated to p, and variable can
be abbreviated to v.
If your program has been compiled with the -g+ compiler option you can display source
code as follows:
Some features of armsd are specified by the value of the debugger variables. These can
be viewed and set in the same way as program variables.
For example, the read-write variable $list_lines is an integer value that specifies the
number of lines displayed when the list command is issued.
Note
Some armsd variables are read-only.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 4-9
Command-Line Development
4-10 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Chapter 5
Basic Assembly Language Programming
This chapter provides an introduction to the general principles of writing ARM and
Thumb assembly language. It contains the following sections:
• Introduction on page 5-2
• Overview of the ARM architecture on page 5-3
• Structure of assembly language modules on page 5-10
• Conditional execution on page 5-17
• Loading constants into registers on page 5-22
• Loading addresses into registers on page 5-27
• Load and store multiple register instructions on page 5-34
• Using macros on page 5-42
• Describing data structures with MAP and # directives on page 5-45.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 5-1
Basic Assembly Language Programming
5.1 Introduction
This chapter gives a basic, practical understanding of how to write ARM and Thumb
assembly language modules. It also gives information on the facilities provided by the
ARM assembler (armasm). For additional details about armasm, see Chapter 5
Assembler in the ARM Software Development Toolkit Reference Guide.
This chapter does not provide a detailed description of either the ARM instruction set
or the Thumb instruction set. This information can be found in the ARM Architectural
Reference Manual, or in an appropriate ARM data sheet.
There are a number of code examples in this chapter. Many of them are supplied in the
examples\asm directory of the Software Development Toolkit.
Follow these steps to build, link, and execute an assembly language file:
1. Type armasm -g filename.s at the command prompt to assemble the file and
generate debug tables.
See:
• Chapter 3 ARM Debuggers for Windows and UNIX for details on ADW and ADU.
• Chapter 6 Linker in the ARM Software Development Toolkit Reference Guide for
details on armlink.
• ARM object file decoder on page 8-10 of the ARM Software Development Toolkit
Reference Guide for additional details on decaof.
5-2 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Basic Assembly Language Programming
The ARM architecture exists in four major versions. The information and examples in
this book assume that you are using a processor that implements Architecture 3 or later.
Refer to the ARM Architectural Reference Manual for a summary of the different
architecture versions.
Versions 4T and 4TxM of the ARM architecture define a 16-bit instruction set called
the Thumb instruction set. The functionality of the Thumb instruction set is a subset of
the functionality of the 32-bit ARM instruction set.
ARM processors always start in ARM state. You must explicitly change to Thumb state
using a BX (Branch and exchange instruction set) instruction.
All processors that implement version 3 or later of the ARM architecture have a 32-bit
addressing range.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 5-3
Basic Assembly Language Programming
5.2.5 Registers
The ARM processor has 37 registers. The registers are arranged in partially overlapping
banks. There is a different register bank for each processor mode. The banked registers
give rapid context switching for dealing with processor exceptions and privileged
operations. Refer to Chapter 9 Handling Processor Exceptions for a detailed description
of how registers are banked.
The following registers are available in version 3 and later of the ARM architecture:
5-4 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Basic Assembly Language Programming
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 5-5
Basic Assembly Language Programming
All ARM instructions are 32 bits long and are stored word-aligned in memory.
Instructions are stored word-aligned, so the bottom two bits of addresses are always set
to zero in ARM state. These bits are ignored by all ARM instructions that have an
address operand, except the Branch Exchange (BX) instruction. The BX instruction uses
the bottom bit to determine whether the code being branched to is Thumb code or ARM
code. See Chapter 5 Assembler in the ARM Software Development Toolkit Reference
Guide for additional information.
Branch instructions
These instructions are used to branch backwards to form loops, to branch
forward in conditional structures, to branch to subroutines, or to change
the processor from ARM state to Thumb state.
Semaphore instructions
These instructions load and alter a memory semaphore.
5-6 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Basic Assembly Language Programming
Coprocessor instructions
These instructions support a general way to extend the ARM
Architecture.
Refer to the ARM Architectural Reference Manual for detailed information on the
syntax of the ARM instruction set.
Conditional execution
All ARM instructions can be executed conditionally on the value of the
ALU status flags in the CPSR. You do not need to use branches to skip
conditional instructions, although it may be better to do so when a series
of instructions depend on the same condition.
You can specify whether a data processing instruction sets the state of
these flags or not. You can use the flags set by one instruction to control
execution of other instructions even if there are many instructions in
between.
Refer to Conditional execution on page 5-17 for a detailed description.
Register access
In ARM state, all instructions can access r0-r14 and most also allow
access to r15 (pc). The MRS and MSR instructions can move the contents
of the CPSR and SPSRs to a general purpose register, where they can be
manipulated by normal data processing operations. Refer to the ARM
Architectural Reference Manual for more information.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 5-7
Basic Assembly Language Programming
The functionality of the Thumb instruction set, with one exception, is a subset of the
functionality of the ARM instruction set. The instruction set is optimized for production
by a C compiler.
All Thumb instructions are 16 bits long and are stored halfword aligned in memory.
Because instructions are stored halfword-aligned, the bottom bit of the address of an
instruction is always set to zero in Thumb state. This bit is ignored by all Thumb
instructions that have an address operand except for the Branch Exchange (BX)
instruction.
In general, the Thumb instruction set differs from the ARM instruction set in the
following ways. Refer to the ARM Architectural Reference Manual for detailed
information on the syntax of the Thumb instruction set, and how Thumb instructions
differ from their ARM counterparts:
Branch instructions
These instructions are used to branch backwards to form loops, to branch
forward in conditional structures, to branch to subroutines, and to change
the processor from Thumb state to ARM state. Program-relative
branches, particularly conditional branches, are more limited in range
than in ARM code, and branches to subroutines can only be
unconditional.
5-8 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Basic Assembly Language Programming
Semaphore instructions
There are no Thumb semaphore instructions.
Coprocessor instructions
There are no Thumb coprocessor instructions.
Conditional execution
The conditional branch instruction is the only Thumb instruction that can
be executed conditionally on the value of the ALU status flags in the
CPSR. All data processing instructions set these flags, except when one
or more high registers are specified as operands to the MOV or ADD
instructions. In these cases the flags cannot be set.
You cannot have any data processing instructions between an instruction
that sets a condition and a conditional branch that depends on it. You must
use conditional branches over any instructions that you wish to be
conditional.
Register access
In Thumb state, most instructions can access only r0-r7. These are
referred to as the low registers.
Registers r8 to r15 are limited access registers. In Thumb state these are
referred to as high registers. They can be used, for example, as fast
temporary storage.
Refer to the ARM Architectural Reference Manual for a complete list of
the Thumb data processing instructions that can access the high registers.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 5-9
Basic Assembly Language Programming
The armasm assembler assembles both ARM and Thumb assembly languages. The
obsolete Thumb assembler, tasm, is provided in the Software Development Toolkit for
backwards compatibility only.
Note
Instructions, pseudo-instructions, and directives must be preceded by white space, such
as a space or a tab, even if there is no label.
All three sections of the source line are optional. You can use blank lines to make your
code more readable.
Case rules
5-10 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Basic Assembly Language Programming
Line length
To make source files easier to read, a long line of source can be split onto several lines
by placing a backslash character at the end of the line. The backslash must not be
followed by any other characters (including spaces and tabs). The backslash/end-of-line
sequence is treated by the assembler as white space.
Note
Do not use the backslash/end-of-line sequence within quoted strings.
The exact limit on the length of lines, including any extensions using backslashes,
depends on the contents of the line, but is generally between 128 and 255 characters.
Labels
Labels are symbols that represent addresses. The address given by a label is calculated
during assembly.
The assembler calculates the address of a label relative to the origin of the area where
the label is defined. A reference to a label within the same area can use the program
counter plus or minus an offset. This is called program-relative addressing.
Labels can be defined in a map. See Describing data structures with MAP and #
directives on page 5-45. The origin of the map is usually placed in a specified register
at run time, and references to the label use the specified register plus an offset. This is
called register-relative addressing.
Addresses of labels in other areas are calculated at link time, when the linker has
allocated specific locations in memory for each area.
Local labels
Local labels are a subclass of label. A local label begins with a number in the range
0-99. Unlike other labels, a local label can be defined many times. Local labels are
useful when you are generating labels with a macro. When the assembler finds a
reference to a local label, it links it to a nearby instance of the local label.
The scope of local labels is limited by the AREA directive. You can use the ROUT
directive to limit the scope more tightly.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 5-11
Basic Assembly Language Programming
Comments
The first semicolon on a line marks the beginning of a comment, except where the
semicolon appears inside a string constant. The end of the line is the end of the
comment. A comment alone is a valid line. All comments are ignored by the assembler.
Constants
Boolean The Boolean constants TRUE and FALSE must be written as {TRUE} and
{FALSE}.
5-12 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Basic Assembly Language Programming
Example 5-1 illustrates some of the core constituents of an assembly language module.
The example is written in ARM assembly language. It is supplied as armex.s in the
examples\asm subdirectory of the toolkit. Refer to Code examples on page 5-2 for
instructions on how to assemble, link, and execute the example.
The constituent parts of this example are described in more detail in the following
sections.
Example 5-1
ARM Object Format (AOF) areas are independent, named, indivisible sequences of
code or data. A single code area is the minimum required to produce an application.
The linker places each area in a program image according to area placement rules. Areas
that are adjacent in source files are not necessarily adjacent in the application image.
Refer to Chapter 6 Linker in the ARM Software Development Toolkit Reference Guide
for more information on how the linker places areas. See also Chapter 10 Writing Code
for ROM.
In an ARM assembly language source file, the start of an area is marked by the AREA
directive. This directive names the area and sets its attributes. The attributes are placed
after the name, separated by commas. Refer to Chapter 5 Assembler in the ARM
Software Development Toolkit Reference Guide for a detailed description of the syntax
of the AREA directive.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 5-13
Basic Assembly Language Programming
You can choose any name for your areas. However, names starting with any
nonalphabetic character must be enclosed in bars, or a missing AREA name error is
generated. For example: |1_DataArea|.
Certain names are conventional. For example, |C$$code| is used for code areas
produced by the C compiler, or for code areas otherwise associated with the C library.
Example 5-1 defines a single area called ARMex that contains code and is marked as
being READONLY.
The ENTRY directive marks the first instruction to be executed within an application.
Because an application cannot have more than one entry point, the ENTRY directive can
appear in only one of the source modules. In applications containing C code, the entry
point is often contained within the C library initialization code.
Application execution
The application code in Example 5-1 begins executing at the label start, where it
loads the decimal values 10 and 3 into registers r0 and r1. These registers are added
together and the result placed in r0.
Application termination
After executing the main code, the application terminates by returning control to the
debugger. This is done using the Angel semihosting SWI (by default this is 0x123456
in ARM state), with the following parameters:
This directive instructs the assembler to stop processing this source file. Every assembly
language source module must finish with an END directive on a line by itself.
5-14 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Basic Assembly Language Programming
To call subroutines in assembly language, use a Branch Link instruction. The syntax is:
BL label
where label is usually the label on the first instruction of the subroutine. (It could
alternatively be a program-relative or register-relative expression, see Register-relative
and program-relative expressions on page 5-89 of the ARM Software Development
Toolkit Reference Guide.)
The BL instruction:
• places the return address in the link register (lr)
• sets pc to the address of the subroutine.
After the subroutine code is executed you can use a MOV pc,lr instruction to return.
By convention, registers r0-r3 are used to pass parameters to subroutines, and to pass
results back to the callers.
Note
Calls between separately assembled or compiled modules must comply with the
restrictions and conventions defined by the ARM and Thumb Procedure Call Standards.
Refer to Chapter 6 Using the Procedure Call Standards for more information.
Example 5-2 shows a subroutine that adds the values of its two parameters and returns
a result in r0. It is supplied as subrout.s in the examples\asm subdirectory of the
toolkit. Refer to Code examples on page 5-2 for instructions on how to assemble, link,
and execute the example.
Example 5-2
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 5-15
Basic Assembly Language Programming
Example 5-3 illustrates some of the core constituents of a Thumb assembly language
module. It is based on subrout.s. It is supplied as thumbsub.s in the
examples\asm subdirectory of the toolkit. Refer to Code examples on page 5-2 for
instructions on how to assemble, link, and execute the example.
Example 5-3
The ARM assembler, armasm, assembles ARM instructions until it reaches a CODE16
directive, unless the -16 option is used in the command line.
BX instruction
This instruction is a branch that can change processor state at runtime. The least
significant bit of the target address specifies whether it is an ARM instruction (clear) or
a Thumb instruction (set). In this example, the ADR pseudo-instruction sets this bit, so
start is a label to a Thumb instruction.
5-16 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Basic Assembly Language Programming
In Thumb state, there is no option. All data processing instructions set the ALU status
flags in the CPSR, except when one or more high registers are used in MOV and ADD
instructions. MOV and ADD cannot update the status flags in these cases.
Every ARM instruction can be executed conditionally on the state of the ALU status
flags in the CPSR. See Table 5-1 on page 5-18 for a list of the suffixes to add to
instructions to make them conditional.
In Thumb state you cannot execute data operations without updating the flags, and
conditional execution can only be achieved using conditional branches. The only
Thumb instruction that can be conditional is the conditional branch instruction (B). The
suffixes for this instruction are the same as in ARM state. The branch with link (BL) or
branch and exchange instruction set (BX) instructions cannot be conditional.
A carry occurs if the result of an add, subtract, or compare is greater than or equal to
232, or as the result of an inline barrel shifter operation in a move or logical instruction.
Overflow occurs if the result of an add, subtract, or compare is greater than or equal to
231, or less than –231.
Add an S suffix to an ARM instruction to make it set the ALU status flags in the CPSR.
Do not use the S suffix with CMP, CMN, TST, or TEQ. These comparison instructions
always update the flags. This is their only effect.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 5-17
Basic Assembly Language Programming
The relation of condition code suffixes to the N, Z, C and V flags is shown in Table 5-1.
EQ Z set Equal
MI N set Negative
VS V set Overflow
VC V clear No overflow
Examples
ADD r0, r1, r2 ; r0 = r1 + r2, don’t update flags.
5-18 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Basic Assembly Language Programming
You can use conditional execution of ARM instructions to reduce the number of branch
instructions in your code.
Branch instructions are expensive in both code density and processor cycles. Typically
it takes three processor cycles to refill the processor pipeline each time a branch is taken.
(The cost is less on ARM processors that have branch prediction hardware.)
You can implement the gcd function with conditional execution of branches only, in the
following way:
gcd
CMP r0, r1
BEQ end
BLT less
SUB r0, r0, r1
B gcd
less
SUB r1, r1, r0
B gcd
end
Because of the number of branches, the code is seven instructions long. Every time a
branch is taken, the processor must refill the pipeline and continue from the new
location. The other instructions and non-executed branches use a single cycle each.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 5-19
Basic Assembly Language Programming
By using the conditional execution feature of the ARM instruction set, you can
implement the gcd function in only four instructions:
gcd
CMP r0, r1
SUBGT r0, r0, r1
SUBLT r1, r1, r0
BNE gcd
In addition to improving code size, this code executes faster in most cases. Table 5-2
and Table 5-3 show the number of cycles used by each implementation for the case
where r0 equals 1 and r1 equals 2. In this case, replacing branches with conditional
execution of all instructions saves three cycles.
The conditional version of the code executes in the same number of cycles for any case
where r0 equals r1. In all other cases the conditional version of the code executes in
fewer cycles.
1 2 CMP r0, r1 1
1 2 BLT less 3
1 2 B gcd 3
1 1 CMP r0, r1 1
1 1 BEQ end 3
Total = 13
5-20 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Basic Assembly Language Programming
1 2 CMP r0, r1 1
1 1 SUBLT r1,r1,r0 1
1 1 BNE gcd 3
1 1 CMP r0,r1 1
Total = 10
Converting to Thumb
Because B is the only Thumb instruction that can be executed conditionally, the Greatest
Common Divisor algorithm in Example 5-4 must be written with conditional branches
in Thumb code.
Like the ARM conditional branch implementation, the Thumb code requires seven
instructions. However, because Thumb instructions are only 16-bits long, the overall
code size is 14 bytes, compared to 16 bytes for the smaller ARM implementation.
In addition, on a system using 16-bit memory the Thumb version runs faster than the
second ARM implementation because only one memory access is required for each
Thumb instruction, whereas each ARM instruction requires two fetches.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 5-21
Basic Assembly Language Programming
A data load can place any 32-bit value in a register, but there are more direct and
efficient ways to load many commonly-used constants.
In ARM state, you can use the MOV and MVN instructions to load a range of 8-bit constant
values directly into a register:
• The MOV instruction loads any 8-bit constant value, giving a range of 0x0 to 0xff
(0-255).
• The MVN instruction loads the bitwise complement of these values, giving a range
of 0xffffff00 to 0xffffffff.
In addition, you can use either MOV or MVN in conjunction with the barrel shifter to
generate a wider range of constants. The barrel shifter can right rotate 8-bit values
through any even number of positions from 2 to 30.
You can use MOV to load values that follow the pattern shown in Table 5-4, in a single
instruction. Use MVN to load the bitwise complement of these values. Right rotates by 2,
4, or 6 bits produce bit patterns with a few bits at each end of a 32-bit word.
5-22 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Basic Assembly Language Programming
Step
Equivalent
Decimal values between Rotate
Hexadecimal
values
You do not need to work out how to load a constant using MOV or MVN. The assembler
attempts to convert any constant value to an acceptable form.
This means that you can use MOV and MVN in two ways:
• Convert the value to an 8-bit constant, followed by the rotate right value. For
example:
MOV r0, #0xFF,30 ; r0 = 1020
• Allow the assembler to do the work of converting the value. If you specify the
constant to be loaded, the assembler converts it to an acceptable form if possible.
For example:
MOV r0, #0x3FC ; r0 = 1020
If the constant cannot be expressed as a right rotated 8-bit value or its bitwise
complement, the assembler reports an error.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 5-23
Basic Assembly Language Programming
Table 5-5 gives an example of how the assembler converts constants. The left-hand
column lists the ARM instructions input to the assembler. The right-hand column shows
the instruction generated by the assembler.
In Thumb state you can use the MOV instruction to load constants in the range 0-255. You
cannot generate constants outside this range because:
• The Thumb MOV instruction does not provide inline access to the barrel shifter.
Constants cannot be right-rotated as they can in ARM state.
• The Thumb MVN instruction can act only on registers and not on constant values.
Bitwise complements cannot be directly loaded as they can in ARM state.
If you attempt to use a MOV instruction with a value outside the range 0-255, the
assembler generates an error message.
5-24 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Basic Assembly Language Programming
The LDR Rd,=const pseudo-instruction can construct any 32-bit numeric constant in
a single instruction. Use this pseudo-instruction to generate constants that are out of
range of the MOV and MVN instructions.
The LDR pseudo-instruction generates the most efficient code for a specific constant:
• If the constant can be constructed with a MOV or MVN instruction, the assembler
generates the appropriate instruction.
• If the constant cannot be constructed with a MOV or MVN instruction, the assembler:
• places the value in a literal pool (a portion of memory embedded in the code
to hold constant values)
• generates an LDR instruction with a program-relative address that reads the
constant from the literal pool.
For example:
LDR rn [pc, #offset to literal pool]
; load register n with one word
; from the address [pc + offset]
You must ensure that there is a literal pool within range of the LDR instruction
generated by the assembler. See Placing literal pools for more information.
The assembler places a literal pool at the end of each area. These are defined by the
AREA directive at the start of the following area, or by the END directive at the end of the
assembly. The END directives at the ends of included files do not signal the end of areas.
In large areas the default literal pool may be out of range of one or more LDR
instructions:
• in ARM state, the offset from the pc to the constant must be less than 4KB
• in Thumb state, the offset from the pc to the constant must be less than 1KB.
• Checks if the constant is available and addressable in any previous literal pools.
If so, it addresses the existing constant.
• Attempts to place the constant in the next literal pool if it is not already available.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 5-25
Basic Assembly Language Programming
If the next literal pool is out of range, the assembler generates an error message. In this
case you must use the LTORG directive to place an additional literal pool in the code.
Place the LTORG directive after the failed LDR pseudo-instruction, and within 4KB
(ARM) or 1KB (Thumb). Refer to Chapter 5 Assembler in the ARM Software
Development Toolkit Reference Guide for a detailed description of the LTORG directive.
You must place literal pools where the processor does not attempt to execute them as
instructions. Place them after unconditional branch instructions, or after the return
instruction at the end of a subroutine.
Example 5-5 shows how this works in practice. It is supplied as loadcon.s in the
examples\asm subdirectory of the toolkit. The instructions listed as comments are the
ARM instructions that are generated by the assembler. Refer to Code examples on page
5-2 for instructions on how to assemble, link, and execute the example.
Example 5-5
5-26 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Basic Assembly Language Programming
Addresses are normally expressed as offsets from the current pc or other register.
This section describes two methods for loading an address into a register:
• Load the register directly by using ADR or ADRL to construct an address from an
offset and the current pc or other register.
• Load the address from a literal pool using the LDR Rd,=label form of the LDR
pseudo-instruction.
The ADR and ADRL pseudo-instructions enable you to load a range of addresses without
performing a memory access. ADR and ADRL accept either:
The range of an ADRL pseudo-instruction is 64KB for a non-word aligned address and
256KB for a word-aligned address.
Refer to Loading addresses with LDR Rd, = label on page 5-31 for information on
loading addresses that are outside the range of the ADRL pseudo-instruction.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 5-27
Basic Assembly Language Programming
Note
• The label used with ADR or ADRL must be within the same code area. There is no
guarantee that the label will be within range after linking if it is defined in a
different area. The assembler can only fault references to labels that are out of
range in the same area.
Example 5-6 shows the type of code generated by the assembler when assembling ADR
and ADRL pseudo-instructions. It is supplied as adrlabel.s in the examples\asm
subdirectory of the toolkit. Refer to Code examples on page 5-2 for instructions on how
to assemble, link, and execute the example.
The instructions listed in the comments are the ARM instructions generated by the
assembler.
Example 5-6
5-28 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Basic Assembly Language Programming
Example 5-7 on page 5-30 shows ARM code that implements a jump table. It is
supplied as jump.s in the examples\asm subdirectory of the toolkit. Refer to Code
examples on page 5-2 for instructions on how to assemble, link, and execute the
example.
In the example, the function arithfunc takes three arguments and returns a result in
r0. The first argument determines which operation is carried out on the second and third
arguments:
The jump table is implemented with the following instructions and assembler
directives:
DCD declares one or more words of store. In this example each DCD stores the
address of a routine that handles a particular clause of the jump table.
LDR The LDR pc,[r3,r0,LSL#2] instruction loads the address of the
required clause of the jump table into the pc. It:
• multiplies the clause number in r0 by 4 to give a word offset
• adds the result to the address of the jump table
• loads the contents of the combined address into the program
counter.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 5-29
Basic Assembly Language Programming
Example 5-7
Converting to Thumb
To convert Example 5-7 to Thumb code you must modify the LDR instruction that is
used to implement the jump. This is because you cannot increment the base register of
LDR and STR instructions in Thumb state. In addition, LDR cannot load a value into the
pc, or do an inline shift of a value held in a register.
The equivalent code to cause the jump to the appropriate routine is:
LSL r0, r0,#2
LDR r3, [r3,r0]
MOV pc, r3
You must place an ALIGN directive before the Jumptable label to ensure that the table
is aligned on a 32-bit boundary.
5-30 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Basic Assembly Language Programming
The LDR Rd,= pseudo-instruction can load any 32-bit constant into a register. See
Loading with LDR Rd, =const on page 5-25. It also accepts program-relative
expressions such as labels, and labels with offsets.
• generating a program-relative LDR instruction that reads the address from the
literal pool.
For example:
LDR rn [pc, #offset to literal pool]
; load register n with one word
; from the address [pc + offset]
You must ensure that there is a literal pool within range. See Placing literal pools
on page 5-25 for more information.
Unlike the ADR and ADRL pseudo-instructions, you can use LDR with labels that are
outside the current area. If the label is outside the current area, the assembler places a
relocation directive in the object code when the source file is assembled. The relocation
directive instructs the linker to resolve the address at link time. The address remains
valid wherever the linker places the area containing the LDR and the literal pool.
Example 5-8 on page 5-32 shows how this works. It is supplied as ldrlabel.s in the
examples\asm subdirectory of the toolkit. Refer to Code examples on page 5-2 for
instructions on how to assemble, link, and execute the example.
The instructions listed in the comments are the ARM instructions that are generated by
the assembler.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 5-31
Basic Assembly Language Programming
Example 5-8
Example 5-9 on page 5-33 shows an ARM code routine that overwrites one string with
another string. It uses the LDR pseudo-instruction to load the addresses of the two strings
from a data area. Note the following instructions and directives:
DCB The DCB (Define Constant Byte) directive defines one or more bytes of
store. In addition to integer values, DCB accepts quoted strings. Each
character of the string is placed in a consecutive byte. Refer to Chapter 5
Assembler in the ARM Software Development Toolkit Reference Guide
for more information.
5-32 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Basic Assembly Language Programming
LDR/STR The LDR and STR instructions use post-indexed addressing to update their
address registers. For example, the instruction:
LDRB r2,[r1],#1
loads r2 with the contents of the address pointed to by r1 and then
increments r1 by 1.
Converting to Thumb
There is no post-indexed addressing mode for Thumb LDR and STR instructions.
Because of this, you must use an ADD instruction to increment the address register after
the LDR and STR instructions. For example:
LDRB r2, [r1] ; load register 2
ADD r1, #1 ; increment the address in
; register 1.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 5-33
Basic Assembly Language Programming
Multiple register transfer instructions provide an efficient way of moving the contents
of several registers to and from memory. They are most often used for block copy and
for stack operations for context changing at subroutine entry and exit. The advantages
of using a multiple register transfer instruction instead of a series of single data transfer
instructions include:
• There is only a single instruction fetch overhead, rather than many instruction
fetches.
• Only one register writeback cycle is required for a multiple register load or store,
as opposed to one for each register.
• On uncached ARM processors, the first word of data transferred by a load or store
multiple is always a nonsequential memory cycle, but all subsequent words
transferred can be sequential memory cycles. Sequential memory cycles are faster
in most systems.
Note
The lowest numbered register is transferred to or from the lowest memory address
accessed, and the highest numbered register to or from the highest address accessed.
The order the of registers in the register list in the instructions makes no difference.
Use the -checkreglist assembler option to check that registers in register lists are
specified in increasing order. See Command syntax on page 5-3 in the ARM Software
Development Toolkit Reference Guide.
5-34 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Basic Assembly Language Programming
The load (or store) multiple instruction loads (stores) any subset of the 16 general
purpose registers from (to) memory, using a single instruction.
Syntax
where:
address-mode
specifies the addressing mode of the instruction. See LDM and STM
addressing modes on page 5-36 for details.
Rn is the base register for the load operation. The address stored in this
register is the starting address for the load operation. Do not specify r15
(pc) as the base register.
! specifies base register write back. If this is specified, the address in the
base register is updated after the transfer. It is decremented or
incremented by one word for each register in the register list.
register-list
is a comma-delimited list of symbolic register names and register ranges
enclosed in braces. There must be at least one register in the list. Register
ranges are specified with a dash. For example:
{r0,r1,r4-r6,pc}
Do not specify writeback if the base register Rn is in register-list.
^ Do not use this option in User or System mode. For details of its use in
privileged modes, see Chapter 9 Handling Processor Exceptions and the
ARM Architectural Reference Manual.
The syntax of the STM instruction corresponds exactly (except for some details in the
effect of the ^ option).
Usage
See Implementing stacks with LDM and STM on page 5-36 and Block copy with LDM
and STM on page 5-38.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 5-35
Basic Assembly Language Programming
There are four different addressing modes. The base register can be incremented or
decremented by one word for each register in the operation, and the increment or
decrement can occur before or after the operation. The suffixes for these options are:
There are alternative addressing mode suffixes that are easier to use for stack operations.
See Implementing stacks with LDM and STM, below.
The load and store multiple instructions can update the base register. For stack
operations, the base register is usually the stack pointer, r13. This means that you can
use load and store multiple instructions to implement push and pop operations for any
number of registers in a single instruction.
The Load and Store Multiple Instructions can be used with several types of stack:
descending or ascending
The stack grows downwards, starting with a high address and progressing
to a lower one (a descending stack), or upwards, starting from a low
address and progressing to a higher address (an ascending stack).
full or empty
The stack pointer can either point to the last item in the stack (a full
stack), or the next free space on the stack (an empty stack).
In practice stacks are almost always full, descending. The C compilers produce full,
descending stacks.
To make it easier for the programmer, stack oriented suffixes can be used instead of the
Increment/Decrement and Before/After suffixes. See Table 5-6 on page 5-37 for a list
of stack oriented suffixes.
5-36 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Basic Assembly Language Programming
For example:
STMFD r13!, {r0-r5} ; Push onto a Full Descending Stack.
LDMFD r13!, {r0-r5} ; Pop from a Full Descending Stack.
STMFA r13!, {r0-r5} ; Push onto a Full Ascending Stack.
LDMFA r13!, {r0-r5} ; Pop from a Full Ascending Stack.
STMED r13!, {r0-r5} ; Push onto Empty Descending Stack.
LDMED r13!, {r0-r5} ; Pop from Empty Descending Stack.
STMEA r13!, {r0-r5} ; Push onto Empty Ascending Stack.
LDMEA r13!, {r0-r5} ; Pop from Empty Ascending Stack.
Stack operations are very useful at subroutine entry and exit. At the start of a subroutine,
any working registers required can be stored on the stack, and at exit they can be popped
off again. In addition, if the link register is pushed onto the stack at entry, additional
subroutine calls can safely be made without causing the return address to be lost. You
can return from a subroutine by popping the pc off the stack at exit, rather than by
popping lr and then moving that value into the pc.
For example:
subroutine STMFD sp!, {r5-r7,lr} ; Push work registers and lr
; code
BL somewhere_else
; code
LDMFD sp!, {r5-r7,pc} ; Pop work registers and pc
Warning
Use this with care in mixed ARM/Thumb systems. You cannot return to Thumb code
by popping directly into the program counter.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 5-37
Basic Assembly Language Programming
Example 5-10 is an ARM code routine that copies a set of words from a source location
to a destination by copying a single word at a time. It is supplied as word.s in the
examples\asm subdirectory of the toolkit. Refer to Code examples on page 5-2 for
instructions on how to assemble, link, and execute the example.
This module can be made more efficient by using LDM and STM for as much of the
copying as possible. Eight is a sensible number of words to transfer at a time, given the
number of registers that the ARM has. The number of eight-word multiples in the block
to be copied can be found (if r2 = number of words to be copied) using:
MOVS r3, r2, LSR #3 ; number of eight word multiples
This value can be used to control the number of iterations through a loop that copies
eight words per iteration. When there are less than eight words left, the number of words
left can be found (assuming that r2 has not been corrupted) using:
ANDS r2, r2, #7
Example 5-11 on page 5-39 lists the block copy module rewritten to use LDM and STM
for copying.
5-38 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Basic Assembly Language Programming
Example 5-11
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 5-39
Basic Assembly Language Programming
The Thumb instruction set contains two pairs of multiple register transfer instructions:
• LDM and STM for block memory transfers
• PUSH and POP for stack operations.
These instructions can be used to load or store any subset of the low registers from or
to memory. The base register is always updated at the end of the multiple register
transfer instruction. You must specify the ! character. The only valid suffix for these
instructions is IA.
These instructions can be used to push any subset of the low registers and (optionally)
the link register onto the stack, and to pop any subset of the low registers and
(optionally) the pc off the stack. The base address of the stack is held in r13. Examples
of these instructions are:
PUSH {r0-r3}
POP {r0-r3}
PUSH {r4-r7,lr}
POP {r4-r7,pc}
The optional addition of the lr/pc to the register list provides support for subroutine
entry and exit.
The block copy example, Example 5-10 on page 5-38, can be converted into Thumb
instructions. An example conversion can be found as tblock.s in the examples\asm
subdirectory of the toolkit.
Because the Thumb LDM and STM instructions can access only the low registers, the
number of words copied per iteration is reduced from eight to four. In addition, the
LDM/STM instructions can be used to carry out the single word at a time copy, because
they update the base pointer after each access. If LDR/STR were used for this, separate
ADD instructions would be required to update each base pointer.
5-40 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Basic Assembly Language Programming
Example 5-12
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 5-41
Basic Assembly Language Programming
See MACRO directive on page 5-73 of the ARM Software Development Toolkit
Reference Guide for more details.
The line after the MACRO directive is the macro prototype statement. The macro
prototype statement defines the name (TestAndBranch) you use to invoke the macro. It
also defines parameters ($label, $dest, $reg, and $cc). You must give values to the
parameters when you invoke the macro. The assembler substitutes the values you give
into the code.
5-42 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Basic Assembly Language Programming
Example 5-13 shows a macro that performs an unsigned integer division. It takes four
parameters:
• $Bot is the register that holds the divisor.
• $Top is the register that holds the dividend before the instructions are executed.
After the instructions are executed it holds the remainder.
• $Div is the register where the quotient of the division is placed. It may be NULL
("") if only the remainder is required.
• $Temp is a temporary register used during the calculation.
Example 5-13
MACRO
$Lab DivMod $Div,$Top,$Bot,$Temp
ASSERT $Top <> $Bot ; Produce an error message if the
ASSERT $Top <> $Temp ; registers supplied are
ASSERT $Bot <> $Temp ; not all different.
IF "$Div" <> ""
ASSERT $Div <> $Top ; These three only matter if $Div
ASSERT $Div <> $Bot ; is not null ("")
ASSERT $Div <> $Temp ;
ENDIF
$Lab
MOV $Temp, $Bot ; Put divisor in $Temp
CMP $Temp, $Top, LSR #1 ; double it until
90 MOVLS $Temp, $Temp, LSL #1 ; 2 * $Temp > $Top.
CMP $Temp, $Top, LSR #1
BLS %b90 ; The b means search backwards
IF "$Div" <> "" ; Omit next instruction if $Div is null
MOV $Div, #0 ; Initialize quotient
ENDIF
91 CMP $Top, $Temp ; Can we subtract $Temp?
SUBCS $Top, $Top,$Temp ; If we can, do so.
IF "$Div" <> "" ; Omit next instruction if $Div is null
ADC $Div, $Div, $Div ; Double $Div
ENDIF
MOV $Temp, $Temp, LSR #1 ; Halve $Temp,
CMP $Temp, $Bot ; and loop until
BHS %b91 ; less than divisor
MEND
The macro checks that no two parameters use the same register. It also optimizes the
code produced if only the remainder is required.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 5-43
Basic Assembly Language Programming
To avoid multiple definitions of labels if DivMod is used more than once in the
assembler source, the macro uses local labels (90, 91). See Local labels on page 5-28
of the ARM Software Development Toolkit Reference Guide.
Example 5-14 shows the code that this macro produces if it is invoked as follows:
ratio DivMod r0,r5,r4,r2
Example 5-14
5-44 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Basic Assembly Language Programming
The MAP directive specifies the base address of the data structure. See ^ or MAP
directive on page 5-35 of the ARM Software Development Toolkit Reference Guide.
The # directive specifies the amount of memory required for a data item, and can give
the data item a label. It is repeated for each data item in the structure. See # directive on
page 5-31 of the ARM Software Development Toolkit Reference Guide.
Note
No space in memory is allocated when a map is defined. Use Define Constant (DC)
directives to allocate space in memory.
Example 5-15 shows a data structure described using MAP and #. It is located at an
absolute (fixed) address, 4096 (0x1000) in this case.
Example 5-15
MAP 4096
consta # 4 ; consta uses four bytes, and is located at 4096
constb # 4 ; constb uses four bytes, and is located at 5000
x # 8 ; x uses eight bytes, and is located at 5004
y # 8 ; y uses eight bytes, and is located at 5012
string # 256 ; string can be up to 256 bytes long, starting at 5020
You can access data at these locations with LDR or STR instructions, such as:
LDR r4,constb
You can only do this if each instruction is within 4KB (in either direction) of the data
item it accesses. See the ARM Architectural Reference Manual for details of the LDR and
STR instructions.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 5-45
Basic Assembly Language Programming
If you need to access data from more than 4KB away, you can use a register-relative
instruction, such as:
LDR r4,[r9,offset]
offset is limited to 4096, so r9 must already contain a value within 4KB of the address
of the data.
You can access data in the structure described in Example 5-15 from an instruction at
any address. This program fragment shows how:
MOV r9,#4096 ; or #0x1000
LDR r4,[r9,constb - 4096]
The assembler calculates (constb - 4096) for you. However, it is better to redesign
the map description as in Example 5-16.
Example 5-16
MAP 0
consta # 4 ; consta uses four bytes, located at offset 0
constb # 4 ; constb uses four bytes, located at offset 4
x # 8 ; x uses eight bytes, located at offset 8
y # 8 ; y uses eight bytes, located at offset 16
string # 256 ; string is up to 256 bytes long, starting at offset 24
Using the map in Example 5-16, you can access the data structure at the same location
as before:
MOV r9,#4096
LDR r4,[r9,constb]
This program fragment assembles to exactly the same machine instructions as before.
The value of each label is 4096 less than before, so the assembler does not need to
subtract 4096 from each label to find the offset. The labels are relative to the start of the
data structure, instead of being absolute. The register used to hold the start address of
the map (r9 in this case) is called the base register.
There are likely to be many LDR or STR instructions accessing data in this data structure.
You avoid typing - 4096 repeatedly by using this method. The code is also easier to
follow.
This map does not contain the location of the data structure. The location of the
structure is determined by the value loaded into the base register at runtime.
5-46 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Basic Assembly Language Programming
The same map can be used to describe many instances of the data structure. These may
be located anywhere in memory.
There are restrictions on what addresses can be loaded into a register using the MOV
instruction. See Loading addresses into registers on page 5-27 for details of how to load
arbitrary addresses.
In many cases, you can use the same register as the base register every time you access
a data structure. You can include the name of the register in the base address of the map.
Example 5-17 shows such a register-based map. The labels defined in the map include
the register.
Example 5-17
MAP 0,r9
consta # 4 ; consta uses four bytes, located at offset 0 (from r9)
constb # 4 ; constb uses four bytes, located at offset 4
x # 8 ; x uses eight bytes, located at offset 8
y # 8 ; y uses eight bytes, located at offset 16
string # 256 ; string is up to 256 bytes long, starting at offset 24
Using the map in Example 5-17, you can access the data structure wherever it is:
ADR r9,datastart
LDR r4,constb ; => LDR r4,[r9,#4]
constb contains the offset of the data item from the start of the data structure, and also
includes the base register. In this case the base register is r9, defined in the MAP directive.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 5-47
Basic Assembly Language Programming
You can use the program counter (r15) as the base register for a map. In this case, each
STM or LDM instruction must be within 4KB of the data item it addresses, because the
offset is limited to 4KB. The data structure must be in the same area as the instructions,
because otherwise there is no guarantee that the data items will be within range after
linking.
Example 5-18 shows a program fragment with such a map. It includes a directive which
allocates space in memory for the data structure, and an instruction which accesses it.
Example 5-18
In this case, there is no need to load the base register before loading the data as the
program counter already holds the correct address. (This is not actually the same as the
address of the LDR instruction, because of pipelining in the processor. However, the
assembler takes care of this for you.)
5-48 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Basic Assembly Language Programming
You can use the # directive with an operand of 0 to label a location within a structure.
The location is labeled, but the location counter is not incremented.
The size of the data structure defined in Example 5-19 depends on the values of
MaxStrLen and ArrayLen. If these values are too large, the structure overruns the end
of available memory.
Example 5-19
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 5-49
Basic Assembly Language Programming
You are likely to have problems if you include some character variables in the data
structure, as in Example 5-20. This is because a lot of words are misaligned.
Example 5-20
You cannot use the ALIGN directive, because the ALIGN directive aligns the current
location within memory. MAP and # directives do not allocate any memory for the
structures they define.
You could insert a dummy # 1 after Char3 # 1. However, this makes maintenance
difficult if you change the number of character variables. You must recalculate the right
amount of padding each time.
Example 5-21 on page 5-51 shows a better way of adjusting the padding. The example
uses a # directive with a 0 operand to label the end of the character data. A second #
directive inserts the correct amount of padding based on the value of the label. An
:AND: operator is used to calculate the correct value.
This automatically adjusts the amount of padding used whenever character variables are
added or removed.
5-50 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Basic Assembly Language Programming
Example 5-21
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 5-51
Basic Assembly Language Programming
Register-based MAP and # directives define register-based symbols. There are two main
uses for register-based symbols:
• defining structures similar to C structures
• gaining faster access to memory areas described by non-register-based MAP and #
directives.
Register-based symbols can be very useful, but you must be careful when using them.
As a general rule, use them only in the following ways:
• As the location for a load or store instruction to load from or store to. If Location
is a register-based symbol based on the register Rb and with numeric offset, the
assembler automatically translates, for example, LDR Rn,Location into LDR
Rn,[Rb,#offset].
In an ADR or ADRL instruction, ADR Rn,Location is converted by the assembler
into ADD Rn,Rb,#offset.
Other uses usually result in assembler error messages. For example, if you write LDR
Rn,=Location, where Location is register-based, you are asking the assembler to
load Rn from a memory location that always has the current value of the register Rb plus
offset in it. It cannot do this, because there is no such memory location.
5-52 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Basic Assembly Language Programming
Point origin,oldloc,newloc;
The following assembly language code is equivalent to the typedef statement above:
PointBase RN r11
MAP 0,PointBase
Point_x # 4
Point_y # 4
Point_z # 4
The following assembly language code allocates space in memory. This is equivalent to
the last line of C code:
origin % 12
oldloc % 12
newloc % 12
You must load the base address of the data structure into the base register before you
can use the labels defined in the map. For example:
LDR PointBase,=origin
MOV r0,#0
STR r0,Point_x
MOV r0,#2
STR r0,Point_y
MOV r0,#3
STR r0,Point_z
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 5-53
Basic Assembly Language Programming
Example 5-22
With the definitions as above, the assembly language code could be as in Example 5-23.
Example 5-23
MOV r0,#1
LDR r1,=Integer
STR r0,[r1]
MOV r0,#0
LDR r1,=String
STRB r0,[r1]
MOV r0,#0xA000000A
LDR r1,=BitMask
STRB r0,[r1]
Example 5-23 uses LDR pseudo-instructions. See Loading with LDR Rd, =const on page
5-25 for an explanation of these.
5-54 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Basic Assembly Language Programming
Example 5-23 contains separate LDR pseudo-instructions to load the address of each of
the data items. Each LDR pseudo-instruction is converted to a separate instruction by the
assembler. However, it is possible to access the entire data area with a single LDR
pseudo-instruction. Example 5-24 shows how to do this. Both speed and code size are
improved.
Example 5-24
Note
The MAP directive is
MAP 0, DataAreaBase,
not
MAP StartOfData,DataAreaBase.
The MAP and # directives give the position of the data relative to the DataAreaBase
register, not the absolute position. The LDR DataAreaBase,=StartOfData
statement provides the absolute position of the entire data area.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 5-55
Basic Assembly Language Programming
If you use the same technique for an area of memory containing memory mapped I/O
(or whose absolute addresses must not change for other reasons), you must take care to
keep the code maintainable.
One method is to add comments to the code warning maintainers to take care when
modifying the definitions. A better method is to use definitions of the absolute addresses
to control the register-based definitions.
Example 5-25
Load the base address with LDR IOAreaBase,=StartOfIOArea. This allows the
individual locations to be accessed with statements like LDR R0,RcvFlag and STR
R4,SendData.
5-56 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Basic Assembly Language Programming
Sometimes you need to operate on two structures of the same type at the same time. For
example, if you want the equivalent of the pseudo-code:
newloc.x = oldloc.x + (value in r0);
newloc.y = oldloc.y + (value in r1);
newloc.z = oldloc.z + (value in r2);
The base register needs to point alternately to the oldloc structure and to the newloc one.
Repeatedly changing the base register would be inefficient. Instead, use a non-register
based map, and set up two pointers in two different registers as in Example 5-26:
Example 5-26
; code
ADR r8,oldloc
ADR r9,newloc
LDR r3,[r8,Pointx] ; load from oldloc (r8)
ADD r3,r3,r0
STR r3,[r9,Pointx] ; store to newloc (r9)
LDR r3,[r8,Pointy]
ADD r3,r3,r1
STR r3,[r9,Pointy]
LDR r3,[r8,Pointz]
ADD r3,r3,r2
STR r3,[r9,Pointz]
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 5-57
Basic Assembly Language Programming
Using MAP and # directives can help you to produce maintainable data structures.
However, this is only true if the order the elements are placed in memory is not
important to either the programmer or the program.
You can have problems if you load or store multiple elements of a structure in a single
instruction. These problems arise in operations such as:
• loading several single byte elements into one register
• using a Store Multiple or Load Multiple instruction (STM and LDM) to store or load
multiple words from or to multiple registers.
These operations require the data elements in the structure to be contiguous in memory,
and to be in a specific order. If the order of the elements is changed, or a new element
is added, the program is broken in a way that cannot be detected by the assembler.
Example 5-27
MiscBase RN r10
MAP 0,MiscBase
MiscStart # 0
Misc_a # 1
Misc_b # 1
Misc_c # 1
Misc_d # 1
MiscEndOfChars # 0
MiscPadding # (-:INDEX:MiscEndOfChars) :AND: 3
Misc_I # 4
Misc_J # 4
Misc_K # 4
Misc_data # 4*20
MiscEnd # 0
MiscLen EQU MiscEnd-MiscStart
There is no problem in using LDM/STM instructions for accessing single data elements
that are larger than a word (for example, arrays). An example of this is the 20-word
element Misc_data. It could be accessed as follows:
ArrayBase RN R9
ADR ArrayBase, MiscBase
LDMIA ArrayBase, {R0-R5}
5-58 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Basic Assembly Language Programming
This example loads the first six items in the array Misc_data. The array is a single
element and therefore covers contiguous memory locations. It is unlikely that in the
future anyone will split it into separate arrays.
However, for the case of loading Misc_I, Misc_J, and Misc_K into registers r0, r1, and
r2 the following would work, but could cause problems in the future:
ArrayBase RN R9
Problems arise if the order of Misc_I, Misc_J, and Misc_K is changed, or if a new
element Misc_New is added in the middle. Either of these small changes breaks the
code.
If the code is strongly commented, no deliberate changes are likely to be made that
would affect the workings of the program. Unfortunately, mistakes can still occur. A
second method of catching these problems would be to add ASSERT directives just
before the STM/LDM instructions to check that the labels are consecutive and in the
correct order:
ArrayBase RN R9
This ASSERT directive stops assembly at this point if the structure is not in the correct
order to be loaded with an LDM. Remember that the element with the lowest address is
always loaded from, or stored to, the lowest numbered register.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 5-59
Basic Assembly Language Programming
5-60 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Chapter 6
Using the Procedure Call Standards
This chapter describes how to use the ARM and Thumb Procedure Call Standards to
ensure that separately compiled and assembled modules follow a standard set of rules
for interworking. It contains the following sections:
• About the procedure call standards on page 6-2
• Using the ARM Procedure Call Standard on page 6-3
• Using the Thumb Procedure Call Standard on page 6-11
• Passing and returning structures on page 6-13.
Refer to the ARM Software Development Toolkit Reference Guide for a complete
description of the procedure call standards.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 6-1
Using the Procedure Call Standards
The ARM Software Development Toolkit enables you to generate object files from C,
C++, and assembly language source, and then link them with one or more libraries to
produce an executable file, as shown in Figure 6-1.
.s
ASM source module(s) armasm .o
.c
C source module(s) armcc -c .o
Irrespective of the language in which they are written, routines that make calls to other
modules must observe a common convention of argument and result passing. For the
ARM and Thumb instruction sets, these are:
• the ARM Procedure Call Standard (APCS)
• the Thumb Procedure Call Standard (TPCS).
This chapter introduces these standards, and discusses their role in ARM assembly
language for passing and returning values and pointers to structures for use by C and
C++ routines.
6-2 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Using the Procedure Call Standards
Code produced by compilers is expected to adhere to the APCS at all times. Such code
is said to be strictly conforming. Handwritten code is expected to adhere to the APCS
only when making calls to externally visible functions. Such code is said to be
conforming.
The APCS comprises a family of variants. Each variant is exclusive. Code that conforms
to one variant cannot be used with code that conforms to another.
Note
The reentrant APCS variants are obsolete.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 6-3
Using the Procedure Call Standards
Table 6-1 and Table 6-2 on page 6-5 summarize the names and roles of integer and
floating-point registers under the APCS.
Note
Not all ARM systems support floating-point. Refer to Chapter 11 Floating-point
Support in the ARM Software Development Toolkit Reference Guide for more
information.
r4 v1 register variable
r5 v2 register variable
r6 v3 register variable
r7 v4 register variable
r8 v5 register variable
6-4 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Using the Procedure Call Standards
To summarize:
a1-a4, [f0-f3] These are used to pass arguments to functions. a1 is also used to
return integer results, and f0 to return FP results. These registers
can be corrupted by a called function.
v1-v8, [f4-f7] These are used as register variables. They must be preserved by
called functions.
Hand coded assembly language routines that interface with C or C++ must conform to
the APCS. They are not required to conform strictly. This means that any register that
is not used in its APCS role by an assembly language routine (for example, fp) can be
used as a working register, provided that its value on entry is restored before returning.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 6-5
Using the Procedure Call Standards
This example illustrates how to use ARM assembly language to code a small function
so that it can be used by C modules.
The function performs a 64-bit integer addition. It uses a two-word data structure to
store each 64-bit operand. We will consider the following stages:
• writing the function in C
• examining the compiler output
• modifying the compiler output
• looking at the effects of the APCS
• revisiting the first implementation.
In ARM assembly language, you can code the addition of double-length integers by
using the Carry flag from the low word addition in the high word addition. However, in
C there is no way of specifying the Carry flag. Example 6-1 shows a workaround.
Example 6-1
The highest bits of the low words in the two operands are calculated (shifting them into
bit 0, while clearing the rest of the register). These bits are then used to determine the
value of the carry bit (in the same way as the ARM itself does).
If the addition routine were to be used a great deal, an implementation such as this
would probably be inadequate. To consider the quality of the implementation, examine
the code produced by the compiler. Follow these steps to produce an assembly language
listing:
6-6 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Using the Procedure Call Standards
Example 6-2 shows the assembly language output in file add64_1.s. It reveals that this
is an inefficient implementation (instructions may vary between compiler releases).
Example 6-2
add_64
STMDB sp!,{v1,lr}
LDR v1,[a2,#0]
MOV a4,v1,LSR #31
LDR ip,[a3,#0]
MOV lr,ip,LSR #31
ADD ip,v1,ip
STR ip,[a1,#0]
MOV ip,ip,LSR #31
LDR a2,[a2,#4]
LDR a3,[a3,#4]
ADD a2,a2,a3
TST a4,lr
CMPEQ a4,ip
MOVNE a3,#1
MOVEQ a3,#0
ADD a2,a2,a3
STR a2,[a1,#4]!
LDMIA sp!,{v1,pc}
Because you cannot specify the Carry flag in C, you must get the compiler to produce
almost the right code, and then modify it by hand. Start with (incorrect) code that does
not perform the carry addition, as in Example 6-3 on page 6-8.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 6-7
Using the Procedure Call Standards
Example 6-3
You can find the assembly language produced by the compiler in the file add64_2.s.
Example 6-4
add_64
LDR a4,[a2,#0]
LDR ip,[a3,#0]
ADD a4,a4,ip
STR a4,[a1,#0]
LDR a2,[a2,#4]
LDR a3,[a3,#4]
ADD a2,a2,a3
STR a2,[a1,#4]
MOV pc,lr
Comparing this to the C source, you can see that the first ADD instruction produces the
low order word, and the second produces the high order word. To correct this, get the
carry from the low to high word by changing:
• the first ADD to ADDS (add and set flags)
• the second ADD to an ADC (add with carry)
You can find this modified code in the directory examples/candasm as add64_3.s.
6-8 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Using the Procedure Call Standards
The most obvious effect of the APCS on the example code is the change in register
names:
• a1 holds a pointer to the destination structure.
• a2 and a3 hold pointers to the operand structures.
• a4 and ip are used as temporary registers that are not preserved. The conditions
under which ip can be corrupted are discussed in A more detailed look at APCS
register usage on page 6-10.
This is a simple leaf function that uses few temporary registers, so none are saved to the
stack and restored on exit. Therefore you can use a simple MOV pc,lr to return.
If you wish to return another result, such as the carry out from the addition, you must
load it into a1 prior to exit. You can do this as follows:
Change the second ADD to ADCS (add with carry and set flags).
Add the following instructions to load a1 with 1 or 0 depending on the carry out from
the high order addition.
MOV a1, #0
ADC a1, a1, #0
Change the return type of function declaration for add-64() from void to int.
Although the first C implementation is inefficient, it shows more about the APCS than
the hand-modified version.
You have already seen a4 and ip being used as non-preserved temporary registers.
However, here v1 and lr are also used as temporary registers. v1 is preserved by being
stored (together with lr) on entry. Register lr is corrupted, but a copy is saved onto the
stack and reloaded into pc when v1 is restored. This means that there is still only a single
exit instruction, but now it is:
LDMIA sp!,{v1,pc}
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 6-9
Using the Procedure Call Standards
Although sb, sl, fp, ip, sp and lr are dedicated registers, the example in Example 6-2 on
page 6-7 shows ip and lr being used as temporary registers. Sometimes these registers
are not used for their APCS roles. The details given below will enable you to write
efficient and safe code that uses as many of the registers as possible, and avoids
unnecessary saving and restoring of registers:
lr Holds the address to which control must return on function exit. It can be
(and often is) used as a temporary register after pushing its contents onto
the stack. This value can be loaded directly into the program counter
when returning. lr is not preserved in either its dedicated or non-dedicated
APCS role.
sp Is the stack pointer. It is always valid in strictly conforming code, but need
only be preserved in handwritten code. Note, however, that if any
handwritten code makes use of the stack, or if interrupts can use the user
mode stack, sp must be valid. In its non-dedicated APCS role, sp must be
preserved. sp must be preserved on function exit for APCS conforming
code.
fp Is the frame pointer register. In the obsolete APCS variants that use fp,
this register contains either zero, or a pointer to the most recently created
stack backtrace data structure. As with the stack pointer, the frame
pointer must be preserved, but in handwritten code it does not need to be
available at every instant. However, it must be valid whenever any strictly
conforming function is called. fp must always be preserved.
sb Is the static base register. This register is used to access static data. If sb
is not used, it is available as an additional register variable, v6, that must
be preserved across function calls. sb must always be preserved.
6-10 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Using the Procedure Call Standards
There are fewer options with TPCS than with the APCS. This reflects the different ways
in which ARM and Thumb code are used, and also reflects the reduced nature of the
Thumb instruction set.
reentrancy Reentrant code is code that calls the same entry point with different sets
of static data.
You can implement reentrancy by placing in a struct all variables that
must be multiply instantiated, and passing each function a pointer to the
struct.
hardware floating-point
Thumb code cannot access floating-point instructions without switching
to ARM state. Floating-point is supported indirectly by defining how FP
values are passed to and returned from Thumb functions in the Thumb
registers.
Refer to the ARM Software Development Toolkit Reference Guide for the full
specification of the TPCS.
In addition, the Thumb subset can access the other ARM registers (r8-r12, called the
high registers) singly using a set of special instructions. Refer to the ARM Architectural
Reference Manual for details.
In the context of the TPCS, each Thumb register has a special name and function as
shown in Table 6-3 on page 6-12.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 6-11
Using the Procedure Call Standards
r4 v1 register variable
r5 v2 register variable
r6 v3 register variable
6-12 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Using the Procedure Call Standards
Unless special conditions apply (as detailed in following sections), C structures are
passed in registers that, if necessary, overflow onto the stack and are returned through a
pointer to the memory location of the result.
For struct-valued functions, a pointer to the location where the struct result is to be
placed is passed in a1 (the first argument register). The first argument is then passed in
a2, the second in a3, and so on. It is as if:
struct s f(int x)
Example 6-5
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 6-13
Using the Procedure Call Standards
Example 6-6 shows the code armcc produces (the version of armcc supplied with your
release may produce output slightly different from that listed here).
Example 6-6
max
STMDB sp!,{a1-a3}
LDRB a3,[sp,#4]
LDRB a2,[sp,#8]
CMP a3,a2
ADDLE a2,sp,#8
ADDGT a2,sp,#4
LDR a2,[a2,#0]
STR a2,[a1,#0]
ADD sp,sp,#0xc
MOV pc,lr
The STMDB instruction saves the arguments onto the stack. Registers a2 and a3 are used
as temporary registers to hold the required part of the structures passed, and a1 is a
pointer to an area in memory in which the resulting structure is placed.
The APCS specifies different rules for returning integer-like structures. An integer-like
structure:
• is no larger than one word in size
• has addressable subfields, all of which have an offset of 0.
union polymorphic_ptr
{
struct A *a;
struct B *b;
int *i;
}
6-14 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Using the Procedure Call Standards
An integer-like structure has its contents returned in a1. This means that a1 is not needed
to pass a pointer to a result structure in memory, and is instead used to pass the first
argument. Example 6-7 demonstrates this.
Example 6-7
Arguments a and b are passed in registers a1 and a2, and because half_word_struct
is integer-like, you would expect a1 to return the result structure directly, rather than a
pointer to it.
Example 6-8 shows the code armcc produces. The version of armcc supplied with your
release may produce output slightly different from that listed here.
Example 6-8
max
MOV a3,a1,LSL #16
CMP a3,a2,LSL #16
MOVLS a1,a2
MOV pc,lr
From this you can see that the contents of the half_words structure is returned directly
in a1 as expected.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 6-15
Using the Procedure Call Standards
There are occasions when a function must return more than one value. The usual way
to achieve this is to define a structure that holds all the values to be returned, and to pass
a pointer to the structure back in a1. The pointer is then dereferenced, allowing the
values to be stored.
This is only useful for returning structures that are no larger than four words.
To make such a function work, you must split the two 32-bit numbers (a, b) into high
and low 16-bit parts (a_hi, a_lo, b_hi, b_lo). You then perform the four
multiplications a_lo * b_lo, a_hi * b_lo, a_lo * b_hi, a_hi * b_lo and add the
results together, taking care to deal with carry correctly.
Since the problem involves manipulation of the Carry flag, writing this function in C
does not produce optimal code (see An example of APCS register usage: 64-bit integer
addition on page 6-6). Therefore you must code the function in ARM assembly
language. Example 6-9 on page 6-17 shows code that implements the algorithm.
6-16 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Using the Procedure Call Standards
Example 6-9
mul64
MOV ip, a1, LSR #16 ; ip = a_hi
MOV a4, a2, LSR #16 ; a4 = b_hi
BIC a1, a1, ip, LSL #16 ; a1 = a_lo
BIC a2, a2, a4, LSL #16 ; a2 = b_lo
MUL a3, a1, a2 ; a3 = a_lo * b_lo(m_lo)
MUL a2, ip, a2 ; a2 = a_hi * b_lo(m_mid1)
MUL a1, a4, a1 ; a1 = a_lo * b_hi(m_mid2)
MUL a4, ip, a4 ; a4 = a_hi * b_hi(m_hi)
ADDS ip, a2, a1 ; ip = m_mid1 + m_mid2(m_mid)
ADDCS a4, a4, #&10000 ; a4 = m_hi + carry(m_hi’)
ADDS a1, a3, ip, LSL #16 ; a1 = m_lo + (m_mid<<16)
ADC a2, a4, ip, LSR #16 ; a2 = m_hi’ + (m_mid>>16) + carry
MOV pc, lr
Note
On processors with a fast multiply unit such as the ARM7TDMI and ARM7DMI this
example can be recoded using the UMULL instructions.
Example 6-9 is fine for use with assembly language modules, but to use it from C you
must tell the compiler that this routine returns its 64-bit result in registers. You can do
this by making the following declarations in a header file.
typedef struct int64_struct
{
unsigned int lo;
unsigned int hi;
}
int64;
The above assembly language code and declarations, together with a test program, are
in the directory examples/candasm as the files mul64.s, mul64.h, int64.h and
multest.c.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 6-17
Using the Procedure Call Standards
To compile, assemble, and link these to produce an executable image suitable for armsd,
copy them to your current directory, and then execute the following commands:
armasm mul64.s -o mul64.o -li
armcc -c multest.c -li
armlink mul64.o multest.o -o multest
where -li can be omitted if armcc and armasm (and armsd, below) have been
configured with it as a default.
2. Type go at the armsd prompt to run the program. The following line is displayed:
Enter two unsigned 32-bit numbers in hex eg.(100 FF43D)
6-18 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Chapter 7
Interworking ARM and Thumb
This chapter explains how to change between ARM state and Thumb state when writing
code for processors that implement the Thumb instruction set. It contains the following
sections:
• About interworking on page 7-2
• Basic assembly language interworking on page 7-4
• C and C++ interworking and veneers on page 7-13
• Assembly language interworking using veneers on page 7-21
• ARM-Thumb interworking with the ARM Project Manager on page 7-25.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 7-1
Interworking ARM and Thumb
The ARM linker detects when ARM and Thumb code is being mixed, and can generate
small code segments called veneers. These veneers perform an ARM-Thumb state
change on function entry and exit whenever an ARM function is called from Thumb
state, or a Thumb function is called from ARM state.
When you write code for a Thumb-capable ARM processor, you will probably write
most of your application to run in Thumb state, because this provides the best possible
code density and performance with 8-bit or 16-bit memory. However, you may want
parts of your application to run in ARM state for reasons such as:
Speed Some parts of an application may be highly speed critical. These sections
may be more efficient running in ARM state than in Thumb state, because
in some circumstances a single ARM instruction can do more than the
equivalent Thumb instruction.
Some systems include a small amount of fast 32-bit memory from which
ARM code can be run, without the overhead of fetching each instruction
from 8-bit or 16-bit memory.
Functionality
Thumb instructions are less flexible than their ARM equivalents. Some
operations, such as accessing the program status registers directly, are not
possible in Thumb state. This means that a state change is required in
order to carry out these operations.
Exception handling
The processor automatically enters ARM state when a processor
exception occurs. This means that the first part of an exception handler
must be coded with ARM instructions, even if it re-enters Thumb state to
carry out the main processing of the exception. At the end of such
processing, the processor must be returned to ARM state to return from
the handler to the main application.
Refer to Handling exceptions on Thumb-capable processors on page
9-41 for more information.
7-2 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Interworking ARM and Thumb
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 7-3
Interworking ARM and Thumb
Refer to Assembly language interworking using veneers on page 7-21 for information
on using linker-generated interworking veneers from assembly language.
The BX instruction branches to the address contained in a specified register. The value
of bit 0 of the branch address determines whether execution continues in ARM state or
Thumb state.
• All ARM instructions are word-aligned. This means that bits 0 and 1 of the
address of any ARM instruction are ignored because these bits refer to the
halfword and byte part of the address.
• All Thumb instructions are halfword-aligned. This means that bit 0 of the address
of any Thumb instruction is ignored because it refers to the byte part of the
address.
7-4 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Interworking ARM and Thumb
Syntax
where:
Rn is a register in the range r0 to r15 that contains the address to branch to.
The value of bit 0 in this register determines the processor state:
• if bit 0 is set, the instruction at the branch address is executed in
Thumb state
• if bit 0 is clear, the instruction at the branch address is executed in
ARM state.
cond is an optional condition code. Only the ARM version of BX can be
executed conditionally.
Usage
• You can also use BX for branches that do not change state. You can use this to
execute branches that are out of range of the normal branch instructions. Because
BX takes a 32-bit register operand it can branch anywhere in 32-bit memory. The
B and BL instructions are limited to:
• 32 MB in ARM state, for both conditional and unconditional B and BL
instructions
• 4 MB in Thumb state, for unconditional B and BL instructions
• -128 to +127 instructions in Thumb state, for the conditional B instruction.
Note
The BX instruction is only implemented on ARM processors that are Thumb-capable. If
you use BX to execute long branches your code will fail on processors that are not
Thumb-capable. The result of a BX instruction on a processor that is not Thumb-capable
is unpredictable.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 7-5
Interworking ARM and Thumb
The ARM assembler can assemble both Thumb code and ARM code. By default, it
assembles ARM code unless it is invoked with the -16 option.
Because all Thumb-capable ARM processors start in ARM state, you must use the BX
instruction to branch and exchange to Thumb state, and then use the CODE16 directive
to instruct the assembler to assemble Thumb instructions.
Refer to the ARM Software Development Toolkit Reference Guide for more information
on these directives.
Example 7-1 on page 7-7 implements a short header section of ARM code that changes
the processor to Thumb state.
• An ADR instruction to load the branch address and set the least significant bit. The
ADR instruction generates the address by loading r2 with the value pc+offset.
See Direct loading with ADR and ADRL on page 5-27 for more information on
the ADR instruction.
The main body of the module is prefixed by a CODE16 directive that instructs the
assembler to treat the following code as Thumb code. The Thumb code adds the
contents of two registers together.
The code section labeled stop uses the Thumb Angel SWI to exit. The SWI reports an
exception reason, specified in r1, to the debugger. In this case it is used to report normal
application exit. Refer to Chapter 13 Angel for more information on Angel.
Note
The Thumb Angel semihosting SWI is, by default, a different number from the ARM
semihosting SWI (0xAB rather than 0x123456).
7-6 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Interworking ARM and Thumb
Example 7-1
AREA AddReg,CODE,READONLY
; Name this block of code.
1. Enter the code using any text editor and save the file as addreg.s.
2. Type asm -g addreg.s at the command prompt to assemble the source file.
4. Type armsd addreg to load the module into the command-line debugger
5. Type break @start at the armsd command prompt to set a breakpoint on the
label start.
7. When the breakpoint is hit, type step to single step through the rest of the
program. Type reg to display the registers after each step and watch the processor
enter Thumb state. This is denoted by the T in the Current Program Status
Register (cpsr) changing from a lowercase "t" to an uppercase "T".
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 7-7
Interworking ARM and Thumb
In the case of non-interworking subroutine calls, you can carry out both operations in a
single BL instruction.
In the interworking case, where the subroutine is coded for the other state, you must
allow for state changes both when calling the subroutine, and when returning from the
subroutine.
To call the subroutine and change the processor state, use a BX instruction as described
in The Branch Exchange instruction on page 7-4.
Unlike the BL instruction, BX does not store the return address in the link register. You
must ensure that the link register is loaded with the return address before you use the BX
instruction. If the call is from Thumb code to ARM code you must also set bit 0 in the
link register to ensure that the processor executes in Thumb state when the subroutine
returns.
In addition, the Thumb instruction set version of BL sets bit 0 when it loads the link
register with the return address. When a Thumb-to-ARM interworking subroutine call
returns using a BX lr instruction, it causes the required state change to occur
automatically.
If you always use the same register to store the address of the ARM subroutine that is
being called from Thumb, this segment can be used to send an interworking call to any
ARM subroutine. The __call_via_r4 procedure in Example 7-2 demonstrates this
technique.
Note
You must use a BX lr instruction at the end of the ARM subroutine to return to the
caller. You cannot use the MOV pc,lr instruction to return in this situation because it
does not cause the required change of state.
7-8 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Interworking ARM and Thumb
If you do not use a BL instruction to call the BX instruction then you must ensure that the
link register is updated and that bit 0 is set, either by the calling Thumb routine or by
the called ARM routine.
When carrying out an ARM-to-Thumb interworking subroutine call you do not need to
set bit 0 of the link register because the routine is returning to ARM state. In this case,
you can store the return address by copying the program counter into the link register
with a MOV lr,pc instruction immediately before the BX instruction.
Remember that the address operand to the BX instruction that calls the Thumb
subroutine must have bit 0 set so that the processor executes in Thumb state on arrival.
Example 7-2 on page 7-10 has an ARM code header and a Thumb code main routine.
The program sets up two parameters (r0 and r1), and makes an interworking call to an
ARM subroutine that adds the two parameters together and returns.
1. Type asm -g armadd.s at the system command prompt to assemble the module.
2. Type armlink armadd.o -o armadd to link the object file.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 7-9
Interworking ARM and Thumb
Example 7-2
AREA ArmAdd,CODE,READONLY
; name this block of code.
ENTRY ; Mark 1st instruction to call.
; Assembler starts in ARM mode.
main
ADR r2, ThumbProg + 1
; Generate branch target address and set bit 0,
; hence arrive at target in Thumb state.
BX r2 ; Branch exchange to ThumbProg.
ARMSubroutine
ADD r0, r0, r1 ; Add the numbers together
BX LR ; and return to Thumb caller
; (bit 0 of LR set by Thumb BL).
7-10 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Interworking ARM and Thumb
Example 7-3 is a modified form of Example 7-2. The main routine is now in ARM code
and the subroutine is in Thumb code. Notice that the call sequence is now a MOV
instruction followed by a BX instruction.
Example 7-3
ADR r4, ThumbSub + 1 ; Generate branch target address and set bit 0,
; hence arrive at target in Thumb state.
MOV lr, pc ; Store the return address.
BX r4 ; Branch exchange to subroutine ThumbSub.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 7-11
Interworking ARM and Thumb
You must use the DATA directive when you define data within a Thumb code area.
When the linker relocates a label in a Thumb code area, it assumes that the label
represents the address of a Thumb code routine. Consequently it sets bit 0 of the label
so that the processor is switched to Thumb state if the routine is called with a BX
instruction.
The linker cannot distinguish between code and data within a code area. If the label
represents a data item, rather than an address, the linker adds 1 to the value of the data
item.
The DATA directive marks a label as pointing to data within a code area and the linker
does not add 1 to its value. For example:
AREA code, CODE
Thumb_fn ; ...
MOV pc, lr
Thumb_Data DATA
DCB 1, 3, 4, ...
Note that the DATA directive must be on the same line as the symbol. Refer to the
description of the DATA directive in the ARM Software Development Toolkit Reference
Guide for more information.
7-12 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Interworking ARM and Thumb
By default, the APCS options for the ARM assembler and compilers are the same for
ARM and Thumb. The default options are:
/nofp/noswstackcheck
If your code is compiled with other options, for example with software stack checking
enabled (/swstackcheck), then you must ensure that all ARM modules and Thumb
modules are compiled to the same standard if they are to be interworked.
If you do not do this, the linker informs you where the incompatibilities occurred by
generating warning messages of the form:
Attribute conflict between AREA object(area) and image code.
(attribute difference = {NO_SW_STACK_CHECK}).
Refer to Chapter 6 Using the Procedure Call Standards for more information on APCS.
Refer to the ARM Software Development Toolkit Reference Guide for more information
on command-line options to the assembler and compilers.
The -apcs /interwork compiler option enables all ARM and Thumb C and C++
compilers to compile modules containing routines that can be called by routines
compiled for the other processor state:
tcc -apcs /interwork
armcc -apcs /interwork
tcpp -apcs /interwork
armcpp -apcs /interwork
Modules that are compiled for interworking generate slightly (typically 2%) larger code
for Thumb and marginally larger code for ARM.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 7-13
Interworking ARM and Thumb
For a leaf function, (that is, a function whose body contains no function calls), the only
change in the code generated by the compiler is to replace MOV pc,lr with BX lr. For
non-leaf functions, the Thumb compiler must replace, for example, the single
instruction:
POP {r4,r5,pc}
In addition, the -apcs /interwork option sets the interwork attribute for the code
area into which the modules are compiled. The linker detects this attribute and inserts
the appropriate veneer. The sizes of the veneers are:
• Eight bytes for each called routine for calls from Thumb to ARM. This consists
of:
• a Thumb BX instruction
• a halfword of padding for alignment
• an ARM branch instruction.
• Twelve bytes for each called routine for calls from ARM to Thumb. This consists
of:
• an ARM LDR instruction to get the address of the function being called
• an ARM BX instruction to execute the call
• a word to hold the address of the function.
Note
ARM code compiled for interworking cannot be used on ARM processors that are not
Thumb-capable because these processors do not implement the BX instruction.
Use the armlink -info total option to find the amount of space taken by the
veneers. The interworking veneers are included in the const data column of the
object totals. See Figure 7-1 on page 7-15 for an example.
7-14 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Interworking ARM and Thumb
Use the armlink -info size option to see more detail. The space taken by the
veneers is displayed as an <anon> row entry at the top of the table. See Figure 7-2 for
an example.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 7-15
Interworking ARM and Thumb
The two modules in Example 7-4 can be built to produce an application where main()
is a Thumb routine that carries out an interworking call to an ARM subroutine. The
subroutine call itself makes an interworking call to the Thumb library routine,
printf().
Example 7-4
/**********************
* thumb.c *
**********************/
#include <stdio.h>
extern void arm_function(void);
int main(void)
{
printf("Hello from Thumb World\n");
arm_function();
printf("And goodbye from Thumb World\n");
return (0);
}
/**********************
* arm.c *
**********************/
#include <stdio.h>
void arm_function(void)
{
printf("Hello and Goodbye from ARM world\n");
}
7-16 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Interworking ARM and Thumb
• You must use the -apcs /interwork command-line option to compile any C
or C++ modules that contain functions that are called by interworking calls.
• You may compile modules that are never called by an interworking call without
the -apcs /interwork option. These modules may make interworking calls,
but may not be called by interworking calls.
• By default, the linker selects the appropriate interworking ANSI C or C++ library
based on the area definitions in the code generated by the compilers.
If you specify a library explicitly on the linker command line you must ensure that
it is an appropriate interworking library. The library should match the state in
which the main() function executes. Refer to The C and C++ interworking
libraries on page 7-19 for further details.
Note
You must take great care when using function pointers in applications that contain both
ARM and Thumb code. The linker cannot generate warnings about illegal indirect calls,
and the code will fail at runtime.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 7-17
Interworking ARM and Thumb
No calls possible
Non-interworking Non-interworking
Thumb code ARM code
Non-interworking to
Thumb-Thumb calls ARM-ARM calls
interworking
permitted permitted
ARM/Thumb calls
The linker generates an error if it detects a direct ARM-Thumb interworking call where
the called routine is not compiled for interworking. You must recompile the called
routine for interworking.
For example, Figure 7-4 shows the errors that are produced if the ARM routine in
Example 7-2 on page 7-10 is compiled without the -apcs /interwork option.
Error: Unsupported call from Thumb code to ARM symbol _printf in thumb.o(C$$code).
Error: Unsupported call from Thumb code to ARM symbol arm_function in
thumb.o(C$$code).
Error: Unsupported call from Thumb code to ARM symbol _printf in thumb.o(C$$code).
7-18 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Interworking ARM and Thumb
You may wish to include two functions with the same name, one compiled for ARM and
the other for Thumb.
Duplicate definitions can be useful, for example, if you have a speed-critical routine in
a system with 16-bit and 32-bit memory where the overhead of the interworking veneer
would degrade the performance too much.
The linker allows duplicate definitions provided that each definition is of a different
type. That is, one definition defines a Thumb routine and the other defines an ARM
routine. The linker generates a warning message if there is a duplicate definition of a
symbol:
Both ARM & Thumb versions of symbol present in image
This is a warning to advise you in case you accidentally include two copies of the same
routine. If that is what you intended, you can ignore the warning.
Note
When both versions of an identically-named routine are present in an image, and a call
is made through a function pointer, it is not possible to determine which version of the
routine will be called. Therefore, if you are using function pointers to call such routines,
you must compile both routines, and the routine making the call, for interworking.
Two variants of the Thumb C libraries are provided with the Toolkit:
• compiled for interworking (armlib_i.16l and armlib_i.16b)
• not compiled for interworking (armlib.16l and armlib.16b).
Use the non-interworking set only if your application consists solely of Thumb code.
For example, it is unlikely that you will want a Thumb routine running from 16-bit
memory to use an ARM library routine that takes up more memory and takes longer to
execute than the Thumb library equivalent. If you want to build interworking versions
of the ARM library, refer to ARM Software Development Toolkit Reference Guide for
details of how to rebuild the libraries.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 7-19
Interworking ARM and Thumb
Remember that if interworking takes place within an application, you must use an
interworking main library. See Simple rules for interworking on page 7-17.
If you need to select the ARM or Thumb version of a standard C library routine
explicitly, or if you want to include both ARM and Thumb versions of a routine, you
can force the inclusion of specific modules from a library.
To force inclusion of a library module, put the name of the module in parentheses after
the library name. Ensure that there are no spaces between the library name and the
opening parenthesis. You can specify more than one module by separating module
names with a comma. Ensure that there are no spaces in the list of module names.
Examples
To force the use of the ARM version of strlen() and take all other routines from the
interworking Thumb library enter:
armlink -o prog thumb.o arm.o armlib.32l(strlen.o) armlib_i.16l
To force the inclusion of both ARM and Thumb versions of all functions starting with
str and take all other routines from the interworking Thumb library enter:
armlink -o prog thumb.o arm.o armlib.16l(str*) armlib.32l(str*)
armlib_i.16l
Note
On UNIX platforms, depending on the command shell you are using, you may need to
put the characters (, ) and * in quotes in order to enter them on the command line.
7-20 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Interworking ARM and Thumb
This section describes how you can make use of interworking veneers to:
• interwork between assembly language modules
• interwork between assembly language and C or C++ modules.
You can write assembly language ARM-Thumb interworking code to make use of
interworking veneers generated by the linker. To do this, you write:
• the callee routine using a BX instruction to return, and set the INTERWORK attribute
for the area in which it is located.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 7-21
Interworking ARM and Thumb
Example 7-5
; *****
; arm.s
; *****
AREA Arm,CODE,READONLY ; Name this block of code.
IMPORT ThumbProg
ENTRY ; Mark 1st instruction to call.
ARMProg
MOV r0,#1 ; Set r0 to show in ARM code.
BL ThumbProg ; Call Thumb subroutine.
MOV r2,#3 ; Set r2 to show returned to ARM.
; Terminate execution.
MOV r0, #0x18 ; angel_SWIreason_ReportException
LDR r1, =0x20026 ; ADP_Stopped_ApplicationExit
SWI 0xAB ; Angel semihosting Thumb SWI
END
; *******
; thumb.s
; *******
AREA Thumb,CODE,READONLY,INTERWORK
; Name this block of code.
CODE16 ; Subsequent instructions are Thumb.
EXPORT ThumbProg
ThumbProg
MOV r1, #2 ; Set r1 to show reached Thumb code.
BX lr ; Return to ARM subroutine.
END ; Mark end of this file.
Follow these steps to build and link the modules, and examine the interworking veneers:
3. Type armlink arm.o thumb.o -o count to link the two object files.
5. Type list 0x8000 at the armsd command prompt to list the code. Figure 7-5
shows an example.
7-22 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Interworking ARM and Thumb
Note
The addresses may vary depending on the version of the toolkit you are using.
C and C++ code compiled to run in one state can call assembly language code designed
to run in the other state, and vice versa. To do this, write the caller routine as any
non-interworking routine and, if calling from assembly language, use a BL instruction
to make the call. Then:
• if the callee routine is in assembly language, set the INTERWORK attribute and
return using BX lr.
Note
Any assembly language code used in this manner must conform to the APCS where
appropriate.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 7-23
Interworking ARM and Thumb
Example 7-6
/**********************
* thumb.c *
**********************/
#include <stdio.h>
extern int arm_function(int);
int main(void)
{
int i = 1;
printf("i = %d\n", i);
printf("And now i = %d\n", arm_function(i));
return (0);
}
; *****
; arm.s
; *****
AREA Arm,CODE,READONLY,INTERWORK
; Name this block of code.
EXPORT arm_function
arm_function
ADD r0,r0,#4 ; Add 4 to first parameter.
BX LR ; Return
END
3. Type armlink arm.o thumb.o -o add to link the two object files.
7-24 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Interworking ARM and Thumb
Additionally, projects created from either the ARM Executable Image template or
Thumb Executable Image template may be easily modified to support interworking
with Thumb or ARM code respectively. For example, an ARM-only application can
easily be made into an ARM-mostly project and a Thumb-only project can easily be
made into a Thumb-mostly project.
A Thumb application written only in C that must implement exception handlers will, by
architectural necessity, have these in ARM assembly code and should probably be
created using the Thumb Executable Image template.
2. In the New dialog select Project and click OK. The New Project dialog is
displayed.
3. Select a template from the Type box. A descriptions of the template is displayed
in the field Template description when you make a selection.
For interworking it is best to choose the Thumb-ARM interworking image or the
Thumb-ARM C++ Interworking image and follow the instructions in Using the
Thumb-ARM interworking image project on page 7-26.
Refer to Modifying a project to support interworking on page 7-27 for
information on converting an existing Thumb or ARM project to an interworking
project.
4. Enter a Project Name and a Directory in which to create it and click OK. An
empty project based on the template is created in the directory you specified.
The project tree view is displayed:
• press * on the numeric keypad to expand all branches
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 7-25
Interworking ARM and Thumb
This section describes how to use the Thumb-ARM interworking image project to start
a new interworking project.
Adding files
2. In the Add Files to Project dialog, find the directory containing the files to be
added.
3. Select the required file or files and click Open. The files are added to the selected
partition.
After adding files you may have to expand branches of the tree to make them visible.
Branches containing subtrees have a + button. If you added assembly language files to
the ASM-Source partition that do not contain CODE32 directives perform the steps listed
in Configuring the assembler to read ARM assembly source below.
By default, the interworking templates call the assembler with the -16 option to instruct
the assembler to assemble Thumb code. The templates assume that assembly language
source uses CODE16 and CODE32 directives to switch between Thumb and ARM
assembly where required.
7-26 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Interworking ARM and Thumb
If you have ARM assembly language files that do not use CODE32 directives you can
configure the assembler to avoid changing the assembly language source.
Follow these steps to change the assembler configuration for an individual source file:
1. In the Project View, expand the ASM-Sources partition and select the ARM
assembler source, for example, armer_kerl.s
3. Click the Target tab and select the ARM radio button in the Initial state group.
4. Select the Call Standard tab and ensure that the APCS3 radio button is selected
in the APCS3 Qualifiers group.
Follow these steps for each file in the Sources partition that you want to be compiled
with tcc rather than armcc:
1. Select the C file to be compiled into Thumb code from the Sources partition, for
example, foo.c.
2. Select Edit variable for foo.c from the Project menu. The Edit Variables dialog
box is displayed.
3. Type cc in the Name field and tcc in the Value field and click OK.
4. Configure the Thumb compiler for interworking for this file:
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 7-27
Interworking ARM and Thumb
Note
To revert to armcc set the Value from step 3 to an empty string, and perform step 4
clicking Unset. This may remove any other per file options you had set.
Follow these steps for each file in the Sources partition that you want to be compiled
with armcc rather than tcc:
1. Select a C file in the partition Sources that is to be compiled into ARM code, for
example, foo.c.
2. Select Edit Variable for foo.c from the Project menu. The Edit Variables dialog
is displayed.
Note
To revert to tcc, set the Value from step 3 to an empty string, and perform step 4 clicking
Unset. This may remove any other per file options you had set.
In certain circumstances, you may not require the default ANSI C library, for example,
if you are implementing an RTOS with its own stack and heap management.
7-28 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Interworking ARM and Thumb
3. Click the General tab and ensure that the Search standard libraries check box
is not selected.
4. Click the Listings tab and add any libraries you want to link with to the Extra
command-line arguments field.
As described in The C and C++ interworking libraries on page 7-19, you may
sometimes need to force the inclusion of a specific module from a particular library.
Follow these steps to do this when using ARM Project Manager:
3. Click the Listings tab and enter the library modules that you want to be forcibly
included in the Extra command line arguments field. For example, to force the
inclusion of strcpy() and strcmp()
c:\arm250\lib\armlib.32l(strcpy.o)
c:\arm250\lib\armlib.32l(strcmp.o)
This can also be written within quotes to override the normal meaning of space as
an argument separator.
Alternatively, you can use a pattern for the name of the modules:
c:\arm250\lib\armlib.32l(strc*)
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 7-29
Interworking ARM and Thumb
7-30 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Chapter 8
Mixed Language Programming
This chapter describes how to write mixed C, C++, and ARM assembly language code.
It also describes how to use the ARM inline assemblers from C and C++. It contains the
following sections:
• Using the inline assemblers on page 8-2
• Accessing C global variables from assembly code on page 8-15
• Using C header files from C++ on page 8-16
• Calling between C, C++, and ARM assembly language on page 8-18.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 8-1
Mixed Language Programming
The inline assembler supports very flexible interworking with C and C++. Any register
operand may be an arbitrary C or C++ expression. The inline assembler also expands
complex instructions and optimizes the assembly language code.
Note
Inline assembly language is subject to optimization by the compiler if optimization is
enabled either by default, or with the -O1 or -O2 compiler options.
The armcc and armcpp inline assemblers implement the full ARM instruction set,
including generic coprocessor instructions, halfword instructions and long multiply.
The tcc and tcpp inline assemblers implement the full Thumb instruction set.
The inline assembler is a high-level assembler. Some low-level features that are
available to armasm, such as branching by writing to pc, are not supported.
The ARM C compilers support inline assembly language with the __asm specifier.
The ARM C++ compilers support the asm syntax proposed in the Draft C++ Standard,
with the restriction that the string literal must be a single string. For example:
asm("instruction[;instruction]");
The asm syntax is supported by the C++ compilers when compiling both C and C++.
The asm statement must be inside a C or C++ function. Do not include comments in the
string literal. An asm statement can be used anywhere a C or C++ statement is expected.
In addition to the asm syntax, ARM C++ supports the C compiler __asm syntax when
used with both asm and __asm.
The inline assembler is invoked with the assembler specifier, and is followed by a list
of assembler instructions inside braces. For example:
8-2 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Mixed Language Programming
__asm
{
instruction [; instruction]
...
[instruction]
}
If two instructions are on the same line, you must separate them with a semicolon. If an
instruction is on multiple lines, line continuation must be specified with the backslash
character (\). C or C++ comments may be used anywhere within an inline assembly
language block.
Example 8-1 on page 8-4 shows how to use labels and branches in a string copy routine.
The syntax of labels inside assembler blocks is the same as in C. Function calls that use
BL from inline assembly language must specify the input registers, the output registers,
and the corrupted registers. In this example, the inputs to my_strcpy are r0 and r1,
there are no outputs, and the default APCS registers {r0-r3, r12, lr, PSR} are corrupted.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 8-3
Mixed Language Programming
Example 8-1
#include <stdio.h>
int main(void)
{
char a[] = "Hello world!";
char b[20];
__asm
{
MOV R0, a
MOV R1, b
BL my_strcpy, {R0, R1}, {}, {}
}
printf("Original string: %s\n", a);
printf("Copied string: %s\n", b);
return 0;
}
8-4 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Mixed Language Programming
The ARM and Thumb instruction sets are described in the ARM Architectural Reference
Manual. All instruction opcodes and register specifiers may be written in either
lowercase or uppercase.
Operand expressions
When an operand is used as a destination, the expression must be assignable (an lvalue).
When writing code that uses both physical registers and expressions, you must take care
not to use complex expressions that require too many registers to evaluate. The compiler
issues an error message if it detects conflicts during register allocation.
Physical registers
The inline assemblers allow restricted access to the physical registers. It is illegal to
write to pc. Only Branches using B or BL are allowed. In addition, it is inadvisable to
intermix inline assembler instructions that use physical registers and complex C or C++
expressions.
The compiler uses r12 (ip) for intermediate results, and r0-r3, r12 (ip), r14 (lr) for
function calls while evaluating C expressions, so these cannot be used as physical
registers at the same time.
Physical registers, like variables, must be set before they can be read. When physical
registers are used the compiler saves and restores C/C++ variables that may be allocated
to the same physical register. However, the compiler cannot restore sp, sl, fp, or sb in
calling standards where these registers have a defined role.
Constants
The constant expression specifier (#) is optional. If it is used, the expression following
it must be constant.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 8-5
Mixed Language Programming
Instruction expansion
The constant in instructions with a constant operand is not limited to the values allowed
by the instruction. Instead, such an instruction is translated into a sequence of
instructions with the same effect. For example:
ADD r0, r0, #1023
With the exception of coprocessor instructions, all ARM and Thumb instructions with
a constant operand support instruction expansion.
In addition, the MUL instruction can be expanded into a sequence of adds and shifts when
the third operand is a constant.
• Logical instructions:
• set the NZ flags correctly
• do not change the V flag
• corrupt the C flag.
Labels
C and C++ labels can be used in inline assembler statements. C and C++ labels can be
branched to by branch instructions only in the form:
B{cond} label
Storage declarations
All storage can be declared in C or C++ and passed to the inline assembler using
variables. Therefore, the storage declarations that are supported by armasm are not
implemented.
8-6 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Mixed Language Programming
SWIs and branch link instructions must specify exactly which calling standard is used.
Three optional register lists follow the normal instruction fields. The register lists
specify:
• the registers that are the input parameters
• the registers that are output parameters after return
• the registers that are corrupted by the called function.
For example:
SWI{cond} swi_num, {input_regs}, {output_regs}, {corrupted_regs}
BL{cond} function, {input_regs}, {output_regs}, {corrupted_regs}
An omitted list is assumed to be empty, except for BL, which always corrupts r0-r3, ip,
and lr.
The register lists have the same syntax as LDM and STM register lists. If the NZCV flags
are modified you must specify PSR in the corrupted register list.
There are a number of differences between the assembly language accepted by the
inline assemblers and the assembly language accepted by the ARM assembler. For the
inline assemblers:
• You cannot get the address of the current instruction using dot notation (.) or
{PC}.
• The LDR Rn, =expression pseudo-instruction is not supported. Use MOV Rn,
expression instead (this may generate a load from a literal pool).
• The & operator cannot be used to denote hexadecimal constants. Use the 0x prefix
instead. For example:
__asm {AND x, y, 0xF00}
• The notation to specify the actual rotate of an 8-bit constant is not available in
inline assembly language. This means that where an 8-bit shifted constant is used,
the C flag should be regarded as corrupted if the NZCV flags are updated.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 8-7
Mixed Language Programming
8.1.4 Restrictions
• Physical registers, such as r0-r3, ip, lr, and the NZCV flags in the cpsr must be
used with caution. If you use C or C++ expressions, these may be used as
temporary registers and NZCV flags may be corrupted by the compiler when
evaluating the expression.
• LDM and STM instructions only allow physical registers to be specified in the
register list.
• You can change processor modes, alter the APCS registers fp, sl, and sb, or alter
the state of coprocessors, but the compiler is unaware of the change. If you change
processor mode, you must not use C or C++ expressions until you change back to
the original mode.
Similarly, if you change the state of an FP coprocessor by executing FP
instructions, you must not use floating-point expressions until the original state
has been restored.
8.1.5 Usage
• If you are using physical registers, you must ensure that the compiler does not
corrupt them when evaluating expressions. For example:
__asm
{
MOV r0, x
ADD y, r0, x / y // (x / y) overwrites r0
// with the result.
}
Because the compiler uses a function call to evaluate x / y, it:
• corrupts r2, r3, ip, and lr
• updates the NZCV flags in the cpsr
• alters r0 and r1 with the divident and modulo.
8-8 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Mixed Language Programming
The value in r0 is lost. You can work around this by using a C variable instead of
r0:
mov var,x
add y, var, x / y
The compiler can detect the corruption in many cases, for example when it needs
a temporary register and the register is already in use:
__asm
{
MOV ip, #3
ADDS x, x, #0x12345678 // this instruction is expanded
ORR x, x, ip
}
The compiler uses ip as a temporary register when it expands the ADD instruction,
and corrupts the value 3 in ip. An error message is issued.
• Do not use physical registers to address variables, even when it seems obvious
that a specific variable is mapped onto a specific register. If the compiler detects
this it either generates an error message or puts the variable into another register
to avoid conflicts:
int bad_f(int x) // x in r0
{
__asm
{
ADD r0, r0, #1 // wrongly asserts that x is
// still in r0
}
return x; // x in r0
}
This code returns x unaltered. The compiler assumes that x and r0 are two
different variables, despite the fact that x is allocated to r0 on both function entry
and function exit. As the assembly language code does not do anything useful, it
is optimized away. The instruction should be written as:
ADD x, x, #1
• Do not save and restore physical registers that are used by an inline assembler.
The compiler will do this for you. If physical registers other than cpsr and spsr are
read without being written to, an error message is issued. For example:
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 8-9
Mixed Language Programming
int f(int x)
{
__asm
{
STMFD sp!, {r0} // save r0 - illegal: read
// before write
ADD r0, x, 1
EOR x, r0, x
LDMFD sp!, {r0} // restore r0 - not needed.
}
return x;
}
8.1.6 Examples
The following examples demonstrate some of the ways in which you can use inline
assembly language effectively.
Interrupts are enabled or disabled by reading the cpsr flags and updating bit 7. Example
8-2 on page 8-11 shows how this can be done by using small functions that can be
inlined. These functions work only in a privileged mode, because the control bits of the
cpsr and spsr cannot be changed while in User mode.
8-10 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Mixed Language Programming
Example 8-2
int main(void)
{
disable_IRQ();
enable_IRQ();
}
Dot product
Example 8-3 on page 8-12 calculates the dot product of two integer arrays. It
demonstrates how inline assembly language can interwork with C or C++ expressions
and data types that are not directly supported by the inline assembler. The inline
function mlal() is optimized to a single SMLAL instruction. Use the -S -fs compiler
option to view the assembly language code generated by the compiler.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 8-11
Mixed Language Programming
Example 8-3
#include <stdio.h>
{
__int64 sum = 0;
do
sum = mlal(sum, *a++, *b++);
while (--n != 0);
return sum;
}
int a[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int b[10] = { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 };
int main(void)
{
printf("Dotproduct %lld (should be %d)\n", dotprod(a, b, 10), 220);
return 0;
}
8-12 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Mixed Language Programming
Long multiplies
You can use the inline assembler to optimize long multiplies on processors that support
MULL instructions. Example 8-4 shows a simple long multiply routine in C.
Example 8-5 shows how you can use inline assembly language to generate optimal code
for the same routine. You can use the inline assembler to write the high word and the
low word of the long long separately. The compiler optimization routines detect this
case and optimize the code as if the address of res was not taken.
Note
This works only at the highest compiler optimization level (-O2 compiler option).
The inline assembly language code depends on the word ordering of long long types,
because it assumes that the low 32 bits are at offset 0.
Example 8-4
Writing the multiply routine in C:
MOV a3,a1
MOV a1,a2
MOV a2,a3
SMULL ip,a2,a1,a2
MOV a1,ip
MOV pc,lr
Example 8-5
Writing the same routine using inline assembly language:
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 8-13
Mixed Language Programming
MOV a3,a1
SMULL a1,a2,a3,a2
MOV pc,lr
8-14 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Mixed Language Programming
Small structures of less than eight words can be accessed as a whole using LDM/STM
instructions. Individual members of structures can be accessed by a load/store
instruction of the appropriate type. You must know the offset of a member from the start
of the structure in order to access it.
Example 8-6 loads the address of the integer global globvar into r1, loads the value
contained in that address into r0, adds 2 to it, then stores the new value back into
globvar.
Example 8-6
AREA globals,CODE,READONLY
EXPORT asmsubroutine
IMPORT globvar
asmsubroutine
LDR r1, =globvar ; read address of globvar into
; r1 from literal pool
LDR r0, [r1]
ADD r0, r0, #2
STR r0, [r1]
MOV pc, lr
END
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 8-15
Mixed Language Programming
To include standard system C header files, such as stdio.h, you need do nothing
special. The standard C header files already contain the appropriate extern "C"
directives. For example:
// C++ code
#include <stdio.h>
int main()
{
//...
return 0;
}
The C++ standard specifies that the functionality of the C header files is available
through C++ specific header files. These files are installed in c:\arm250\include,
together with the standard C header files, and may be referenced in the usual way. For
example:
// C++ code
#include <cstdio>
int main()
{
// ...
return 0;
}
Note
Both the C and C++ standard header files are available as precompiled headers in the
compilers in-memory file system. Refer to Chapter 2 The ARM Compilers in the ARM
Software Development Toolkit Reference Guide for more information.
8-16 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Mixed Language Programming
To include your own C header files, you must wrap the #include directive in an
extern "C" statement. You can do this in two ways:
• When the file is #included. This is shown in Example 8-7.
• By adding the extern "C" statement to the header file. This is shown in Example
8-8.
Example 8-7
// C++ code
extern "C"{
#include "my-header1.h"
#include "my-header2.h"
}
int main()
{
// ...
return 0;
}
Example 8-8
/* C header file */
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 8-17
Mixed Language Programming
You can mix calls between C and C++ and assembly language routines provided you
follow the appropriate procedure call standard. For more information on the APCS and
TPCS, see Using the Procedure Call Standards on page 6-1.
Note
The information in this section is implementation dependent and may change in future
toolkit releases.
The following general rules apply to calling between C, C++, and assembly language.
You should not rely on the following C++ implementation details. These
implementation details are subject to change in future releases of ARM C++:
• the way names are mangled
• the way the implicit this parameter is passed
• the way virtual functions are called
• the representation of references
• the layout of C++ class types that have base classes or virtual member functions
• the passing of class objects that are not plain old data (POD) structures.
The following rules apply to calling C++ functions from C and assembly language:
8-18 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Mixed Language Programming
• Member functions (both static and non-static) always have mangled names. You
can determine the mangled symbol by using decaof -sm on the object file that
defines the function. Refer to Chapter 8 Toolkit Utilities in the ARM Software
Development Toolkit Reference Guide for information on decaof.
• C++ inline functions cannot be called from C unless you ensure that the C++
compiler generates an out-of-line copy of the function. For example, taking the
address of the function results in an out-of-line copy.
ARM C++ uses the same calling conventions as ARM C with the following exceptions:
• When an object of type struct or class is passed to a function and the type has
an explicit copy constructor, the object is passed by reference and the called
function makes a copy.
• Non-static member functions are called with the implicit this parameter as the
first argument, or as the second argument if the called function returns a non
int-like struct.
ARM C++ uses the same data types as ARM C with the following exceptions and
additions:
• C++ objects of type struct or class have the same layout as would be expected
from the ARM C compiler if they have no base classes or virtual functions. If such
a struct has neither a user-defined copy assignment operator, or a user-defined
destructor, it is a plain old data (POD) structure.
• Pointers to data members and pointers to member functions occupy four bytes.
They have the same null pointer representation as normal pointers.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 8-19
Mixed Language Programming
ARM C++ mangles external names of functions and static data members in a manner
similar to that described in section 7.2c of Ellis, M.A. and Stroustrup, B., The Annotated
C++ Reference Manual (1990). The linker, decaof, and decaxf unmangle symbols.
C names must be declared as extern "C" in C++ programs. This is done already for
the ARM ANSI C headers. Refer to Using C header files from C++ on page 8-16 for
more information.
8.4.3 Examples
Example 8-9 shows a C program that uses a call to an assembly language subroutine to
copy one string over the top of another string.
#include <stdio.h>
extern void strcopy(char *d, char *s);
int main()
{ char *srcstr = "First string - source ";
char *dststr = "Second string - destination ";
printf("Before copying:\n");
printf(" %s\n %s\n",srcstr,dststr);
strcopy(dststr,srcstr);
printf("After copying:\n");
printf(" %s\n %s\n",srcstr,dststr);
return (0);
}
The ARM assembly language module that implements the string copy subroutine:
8-20 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Mixed Language Programming
1. Type armasm scopy.s at the command line to build the assembly language
source.
4. Type armsd strtest to load the files into the command-line debugger, and type
go at the debugger command line to execute the example.
In assembly language:
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 8-21
Mixed Language Programming
EXPORT f
AREA f, CODE, READONLY
IMPORT g
STR lr, [sp, #-4]! ; preserve lr
ADD r1, r0, r0 ; compute 2*i (2nd param)
ADD r2, r1, r0 ; compute 3*i (3rd param)
ADD r3, r1, r2 ; compute 5*i
STR r3, [sp, #-4]! ; 5th param on stack
ADD r3, r1, r1 ; compute 4*i (4th param)
BL g ; branch to C function
ADD sp, sp, #4 ; remove 5th param
RSB r0, r0, #0 ; negate result
LDR pc, [sp], #4 ; return
END
8-22 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Mixed Language Programming
struct S {
int i;
};
void cfunc(struct S *p) { /* the definition of the C */
/* function to be called from C++ */
p->i += 5;
}
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 8-23
Mixed Language Programming
struct S {
int i;
};
int f(void) {
struct S s;
s.i = 2; /* initialize ’s’ */
cppfunc(&s); /* call ’cppfunc’ so it */
/* can change ’s’ */
return s.i * 3;
}
8-24 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Mixed Language Programming
In ARM assembly language, import the name of the C++ function and use a Branch
with link instruction to call it:
EXPORT f
f
STMDB sp!,{lr}
MOV r0,#2
STR r0,[sp,#-4]! ; initialize struct
MOV r0,sp ; argument is pointer to struct
BL cppfunc ; call ’cppfunc’ so it can change
; the struct
LDR r0, [sp], #4
ADD r0, r0, r0,LSL #1
LDMIA sp!,{pc}
END
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 8-25
Mixed Language Programming
In C++:
struct T {
T(int i) : t(i) { }
int t;
int f(int i);
};
int f() {
T t(5); // create an object of type T
return cfunc(&t);
}
In C:
struct T;
extern int f__1TFi(struct T*, int);
/* the mangled name of the C++ */
/* function to be called */
8-26 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Mixed Language Programming
EXPORT cfunc
AREA cfunc, CODE
IMPORT f__1TFi
int f() {
int i = 3;
return cfunc(i); // passes a pointer to ’i’
}
In C:
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 8-27
Mixed Language Programming
8-28 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Chapter 9
Handling Processor Exceptions
This chapter describes how to handle the various types of exception supported by ARM
processors. It contains the following sections:
• Overview on page 9-2
• Entering and leaving an exception on page 9-5
• Installing an exception handler on page 9-9
• SWI handlers on page 9-14
• Interrupt handlers on page 9-23
• Reset handlers on page 9-34
• Undefined instruction handlers on page 9-35
• Prefetch abort handler on page 9-36
• Data abort handler on page 9-37
• Chaining exception handlers on page 9-39
• Handling exceptions on Thumb-capable processors on page 9-41
• System mode on page 9-46.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 9-1
Handling Processor Exceptions
9.1 Overview
During the normal flow of execution through a program, the program counter increases
sequentially through the address space, with branches to nearby labels or branch and
links to subroutines.
Processor exceptions occur when this normal flow of execution is diverted, to allow the
processor to handle events generated by internal or external sources. Examples of such
events are:
• externally generated interrupts
• an attempt by the processor to execute an undefined instruction
• accessing privileged operating system functions.
It is necessary to preserve the previous processor status when handling such exceptions,
so that execution of the program that was running when the exception occurred can
resume when the appropriate exception routine has completed.
Table 9-1 shows the seven different types of exception recognized by ARM processors.
Exception Description
Reset Occurs when the processor reset pin is asserted. This exception is only
expected to occur for signalling power-up, or for resetting as if the
processor has just powered up. A soft reset can be done by branching
to the reset vector (0x0000).
Prefetch Abort Occurs when the processor attempts to execute an instruction that has
prefetched from an illegal address, that is, an address that the memory
management subsystem has determined is inaccessible to the processor
in its current mode.
Data Abort Occurs when a data transfer instruction attempts to load or store data at
an illegal address.
IRQ Occurs when the processor external interrupt request pin is asserted
(LOW) and the I bit in the CPSR is clear.
FIQ Occurs when the processor external fast interrupt request pin is
asserted (LOW) and the F bit in the CPSR is clear.
9-2 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Handling Processor Exceptions
This is not enough space to contain the full code for a handler, so the vector entry for
each exception type typically contains a branch instruction or load pc instruction to
continue execution with the appropriate handler.
Typically, an application runs in user mode, but servicing exceptions requires privileged
(that is, non-user mode) operation. An exception changes the processor mode, and this
in turn means that each exception handler has access to a certain subset of the banked
registers:
• its own r13 or Stack Pointer (sp_mode)
• its own r14 or Link Register (lr_mode)
• its own Saved Program Status Register (spsr_mode)
and, in the case of a FIQ, five more general purpose registers (r8_FIQ to r12_FIQ).
Each exception handler must ensure that other registers are restored to their original
contents upon exit. You can do this by saving the contents of any registers the handler
needs to use onto its stack and restoring them before returning. If you are using Angel
or ARMulator, the required stacks are set up for you. Otherwise, you must set them up
yourself. Refer to Chapter 10 Writing Code for ROM for more information.
Note
As supplied, the assembler does not predeclare symbolic register names of the form
register_mode. To use this form, you must declare the appropriate symbolic names
with the RN assembler directive. For example, lr_FIQ RN r14 declares the symbolic
register name lr_FIQ for r14. Refer to the ARM Software Development Toolkit
Reference Guide for more information on the RN directive.
When several exceptions occur simultaneously, they are serviced in a fixed order of
priority. Each exception is handled in turn before execution of the user program
continues. It is not possible for all exceptions to occur concurrently. For example, the
undefined instruction and SWI exceptions are mutually exclusive because they are both
triggered by executing an instruction.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 9-3
Handling Processor Exceptions
Table 9-2 shows the exceptions, their corresponding processor modes and their
handling priorities.
Because the Data Abort exception has a higher priority that the FIQ exception, the Data
Abort is actually registered before the FIQ is handled. The Data Abort handler is
entered, but control is then passed immediately to the FIQ handler. When the FIQ has
been handled, control returns to the Data Abort Handler. This means that the data
transfer error does not escape detection as it would if the FIQ were handled first.
Table 9-2
9-4 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Handling Processor Exceptions
1. Copies the Current Program Status Register (CPSR) into the Saved Program
Status Register (SPSR) for the mode in which the exception is to be handled.
This saves the current mode, interrupt mask, and condition flags.
3. Sets lr_mode to the return address, as defined in The return address and return
instruction on page 9-6.
4. Sets the program counter to the vector address for the exception. This forces a
branch to the appropriate exception handler.
Note
If the application is running on a Thumb-capable processor, the processor response is
slightly different. See Handling exceptions on Thumb-capable processors on page 9-41
for more details.
The method used to return from an exception depends on whether the exception handler
uses stack operations or not.
In both cases, to return execution to the place where the exception occurred an exception
handler must:
• restore the CPSR from spsr_mode
• restore the program counter using the return address stored in lr_mode.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 9-5
Handling Processor Exceptions
For a simple return that does not require the destination mode registers to be restored
from the stack, the exception handler carries out these two operations by performing a
data processing instruction with:
• the S flag set
• the program counter as the destination register.
The return instruction required depends on the type of exception. Refer to the following
section for instructions on how to return from each exception type.
Note
You do not need to return from the reset handler because the reset handler should
execute your main code directly.
If the exception handler entry code uses the stack to store registers that must be
preserved while it handles the exception, it must return using a load multiple instruction
with the ^ qualifier. For example, if an exception handler stores:
• the link register, modified to produce the same effect as the data processing
instructions described below.
The ^ qualifier specifies that the CPSR is restored from the SPSR. It must be used only
from a privileged mode. Refer to Implementing stacks with LDM and STM on page 5-36
for more general information on stack operations.
The actual location pointed to by the program counter when an exception is taken
depends on the exception type. Because of the way in which the ARM processor fetches
instructions, when an exception is taken the program counter may or may not be
updated to the next instruction to be fetched. This means that the return address may not
necessarily be the next instruction pointed to by the program counter.
ARM processors use a pipeline with at least a fetch, a decode, and an execute stage.
There is one instruction in each stage of the pipeline at any time. The program counter
points to the instruction currently being fetched. Because each instruction is one word
long, the instruction being decoded is at address (pc – 4) and the instruction being
executed is at (pc – 8).
9-6 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Handling Processor Exceptions
Note
See The return address on page 9-43 for details of the return address on Thumb-capable
processors when an exception occurs in Thumb state.
The SWI and Undefined instruction exceptions are generated by the instruction itself,
so the program counter is not updated when the exception is taken. Therefore, storing
(pc – 4) in lr_mode makes lr_mode point to the next instruction to be executed.
Restoring the program counter from the lr with:
MOVS pc, lr
The handler entry and exit code to stack the return address and pop it on return is:
STMFD sp!,{reglist,lr}
;...
LDMFD sp!,{reglist,pc}^
After executing each instruction, the processor checks to see whether the interrupt pins
are LOW and whether the interrupt disable bits in the CPSR are clear. As a result, IRQ
or FIQ exceptions are generated only after the program counter has been updated.
Storing (pc – 4) in lr_mode causes lr_mode to point two instructions beyond where the
exception occurred. When the handler has finished, execution must continue from the
instruction prior to the one pointed to by lr_mode. The address to continue from is one
word (four bytes) less than that in lr_mode, so the return instruction is:
SUBS pc, lr, #4
The handler entry and exit code to stack the return address and pop it on return is:
SUB lr,lr,#4
STMFD sp!,{reglist,lr}
;...
LDMFD sp!,{reglist,pc}^
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 9-7
Handling Processor Exceptions
If the processor attempts to fetch an instruction from an illegal address, the instruction
is flagged as invalid. Instructions already in the pipeline continue to execute until the
invalid instruction is reached, at which point a prefetch abort is generated.
The exception handler invokes the MMU to load the appropriate virtual memory
locations into physical memory. It must then return to the address that caused the
exception and reload the instruction. The instruction should now load and execute
correctly.
Because the program counter is not updated at the time the prefetch abort is issued,
lr_ABT points to the instruction following the one that caused the exception. The
handler must return to lr_ABT – 4 with:
SUBS pc,lr, #4
The handler entry and exit code to stack the return address and pop it on return is:
SUB lr,lr,#4
STMFD sp!,{reglist,lr}
;...
LDMFD sp!,{reglist,pc}^
When a load or store instruction tries to access memory, the program counter has been
updated. A stored value of (pc – 4) in lr_ABT points to the second instruction beyond
the address where the exception was generated. When the MMU has loaded the
appropriate address into physical memory, the handler should return to the original,
aborted instruction so that a second attempt can be made to execute it. The return
address is therefore two words (eight bytes) less than that in lr_ABT, making the return
instruction:
SUBS pc, lr, #8
The handler entry and exit code to stack the return address and pop it on return is:
SUB lr,lr,#8
STMFD sp!,{reglist,lr}
;...
LDMFD sp!,{reglist,pc}^
9-8 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Handling Processor Exceptions
Branch instruction
This is the simplest method of reaching the exception handler. Each entry
in the vector table contains a branch to the required handler routine.
However, this method does have a limitation. Because the branch
instruction only has a range of 32MB relative to the pc, with some
memory organizations the branch may be unable to reach the handler.
Load pc instruction
With this method, the program counter is forced directly to the handler
address by:
If your application does not rely on the debugger or debug monitor to start program
execution, you can load the vector table directly from your assembly language reset (or
startup) code.
If your ROM is at location 0x0 in memory, you can simply have a branch statement for
each vector at the start of your code. This could also include the FIQ handler if it is
running directly from 0x1c. See Interrupt handlers on page 9-23.
Example 9-1 on page 9-10 shows code that sets up the vectors if they are located in
ROM at address zero. Note that you can substitute branch statements for the loads.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 9-9
Handling Processor Exceptions
Example 9-1
Vector_Init_Block
LDR PC, Reset_Addr
LDR PC, Undefined_Addr
LDR PC, SWI_Addr
LDR PC, Prefetch_Addr
LDR PC, Abort_Addr
NOP ;Reserved vector
LDR PC, IRQ_Addr
LDR PC, FIQ_Addr
If there is RAM at location zero, the vectors (plus the FIQ handler if required) must be
copied down from an area in ROM into the RAM. In this case, you must use load pc
instructions, and copy the storage locations, to make the code relocatable.
Example 9-2 copies down the vectors given in Example 9-1 to the vector table in RAM.
Example 9-2
MOV r8, #0
ADR r9, Vector_Init_Block
LDMIA r9!,{r0-r7} ;Copy the vectors (8 words)
STMIA r8!,{r0-r7}
LDMIA r9!,{r0-r7} ;Copy the DCD’ed addresses
STMIA r8!,{r0-r7} ;(8 words again)
Alternatively, you can use the scatter loading mechanism to install the vector table.
Refer to Chapter 10 Writing Code for ROM for more information.
9-10 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Handling Processor Exceptions
Branch method
4. Shift the result to the right by two to give a word offset, rather than a byte offset.
5. Test that the top eight bits of this are clear, to ensure that the result is only 24 bits
long (because the offset for the branch is limited to this).
6. Logically OR this with 0xea000000 (the opcode for the Branch instruction) to
produce the value to be placed in the vector.
Example 9-3 on page 9-12 shows a C function that implements this algorithm. It takes
the following arguments:
• the address of the handler
• the address of the vector in which the handler is to be to installed.
The function can install the handler and return the original contents of the vector. This
result can be used to create a chain of handlers for a particular exception. Refer to
Chaining exception handlers on page 9-39 for further details.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 9-11
Handling Processor Exceptions
Example 9-3
In this case, the returned, original contents of the IRQ vector are discarded.
Load pc method
4. Logically OR this with 0xe59ff000 (the opcode for LDR pc, [pc,#offset])
to produce the value to be placed in the vector.
Example 9-4 on page 9-13 shows a C routine that implements this method.
9-12 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Handling Processor Exceptions
Example 9-4
Again in this example the returned, original contents of the IRQ vector are discarded,
but they could be used to create a chain of handlers. Refer to Chaining exception
handlers on page 9-39 for more information.
Note
If you are operating on a processor with separate instruction and data caches, such as
StrongARM, or ARM940T, you must ensure that cache coherence problems do not
prevent the new contents of the vectors from being used.
The data cache (or at least the entries containing the modified vectors) must be cleaned
to ensure the new vector contents is written to main memory. You must then flush the
instruction cache to ensure that the new vector contents is read from main memory.
For details of cache clean and flush operations, see the datasheet for your target
processor.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 9-13
Handling Processor Exceptions
31 28 27 26 25 24 23 0
cond 1 1 1 1 24_bit_immediate
comment field
The top-level SWI handler typically accesses the link register and loads the SWI
instruction from memory, and therefore has to be written in assembly language. The
individual routines that implement each SWI handler can be written in C if required.
The handler must first load the SWI instruction that caused the exception into a register.
At this point, lr_SVC holds the address of the instruction that follows the SWI
instruction, so the SWI is loaded into the register (in this case r0) using:
LDR r0, [lr,#-4]
The handler can then examine the comment field bits, to determine the required
operation. The SWI number is extracted by clearing the top eight bits of the opcode:
BIC r0, r0, #0xff000000
Example 9-5 on page 9-15 shows how these instructions can be put together to form a
top-level SWI handler.
See Determining the processor state on page 9-44 for an example of a handler that deals
with both ARM-state and Thumb-state SWI instructions.
9-14 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Handling Processor Exceptions
Example 9-5
The easiest way to call the handler for the requested SWI number is to use a jump table.
If r0 contains the SWI number, the code in Example 9-6 can be inserted into the
top-level handler given in Example 9-5, following on from the BIC instruction.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 9-15
Handling Processor Exceptions
Although the top-level header must always be written in ARM assembly language, the
routines that handle each SWI can be written in either assembly language or in C. Refer
to Using SWIs in supervisor mode on page 9-17 for a description of restrictions.
The top-level header uses a BL (Branch with Link) instruction to jump to the appropriate
C function. Because the SWI number is loaded into r0 by the assembly routine, this is
passed to the C function as the first parameter (in accordance with the ARM Procedure
Call Standard). The function can use this value in, for example, a switch() statement.
The following line can be added to the SWI_Handler routine in Example 9-5:
BL C_SWI_Handler ; Call C routine to handle the SWI
Example 9-7
The supervisor stack space may be limited, so avoid using functions that require a large
amount of stack space.
You can pass values in and out of such a handler written in C, provided that the top-level
handler passes the stack pointer value into the C function as the second parameter (in
r1):
MOV r1, sp ; Second parameter to C routine...
; ...is pointer to register values.
BL C_SWI_Handler ; Call C routine to handle the SWI
9-16 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Handling Processor Exceptions
The C function can now access the values contained in the registers at the time the SWI
instruction was encountered in the main application code (see Figure 9-2). It can read
from them:
value_in_reg_0 = reg [0];
value_in_reg_1 = reg [1];
value_in_reg_2 = reg [2];
value_in_reg_3 = reg [3];
causing the updated value to be written into the appropriate stack position, and then
restored into the register by the top-level handler.
Previous sp_SVC
lr_SVC
r3 reg[3]
r2
r1
r0 reg[0]
sp_SVC
When a SWI instruction is executed, the processor enters supervisor mode, the CPSR is
stored into spsr_SVC, and the return address is stored in lr_SVC (see The processor
response to an exception on page 9-5). If the processor is already in supervisor mode,
lr_SVC and spsr_SVC are corrupted.
If you call a SWI while in supervisor mode you must store lr_SVC and spsr_SVC to
ensure that the original values of the link register and the SPSR are not lost. For
example, if the handler routine for a particular SWI number calls another SWI, you
must ensure that the handler routine stores both lr_SVC and spsr_SVC on the stack.
This ensures that each invocation of the handler saves the information needed to return
to the instruction following the SWI that invoked it. Example 9-8 on page 9-18 shows
how to do this.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 9-17
Handling Processor Exceptions
Nested SWIs in C
By default, the ARM compilers do not take into account the fact that an inline SWI will
overwrite the contents of the link register if it is called from Supervisor mode. If the
nested SWI handlers are written in C or C++, you must use the -fz compiler option to
instruct the compiler to generate code that stores lr_SVC. For example, if the C function
is in module c_swi_handle.c, the following command produces the object code file:
9-18 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Handling Processor Exceptions
The easiest way to call SWIs from your application code is to set up any required
register values and call the relevant SWI in assembly language. For example:
MOV r0, #65 ; load r0 with the value 65
SWI 0x0 ; Call SWI 0x0 with parameter
; value in r0
The SWI instruction can be conditionally executed, as can all ARM instructions.
Calling a SWI from C is more complicated because it is necessary to map a function call
onto each SWI with the __swi compiler directive. This allows a SWI to be compiled
inline, without additional calling overhead, provided that:
• any arguments are passed in r0-r3 only
• any results are returned in r0-r3 only.
Note
You must use the -fz compiler option when compiling code that contains inline SWIs.
The parameters are passed to the SWI as if the SWI were a real function call. However,
if there are between two and four return values, you must tell the compiler that the return
values are being returned in a structure, and use the __value_in_regs directive. This
is because a struct-valued function is usually treated as if it were a void function whose
first argument is the address where the result structure should be placed.
Example 9-9 on page 9-20 shows a SWI handler that provides SWI numbers 0x0 and
0x1. SWI 0x0 takes four integer parameters and returns a single result. SWI 0x1 takes
a single parameter and returns four results.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 9-19
Handling Processor Exceptions
Example 9-9
struct four
{ int a, b, c, d;
};
In some circumstances it may be necessary to call a SWI whose number is not known
until runtime. This situation can occur, for example, when there are a number of related
operations that can be performed on an object, and each operation has its own SWI. In
such a case, the methods described above are not appropriate.
• Construct the SWI instruction from the SWI number, store it somewhere, then
execute it.
• Use a generic SWI that takes, as an extra argument, a code for the actual operation
to be performed on its arguments. The generic SWI decodes the operation and
performs it.
9-20 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Handling Processor Exceptions
For example, an operating system might make use of only a single SWI instruction and
employ a register to pass the number of the required operation. This leaves the rest of
the SWI space available for application-specific SWIs. This method can also be used if
the overhead of extracting the SWI number from the instruction is too great in a
particular application.
A mechanism is included in the compiler to support the use of r12 to pass the value of
the required operation. Under the ARM Procedure Call Standard, r12 is the ip register
and has a dedicated role only during function call. At other times it may be used as a
scratch register. The arguments to the generic SWI are passed in registers r0-r3 and
values are optionally returned in r0-r3 as described earlier. The operation number
passed in r12 could be, but need not be, the number of the SWI to be called by the
generic SWI.
Example 9-10
__swi_indirect(0x80)
unsigned SWI_ManipulateObject(unsigned operationNumber,
unsigned object,unsigned parameter);
It is also possible to pass the SWI number in r0 from C using the __swi mechanism.
For example, if SWI 0x0 is used as the generic SWI and operation 0 is a character read
and operation 1 a character write, the following can be set up:
__swi (0) char __ReadCharacter (unsigned op);
__swi (0) void __WriteCharacter (unsigned op, char c);
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 9-21
Handling Processor Exceptions
However, using r0 in this way means that only three registers are available for passing
parameters to the SWI. Usually, if more parameters need to be passed to a subroutine in
addition to r0-r3, this can be done using the stack. However, stacked parameters are not
easily accessible to a SWI handler, because they typically exist on the user mode stack
rather than the supervisor stack employed by the SWI handler.
Alternatively, one of the registers (typically r1) can be used to point to a block of
memory storing the other parameters.
9-22 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Handling Processor Exceptions
• Servicing a FIQ causes IRQs to be disabled, preventing them from being serviced
until after the FIQ handler has re-enabled them. This is usually done by restoring
the CPSR from the SPSR at the end of the handler.
The FIQ vector is the last entry in the vector table (at address 0x1c) so that the FIQ
handler can be placed directly at the vector location and run sequentially from that
address. This removes the need for a branch and its associated delays, and also means
that if the system has a cache, the vector table and FIQ handler may all be locked down
in one block within it. This is important because FIQs are designed to service interrupts
as quickly as possible. The five extra FIQ mode banked registers enable status to be held
between calls to the handler, again increasing execution speed.
Note
An interrupt handler should contain code to clear the source of the interrupt.
You can write simple C interrupt handlers by using the __irq function declaration
keyword. You can use the __irq keyword both for simple one-level interrupt handlers,
and interrupt handlers that call subroutines. However, you cannot use the __irq
keyword for reentrant interrupt handlers, because it does not store all the required state.
In this context, reentrant means that the handler re-enables interrupts, and may itself be
interrupted. Refer to Reentrant interrupt handlers on page 9-26 for more information.
If the function calls a subroutine, __irq preserves the link register for the interrupt
mode in addition to preserving the other corruptible registers. See Calling subroutines
from interrupt handlers on page 9-24 for more information.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 9-23
Handling Processor Exceptions
Note
C interrupt handlers cannot be produced in this way using tcc. The __irq keyword is
faulted by tcc because tcc can only produce Thumb code, and the processor is always
switched to ARM state when an interrupt, or any other exception, occurs.
However, the subroutine called by an __irq function can be compiled for Thumb, with
interworking enabled. Refer to Chapter 7 Interworking ARM and Thumb for more
information on interworking.
Example 9-11 shows a simple handler that does not call any subroutines. The handler
reads a byte from location 0x80000000 and clears the interrupt by writing it to location
0x80000004.
The __irq keyword ensures that r0-r3 and r12 are preserved, and that the function exits
with SUBS pc,lr,#4.
Example 9-11
If you call subroutines from your top level interrupt handler, the __irq keyword also
restores the value of lr_IRQ from the stack so that it can be used by a SUBS instruction
to return to the correct address after the interrupt has been handled.
9-24 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Handling Processor Exceptions
Example 9-12 shows how this works. The top level interrupt handler reads the value of
a memory mapped interrupt controller base address at 0x80000000. If the value of the
address is 1, the top level handler branches to a handler written in C.
Example 9-12
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 9-25
Handling Processor Exceptions
Note
The following method works for both IRQ and FIQ interrupts. However, because FIQ
interrupts are meant to be serviced as quickly as possible there will normally be only
one interrupt source, so it may not be necessary to allow for reentrancy.
A reentrant interrupt handler must save the necessary IRQ state, switch processor
modes, and save the state for the new processor mode before branching to a nested
subroutine or C function.
In ARM architecture 4 or later you can switch to System mode. System mode uses the
User mode registers, and allows privileged access that may be required by your
exception handler. Refer to System mode on page 9-46 for more information. In ARM
architectures prior to architecture 4 you must switch to Supervisor mode instead.
9-26 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Handling Processor Exceptions
Example 9-13 shows how this works for System mode. Registers r12 and r14 are used
as temporary work registers after lr_IRQ is pushed on the stack.
Example 9-13
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 9-27
Handling Processor Exceptions
Interrupt handlers are often written in assembly language to ensure that they execute
quickly. The following sections give some examples.
Example 9-14 shows an interrupt handler that performs interrupt driven I/O to memory
transfers (soft DMA). The code is an FIQ handler. It uses the banked FIQ registers to
maintain state between interrupts. This code is best situated at location 0x1c.
r8 Points to the base address of the I/O device that data is read from.
IOData Is the offset from the base address to the 32-bit data register that is read.
Reading this register clears the interrupt.
The entire sequence for handling a normal transfer is four instructions. Code situated
after the conditional return is used to signal that the transfer is complete.
Example 9-14
LDR r11, [r8, #IOData] ; Load port data from the IO device.
STR r11, [r9], #4 ; Store it to memory: update the pointer.
CMP r9, r10 ; Reached the end ?
SUBLES pc, lr, #4 ; No, so return.
; Insert transfer complete code here.
Byte transfers can be made by replacing the load instructions with load byte
instructions. Transfers from memory to an I/O device are made by swapping the
addressing modes between the load instruction and the store instruction.
Example 9-15 on page 9-29 is similar to Example 9-14, except that there are two
channels being handled (which may be the input and output side of the same channel).
The code is an FIQ handler. It uses the banked FIQ registers to maintain state between
interrupts. It is best situated at location 0x1c.
9-28 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Handling Processor Exceptions
r8 Points to the base address of the I/O device from which data is read.
IOStat Is the offset from the base address to a register indicating which of two
ports caused the interrupt.
IOPort1Active
Is a bit mask indicating if the first port caused the interrupt (otherwise it
is assumed that the second port caused the interrupt).
IOPort1, IOPort2
Are offsets to the two data registers to be read. Reading a data register
clears the interrupt for the corresponding port.
r9 Points to the memory location to which data from the first port is being
transferred.
r10 Points to the memory location to which data from the second port is being
transferred.
r11 and r12 Point to the last address to transfer to (r11 for the first port, r12 for the
second).
The entire sequence to handle a normal transfer takes nine instructions. Code situated
after the conditional return is used to signal that the transfer is complete.
Example 9-15
Byte transfers can be made by replacing the load instructions with load byte
instructions. Transfers from memory to an I/O device are made by swapping the
addressing modes between the conditional load instructions and the conditional store
instructions.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 9-29
Handling Processor Exceptions
Interrupt prioritization
External hardware is used to prioritize the interrupt and present the high-priority active
interrupt in an I/O register.
IntLevel Holds the offset of the register containing the highest-priority active
interrupt.
Interrupts are enabled after ten instructions, including the branch to this code.
The specific handler for each interrupt is entered after a further two instructions (with
all registers preserved on the stack).
In addition, the last three instructions of each handler are executed with interrupts
turned off again, so that the SPSR can be safely recovered from the stack.
Note
Application Note 30: Software Prioritization of Interrupts (ARM DAI 0030) describes
multiple source prioritization of interrupts using software, as opposed to using hardware
as described here.
Example 9-16
9-30 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Handling Processor Exceptions
; Now that interrupt disabled, can safely restore SPSR then return.
LDMFD sp!, {r12, r14} ; Restore r12 and get SPSR.
MSR SPSR_csxf, r14 ; Restore status register from r14.
LDMFD sp!, {pc}^ ; Return from handler.
Priority1Handler
; ...
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 9-31
Handling Processor Exceptions
Context switch
Example 9-17 on page 9-33 performs a context switch on the user mode process. The
code is based around a list of pointers to Process Control Blocks (PCBs) of processes
that are ready to run.
Figure 9-3 shows the layout of the PCBs that the example expects.
r14
r13
r12
r11
r10
r9
r8
r7 User mode registers
r6
r5
r4
r3
r2
r1
PCB pointer r0
lr
spsr
The pointer to the PCB of the next process to run is pointed to by r12, and the end of the
list has a zero pointer. Register r13 is a pointer to the PCB, and is preserved between
time slices, so that on entry it points to the PCB of the currently running process.
9-32 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Handling Processor Exceptions
Example 9-17
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 9-33
Handling Processor Exceptions
9-34 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Handling Processor Exceptions
1. Attach itself to the undefined instruction vector and store the old contents.
3. Otherwise the emulator should pass the exception onto the original handler (or the
next emulator in the chain) using the vector stored when the emulator was
installed.
Note
The Thumb instruction set does not have coprocessor instructions, so there should be
no need for the undefined instruction handler to emulate such instructions.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 9-35
Handling Processor Exceptions
9-36 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Handling Processor Exceptions
The instruction that caused the abort is at lr_ABT – 8 because lr_ABT points two
instructions beyond the instruction that caused the abort.
Load/Store Multiple
The response depends on the processor type:
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 9-37
Handling Processor Exceptions
In each of the three cases the MMU can load the required virtual memory into physical
memory. The MMU Fault Address Register (FAR) contains the address that caused the
abort. When this is done, the handler can return and try to execute the instruction again.
9-38 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Handling Processor Exceptions
• Angel uses a SWI for various purposes, including getting into supervisor mode
from user mode and supporting semihosting requests. However, an RTOS or an
application may also wish to implement some SWIs.
In such situations there are two approaches that can be taken to extend the exception
handling code. These are described below.
In some circumstances it is possible to extend the code in the exception handler to work
out what the source of the exception was, and then directly call the appropriate code. In
this case, you are modifying the source code for the exception handler.
Angel has been written to make this approach simple. Angel decodes SWIs and
undefined instructions, and the Angel exception handlers can be extended to deal with
non-Angel SWIs and undefined instructions.
However, this approach is only useful if all the sources of an exception are known when
the single exception handler is written.
Some circumstances require more than a single handler. Consider the situation in which
a standard Angel debugger is executing, and a standalone user application (or RTOS)
which wants to support some additional SWIs is then downloaded. The newly loaded
application may well have its own entirely independent exception handler that it wants
to install, but which cannot simply replace the Angel handler.
In this case the address of the old handler must be noted so that the new handler is able
to call the old handler if it discovers that the source of the exception is not a source it
can deal with. For example, an RTOS SWI handler would call the Angel SWI handler
on discovering that the SWI was not an RTOS SWI, so that the Angel SWI handler gets
a chance to process it.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 9-39
Handling Processor Exceptions
This approach can be extended to any number of levels to build a chain of handlers. Note
that, although code that takes this approach allows each handler to be entirely
independent, it is less efficient than code that uses a single handler, or at least it becomes
less efficient the further down the chain of handlers it has to go.
Both routines given in Installing the handlers from C on page 9-11 return the old
contents of the vector. This value can be decoded to give:
In most cases, such calculations may not be necessary because information on the debug
monitor or RTOS handlers should be available to you. If so, the instructions required to
chain in the next handler can be hard coded into the application. The last section of the
handler must check that the cause of the exception has been handled. If it has, the
handler can return to the application. If not, it must call the next handler in the chain.
Note
When chaining in a handler before a debug monitor handler, you must remove the chain
when the monitor is removed from the system, then directly install the application
handler.
9-40 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Handling Processor Exceptions
This section describes the additional considerations you must take into account when
writing exception handlers suitable for use on Thumb-capable processors.
The same vector table is used for both Thumb-state and ARM-state exceptions. An
initial step that switches to ARM state is added to the exception handling procedure
described in The processor response to an exception on page 9-5.
3. Stores the return address in lr_mode. See The return address on page 9-43 for
further details.
4. Sets the program counter to the vector address for the exception. The switch from
Thumb state to ARM state in step 1 ensures that the ARM instruction installed at
this vector address (either a branch or a pc-relative load) is correctly fetched,
decoded, and executed. This forces a branch to a top level veneer that you must
write in ARM code.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 9-41
Handling Processor Exceptions
Your top-level veneer routine should save the processor status and any required registers
on the stack. You then have two options for writing the exception handler:
• Perform a BX (branch and exchange) to a Thumb code routine that handles the
exception. The routine must return to an ARM code veneer in order to return from
the exception, because the Thumb instruction set does not have the instructions
required to restore cpsr from spsr.
This second strategy is shown in Figure 9-4. See Chapter 7 Interworking ARM and
Thumb for details of how to combine ARM and Thumb code in this way.
Exit veneer
9-42 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Handling Processor Exceptions
If an exception occurs in ARM state, the value stored in lr_mode is (pc – 4) as described
in The return address and return instruction on page 9-6. However, if the exception
occurs in Thumb state, the processor automatically stores a different value for each of
the exception types. This adjustment is required because Thumb instructions take up
only a halfword, rather than the full word that ARM instructions occupy.
If this correction were not made by the processor, the handler would have to determine
the original state of the processor, and use a different instruction to return to Thumb
code rather than ARM code. By making this adjustment, however, the processor allows
the handler to have a single return instruction that will return correctly, regardless of the
processor state (ARM or Thumb) at the time the exception occurred.
The following sections give a summary of the values to which the processor sets
lr_mode if an exception occurs when the processor is in Thumb state.
The handler's return instruction (MOVS pc,lr) changes the program counter to the
address of the next instruction to execute. This is at (pc – 2), so the value stored by the
processor in lr_mode is (pc – 2).
The handler's return instruction (SUBS pc,lr,#4) changes the program counter to the
address of the next instruction to execute. Because the program counter is updated
before the exception is taken, the next instruction is at (pc – 4). The value stored by the
processor in lr_mode is therefore pc.
The handler's return instruction (SUBS pc,lr,#4) changes the program counter to the
address of the aborted instruction. Because the program counter is not updated before
the exception is taken, the aborted instruction is at (pc – 4). The value stored by the
processor in lr_mode is therefore pc.
The handler's return instruction (SUBS pc,lr,#8) changes the program counter to the
address of the aborted instruction. Because the program counter is updated before the
exception is taken, the aborted instruction is at (pc – 6). The value stored by the
processor in lr_mode is therefore (pc + 2).
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 9-43
Handling Processor Exceptions
An exception handler may need to determine whether the processor was in ARM or
Thumb state when the exception occurred. SWI handlers, especially, may need to read
the processor state. This is done by examining the SPSR T bit. This bit is set for Thumb
state and clear for ARM state.
Both ARM and Thumb instruction sets have the SWI instruction. We have already
examined how to handle SWIs called from ARM state (in SWI handlers on page 9-14).
Here we address the handling of SWIs that are called from Thumb state. When doing
so there are three considerations to bear in mind:
• the address of the instruction is at (lr – 2), rather than (lr – 4)
• the instruction itself is 16-bit, and so requires a halfword load
• the SWI number is held in 8 bits instead of the 24 bits in ARM state.
15 14 13 12 11 10 9 8 7 0
1 1 0 1 1 1 1 1 8_bit_immediate
comment field
Example 9-18 on page 9-45 shows ARM code that handles a SWI from both sources.
Note the following points:
• Each of the do_swi_x routines could carry out a switch to Thumb state and back
again to improve code density if required.
• The range of SWI numbers accessible from Thumb state can be increased by
calling SWIs dynamically as described in SWI handlers on page 9-14.
9-44 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Handling Processor Exceptions
Example 9-18
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 9-45
Handling Processor Exceptions
The ARM Architecture defines a User mode that has 15 general purpose registers, a pc
and a CPSR. In addition to this mode there are five privileged processor modes, each of
which have an SPSR and a number of registers that replace some of the 15 User mode
general purpose registers.
When a processor exception occurs, the current program counter is copied into the link
register for the exception mode, and the CPSR is copied into the SPSR for the exception
mode. The CPSR is then altered in an exception-dependent way, and the program
counter is set to an exception-defined address to start the exception handler.
The ARM subroutine call instruction (BL) copies the return address into r14 before
changing the program counter, so the subroutine return instruction moves r14 to pc (MOV
pc,lr).
Together these actions imply that ARM modes that handle exceptions must ensure that
they do not cause the same type of exceptions if they call subroutines, because the
subroutine return address will be overwritten with the exception return address.
In earlier versions of the ARM architecture, this problem has been solved by either
carefully avoiding subroutine calls in exception code, or changing from the privileged
mode to user mode. The first solution is often too restrictive, and the second means the
task may not have the privileged access it needs to run correctly.
ARM Architecture 4 and later provide a processor mode called system mode, to
overcome this problem. System mode is a privileged processor mode that shares the
User mode registers. Privileged mode tasks can run in this mode, and exceptions no
longer overwrite the link register.
Note
System mode cannot be entered by an exception. The exception handler modify the
CPSR to enter System mode. Refer to Reentrant interrupt handlers on page 9-26 for an
example.
9-46 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Chapter 10
Writing Code for ROM
This chapter describes how to build ROM images, typically for embedded applications.
There are also hints on how to avoid the most common errors in writing code for ROM.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 10-1
Writing Code for ROM
This chapter contains examples of using scatter loading to build complex images. For
detailed reference information on scatter loading, refer to Chapter 6 Linker in the ARM
Software Development Toolkit Reference Guide.
• a scatter loading application that runs under the ARMulator, and also uses
sprintf() from the Embedded C library. The example displays the
linker-generated scatter symbols on the screen.
• a more complex scatter loading application that runs from Flash memory on an
ARM Development Board (PID7T).
10-2 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Writing Code for ROM
The simplest layout is to locate the application in ROM at address 0 in the memory map.
The application can then branch to the real entry point when it executes its first
instruction (at the reset vector at address 0x0).
0x10000000
SRAM
0x0F000000
DRAM
0x04000000
ROM
0x00000000
However, there are disadvantages with this layout. ROM is typically narrow and slow
(requires wait states to access it). This slows down the handling of processor exceptions
(especially interrupts) through the vector table. Also, if the vector table is in ROM, it
cannot be modified by the code.
RAM is normally faster and wider than ROM. For this reason, it is better for the vector
table and FIQ handlers if the memory at 0x0 is RAM.
However, if RAM is located at address 0x0, there is not a valid instruction in the reset
vector entry on power-up. Therefore, you need to allow ROM to be located at 0x0 at
power-up (so there is a valid reset vector), but to also allow RAM to be located at 0x0
during normal execution. The changeover from the reset to the normal memory map is
normally caused by writing to a memory mapped register.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 10-3
Writing Code for ROM
For example, on reset, an aliased copy of ROM is present at 0x0, but RAM is remapped
to zero when code writes to the RPS REMAP register. For more information, refer to
the ARM Reference Peripheral Specification.
Normal
RESET (Remapped)
0x10000000 0x10000000
ROM ROM
0x0F000000 0x0F000000
ROM aliased to
DRAM address 0x00000000 DRAM
by system decoder
0x04000000 0x04000000
ROM SRAM
0x00000000 0x00000000
1. Power on to fetch the RESET vector at 0x00000000 (from the aliased copy of
ROM).
4. Complete the rest of the initialization code, as described in Initializing the system
on page 10-6.
System decoder
10-4 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Writing Code for ROM
case ADDR(31:24) is
when "0x00"
if REMAP = "0" then
select ROM
else
select SRAM
when "0x0F"
select ROM
when ....
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 10-5
Writing Code for ROM
No automatic initialization takes place on RESET, so the application entry point must
perform some initialization before it can call any C code.
Typically, the initialization code should carry out some or all of the following tasks:
• defining the entry point
• setting up exception vectors
• initializing the memory system
• initializing the stack pointer registers
• initializing any critical I/O devices
• initializing any RAM variables required by the interrupt system
• enabling interrupts
• changing processor mode if necessary
• changing processor state if necessary
• initializing memory required by C
• entering C code.
The initialization code must define the entry point. The assembler directive ENTRY
marks the entry point.
10-6 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Writing Code for ROM
If your system has a Memory Management or Protection Unit, you must make sure that
it is initialized:
• before interrupts are enabled
• before any code is called that might rely on RAM being accessible at a particular
address, either explicitly, or implicitly through the use of stack.
The initialization code initializes the stack pointer registers. You may need to initialize
some or all of the following stack pointers, depending on which interrupts and
exceptions you use:
sp_SVC must always be initialized.
sp_IRQ must be initialized if IRQ interrupts are used. It must be initialized before
interrupts are enabled.
sp_FIQ must be initialized if FIQ interrupts are used. It must be initialized before
interrupts are enabled.
sp_ABT must be initialized for data and prefetch abort handling.
Generally, sp_ABT and sp_UND are not used in a simple embedded system. However,
you may wish to initialize them for debugging purposes.
Note
You can set up the stack pointer sp_USR when you change to User mode to start
executing the application.
Critical I/O devices are any devices that you must initialize before you enable
interrupts. Typically, you must initialize these devices at this point. If you do not, they
may cause spurious interrupts when interrupts are enabled.
If your interrupt system has buffer pointers to read data into memory buffers, the
pointers must be initialized before interrupts are enabled.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 10-7
Writing Code for ROM
The initial values for any initialized variables (RW) must be copied from ROM to RAM.
All other ZI variables must be initialized to zero.
Note
If the application uses scatter loading, see Initialization code on page 10-26 for details
of how to initialize these areas.
The initialization code should enable interrupts if necessary, by clearing the interrupt
disable bits in the CPSR.
At this stage the processor is in Supervisor mode. If your application runs in User mode,
change to User mode and initialize the User mode sp register, sp_USR.
10-8 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Writing Code for ROM
For more details on changing between ARM and Thumb state, refer Chapter 7
Interworking ARM and Thumb.
When building a ROM image using the Embedded C Library, call the C entry point
something other than main(), for example C_entry or ROM_entry.
When the compiler compiles a function called main(), it generates a reference to the
symbol __main to force the linker to include the basic C run-time system from the
semihosting ANSI C library. If you are not linking with the C library (when building the
ROM), this causes an error.
If you use the main() function only when building an application version for
debugging, comment it out with an #ifdef when building a ROM image.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 10-9
Writing Code for ROM
The code for init.s and ex.c is in the Examples\ROM\init subdirectory of your
SDT install directory (normally c:\ARM250\Examples\ROM\init), and is included
in Sample code on page 10-13 for reference.
Note
On UNIX systems, use single quotes (‘) instead of double quotes (“), or put a
backslash before any double quotes. For example:
The assembler file init.s tests this symbol and generates different code
depending on whether or not the symbol is set. If the symbol is set, it generates a
sequence of branches to be loaded directly over the vector area at address 0.
10-10 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Writing Code for ROM
-ro-base 0x0
tells the linker that the read-only or code segment will be placed at
0x00000000 in the address map.
-rw-base 0x10000000
tells the linker that the read-write or data segment will be placed at
0x10000000 in the address map. This is the base of the RAM in this
example.
-first init.o(Init)
tells the linker to place this area first in the image. On UNIX systems
you might need to put a backslash \ before each parenthesis.
-map tells the linker to print an area map or listing showing where each code
or data section will be placed in the address space. The output is shown
in Area listing for the code on page 10-12.
-info Sizes
tell the linker to print information on the code and data sizes of each
object file along with the totals for each type of code or data. The
output generated is shown in Output from -info Sizes option on page
10-12.
4. Run the fromELF utility to produce a plain binary version of the image:
fromelf -nozeropad rom0.axf -bin rom0.bin (ARM)
fromelf -nozeropad trom0.axf -bin trom0.bin (Thumb)
where:
-nozeropad
tells the linker not to pad the end of the image with zeros to make space
for variables. This option should always be used when building ROM
images.
-bin specifies a binary output image with no header.
5. Load and execute the ROM image under ARMulator by starting armsd, ADW, or
ADU, then type the following on the command line:
getfile rom0.bin 0 (ARM)
getfile trom0.bin 0 (Thumb)
pc=0
go
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 10-11
Writing Code for ROM
Example 10-2 shows the map (area listing) for the sample code:
This shows that the linker places three code areas at successive locations starting from
0x0000000 (where the ROM is based), and two data areas starting at address
0x10000000 (where the RAM is based).
Note
The figures may differ, depending on which version of the ARM Software Development
Toolkit is being used.
The output from the -info Sizes option is shown in Example 10-3.
The required RAM size is the sum of the RW data (4) and the 0-Init data (320), in
this case 324 bytes.
The required ROM size is the sum of the code size (412), the inline data size
(28), the inline strings (356), the const data (16) and the RW data (4). In this
example, the required ROM size is 816 bytes.
The RW data is included in both the ROM and the RAM counts. This is because the
ROM contains the initialization values for the RAM data.
10-12 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Writing Code for ROM
;
; The AREA must have the attribute READONLY, otherwise the linker will not
; place it in ROM.
;
; The AREA must have the attribute CODE, otherwise the assembler will not
; allow any code in this AREA
;
; Note the ’|’ character is used to surround any symbols which contain
; non standard characters like ’!’.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 10-13
Writing Code for ROM
B Abort_Handler
NOP ; Reserved vector
B IRQ_Handler
B FIQ_Handler
ELSE
; Otherwise, copy a sequence of LDR PC instructions over the vectors
; (Note: Copy LDR PC instructions because branch instructions
; could not simply be copied, the offset in the branch instruction
; would have to be modified so that it branched into ROM. Also, a
; branch instructions might not reach if the ROM is at an address
; > 32M).
MOV R8, #0
ADR R9, Vector_Init_Block
LDMIA R9!, {R0-R7}
STMIA R8!, {R0-R7}
LDMIA R9!, {R0-R7}
STMIA R8!, {R0-R7}
; Now fall into the LDR PC, Reset_Addr instruction which will continue
; execution at ’Reset_Handler’
Vector_Init_Block
LDR PC, Reset_Addr
LDR PC, Undefined_Addr
LDR PC, SWI_Addr
LDR PC, Prefetch_Addr
LDR PC, Abort_Addr
NOP
LDR PC, IRQ_Addr
LDR PC, FIQ_Addr
10-14 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Writing Code for ROM
Prefetch_Handler
B Prefetch_Handler
Abort_Handler
B Abort_Handler
IRQ_Handler
B IRQ_Handler
FIQ_Handler
B FIQ_Handler
; Set up the SVC stack pointer last and return to SVC mode
MOV R0, #Mode_SVC:OR:I_Bit:OR:F_Bit ; No interrupts
MSR CPSR_c, R0
LDR R13, =SVC_Stack
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 10-15
Writing Code for ROM
; --- Now change to User mode and set up User mode stack.
MOV R0, #Mode_USR:OR:I_Bit:OR:F_Bit
MSR CPSR_c, R0
LDR sp, =USR_Stack
IMPORT C_Entry
[ :DEF:THUMB
ORR lr, pc, #1
BX lr
CODE16 ; Next instruction will be Thumb
]
BL C_Entry
; A real application wouldn’t normally be expected to return, however
; in case it does, the debug monitor swi is used to halt the application.
MOV r0, #0x18 ; angel_SWIreason_ReportException
LDR r1, =0x20026 ; ADP_Stopped_ApplicationExit
[ :DEF: THUMB
SWI 0xAB ; Angel semihosting Thumb SWI
|
SWI 0x123456 ; Angel semihosting ARM SWI
]
END
10-16 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Writing Code for ROM
#ifdef __thumb
/* Define Angel Semihosting SWI to be Thumb one */
#define SemiSWI 0xAB
#else
/* Define Angel Semihosting SWI to be ARM one */
#define SemiSWI 0x123456
#endif
/* Write a character */
__swi(SemiSWI) void _WriteC(unsigned op, const char *c);
#define WriteC(c) _WriteC (0x3,c)
/* Write a string */
__swi(SemiSWI)void _Write0(unsigned op, const char *string);
#define Write0(string) _Write0 (0x4,string)
/* Exit */
__swi(SemiSWI) void _Exit(unsigned op, unsigned except);
#define Exit() _Exit (0x18,0x20026)
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 10-17
Writing Code for ROM
void C_Entry(void)
{
if (rom_data_base == ram_data_base) {
Write0("Warning: Image has been linked as an application.\r\n");
Write0(" To link as a ROM image, link with the options\r\n");
Write0(" -RO <rom-base> -RW <ram-base>\r\n");
}
10-18 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Writing Code for ROM
The code for init.s and ex.c is in the Examples\ROM\init subdirectory of your
SDT install directory (normally c:\ARM250\Examples\ROM\init), and are included
in Sample code on page 10-13 for reference.
4. Run the fromELF utility to produce a plain binary version of the image:
fromelf -nozeropad ram0.axf -bin ram0.bin (ARM)
fromelf -nozeropad tram0.axf -bin tram0.bin (Thumb)
5. Load and execute the ROM image under ARMulator by starting armsd, ADW, or
ADU, then type the following on the command line:
getfile ram0.bin 0xf0000000 (ARM)
getfile tram0.bin 0xf0000000 (Thumb)
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 10-19
Writing Code for ROM
This tells armsd to load the file ram0 at address 0xf0000000 in the ARMulator
memory map.
6. Check that the ROM has been loaded correctly by disassembling its first section:
list 0xf0000000
Sample output is shown in Sample disassembly below.
7. Set the program counter to the base of the ROM image, then run it:
pc=0xf0000000
go
This produces the following output:
’factory_id’ is at address 10000000, contents = AA55AA55
’display’ is at address 10000004
Note
If the disassembly produces output that has each word byte-reversed (that is, the word
at 0xf0000000 is 0x0080a0e3 instead of 0xe3a08000), there is a problem with
endianness. Check that your compiler, assembler, and debugger are all configured for
the same endianness.
10-20 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Writing Code for ROM
For more information on the Embedded C library, refer to Chapter 4 The C and C++
Libraries in the ARM Software Development Toolkit Reference Guide.
Before any C code can be called, some startup code to initialize the system is needed.
For the ARMulator, all that is required is to initialize the stack pointer. The initialization
code is called startup.s and is shown in Code listings for example 3 on page 10-22.
10.6.2 C code
The Embedded C Library does not contain printf(), so here, Angel SWIs are used
together with sprintf() to display text onto the console. This mechanism is portable
across ARMulator, Angel, EmbeddedICE, and Multi-ICE.
The C code to print ten strings using sprintf() is shown in full in Code listings for
example 3 on page 10-22.
3. Type:
armlink -o print.axf -info totals startup.o print.o
c:\ARM250\lib\embedded\armlib_cn.32l
or, for Thumb:
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 10-21
Writing Code for ROM
4. Start armsd, ADW, or ADU and type the following on the command line:
load print.axf
go
IMPORT C_Entry
ENTRY
END
10-22 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Writing Code for ROM
#include <stdio.h>
#ifdef __thumb
/* Define Angel Semihosting SWI to be Thumb one */
#define SemiSWI 0xAB
#else
/* Define Angel Semihosting SWI to be ARM one */
#define SemiSWI 0x123456
#endif
/* Write a string */
__swi(SemiSWI) void _Write0(unsigned op, char *string);
#define Write0(string) _Write0 (0x4,string)
/* Exit */
__swi(SemiSWI) void _Exit(unsigned op, unsigned except);
#define Exit() _Exit (0x18,0x20026)
void C_Entry(void)
{
int i;
char buf[20];
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 10-23
Writing Code for ROM
The following example shows a scatter loading application that runs under the
ARMulator, and also uses sprintf() from the Embedded C library. The example
displays the linker-generated scatter symbols on the screen. It is not normally necessary
to access these linker symbols in application code (they are only really needed in
initialization code). The linker symbols are accessed here for illustration only.
0x08000000
Initialized RW data
10-24 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Writing Code for ROM
On reset, an aliased copy of FLASH is re-mapped (by hardware) to address zero (as
described in Memory map considerations on page 10-3). Following reset, 32bitRAM is
mapped to address zero, by the first few instructions in boot.o.
The 32bitRAM region might be fast on-chip (internal) RAM, and is typically used for
code that must be executed quickly. Here, the exception vectors of vectors.o get
relocated (copied) from FLASH to 32bitRAM. It can also be advantageous to locate the
stack here, if enough memory is available.
The 16bitRAM region might be slower off-chip (external) DRAM, and is typically used
for less frequently accessed RW variables and ZI data. Here, the RW and ZI areas of
C_main and C_func are relocated/initialized to the region 16bitRAM.
All other read-only code (* (+RO)), for example region initialization and library code,
is executed from FLASH, by using a wildcard in the description file.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 10-25
Writing Code for ROM
This example illustrates the use of boot code (boot.s), which is an extended version
of the init.s code used in Example 1: Building a ROM to be loaded at address 0 on
page 10-10). The boot code defines the ENTRY point and initializes the stack pointers
for each mode.
This example uses region initialization code (regioninit.s) to perform all the
initialization required before branching to the main C application code. The region
initialization code copies RO code and RW data from ROM to RAM, and
zero-initializes the ZI data areas used by the C code.
To re-use this code in your own scatter-loaded applications, call the macro RegionInit
for each of your execution regions.
Note
The initialization code should move all the execution regions from their load addresses
to their execution addresses before creating any zero-initialized areas. This ensures that
the creation of a zero-initialized area does not overwrite any execution region contents
before they are moved from their load address to their execution address. Failure to do
so may produce unpredictable results when the image executes.
10.7.5 C code
The C entry point is called C_Entry(), not main(), to prevent the semihosted ANSI
C libraries being pulled in during the link step, because the Embedded C libraries are
being used here instead.
The Embedded C libraries do not contain printf(), so here Angel SWIs together with
sprintf() are used to display text onto the console.
10-26 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Writing Code for ROM
This creates:
• an ELF debug image (scatter.axf) for loading into a debugger (ADW, ADU,
or armsd)
• a binary ROM image (scatter.bin) suitable for downloading into the Flash
memory of a PID board.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 10-27
Writing Code for ROM
Note
This code is a modified version of the code provided in the sample code suite of the
ARM Development Board.
0x08000000
Initialized RW data
Exception Handlers
Exception Vectors
10-28 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Writing Code for ROM
The scatter load description file shown in Example 10-10 defines one load region
(FLASH) and three execution regions:
• FLASH (at 0x04000000)
• SSRAM (at 0x0000)
• SRAM (at 0x2000).
The SSRAM area might be fast on-chip (internal) 32-bit RAM, and is typically used for
the stack, and code that must be executed quickly. The exception vectors (in
vectors.o) and interrupt handler (in C_int_handler.o) are relocated (copied) from
FLASH to (fast) SSRAM at address 0x0000 for speed.
SRAM might be slower off-chip (external) 16-bit DRAM or SRAM, and is typically
used for less frequently accessed RW variables and ZI data. Here, the RW variables and
ZI data of the main program code (in C_main.c) get copied/initialized in SRAM at
address 0x2000.
All other read-only code, (* (+RO)), for example region initialization and library code,
is executed from FLASH, by using a wildcard in the description file.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 10-29
Writing Code for ROM
This example illustrates the use of boot code (boot.s), as described in Initialization
code on page 10-26.
Note
The initialization code should move all the execution regions from their load addresses
to their execution addresses before creating any zero-initialized areas. This ensures that
the creation of a zero-initialized area does not overwrite any execution region contents
before they are moved from their load address to their execution address. Failure to do
so may produce unpredictable results when the image executes.
This creates:
• an ELF debug image (scatter.axf) for loading into a debugger (ADW, ADU,
or armsd)
• a binary ROM image (scatter.bin) suitable for downloading into the Flash
memory of a PID board.
10-30 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Writing Code for ROM
Follow these steps to execute/debug the image with ADW, EmbeddedICE and a PID
board:
3. In ADW, select Configure debugger from the Options menu and select
remote_a.
4. Select Flash download from the File menu and enter the name of the ROM image
(scatter.bin).
The Command Window displays:
ARM Flash Programming Utility
AT29C040A recognised
Input File Is : - (your_ROM_filename)
Please enter the number of the first sector to write
Default is to start at sector 0
Start at sector 0x0
6. Exit ADW and switch off the power to the PID board.
9. In ADW, select Load from the File menu and enter the name of the debug image
(scatter.axf).
10. Select Debugger Internals from the View menu and make vector_catch=0, to
free a watchpoint unit.
11. You can now debug your ROM code (for example, set breakpoints, single-step,
view backtrace).
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 10-31
Writing Code for ROM
• The branch instructions in the ARM instruction set allow a branch forwards or
backwards by up to 32MB. A subroutine call is a variant of the standard branch.
As well as allowing a branch forwards or backwards up to 32MB, the BL (Branch
with Link) instruction preserves the return address in register 14 (link register, lr).
The linker ensures that no branch or subroutine call violates these range restrictions. If
you place your execution regions in such a way as to require inter-region branches
beyond the range, the linker generates an error message stating:
Function pointers
10-32 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Writing Code for ROM
If you use assembly language veneers, you can write the function as:
asm_func(a,b);
Because ARM and Thumb assembly languages differ, the code for the veneers is
slightly different.
Note
You must ensure that the file containing these veneers is within range of the module
calling asm_func(a,b).
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 10-33
Writing Code for ROM
For more information on the ARM ELF implementation, refer to the ELF
documentation in c:\ARM250\PDF\specs. For the command-line options for
fromELF, see Chapter 8 Toolkit Utilities in the ARM Software Development Toolkit
Reference Guide.
1. Select the root of the project tree view. Choose Edit variables for project.apj...
from the Project menu. The Edit variables dialog is displayed.
2. Find the variable named build_target and change its value from
<$projectname>.axf to <$projectname>.bin and click OK.
3. Choose Edit Project template from the Project menu. The Project Template
Editor dialog is displayed.
5. Create a CreateROM build step by clicking on the New... button in the Project
template Editor dialog.
The Create a new build step pattern dialog is displayed.
6. Type CreateROM in the Name field, and click OK. An empty Edit Build Step
Pattern dialog for CreateROM appears.
10-34 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Writing Code for ROM
14. Select Edit variables for project.apj... from the Project menu.
16. If you want to re-use this template for another project, save the template with the
Save As Template option from the File menu.
a. Remove all source files from your project by highlighting the files, then
pressing delete.
b. Replace all source files into your project using the Add Files to Project
from the Project menu.
This example uses -bin to produce a plain binary image, suitable for blowing into
ROM. Other output formats are also possible (Motorola 32 bit Hex, Intel 32 bit Hex,
and Intellec Hex. Multiple outputs are also possible. For example, step 7 might read (on
one line):
<fromelf> <FROMELFOPTIONS> <$projectname>.axf -m32
<$projectname>.m32 -bin <$projectname>.bin
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 10-35
Writing Code for ROM
10.10.2 Configuration
The Project→Tool configuration menu will now contain an entry fromelf. You will
not need to use this configuration tool, because you can change the fromELF options
using the template variables.
10-36 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Writing Code for ROM
Users of EmbeddedICE 2.04 or earlier may find problems with the semihosting SWI
SYS_WRITE0, used by the examples in this chapter to print to the debugger console.
Upgrade to the latest ICEagent (currently 2.07) to remedy this problem.
Cause
These are runtime support functions called by compiler-generated code to perform tasks
that cannot be performed simply in ARM or Thumb code (for example, integer division
or floating-point operations).
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 10-37
Writing Code for ROM
For example, the following code generates a call to runtime support function
__rt_sdiv to perform a division.
Solution
Link with a C library so that these functions are defined.
Cause
You have compiled your C code with software stack checking enabled. The C compiler
generates code that calls one of the above functions when stack overflow is detected.
Solutions
• Recompile your C code with stack checking disabled. Stack checking is disabled
by default.
• Link with a C library that provides support for stack limit checking. This is
usually possible only in an application environment because C library stack
overflow handling code relies heavily on the application environment.
10-38 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Writing Code for ROM
Cause
Parts of your code have been compiled or assembled with software stack checking
enabled and parts without. Alternatively, you have linked with a library that has
software stack checking enabled whereas your code has it disabled, or vice versa.
Solution
Recompile your C code with stack checking disabled. Stack checking is disabled by
default. Link with a library built with the same options.
undefined __main
Cause
When the compiler compiles the function main(), it generates a reference to the
symbol __main to force the linker to include the basic C runtime system from the ANSI
semihosted C library. If you are not linking with an ANSI semihosted C library and have
a function main() you may get this error.
Solution
This problem may be fixed in one of the following ways:
• If the main() function is used only when building an application version of your
ROM image for debugging purposes, comment it out with an #ifdef when
building a ROM image.
• When building a ROM image and linking with the Embedded C Library, call the
C entry point something other than main(), such as C_Entry or ROM_Entry.
• If you do need a function called main(), define a symbol __main in your ROM
initialization code. Usually this is defined to be the entry point of the ROM image,
so you should define it just before the ENTRY directive as follows:
EXPORT __main
ENTRY
__main
B main
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 10-39
Writing Code for ROM
10-40 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Chapter 11
Benchmarking, Performance Analysis, and
Profiling
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 11-1
Benchmarking, Performance Analysis, and Profiling
When developing application software or comparing the ARM with another processor,
it is often useful to measure:
• code and data sizes
• overall execution time
• time spent in specific parts of an application.
11-2 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Benchmarking, Performance Analysis, and Profiling
-info sizes this option gives a breakdown of the code and data sizes of each
object file or library member making up an image
-info totals this option gives a summary of the total code and data sizes of all
object files and all library members making up an image
The information provided by the -info sizes and -info totals options can be
broken down into:
• code (or read-only) segment
• data (or read-write) segment
• debug data.
inline data
Size of read-only data included in the code segment by the compiler.
Typically, this data contains the addresses of variables that are accessed
by the code, plus any floating-point immediate values or immediate
values that are too big to load directly into a register. It does not include
inline strings, which are listed separately (see Table 11-1 on page 11-5).
inline strings
Size of read-only strings placed in the code segment.
The compiler puts such strings here whenever possible to reduce runtime
RAM requirements.
const Size of any variables explicitly declared as const.
These variables are guaranteed to be read-only and so are placed in the
code segment by the compiler.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 11-3
Benchmarking, Performance Analysis, and Profiling
RW data Size of read-write data. This is data that is read-write and also has an
initializing value. Read-write data occupies the displayed amount of
RAM at runtime, but also requires the same amount of ROM to hold the
initializing values that are copied into RAM on image startup.
0-init data
Size of read-write data that is zero-initialized at image startup.
Typically this contains arrays that are not initialized in the C source code.
Zero-initialized data requires the displayed amount of RAM at runtime
but does not require any space in ROM.
Debug data
debug data
Reports the size of any debugging data if the files are compiled with the
-g+ option.
Note
There are totals for the debug data, even though the code has not been compiled for
source-level debugging, because the compiler automatically adds information to an AIF
file to allow stack backtrace debugging.
Calculate the ROM and RAM requirements for your system as follows:
In addition you must allow some RAM for stacks and heaps.
In more complex systems, you may require part (or all) of the code segment to be
downloaded from ROM into RAM at runtime. This increases the system RAM
requirements but could be necessary if, for example, RAM access times are faster than
ROM access times and the execution speed of the system is critical.
11-4 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Benchmarking, Performance Analysis, and Profiling
The compiler produces a number of warnings that you can either ignore, or suppress
using the -w option. The warnings are generated because the Dhrystone application is
coded in Kernighan and Ritchie style C, rather than ANSI C.
Perform the link, with the -info totals option to give a report on the total code and
data sizes in the image, broken into separate totals for the object files and library files:
armlink -info totals dhry_1.o dhry_2.o -o dhry
You can use this easier method if you use ADW and are running APM.
Load the Dhrystone project file dhry.apj into the ARM Project Manager (APM).
Change the project setting to produce a release build with a little-endian memory model,
using the ARM tools instead of the Thumb tools (see Configuring tools on page 2-21).
Click the Force Build button. This compiles and links the project, automatically
generating a summary of the total code and data sizes in the image.
Results
Your figures may differ, depending on the version of the compiler, linker, and library.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 11-5
Benchmarking, Performance Analysis, and Profiling
There are two debugger internal variables that contain the cycle counts. These can be
displayed using the armsd print command, or by selecting Debugger Internals from
the ADW or ADU View menu:
$statistics
can be used to output any statistics that the ARMulator has been keeping.
$statistics_inc
shows the number of cycles of each type since the previous time
$statistics or $statistics_inc was displayed. This is only
applicable for armsd, or the command-line window in ADW or ADU.
$statistics_inc_w
outputs the difference between the current statistics and the point at
which you asked for the $statistics_inc_w window. This is only
applicable for ADW or ADU, not for armsd.
Make sure you have not compiled with source-level debugging enabled (armcc -g+),
because this causes sub-optimal code to be generated (larger and slower). The -01, -02
and -gt compiler options can reduce this. Refer to Chapter 2 The ARM Compilers in
the ARM Software Development Toolkit Reference Guide for more information on the
effect of debug and optimization options.
In this example, the number of instructions executed by the main loop of the Dhrystone
application and the number of cycles consumed are determined. A suitable place to
break within the loop is the invocation of function Proc_5.
1. Load the executable, produced in Code and data sizes example: Dhrystone on
page 11-4, into the debugger:
armsd -nofpe dhry
11-6 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Benchmarking, Performance Analysis, and Profiling
3. Type go at the armsd prompt to begin execution. When prompted, request at least
two runs through Dhrystone.
4. When the breakpoint at the start of Proc_5 is reached, display the system variable
$statistics (which gives the total number of instructions and cycles taken so
far) and restart execution:
print $statistics
go
5. When the breakpoint is reached again, you can obtain the number of instructions
and cycles consumed by one iteration:
print $statistics_inc
1. If you have not already done so, build the Dhrystone project as described in Code
and data sizes example: Dhrystone on page 11-4.
2. If you use ADW and are running APM then click on the Debug button to start
ADW and load the Dhrystone project. If you use ADU then start ADU and select
Load Image... from the File menu to load the Dhrystone project.
4. Locate function Proc_5 by selecting Low Level Symbols from the View menu.
9. When the breakpoint set at main is reached, click Go again to begin execution of
the main application.
10. When the breakpoint at Proc_5 is reached, choose Debugger Internals from the
View menu.
11. Double click on the statistics_inc field to display the detail for this variable.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 11-7
Benchmarking, Performance Analysis, and Profiling
12. Click the Go button. When the breakpoint at Proc_5 is reached again, the
contents of the statistics_inc_w field is updated to reflect the number of
instructions and cycles consumed by one iteration of the loop.
Results
S-cycles Sequential cycles. The CPU requests transfer to or from the same
address, or from an address that is a word or halfword after the preceding
address.
I-cycles Internal cycles. The CPU does not require a transfer because it is
performing an internal function (or running from cache).
Note
You may obtain slightly different figures, depending on the version of the compiler,
linker, or library in use, and the processor for which the ARMulator is configured.
The ARMulator also provides facilities for real-time simulation. To carry out such a
simulation, you must specify:
• the type and speed of the memory attached to the processor
• the speed of the processor.
Refer to Map files on page 11-9 for more information and examples.
While it is executing your program, the ARMulator counts the total number of clock
ticks taken. This allows you to determine how long your application would take to
execute on real hardware.
11-8 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Benchmarking, Performance Analysis, and Profiling
When it performs a simulation, the ARMulator keeps track of the total time elapsed.
This value may be read either by the simulated program or by the debugger.
To read the simulated clock from an assembly language program use the Angel
SYS_CLOCK SWI.
From C, use the standard C library function clock(). This function returns the number
of elapsed centiseconds.
The internal variable $clock contains the number of microseconds since simulation
started. To display this value, use the command:
Print $clock
if you are using armsd, or select Debugger Internals from the View menu if you are
using ADW or ADU.
Note
The $clock internal variable is unavailable if the processor clock frequency is set to
0.00. You must specify a processor clock frequency for ARMulator if you wish to read
the $clock variable. Select Options →Configure Debugger... →Target →ARMulate
→ Configure... and use the ARMulator Configuration dialog.
The type and speed of memory in a simulated system is detailed in a map file. This
defines the number of regions of attached memory, and for each region:
• the address range to which that region is mapped
• the data bus width in bytes
• the access time for the memory region.
armsd expects the map file to be in the current working directory under the name
armsd.map.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 11-9
Benchmarking, Performance Analysis, and Profiling
ADW or ADU accept a map file of any name, provided that it has the extension .map.
See Real-time simulation example: Dhrystone on page 11-13 for details of how to
associate a map file into an ADW or ADU session.
To calculate the number of wait states for each possible type of memory access, the
ARMulator uses the values supplied in the map file and the clock frequency. See
ARMulator configuration on page 3-57 for details of how the wait states are calculated.
where:
start is the start address of the memory region in hexadecimal, for example,
80000.
size is the size of the memory region in hexadecimal, for example, 4000.
name is a single word that you can use to identify the memory region when
memory access statistics are displayed. You can use any name. To ease
readability of the memory access statistics, give a descriptive name such
as SRAM, DRAM, or EPROM.
width is the width of the data bus in bytes (that is, 1 for an 8-bit bus, 2 for a
16-bit bus, or 4 for a 32-bit bus).
access describes the type of access that may be performed on this region of
memory:
r for read-only.
w for write-only.
rw for read-write.
- for no access.
An asterisk (*) may be appended to the access to describe a Thumb-based
system that uses a 32-bit data bus, but which has a 16-bit latch to latch the
upper 16 bits of data, so that a subsequent 16-bit sequential access can be
fetched directly out of the latch.
11-10 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Benchmarking, Performance Analysis, and Profiling
read-times
describes the nonsequential and sequential read times in nanoseconds.
These should be entered as the nonsequential read access time followed
by / (slash), followed by the sequential read access time. Omitting the /
and using only one figure indicates that the nonsequential and sequential
access times are the same.
Note
Do not simply enter the times quoted on top of a memory chip. You must
add a 20-30ns signal propagation time to them.
write-times
describes the nonsequential and sequential write times. The format is
identical to that of read times.
Example 1
0 80000000 RAM 4 rw 135/85 135/85
This describes a system with a single contiguous section of RAM from 0 to 0x7fffffff
with a 32-bit data bus, read-write access, and N and S access times of 135ns and 85ns
respectively.
The N-cycle access time is one clock cycle longer than the S-cycle access time. For a
faster system, a smaller N-cycle access time should be used. For example, for a 33MHz
system, the access times would be defined as 115/85 115/85.
Example 2
0 80000000 RAM 1 rw 150/100 150/100
This describes a system with the same single contiguous section of memory, but with
an 8-bit external data bus and slightly different access times.
Example 3
The following description file details a typical embedded system with 32KB of on-chip
memory, 16-bit ROM and 32KB external DRAM:
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 11-11
Benchmarking, Performance Analysis, and Profiling
In the final hardware, the two distinct regions of the external DRAM would be
combined. This does not make any difference to the accuracy of the simulation.
The SRAM region is given access times of 1ns. In effect, this means that each access
takes 1 clock cycle, because ARMulator rounds this up to the nearest clock cycle.
However, specifying it as 1ns allows the same map file to be used for a number of
simulations with differing clock speeds.
Note
To ensure accurate simulations, take care that all areas of memory likely to be accessed
by the image you are simulating are described in the memory map.
To ensure that you have described all areas of memory you think the image should
access, you can define a single memory region that covers the entire address range as
the last line of the map file.
For example, you could add the following line to the above description:
00000000 80000000 Dummy 4 - 1/1 1/1
You can then detect if any reads or writes are occurring outside the regions of memory
you expect using the print $memory_statistics command. This can be a very
useful debugging tool.
11-12 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Benchmarking, Performance Analysis, and Profiling
Example 11-1
You must specify the clock speed of the processor being simulated in the debugger. In
armsd, this is set by the command-line option -clock value. The value is presumed
to be in Hz unless MHz is specified.
In ADW or ADU, the clock speed is set in the Debugger Configuration dialog. To
display this dialog:
To work through this example, you must create a map file. (If a map file is included in
the files you copied from the toolkit directory, edit it to match the one shown here.) Call
it armsd.map.
00000000 80000000 RAM 4 RW 135/85 135/85
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 11-13
Benchmarking, Performance Analysis, and Profiling
1. Load the executable produced in Code and data sizes example: Dhrystone on
page 11-4 into the debugger, telling the debugger that its clock speed is 20MHz:
armsd -clock 20MHz -nofpe dhry
As the debugger loads, you can see the information about the memory system that
the debugger has obtained from the armsd.map file.
4. When the application completes, record the number of Dhrystones per second
reported. This is your performance figure.
ADW and ADU by default use a file called armsd.map as their map file. To change to
the map file you have created:
1. Select Configure Debugger from the Options menu. This displays the Debugger
configuration dialog.
2. Select the Memory Maps tab to change the default memory map. Click the Local
Map File button and select the map file you created.
The association is now set up, and you can run the program.
1. If you use ADW and are running APM then click on the Debug button to start
ADW and load the project. If you use ADU then start ADU and select Load
Image... from the File menu to load the project. If a dialog box prompts you to
save the changes to the project file, click Yes.
3. Click the Go button to begin execution, and again when the breakpoint on main
is reached.
11-14 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Benchmarking, Performance Analysis, and Profiling
5. When the application completes, record the number of Dhrystones per second
reported. This is your performance figure.
When the debugger is configured to emulate a processor of the required clock speed (in
this case 20MHz), you can repeat the simulation by clicking on Execute rather than
Debug in APM.
Note
You may obtain slightly different figures, depending on the version of the compiler,
linker, and library in use, and the processor for which the ARMulator is configured.
You may be able to significantly reduce the actual time taken for a simulation by
dividing the specified clock speed by a factor of ten or a hundred, and multiplying the
memory access times by the same factor. Take the time reported by the clock()
function (or by SYS_CLOCK) and divide by the same factor.
This works because the simulated time is recorded internally in microseconds, but
SYS_CLOCK only returns centiseconds. Dividing the clock speed shifts digits from the
nanosecond count into the centisecond count, allowing the same level of accuracy but
taking much less time to simulate.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 11-15
Benchmarking, Performance Analysis, and Profiling
This section explains how using compiler options, avoiding the standard C library, and
modifying your source code can all help to achieve these goals.
The ARM C compiler has a number of command-line options that control the way in
which code is generated.
By default, the ARM C compiler is highly optimizing. By default, the code produced
from your source is balanced for a compromise of code size versus execution speed.
However, there are a number of compiler options that can affect the size and
performance of generated code. These may be used individually or may be combined to
give the required effect.
For a full description of optimization and other command-line options see Chapter 2
The ARM Compilers in the ARM Software Development Toolkit Reference Guide. That
chapter includes a description of the -pcc option, but a little more information about
that option follows:
-pcc The code generated by the compiler can be slightly larger when
compiling with the -pcc switch. This is because of extra restrictions on
the C language in the ANSI standard that the compiler can take advantage
of when compiling in ANSI mode.
If your code compiles in ANSI mode, do not use the -pcc option. The
Dhrystone application provides a good example. It is written in old-style
Kernighan and Ritchie C, but compiles more efficiently in ANSI mode,
even though it causes the compiler to generate a number of warning
messages.
You can reduce image size by using the embedded C libraries, instead of the standard
ANSI C library which adds a minimum of around 15KB to an image. Refer to Chapter
4 The C and C++ Libraries in the ARM Software Development Toolkit Reference Guide
for more information. See also Chapter 10 Writing Code for ROM in this book for an
example of their use.
11-16 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Benchmarking, Performance Analysis, and Profiling
You can make further improvements to code size and performance in addition to those
achieved by good use of compiler options by modifying the code to take advantage of
the ARM processor features.
Use of shorts
ARM cores that implement an ARM Architecture earlier than version 4 do not have the
ability to directly load or store halfword quantities (or short types). This affects code
size. Generally, code generated for Architecture 3 that makes use of short is larger
than equivalent code that only performs byte or word transfers. Storing a short is
particularly expensive, because the ARM processor must make two byte stores.
Similarly, loading a short requires a word load, followed by shifting out the unwanted
halfword.
If you are writing or porting for processors that do not have halfword support, you
should minimize the use of short values. However, this is sometimes impossible. C
programs ported from x86 or 68k architectures, for example, frequently make heavy use
of short. If the code has been written with portability in mind, all you may have to do
is change a typedef or #define to use int instead of short. Where this is not the
case, you may have to make some functional changes to the code.
You may be able to establish the extent of code size increase resulting from using shorts
by compiling the code with:
armcc -Dshort=int
which preprocesses all instances of short to int. Be aware that, although it may
compile and link correctly, code created with this option may not function as expected.
Whatever your approach, you need to weigh the change in code size against the opposite
change in data size.
The program below illustrates the effect of using shorts, integers, and the -ARM7T
option on code and data size.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 11-17
Benchmarking, Performance Analysis, and Profiling
#include <stdio.h>
typedef short number;
number array [2000];
number loop;
int main()
{
for (loop=0; loop < 2000; loop++)
array[loop] = loop;
return 0;
}
The results of compiling the program with all three options are shown in the following
table:
short 76 8 0 0 4 4000 64
int 44 8 0 0 4 8000 0
Note
See Specifying the target processor and architecture on page 2-20 of the ARM Software
Development Toolkit Reference Guide for details of hardware support for halfwords.
Other changes
• Modify performance-critical C source to compile efficiently on the ARM. See
Improving performance and code size on page 11-16.
• Port small, performance-critical routines into ARM assembly language.
Compile with the -S option to produce assembly output without generating object code,
and take this as a starting point for your own hand-optimized assembly language. When
you specify the -S option you can also specify-fs to write a file containing interleaved
C or C++ and assembly language (see Specifying output format on page 2-19 of the
ARM Software Development Toolkit Reference Guide).
You can make significant performance improvements by using Load and Store Multiple
instructions in memory-intensive algorithms. When optimizing the routines:
• use load/store multiple instructions for memory-intensive algorithms
11-18 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Benchmarking, Performance Analysis, and Profiling
• use 64-bit result multiply instructions (where available) for fixed-point arithmetic
• replace small, performance-critical functions by macros, or use the __inline
preprocessor directive
• avoid the use of setjmp() in performance-critical routines (particularly in pcc
mode).
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 11-19
Benchmarking, Performance Analysis, and Profiling
11.5 Profiling
Profiling allows the time spent in specific parts of an application to be examined. It does
not require any special compile time or link time options. The only requirement is that
low level symbols must be included in the image. These are inserted by the linker unless
it is instructed otherwise by the -Nodebug option.
Profiling data is collected by the ARM Debugger while the code is being executed. The
data is saved to a file. It is then loaded into the ARM profiler which displays the results.
The profiler in turn generates a profile report.
Profiling is currently available only when you use the ARMulator, or the Angel debug
monitor on a target board such as the PID7T. Profiling is an optional feature for Angel,
selectable at build time. Refer to Chapter 13 Angel for more information. The standard
Angel image supplied with SDT 2.50 for the PID7T has profiling turned on.
When you select Options →Profiling →Toggle Profiling, the debugger determines
whether the target hardware can perform profiling. If so, profiling is enabled. If not, the
message Target Processor can’t do this is displayed.
The ARM profiler, armprof, displays an execution profile of a program from a profile
data file generated by a debugger. The profiler displays one of two types of execution
profile, depending on the amount of information present in the profile data:
• If only pc sampling information is present, the profiler can display only a flat
profile giving the percentage time spent in each function, excluding the time spent
in any of its children.
• If function call count information is present, the profiler can display a call graph
profile that shows not only the percentage time spent in each function, but also the
percentage time accounted for by calls to all children of each function, and the
percentage time allocated to calls from different parents.
The compiler automatically prepares the code for profiling, so no special options are
required at compile time. At link time, you must ensure that your program image
contains symbols. This is the default setting for the linker.
You can only profile programs that are loaded into store from the debugger. Function
call counting for code in ROM is not available. You must inform the debugger that you
wish to gather profile data when the program image is loaded. The debugger then alters
the image, diverting calls to counting veneers.
11-20 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Benchmarking, Performance Analysis, and Profiling
The debuggers allow the collection of pc samples to be turned on and off at arbitrary
times, allowing data to be generated only for the part of a program on which attention
is focussed (omitting initialization code, for example). However, care should be taken
that the time between turning sampling on and off is long compared with the sample
interval, or the data generated may be meaningless. Turning sampling on and off does
not affect the gathering of call counts.
The debugger collects profiling data while an application is executing. You can turn data
collection on and off during execution, so that only the relevant sections of code are
profiled:
• If you are using armsd, use the profon and profoff commands.
• If you are using ADW or ADU, select Options →Profiling →Toggle Profiling
(see Profiling on page 3-43).
The format of the execution profile obtained depends on the type of information stored
in the data file:
pc sampling provides a flat profile of the percentage time spent in each function
(excluding the time spent in its children).
Note
No count is taken if the function calls children through an ARM-Thumb interworking
veneer.
The debugger needs to know which profiling method you require when it loads the
image. The default is pc sampling. To obtain a call graph profile:
• If you are using ADW or ADU, select Options →Profiling →Call Graph
Profiling.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 11-21
Benchmarking, Performance Analysis, and Profiling
• If you are using ADW or ADU, select Options →Profiling →Write to File.
The ARM profiler utility, armprof, generates the profile report using the data in the file.
The report is divided into sections, each of which gives information about a single
function in the program.
A section function (called the current function) is indicated by having its name start at
the left-hand edge of the Name column. If call graph profiling is used, information is
also given about child and parent functions. Functions listed below the current function
are its children. Those listed above the current function are the function parents it.
Name Displays the function names. The current function in a section starts at
the left-hand edge of the column. Parent and child functions are shown
indented.
cum% Shows the total percentage time spent in the current function plus the
time spent in any functions that it called. It is only valid for the current
function.
11-22 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Benchmarking, Performance Analysis, and Profiling
Below is a section of the output from armprof for a call graph profile:
Name cum% self% desc% calls
main 96.04% 0.16% 95.88% 0
qsort 0.44% 0.75% 1
_printf 0.00% 0.00% 3
clock 0.00% 0.00% 6
_sprintf 0.34% 3.56% 1000
check_order 0.29% 5.28% 3
randomise 0.12% 0.69% 1
shell_sort 1.59% 3.43% 1
insert_sort 19.91% 59.44% 1
-------------------------------------------------------------
main 19.91% 59.44% 1
insert_sort 79.35% 19.91% 59.44% 1
strcmp 59.44% 0.00% 243432
-------------------------------------------------------------
From the cum% column, you can see (in the main section) that the program spent 96.04
percent of its time in main and its children. Of this, only 0.16 percent of the time is spent
in main (self% column), whereas 95.88 percent of the time is spent in functions called
by main (desc% column). The call count for main is 0 because it is the top-level
function, and is not called by any other functions, whereas the section for
insert_sort shows that it made 243432 calls to strcmp, and that this accounted for
59.44 percent of the time spent in strcmp (the desc% column shows 0 in this case
because strcmp does not call any functions).
The sorts application can be found in the Examples subdirectory of the ARM
Software Development Toolkit. Copy the files into your working directory.
PC sampling information
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 11-23
Benchmarking, Performance Analysis, and Profiling
5. When execution completes, write the profile data to a file using the ProfWrite
command:
ProfWrite sort1.prf
6. Exit armsd:
Quit
7. Generate the profile for the collected data by entering at the system prompt:
armprof sort1.prf > prof1
The profiler generates the report and sends the output to text file prof1 that you
can examine.
a. Select Open from the Project menu to load the project file sorts.apj into
APM.
b. Build the project by clicking the Force Build button. The project is built
and any messages are displayed in the build log.
c. Load the debugger by clicking the Debug button. ADW is started and the
application is loaded.
If you use ADU then:
a. Compile and link the sorts.c example program with the command:
armcc -Otime -o sorts sorts.c
b. Start ADU.
c. Select Load Image... from the File menu to load the sorts.exe program
file into ADU.
11-24 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Benchmarking, Performance Analysis, and Profiling
4. Click Go again.
The program resumes execution.
6. Exit ADW or ADU and start a DOS session. Make the profile directory the current
directory.
7. Generate the profile for the collected profile data by entering the following at the
system prompt:
armprof sort1.prf > prof1
armprof generates the profile report and sends its output to text file prof1 that
you can examine.
2. Load the sorts program into armsd with the /callgraph option:
load/callgraph sorts
/callgraph tells armsd to prepare an image for function call count profiling by
adding code that counts the number of function calls.
6. Exit armsd:
Quit
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 11-25
Benchmarking, Performance Analysis, and Profiling
The -Parent option instructs armprof to include information about the callers of
each function. armprof generates the profile report and sends its output to text file
prof2, that you can examine.
1. If you are using APM and ADW, reload the debugger by clicking the Debug
button on the APM toolbar. If you are using ADU, start ADU.
3. Click Reload to reload the image. This forces call graph profiling to take effect.
6. Click Go again.
The program resumes execution.
11-26 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Benchmarking, Performance Analysis, and Profiling
In addition to profiling the time spent in specific parts of an application, the ARMulator
provides facilities for profiling other performance statistics, and for generating full
instruction traces.
• Enhanced profiling with the Profiler module. The ARMulator has an Events
mechanism that enables events such as cache misses and branch mispredictions
to be profiled.
For example, profiling cache misses enables you to find areas of code that are
causing high levels of cache activity. You can then optimize and tune the code
accordingly.
The profiling is controlled through a configuration file, rather than from the
debugger. However, the data is collected by the debugger and processed by
armprof in exactly the same way, using the same commands and menus.
• Instruction tracing with the Tracer module. At the cost of a significant runtime
overhead, the Tracer module can generate a continuous trace stream of executing
instructions and memory accesses.
Both modules are supplied in source form, and you can modify them as you want. This
enables profiling and tracing to be customized to your specific needs.
For help with understanding the contents of a trace file, see Interpreting trace file output
on page 12-9. For more information on the ARMulator refer to Chapter 12 ARMulator.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 11-27
Benchmarking, Performance Analysis, and Profiling
11-28 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Chapter 12
ARMulator
This chapter describes the ARMulator, a collection of programs that provide software
emulation of ARM processors. It contains the following sections:
• About the ARMulator on page 12-2
• ARMulator models on page 12-3
• Tracer on page 12-6
• Profiler on page 12-12
• Windows Hourglass on page 12-13
• Watchpoints on page 12-14
• Page table manager on page 12-15
• armflat on page 12-19
• armfast on page 12-20
• armmap on page 12-21
• Dummy MMU on page 12-24
• Angel on page 12-25
• Controlling the ARMulator using the debugger on page 12-27
• A sample memory model on page 12-29
• Rebuilding the ARMulator on page 12-32
• Configuring ARMulator to use the example on page 12-34.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 12-1
ARMulator
The ARMulator is instruction-accurate. It models the instruction set but not the precise
timing characteristics of the processor. The ARMulator supports a full ANSI C library
to allow complete C programs to run on the emulated system.
You can supply models written in C that interface to the ARMulator’s external interface.
12-2 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARMulator
The source of a number of sample models can be found in the rebuild kit on UNIX in:
armsd/source
or on PC in:
C:\ARM250\Source\Win32\ARMulate
Basic models
The following source files are provided for the basic models:
tracer.c The tracer module can trace instruction execution and events from
within the ARMulator.
winglass.c This module is used only with the ARM Debugger for Windows.
pagetab.c This module sets up the MMU/cache and associated pagetables
inside the ARMulator on reset.
Memory models
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 12-3
ARMulator
Coprocessor models
12-4 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARMulator
Each of these models exports a stub (see the ARM Software Development Toolkit
Reference Guide). You declare stubs in models.h, using sets of macros. For example:
MEMORY(ARMul_Flat)
COPROCESSOR(ARMul_DummyMMU)
OSMODEL(ARMul_Angel)
MODEL(ARMul_Profiler)
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 12-5
ARMulator
12.3 Tracer
A sample implementation of a tracer is provided. This can trace instructions, memory
accesses, and events to an RDI log window or a file (in text or binary format). See the
source file, tracer.c, and Configuring the Tracer below, for details of the formats
used in these files. The configuration file armul.cnf controls what is traced.
Alternatively, you can link your own tracing code onto the Tracer module, allowing
real-time tracing. No examples are supplied, but the required functions are documented
here. The formats of Trace_State and Trace_Packet are documented in tracer.h.
unsigned Tracer_Open(Trace_State *ts)
This is called when the tracer is initialized. The implementation in
tracer.c opens the output file from this function, and writes a header.
The Tracer has its own section in the ARMulator configuration file (armul.cnf). Find
the EarlyModels section in the configuration file, and the Tracer section below it:
{ Tracer
;; Output options - can be plaintext to file, binary to file or
:: to RDI log window.(Checked in the order RDILog, File, BinFile.)
RDILog=False
File=armul.trc
BinFile=armul.trc
;; Tracer options - what to trace
TraceInstructions=True
TraceMemory=False
TraceIdle=False
TraceNonAccounted=False
12-6 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARMulator
TraceEvents=False
;; Where to trace memory - if not set, it will trace at the core.
TraceBus=True
;; Flags - disassemble instructions; start with tracing enabled;
Disassemble=True
StartOn=False
}
where:
RDILog instructs the Tracer to output to the RDI Log window (the console
under armsd).
File defines the file where the trace information is written, using the
default Tracer_Open functions. Alternatively, you can use
BinFile to store data in a binary format.
TraceNonAccounted
traces unaccounted RDI accesses to memory.
TraceEvents traces events. For more information, refer to Events on page 12-87
of the ARM Software Development Toolkit Reference Guide.
Sample=n Only every nth trace entry is sent to the trace file.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 12-7
ARMulator
Tracing events
When tracing events, you can select the events to be traced using:
EventMask=mask,value
Only those events whose number when masked (bitwise-AND)
with mask equals value are traced.
Event=number Only number is traced. (This is equivalent to
EventMask=0xffffffff,number.)
See Events on page 12-87 of the ARM Software Development Toolkit Reference Guide
for more information on events.
There is no direct debugger support for tracing. Instead, the tracer uses bit 4 of the RDI
Logging Level ($rdi_log) variable to enable or disable tracing.
Using armsd
12-8 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARMulator
This section describes how you interpret the output from the tracer.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 12-9
ARMulator
For example:
MNR4O__ 00008008 EB00000C
where:
12-10 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARMulator
For example:
IT 00008044 e04ec00f SUB r12,r14,pc
where:
IT instruction taken.
Events (E lines)
For example:
E 00000048 00000000 10005
where:
addr1 gives the first of a pair of words, such as, the pc value.
addr2 gives the second of a pair of words, such as, the aborting address.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 12-11
ARMulator
12.4 Profiler
The profiler is controlled by the debugger. For more details on the profiler, see ARM
profiler on page 8-6 in the ARM Software Development Toolkit Reference Guide.
The file profiler.c contains code to implement the profiling options in the debugger.
It does so by providing an UnkRDIInfoHandler that handles the profiling requests
from the debugger. In addition to profiling program execution time, it allows you to use
the profiling mechanism to profile events, such as cache misses.
By default, this is empty. If uncommented, the example shown allows profiling of cache
misses.
The Type entry controls how the profiling interval is interpreted. (The profiling interval
n is set using the armsd command profon n, or from ADW, using the Debugger tab
of the Debugger Configuration dialog, as shown in Debugger on page 3-53.):
Type=Microsecond
the default is that samples are taken every microsecond.
Type=Instruction
samples are taken every n instructions, where n is set using the
armsd command profon n. For example, profon 2. Setting
this value in the GUI is described in Debugger on page 3-53.
12-12 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARMulator
The WindowsHourglass section in the configuration file controls how regularly this
occurs. Increasing this rate decreases the regularity at which control is yielded to ADW
or ADU. This increases emulation speed but decreases responsiveness.
{ WindowsHourglass
;; We can control how regularly we callback the frontend
;; More often (lower value) means a slower emulator, but
;; faster response. The default is 8192.
Rate=8192
}
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 12-13
ARMulator
12.6 Watchpoints
The Watchpoints module is a memory veneer that provides memory watchpoints. It sits
between the processor core and memory (or cache, as appropriate).
12-14 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARMulator
The Pagetables section in the configuration file controls the contents of the
pagetables, and the configuration of the MMU:
{ Pagetables
For full details of the flags, control register and pagetables described in this section, see
the ARM Architectural Reference Manual.
Some flags only apply to certain processors. For example, BranchPredict only
applies to the ARM810, and ICache to the SA-110 and ARM940T processors.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 12-15
ARMulator
Finally, the configuration file can contain an outline of the pagetable contents. The
module writes out a top-level pagetable (to the address specified for the Translation
Table Base Register) whenever ARMulator resets on MMU-based processors.
VirtualBase is the virtual address of the base of this region. This address should
be aligned to a 1MB boundary on an MMU processor.
PhysicalBase is the address that the base of the region maps to. PhysicalBase
defaults to the same as VirtualBase if it is unset. This address
should be aligned to a 1MB boundary on an MMU processor.
Size specifies the size of this region for an MMU. This value is rounded
down to the nearest megabyte on an MMU processor.
Cacheable controls the C bit in the translation table entry.
Updateable controls the U bit in the translation table entry. (Note that the U bit
is only used for the ARM610 processor.)
Domain specifies the domain field of the table entry.
AccessPermissions
controls the AP field.
Translate controls whether accesses to this region causes translation faults.
Setting Translate=No for a region causes an abort to occur
whenever ARMulator reads from or writes to that region.
12-16 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARMulator
Core models such as the ARM740T and the ARM940T do not have an MMU and
pagetables. Instead, they have a Protection Unit and protection regions.
If you use the PageTable model on a core that has a Protection Unit (PU), instead of
initializing the MMU and setting up pagetables, the PU is initialized. With the above
example, the default set-up initializes the first region (that has the lowest priority) such
that the entire memory space (0 to 4GB) is marked as read/write, cacheable and
bufferable.
• The M, C and W bits are set in the control register (CP15 register 1), to enable the
Protection Unit, the Cache and the Write Buffer.
• Finally, the Memory area definition register for region 0 is initialized to 0x3F,
marking the size of region 0 as 4GB and as enabled.
• The P, D and I bits are set in the control register (CP15 register 1), to enable the
Protection Unit, the data cache and the instruction cache.
• The cacheable registers are initialized to 1, marking region 0 as cacheable for the
I and D caches (CP15 register 2). This is displayed as 0x010, where:
• the low byte (bits 0..7) represent the dcache cacheable register
• the high byte (bits 8..15) represent the icache cacheable register.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 12-17
ARMulator
• The programming lockdown registers are both initialized to zero. (CP15 Register
9). The first register value shown is for data lockdown control, the second for
instruction lockdown control.
• CP15 Register 15, the Test/Debug register, is initialized to zero. Only bits 2 and
3 have any effect in ARMulator. These control whether the cache replacement
algorithm is random or round robin.
12-18 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARMulator
12.8 armflat
ARMflat (armflat.c) provides a memory model of a zero-wait state memory system.
The emulated memory size is not fixed, so host memory is allocated in chunks of 64KB
each time a new region of memory is accessed. The memory size is limited by the host
computer, but in theory all 4GB of the address space is available. ARMflat does not
generate aborts.
You select the ARMflat model by setting Default=Flat in the Memories section of
the armul.cnf file:
{ Memories
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 12-19
ARMulator
12.9 armfast
ARMfast (armfast.c) provides a flat memory model of 2MB of RAM. Emulation
using ARMfast is typically 17% faster than for ARMflat. This performance increase is
partly achieved by not counting cycles, so cycle counts in $statistics will be zero.
This model is intended for use by software developers who want maximum emulation
speed, and are not interested in cycle counts or execution time.
The memory size is limited to 2MB. You can change this by editing armfast.c and
rebuilding ARMulator, as described in Rebuilding the ARMulator on page 12-32.
{ Memories
12-20 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARMulator
12.10 armmap
ARMmap (armmap.c) provides a memory model of a user-configurable memory
system. You can specify the size, access width, access type and access speeds of
individual memory blocks in the memory system in a memory map file.
ARMmap may generate aborts if you specify a memory region with access type as -.
You must specify an emulated clock frequency when using this memory model, or the
number of wait states for each memory region cannot be calculated. To configure the
clock frequency:
• Under the ARM GUI debuggers, select the Configure debugger option from the
Options menu. In the debugger configuration dialog, click on Configure to
display the ARMulator configuration dialog. This contains a Clock Speed box
that you can edit to the required frequency.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 12-21
ARMulator
The number of wait-states inserted is the least number required to take the total access
time over the number of nanoseconds specified in the memory map file. For example,
with a clock speed of 33MHz (a period of 30ns), an access specified to take 70ns in a
memory map file results in two wait-states being inserted, to lengthen the access to
90ns.
This can lead to inefficiencies in your design. For example, if the access time were
60ns—only 14% faster—ARMmap would insert only one wait-state—33% quicker.
A mismatch between processor clock-speed and memory map file can sometimes lead
to faster processor speeds having worse performance. For example, a 100MHz
processor (10ns period) will take 5 wait-states to access 60ns memory—total access
time, 60ns. At 110MHz, ARMmap must insert 6 wait-states—total access time, 63ns.
So the 100MHz-processor system is faster than the 110MHz processor, if connected to
60ns memory. (This does not apply to cached processors, where the 110MHz processor
would be faster.)
You can configure ARMmap to model several memory managers, by editing its entry in
the armul.cnf file:
{ MapFile
;; Options for the mapfile memory model
CountWaitStates=True
AMBABusCounts=False
SpotISCycles=True
ISTiming=Early
}
Counting wait-states
You can configure ARMmap to insert an extra decode cycle for every non-sequential
access from the processor. This models the decode cycle seen on AMBA bus systems.
12-22 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARMulator
ARMmap can optimize merged I-S cycles using one of three strategies:
Early This starts the decode when the ARM declares that the next cycle is going
to be an S-cycle; that is, half-way through the I-cycle. This can result in
one fewer wait-state. (Whether or not there are fewer wait-states depends
on the cycle time and the non-sequential access time for that region of
memory.)
This is the default setting. You can change this by setting
ISTiming=Spec or ISTiming=Late in armul.cnf.
Late This does not start the decode until the S-cycle.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 12-23
ARMulator
Reads from r0 return a dummy ARM ID register value, that can be configured.
Writes to r1 of the dummy coprocessor (the system configuration register) set the
bigend, lateabt and other signals.
You can set the code of the DummyMMU in the configuration file. Use the following
entry in the Coprocessors section of armul.cnf:
{ Coprocessors
#if COPROCESSOR_DummyMMU
;; By default, install a dummy MMU on co-processor 15.
CoProcessor[15]=DummyMMU
The line:
;DummyMMU:ChipID=
can be uncommented and set to any value. For example, to configure DummyMMU to
return the ARM710 ID code (0x44007100), change this line to:
; Here is the configuration for the co-processors.
;; The Dummy MMU can be configured to return a given Chip ID
DummyMMU:ChipID=0x44007100
#endif
12-24 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARMulator
12.12 Angel
The Angel model (angel.c) is an operating system model that allows code that has
been built to run with the Angel Debug Monitor, to run under ARMulator.
The model intercepts Angel SWIs and emulates the functionality of Angel directly on
the host, transparently to the program running under ARMulator.
The configuration for the Angel model exists in a section called OS in the armul.cnf
file. This appears as:
{ OS
;; Angel configuration
[ ...]
}
AngelSWIARM and AngelSWIThumb declare the SWI numbers that Angel uses. For
descriptions, see Chapter 13 Angel in the ARM Software Development Toolkit User
Guide.
Heapbase=0x40000000
HeapLimit=0x70000000
Stackbase=0x80000000
StackLimit=0x70000000
where:
HeapBase/HeapLimit
defines the application heap.
StackBase/StackLimit
defines the application stack.
The Angel model automatically detects at runtime whether a model uses Angel or
Demon SWIs.
The following options define the initial locations of the exception mode stack pointers.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 12-25
ARMulator
AddrSuperStack=0xa00
AddrAbortStack=0x800
AddrUndefStack=0x700
AddrIRQStack=0x500
AddrFIQStack=0x400
The next option is the default location of the user mode stack, and the default value
returned by SWI_SYSHEAPINFO, that returns the top of the memory application. A
different value may be returned if a memory model calls ARMul_SetMemSize, for
example:
AddrUserStack=0x80000
These options define the location in memory where the ARMulator places the code to
handle the hardware exception vectors:
AddrSoftVectors=0xa40
AddrsOfHandlers=0xad0
SoftVectorCode=0xb80
The final option points to a buffer where the Angel model places a copy of the command
line. This can be retrieved be by catching the RDI_Info call, RDISet_Cmdline:
AddrCmdLine=0xf00
In addition to the standard Angel SWIs, the ARMulator uses a set of SWIs for default
exception vector handlers. These are known as the soft vector SWIs. The soft vector
code is installed by the Angel model.
SWIs 0x90 – 0x98 are used to implement $vector_catch; that is, they return
control to the debugger if the user has set $vector_catch for the
relevant exception vector. SWI 0x90 is used for the reset vector;
0x91 for the undefined instruction vector, and so on.
SWIs 0x80 – 0x88 are used to stop the ARMulator if the exception cannot be
handled. The 0x80 SWIs are used as a final stop if the exception
is not caught by such an exception handler.
Note
These SWIs are for internal use by the ARMulator only.
12-26 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARMulator
Other information is sent over the RDI. Models can intercept the UnkRDIInfoUpcall
to receive this data. Some of the sample models do this, for example:
Note
It is not possible to add further control of the ARMulator from the debugger by, for
example, the addition of extra commands or pseudo-variables.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 12-27
ARMulator
The armul.cnf file contains the configuration for the ARMulator. It sets the options
for the various ARMulator components, for example, defining configurations for
different processors and caches. See Application Note 52, The ARMulator
Configuration File, ARM DAI 0052A for more information.
It is the responsibility of the memory model to translate map files. New models do not
understand the map file unless support is written in. Only one supplied model,
armmap.c, supports this.
To support the map data, a memory model has to intercept upcall UnkRDIInfoUpcall,
watching for:
RDIMemory_Map
The debugger makes this call to pass the data parsed from the
armsd.map file.
• arg1 points to an array of RDI_MemDescr structures.
• arg2 gives the number of elements in the array.
RDIMemory_Map can be called many times during initialization.
RDIInfo_Memory_Stats
The model should return RDIError_NoError to indicate that memory
maps are supported.
RDIMemory_Access
The debugger makes this call to obtain access statistics (see
$memory_statistics or the equivalent in the ARM GUI Debuggers).
12-28 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARMulator
This example deals with example.c, a device in which memory is split into two
128KB pages:
• the bottom page is read-only.
• the top page has one of eight 128KB memory pages mapped into it, page 0 being
the low page.
Addresses wrap around above 256KB for the first 1GB of memory, as if bits 29:18 of
the address bus were ignored. Bits 31:30 are statically decoded:
0 0 Memory access.
0 1 Bits 18:16 of the address select the physical page mapped in to the top
page.
1 1 Generates an abort.
This produces the memory map shown in Figure 12-1 on page 12-30.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 12-29
ARMulator
FFFFFFFF
Abort
C0000000
I/O port
80000000
Page select
40000000
Paged RAM
Read-only RAM
Paged RAM
Read-only RAM
00040000
Paged RAM
00020000
Read-only RAM
00000000
The I/O area, that is accessible only in privileged modes, is split as follows:
C0000000
Schedule_IRQ
B0000000
Schedule_FIQ
A0000000
Out channel
90000000
In channel
80000000
Figure 12-2 I/O area split
Schedule_IRQ An IRQ is raised after n cycles, where n is the bottom 8 bits of the
address.
Schedule_FIQ An FIQ is raised after n cycles, where n is the bottom 8 bits of the
address.
Out channel The character represented by the bottom 8 bits of the data is sent
to the screen for a write, and is ignored on read.
In channel A byte is read from the terminal for a read, or ignored for a write.
12-30 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARMulator
12.14.2 Implementation
There are eight banks of 128KB of RAM, one of which is currently mapped in to the
top page. The memory model has two pieces of state:
• an array representing the model of memory
• the number of the page currently mapped into the top page.
In this model, the ARM does not need to run in different endian modes. You can assume
that the ARM is configured to be the same endianness as the host architecture.
Note
If you want to allow the ARM to run in different endian modes, you must have a
ConfigChange callback, as in armflat.c.
However, you do occasionally need to ensure that a write is allowed only if the
nTRANS signal is HIGH, indicating that the processor is in a privileged mode. To
enable you to know this, you must install a callback for changes to nTRANS, because
it is not supplied to the memory access function. The core calls the callback whenever
nTRANS changes (on mode changes), and when executing an LDRT/STRT instruction.
For an example of implementation code, look at the rebuild kit file on UNIX in:
armsd/source/example.c
or on PC in:
C:\ARM250\Source\Win32\ARMulate\example.c
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 12-31
ARMulator
MEMORY(ExampleMemory)
You must also add the object file to the supplied Makefile, along with a rule for building
the model.
12-32 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
ARMulator
To rebuild the ARMulator, load armulate.mak into Microsoft Visual C++ Developer
Studio (version 4.0 or greater).
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 12-33
ARMulator
Follow these steps to edit the configuration file so that the ARMulator selects the sample
memory model:
1. Load the armul.cnf file into a text editor, and find the following lines
approximately halfway through the file:
;; List of memory models
{ Memories
Note
If a map file exists (or for ADW, if a map file is specified), the armmap memory
model is used.
12-34 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Chapter 13
Angel
This chapter describes the Angel debug monitor. It contains the following sections:
• About Angel on page 13-2
• Developing applications with Angel on page 13-10
• Angel in operation on page 13-27
• Porting Angel to new hardware on page 13-41
• Configuring Angel on page 13-67
• Angel communications architecture on page 13-71
• Angel C library support SWIs on page 13-77
• Angel debug agent interaction SWIs on page 13-92
• The Fusion IP stack for Angel on page 13-96.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 13-1
Angel
These activities require you to have some understanding of how Angel components
work together. The more technically challenging ones, such as porting operating
systems, require you to modify Angel itself.
A typical Angel system has two main components that communicate through a physical
link, such as a serial cable:
Debugger The debugger runs on the host computer. It gives instructions to Angel
and displays the results obtained from it. All ARM debuggers support
Angel, and you can use any other debugging tool that supports the
communications protocol used by Angel.
See Figure 13-1 on page 13-6 for an overview of a typical Angel system. The debugger
on the host machine sends requests to Angel on the target system. Angel interprets those
requests and performs an operation such as inserting an undefined instruction where a
breakpoint is required, or reading a portion of memory and sending back a response to
the host.
Angel uses a debugging protocol called the Angel Debug Protocol (ADP) to
communicate between the host system and the target system. ADP supports multiple
channels and provides an error-correcting communications protocol. Refer to the Angel
Debug Protocol specification in Arm250\PDF\specs for more information on ADP.
13-2 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Angel
In addition, full Angel source is provided so that you can port Angel to your own
ARM-based hardware.
ANSI C and C++ libraries that support Angel are supplied with the ARM Software
Development Toolkit. Refer to Chapter 4 The C and C++ Libraries in the ARM
Software Development Toolkit Reference Guide for more information.
These features are described below. See Figure 13-1 on page 13-6 for an overview of
the Angel components that provide this functionality.
Debug support
Angel uses a software interrupt (SWI) mechanism to enable applications linked with the
ARM C and C++ libraries to make semihosting requests. Semihosting requests are
requests such as open a file on the host, or get the debugger command-line, that must be
communicated to the host to be carried out. These requests are referred to as
semihosting because they rely on the C library of the host machine to carry out the
request.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 13-3
Angel
The ARM Software Development Toolkit provides prebuilt ANSI C libraries that you
can link with your application. The toolkit provides 26 prebuilt library variants that are
targeted to Angel. The libraries use the Angel SWI mechanism to request that specific
C library functions, such as input/output, are handled by the host system.
These libraries are used by default when you link code that calls ANSI C library
functions. Refer to Chapter 4 The C and C++ Libraries in the ARM Software
Development Toolkit Reference Guide for more information.
Angel uses a single SWI to request semihosting operations. By default, the SWI is
0x123456 in ARM state and 0xab in Thumb state. You can change this number if
required. Refer to Configuring Angel on page 13-67 for more information.
• In armsd set:
$semihosting_enabled = 0
• In ADW or ADU, select Debugger Internals from the View menu to view and
edit the variable. Refer to Chapter 3 ARM Debuggers for Windows and UNIX for
more information.
Refer to Angel C library support SWIs on page 13-77 for details of the Angel
semihosting SWIs.
Communications support
Angel communicates using ADP, and uses channels to allow multiple independent sets
of messages to share a single communications link. Angel provides an error-correcting
communications protocol over:
• Serial and serial/parallel connection from host to the target board, with Angel
resident on the board.
• Ethernet connection from the host to PID board, with Angel resident on the board.
This requires the Ethernet Upgrade Kit (No. KPI 0015A), available separately
from ARM Limited.
The host and target system channel managers ensure that logical channels are
multiplexed reliably. The device drivers detect and reject corrupted data packets. The
channel managers monitor the overall flow of data and store transmitted data in buffers,
in case retransmission is required. Refer to Angel communications architecture on page
13-71 for more information.
13-4 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Angel
The full Angel Device Driver Architecture uses Angel task management functionality
to control packet processing and to ensure that interrupts are not disabled for long
periods of time.
You can write device drivers to use alternative devices for debug communication, such
as a ROMulator. You can extend Angel to support different peripherals, or your
application can address devices directly.
Task management
All Angel operations, including communications and debug operations, are controlled
by Angel task management. Angel task management:
• ensures that only a single operation is carried out at any time
• assigns task priorities and schedules task accordingly
• controls the Angel environment processor mode.
Refer to Angel task management on page 13-31 for more information.
Exception handling
Angel exception handling provides the basis for each of the system features described
above. Angel installs exception handlers for each ARM exception type except Reset:
Undefined Angel uses three undefined instructions to set breakpoints in code. Refer
to Setting breakpoints on page 13-21 for more information.
FIQ, IRQ Angel installs IRQ and FIQ handlers that enable Angel communications
to run off either, or both types of interrupt. If you have a choice you
should use IRQ for Angel communications, and FIQ for your own
interrupt requirements.
You can chain your own exception handlers for your own purposes. Refer to Chaining
exception handlers on page 13-19 for more information.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 13-5
Angel
The main components of an Angel system are shown in Figure 13-1. The following
sections give a summary of the system components.
Debugger
Debugger toolbox
Channel manager
Device drivers
Target dependent
debug support C Library
13-6 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Angel
Debugger This is the ARM Debugger for Windows (ADW), the ARM Debugger for
UNIX (ADU), the ARM command-line debugger (armsd), or a third
party debugger that supports the Angel Debug Protocol.
Debugger toolbox
This provides an interface between the debugger and the Remote Debug
Interface (RDI).
ADP support
This translates between RDI calls from the debug controller and Angel
ADP messages.
Boot support
This establishes communication between the target and host systems. For
example, it sets baud rates and re-initializes Angel in the target.
C library support
This handles semihosting requests from the target C library.
Device drivers
These implement specific communications devices on the host. Each
driver provides the entry points required by the channel manager.
Device drivers
These implement specific communications devices on the development
boards. Each driver provides the entry points required by the channel
manager.
Channel manager
This handles the communication channels. It provides a streamed packet
interface that hides details of the device driver in use.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 13-7
Angel
Exceptions support
This handles all ARM exceptions.
C library support
C library support consists of the ARM ANSI C libraries supplied with the
SDT, and the semihosting support that is built into Angel to send requests
to the host when necessary.
User application
This is an application on the target system.
Where possible, Angel resource usage can be statically configured at compile and link
time. For example, the memory map, exception handlers, and interrupt priorities are all
fixed at compile and link time. Refer to Configuring Angel on page 13-67 for more
information.
The following sections describe the system and memory resources required by Angel.
System resources
Configurable resources
Angel requires the following for semihosting purposes:
• one ARM SWI
• one Thumb SWI.
13-8 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Angel
Non-configurable resources
For breakpoints, Angel requires:
• two ARM Undefined instructions
• one Thumb Undefined instruction.
Angel requires ROM or Flash memory to store the debug monitor code, and RAM to
store data. The amount of ROM, Flash, and RAM required varies depending on your
configuration.
• if you download a new version of Angel to Flash memory you will require enough
RAM to store the flash download program
Note
The loadagent command cannot write to Flash. If you use loadagent, Angel must
be compiled to run from RAM.
Exception vectors
Angel requires some control over the ARM exception vectors. Exception vectors are
initialized by Angel, and are not written to after initialization. This supports systems
with ROM at address 0, where the vectors cannot be overwritten.
Angel installs itself by initializing the vector table so that it takes control of the target
when an exception occurs. For example, debug communications from the host cause an
interrupt that halts the application and calls the appropriate code within Angel.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 13-9
Angel
Interrupts
Angel requires use of at least one interrupt to support communication between the host
and target systems. You can set up Angel to use:
• IRQ
• FIQ
• both IRQ and FIQ.
It is recommended that you use FIQ for your own interrupt requirements because Angel
has no fast interrupt requirements. Refer to devconf.h on page 13-58 for more
information.
Stacks
Angel requires control over its own Supervisor stack. If you want to make Angel calls
from your application you must set up your own stacks. Refer to Developing an
application under full Angel on page 13-16 for more information.
Angel also requires that the current stack pointer points to a few words of usable full
descending stack whenever an exception is possible, because the Angel exception return
code uses the application stack to return.
Full Angel is a stand-alone system that resides on the target board and is always active.
Full Angel is used during the development of the application code. It supports all
debugger functions and you can use it to:
• download your application image from a host
• debug your application code
• develop the application before converting to stand-alone code.
13-10 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Angel
Prebuilt images
Full Angel is supplied as prebuilt images for the ARM PID board with
SDT 2.50. These are located in:
angel.rom This is a ROM image of full Angel. You can use this
image in place of the Angel in your target board
ROM if your board contains an older version. In
addition, if you are porting Angel to your own
hardware this image provides you with a working
default to test against.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 13-11
Angel
You can use minimal Angel in the final stages of development, and on your production
hardware.
Minimal Angel does not support features that are provided by full Angel, such as:
• debugging over ADP
• semihosting
• multiple channels on one device
• task management.
Minimal Angel is supplied in the following forms:
Prebuilt libraries
There are separate big-endian and little-endian minimal Angel libraries:
• Angel\Images\pid\big\angmin.lib
• Angel\Images\pid\little\angmin.lib.
13-12 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Angel
Figure 13-2 shows an example of this development procedure. The stages of the
development procedure are described in more detail below.
Application under
ARMulator or on an
evaluation board
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 13-13
Angel
If you want to evaluate the ARM to ensure that it is appropriate for your application you
must have a program, or suite of programs to run on the ARM.
You can rebuild your programs using the ARM Software Development Toolkit, and link
them with an ARM C or C++ library.
ARMulator You can run your programs under the ARMulator, and evaluate cycle
counts to see if the performance is sufficient.
This method does not involve Angel, however you can use an
Angel-targeted ARM C or C++ library because the ARMulator supports
the Angel semihosting SWIs, so C library calls are handled by the host C
library support.
Evaluation board
Instead of testing programs under the ARMulator, you can use an ARM
evaluation board to evaluate performance. In this case you use Angel
running as a debug monitor on the ARM evaluation board. You do not
need to rebuild Angel, or to be familiar with the way Angel works.
You can build images that are linked with an Angel-targeted ARM C or
C++ library, and then download the images with an ARM debugger.
After evaluating your application you move to the development stage. At this stage, the
target board is either your own development board or an ARM development board:
13-14 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Angel
When you have chosen your development platform, you build a stand-alone application
that runs next to Angel on your target hardware. You must use one of the methods
described in Downloading new application versions on page 13-25 to download the
application to your development board.
At this stage you are highly reliant on Angel to debug your application. In addition you
must make design decisions about the final form of your application. In particular you
should decide whether the final application is stand alone, or uses minimal Angel to
provide initialization code, interrupt handlers, and device drivers. If you are porting
Angel to your own hardware you must also consider how you will debug your Angel
port. Refer to Debugging your Angel port on page 13-66 for more information.
If you are developing simple embedded applications, you might want to move straight
to building your application on a development board.
As you proceed with your development project and your code becomes more stable, you
will rely less on Angel for debugging and support. For example, you might want to use
your own initialization code, and you might not require C library semihosting support:
• You can switch off semihosting, without building a special cut-down version of
Angel, by setting the $semihosting_enabled variable in the ARM debuggers.
In armsd:
$semihosting_enabled = 0
In ADW or ADU select Debugger Internals from the View menu to view and
edit the variable. Refer to ARM Debuggers for Windows and UNIX on page 3-1
for more information.
• You can build an application that links with the minimal Angel library. This can
be blown into a ROM, soft-loaded into Flash by the ARM debuggers, or installed
using a ROM emulator, Multi-ICE, or EmbeddedICE.
Minimal Angel provides the same initialization code, raw device drivers, and
interrupt support as full Angel. Moving from full Angel to minimal Angel on your
development hardware is straightforward. See Developing an application under
minimal Angel on page 13-22 for a description of minimal Angel.
This is conceptually a step closer to the final product compared with using the
debugger to download an image. You can choose either to keep minimal Angel in
your production system, or remove it for final production.
If you need to debug a minimal Angel application and your hardware supports
JTAG you can use EmbeddedICE or Multi-ICE. These do not require any
resource on the target.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 13-15
Angel
When you are ready to move the application onto final production hardware, you have
a different set of requirements. For example:
• Interrupt handlers for timers might be required in the final product, but debug
support code is not.
At this stage it is not desirable to include any parts of Angel that are not required in the
final product. You can choose to remove Angel functionality completely, or you can
continue to link your application with a minimal Angel library to provide initialization,
raw device, and exception support.
This section gives useful information on how to develop applications under Angel,
including:
• Planning your development project on page 13-16
• Programming restrictions on page 13-17
• Using Angel with an RTOS on page 13-18
• Using Supervisor mode on page 13-19
• Chaining exception handlers on page 13-19
• Linking Angel C library functions on page 13-20
• Using assertions when debugging on page 13-21
• Setting breakpoints on page 13-21
• Changing from little-endian to big-endian Angel on page 13-21.
Before you begin your development project you must make basic decisions about such
things as:
• the APCS variant to be used for your project
• whether or not ARM/Thumb interworking is required
• the endianness of your target system.
Refer to the appropriate chapters of the ARM Software Development Toolkit Reference
Guide and this book for more information on interworking ARM and Thumb code, and
specifying APCS options.
13-16 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Angel
• Whether you are to move to a production system that includes minimal Angel, or
a stand-alone system. If you are not using minimal Angel you must write your
own initialization and exception handling code.
• Whether or not you require C library support in your final application. You must
decide how you will implement C library support if it is required, because the
Angel semihosting SWI mechanism will not be available. Refer to Linking Angel
C library functions on page 13-20 for more information.
• Whether or not debug information is included. You should be aware of the size
overhead when using debuggable images as production code.
• Communications requirements. You must write your own device drivers for your
production hardware.
• Memory requirements. You must ensure that your hardware has sufficient
memory to hold both Angel and your program images.
Programming restrictions
• Angel requires control of its own Supervisor stack. If you are using an RTOS you
must ensure that it does not change processor state while Angel is running. Refer
to Using Angel with an RTOS on page 13-18 for more information.
• You should avoid using SWI 0x123456 or SWI 0xab. These SWIs are used by
Angel to support C library semihosting requests. Refer to Configuring SWI
numbers on page 13-70 for information on changing the default Angel SWI
numbers.
• If you are using SWIs in your application, and using EmbeddedICE or Multi-ICE
for debugging, you should usually set a break point on the SWI handler routine,
where you know it is an Angel SWI, rather than at the SWI vector itself.
• If you are using SWIs in your application you must restore registers to the state
that they were when you entered the SWI.
• If you want to use the Undefined instruction exception for any reason you must
remember that Angel uses this to set breakpoints.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 13-17
Angel
From the application perspective Angel is single threaded, modified by the ability to use
interrupts provided the interrupt is not context switching. External functions must not
change processor modes through interrupts. This means that running Angel and an
RTOS together is difficult, and is not recommended unless you are prepared for a
significant amount of development effort.
If you are using an RTOS you will have difficulties with contention between the RTOS
and Angel when handling interrupts. Angel requires control over its own stacks, task
scheduling, and the processor mode when processing an IRQ or FIQ.
An RTOS task scheduler must not perform context switches while Angel is running.
Context switches should be disabled until Angel has finished processing.
then the ISR switches the Angel context, not the RTOS context. That is, the ISR puts
values in processor registers that relate to the application, not to Angel, and it is very
likely that Angel will crash.
• Detect ISR calls that occur when Angel is active, and do not task switch. The ISR
can run, provided the registers for the other mode are not touched. For example,
timers can be updated.
• Disable either IRQ or FIQ interrupts, whichever Angel is not using, while Angel
is active. This is not easy to do.
In summary, the normal process for handling an IRQ under an RTOS is:
5. Exit by way of the RTOS to switch tasks if a higher priority task is ready to run.
13-18 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Angel
If you want your application to execute in Supervisor mode at any time, you must set
up your own Supervisor stack. If you call an Angel SWI while in Supervisor mode,
Angel uses four words of your Supervisor stack when entering the SWI. After entering
the SWI Angel uses its own Supervisor stack, not yours.
This means that, if you set up your own Supervisor mode stack and call an Angel SWI,
the Supervisor stack pointer register (sp_SVC) must point to four words of a full
descending stack in order to provide sufficient stack space for Angel to enter the SWI.
Angel provides exception handlers for the Undefined, SWI, IRQ/FIQ, Data Abort, and
Prefetch Abort exceptions. If you are working with exceptions you must ensure that any
exception handler that you add is chained correctly with the Angel exception handlers.
Refer to Chapter 9 Handling Processor Exceptions for more information.
If you are chaining an interrupt handler and you know that the next handler in the chain
is the Angel interrupt handler, you can use the Angel interrupt table rather than the
processor vector table. You do not have to modify the processor vector table. The Angel
interrupt table is easier to manipulate because it contains the 32-bit address of the
handler. The processor vector table is limited to 24-bit addresses.
Note
If your application chains exception handlers, Angel must be reset with a hardware reset
if the application is killed. This ensures that the vectors are set up correctly when the
application is restarted.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 13-19
Angel
The consequences of not passing an exception on to Angel from your exception handler
depend on the type of exception, as follows:
Undefined You will not be able to single step or set breakpoints from the debugger.
SWI If you do not implement the EnterSVC SWI, Angel will not work. If you
do not implement any of the other SWIs you will not be able to use
semihosting.
Prefetch abort
The exception will not be trapped in the debugger.
Data abort The exception will not be trapped in the debugger. If a Data abort occurs
during a debugger-originated memory read or write, the operation might
not proceed correctly, depending on the action of the handler.
IRQ This depends on how Angel is configured. Angel will not work if it is
configured to use IRQ as its interrupt source.
FIQ This depends on how Angel is configured. Angel will not work if it is
configured to use FIQ as its interrupt source.
The C libraries provided with the ARM Software Development Toolkit use Angel SWIs
to implement semihosting requests. You have a number of options for using ARM C
library functionality:
• Use the ARM C library for early prototyping only and replace it with your own C
library targeted at your hardware and operating system environment.
• Support Angel SWIs in your own application or operating system and use the
ARM C libraries as provided.
• Port the ARM C library to your own environment. The ARM C libraries are
supplied as full source code so that you can retarget them to your own system.
Refer to Retargeting the ANSI C library on page 4-6 of the ARM Software
Development Toolkit Reference Guide for more information.
• Use the embedded C library with your own startup code. The embedded C library
does not rely on underlying Angel or operating system functionality. Refer to The
embedded C library on page 4-19 of the ARM Software Development Toolkit
Reference Guide for more information.
13-20 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Angel
To speed up debugging, Angel includes runtime assertion code that checks that the state
of Angel is as expected. The Angel code defines the ASSERT_ENABLED option to enable
and disable assertions.
If you use assertions in your code you should wrap them in the protection of
ASSERT_ENABLED macros so that you can disable them in the final version if required.
#if ASSERT_ENABLED
...
#endif
Angel uses such assertions wherever possible. For example, assertions are made when
it is assumed that a stack is empty, or that there are no items in a queue. You should use
assertions whenever possible when writing device drivers. The ASSERT macro is
available if the code is a simple condition check (variable = value).
Setting breakpoints
Angel can set breakpoints in RAM only. You cannot set breakpoints in ROM or Flash.
In addition, you must be careful when using single step or breakpoints on the UNDEF,
IRQ, FIQ, or SWI vectors. Do not single step or set breakpoints on interrupt service
routines on the code path used to enter or exit Angel.
You can use the Flash download program to change from a little-endian version of
Angel on the ARM PID board to a big-endian version. However, because of an
incompatibility between the way big-endian and little-endian code is stored in 16-bit
wide devices, this works only if the target device is an 8-bit Flash device:
1. Make sure you are using the 8-bit Flash device (U12).
3. Run the Flash download program and program the Flash with the big-endian
Angel image. This works because Angel operates out of SRAM.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 13-21
Angel
7. Power up the board and connect the debugger. Make sure that the debugger is
configured for big-endian operation.
When you have a big-endian Angel in Flash, you can use a big-endian version of the
Flash downloader to program a new copy of Angel into the 16-bit device. To do this:
3. Insert the SEL8BIT link (LK6-4) so that the target device is now the 16-bit Flash
chip.
You must provide a 16-bit wide Flash device, because one is not supplied with the
board.
Refer to The Flash downloader on page 8-15 of the ARM Software Development Toolkit
Reference Guide for more information on using the Flash download utility.
Note
There is no performance gain from using a 16-bit wide device in this case, because
Angel copies itself to SRAM and executes from there.
The minimal Angel library is intended to support the later stages of debugging. It does
not include full Angel features such as:
• debugging and packet organization through ADP
• reliable communications through ADP
• channels support
• semihosted C library support
• an Undefined exception handler
• the task serializer.
Minimal Angel is not suitable for use when you are in the development stage of your
project.
The minimal Angel library contains almost the same initialization code, interrupt
handling, and exception handling as full Angel. The device driver architecture is the
same, and any Angel device driver that can be compiled as a raw device is fully
supported.
13-22 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Angel
The minimal library contains sufficient components to allow it to replace a full Angel
system. The main difference is that an image containing an application and the minimal
library initializes, and then immediately enters the application at the __entry symbol.
The minimal library is approximately one third to one fifth the size of full Angel. The
actual size depends on the device drivers that are included, and on compile-time
debugging and assertion options.
Separate build directories, makefiles, and APM project files are provided for minimal
Angel.
The build directories for the PID Angel port are in:
angel/source/pid.min
There are separate subdirectories for Solaris, HPUX, and APM builds.
Within the Angel source code, minimal Angel build specifics are controlled by the
MINIMAL_ANGEL macro. This is set to 0 for full Angel and to 1 for minimal Angel.
Full Angel requires use of at least one device driver for its own communications
requirements. If you are using Angel on a board with more than one serial port, such as
the PID board, you can either:
• use Angel on one serial port and your own device on the other
• use minimal Angel, which requires no serial port, and use either or both of the
serial ports for your application.
The PID Angel port provides examples of raw serial drivers. Refer to the Angel source
code for details of how these are implemented. If you want to use Angel with your own
hardware you must write your own device drivers. Refer to Writing the device drivers
on page 13-61 for more information.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 13-23
Angel
Device Interface
Device Interface
Packet
Angel
Angel
Minimal Angel
Application
Raw Device
Write Switcher
(serraw.c)
Byte
Serial
Devices Packet Packet I/F
Write Send layer
Dev (serpkt.c)
Tx
Devclnt.c
Ring buffer Device
Raw Channels
Read Switcher layer
HARDWARE
Dev Reliable
Rx Packet Packet
Read Read Packets
unreliable, channel reliable,
Ring buffer unordered, ordered,
simplex multiple
Devclnt.c streams streams
Dev uses Rx/Tx
Ctrl code
Dev RW
ISR Poll
either
...or
Angel Poll Device Call
Angel
ISR Handler
You can use cin and cout in armsd and the channel viewer interface to access the TDCC
from the host. You can use the TDCC channel to send ARM DCC instructions to the
processor. No other extra channels are supported.
13-24 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Angel
There are a number of techniques you can use to move successive versions of your
application onto a development board. Each technique has advantages and
disadvantages:
Flash download
This provides slow to fast downloading, depending on the type of
connection you are using.
This method is only available on boards that have Flash memory and are
supported by the Flash download program. It has the advantage that, after
the Flash is set, the image is fixed in memory, even if the board is
switched off.
You can also download application-only images using this method, but
you cannot then use Angel.
Refer to your development board documentation for more information on
downloading to Flash.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 13-25
Angel
If you use one of the ROM replacement methods then you must change from building
application images to building ROM images as soon as the development phase starts.
If you use a simple download method then the transition to the development phase is
easier because you can move to building ROM images when everything else is working
and you are preparing to move to production hardware.
Refer to The Flash downloader on page 8-15 of the ARM Software Development Toolkit
Reference Guide for information on using the Flash download utility.
Refer to The fromELF utility on page 8-3 of the ARM Software Development Toolkit
Reference Guide if you are using an EPROM programmer to program big-endian code
into 16-bit devices.
13-26 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Angel
13.3.1 Initialization
The initialization of the code environment and system is almost identical, whether the
code is to initialize the debugger only (full Angel) or to launch an application (minimal
Angel). The initialization sequence is as follows:
1. The processor is switched from the current privileged mode to Supervisor mode
with interrupts disabled. Angel checks for the presence of an MMU. If an MMU
is present it can be initialized after switching to Supervisor mode.
2. Angel sets the code execution and vector location, depending on the compilation
addresses generated by the values of ROADDR and RWADDR. Refer to Configuring
where Angel runs on page 13-68 for more information.
3. Code and data segments for Angel are copied to their execution addresses.
4. If the application is to be executed then the runtime system setup code and the
application itself are copied to their execution addresses. If the system has ROM
at address 0 and the code is to be run from ROM, only the Data and Zero
Initialization areas are copied.
5. The stack pointers are set up for each processor mode in which Angel operates.
Angel maintains control of its own stacks separately from any application stacks.
You can configure the location of Angel stacks. Refer to Configuring the memory
map on page 13-67 for more information.
7. The Angel serializer is set up. Refer to the Angel task management on page 13-31
for more information on the Angel serializer.
8. The processor is switched to User mode and program execution is passed to the
high level initialization code for the C library and Angel C functions.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 13-27
Angel
9. At this point, the initialization procedure is different for full Angel and minimal
Angel.
For minimal Angel:
a. The device drivers are set up for transmission of raw data only. The ADP
packet protocol and communications channels are not used.
b. The application entry point is called by a branch with link ( BL) instruction
to an __entry label. You must use this label as your application entry point
to ensure that the application is launched.
For full Angel:
After initialization, full Angel enters the idle loop and continually calls the device
polling function. This ensures that any polled communications device is serviced
regularly. When input is detected, it is placed into a buffer and decoded into packet form
to determine which operation has been requested. If an acknowledgment or reply is
required, it is constructed in an output buffer ready for transmission.
All Angel operations are controlled by Angel task management. Refer to Angel task
management on page 13-31 and Example of Angel processing: a simple IRQ on page
13-38 for more information on Angel task management.
13-28 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Angel
This section gives a summary of how Angel performs the basic debugger functions:
• reporting memory and processor status
• downloading a program image
• setting breakpoints.
Angel reports the contents of memory and the processor registers as follows:
Memory The memory address being examined is passed to a function that copies
the memory as a byte stream to the transmit buffer. The data is transmitted
to the host as an ADP packet.
Registers Processor registers are saved into a data block when Angel takes control
of the target (usually at an exception entry point). When processor status
is requested, a subset of the data block is placed in an ADP packet and
transmitted to the host.
When Angel receives a request to change the contents of a register, it
changes the value in the data block. The data block is stored back to the
processor registers when Angel releases control of the target and
execution returns to the target application.
Download
When downloading a program image to your board, the debugger sends a sequence of
ADP memory write messages to Angel. Angel writes the image to the specified memory
location.
Memory write messages are special because they can be longer than other ADP
messages. If you are porting Angel to your own hardware your device driver must be
able to handle messages that are longer than 256 bytes. The actual length of memory
write messages is determined by your Angel port. Message length is defined in
devconf.h with:
#define BUFFERLONGSIZE
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 13-29
Angel
Setting breakpoints
Angel uses three undefined instructions to set breakpoints. The instruction used
depends on:
• the endianness of the target system
• the processor state (ARM or Thumb).
Note
These are not the same as the breakpoint instructions used by Multi-ICE or
EmbeddedICE.
These instructions are used for normal, user interrupt, and vector hit breakpoints. In all
cases, no arguments are passed in registers. The breakpoint address itself is where the
breakpoint occurs.
Note
Angel can set breakpoints only on RAM locations.
2. If the instruction is the predefined breakpoint word for the current processor state
and endianness, Angel:
13-30 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Angel
ARM breakpoints are detected in Thumb state. When an ARM breakpoint is executed
in Thumb state, the undefined instruction vector is taken whether executing the
instruction in the top or bottom half of the word. In both cases these correspond to a
Thumb undefined instruction and result in a branch to the Thumb undefined instruction
handler.
Note
Thumb breakpoints are not detected in ARM state.
All Angel operations are controlled by Angel task management. Angel task
management:
• assigns task priorities and schedules tasks accordingly
• controls the Angel environment processor mode.
Angel task management requires control of the processor mode. This can impose
restrictions on using Angel with an RTOS. Refer to Using Angel with an RTOS on page
13-18 for more information.
Task priorities
Angel assigns task priorities to tasks under its control. Angel ensures that its tasks have
priority over any application task. Angel takes control of the execution environment by
installing exception handlers at system initialization. The exception handlers enable
Angel to check for commands from the debugger and process application semihosting
requests.
Angel will not function correctly if your application or RTOS interferes with the
execution of the interrupt, SWI or Data Abort exception handlers. Refer to Chaining
exception handlers on page 13-19 for more information.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 13-31
Angel
When an exception occurs, Angel either processes it completely as part of the exception
handler processing, or calls Angel_SerialiseTask() to schedule a task. For
example:
• When an Angel SWI occurs, Angel determines whether the SWI is a simple SWI
that can be processed immediately, such as the EnterSVC SWI, or a complex SWI
that requires access to the host communication system, and therefore to the
serializer. Refer to Angel C library support SWIs on page 13-77 for more
information.
• When an IRQ occurs, the Angel PID port determines whether or not the IRQ
signals the receipt of a complete ADP packet. If it does, Angel task management
is called to control the packet decode operation. Refer to Example of Angel
processing: a simple IRQ on page 13-38 for more information. Other Angel ports
can make other choices for IRQ processing, provided the relevant task is
eventually run.
The task management code maintains two values that relate to priority:
Task type The task type indicates type of task being performed. For
example, the application task is of type TP_Application, and
Angel tasks are usually TP_AngelCallback. The task type
labels a task for the lifetime of the task.
Task priority The task priority is initially derived from the task type, but
thereafter it is independent. Actual priority is indicated in two
ways:
• in the value of a variable in the task structure
• in the relative position of the task structure in the task queue.
The task priority of the application task changes when an
application SWI is processed, to ensure correct interleaving of
processing.
Table 13-1 shows the relative task priorities used by Angel.
13-32 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Angel
Lowest IdleLoop
Some of these functions call other Angel functions not documented here. The functions
are described in brief below. For full implementation details, refer to the source code in
serlock.h, serlock.c, and serlasm.s.
Angel_SerialiseTask
In most cases this function is the entrance function to Angel task management. The only
tasks that are not a result of a call to Angel_SerialiseTask() are the boot task, the
idle task, and the application. These are all created at startup. When an exception occurs,
Angel_SerialiseTask() cleans up the exception handler context and calls
Angel_NewTask() to create a new high priority task. It must be entered in a privileged
mode.
Angel_NewTask
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 13-33
Angel
Angel_QueueCallback
This function:
• queues a callback
• specifies the priority of the callback
• specifies up to four arguments to the callback.
The callback executes when all tasks of a higher priority have completed. Table 13-1 on
page 13-32 shows relative task priorities.
Angel_BlockApplication
This function is called to allow or disallow execution of the application task. The
application task remains queued, but is not executed. If Angel is processing an
application SWI when Angel_BlockApplication() is called, the block might be
delayed until just before the SWI returns.
Angel_NextTask
Angel_Yield
13-34 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Angel
Angel_Wait
AngelWait() is called with an event mask. The event mask denotes events that will
result in the task continuing execution. If more than one bit is set, any one of the events
corresponding to those bits will unblock the task. The task remains blocked until some
other task calls Angel_Signal() with one or more of the event mask bits set. The
meaning of the event mask must be agreed beforehand by the routines.
Angel_Signal
• If the task is blocked, Angel_Signal() assumes that the task is waiting and
subtracts the new signals from the signals the task was waiting for. The task is
unblocked if the event corresponds to any of the event bits defined when the task
called Angel_Wait().
• If the task is running, Angel_Signal() assumes that the task will call
Angel_Wait() at some time in the future. The signals are marked in the task
signalWaiting member.
Angel_Signal() takes a task ID that identifies a current task, and signals the task that
the event has occurred. See the description of Angel_Wait() for more information on
event bits. The task ID for the calling task is returned by the Angel_TaskID() macro.
The task must write its task ID to a shared memory location if an external task is to
signal it.
Angel_TaskID
This macro returns the task ID (a small integer) of the task that calls it. There is no way
to obtain the ID of another task unless the other task writes its task ID to a shared
memory location.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 13-35
Angel
Angel maintains context blocks for each task under its control through the life of the
task, and saves the value of all current processor registers when a task switch occurs. It
uses two groups of register context save areas:
• The Angel global register blocks. These are used to store the CPU registers for a
task when events such as interrupt and task deschedule events occur.
• An array of available Task Queue Items (TQI). Each allocated TQI contains the
information Angel requires to correctly schedule a task, and to store the CPU
registers for a task when required.
The Angel global register blocks are used by all the exception handlers and the special
functions Angel_Yield() and Angel_Wait(). Register blocks are defined as an
array of seven elements. Table 13-2 shows the global register blocks.
RB_SWI This is saved on entry to a complex SWI and restored on return to the
application.
RB_Fatal This is used only in a debug build of Angel. It saves the context in
which a fatal error occurred.
In the case of RB_SWI and RB_Interrupted, the register blocks contain the previous
task register context so that the interrupt can be handled. If the handler function calls
Angel_SerialiseTask(), the global register context is saved into the current task
TQI.
In the case of RB_Yield, the register block is used to store temporarily the context of
the calling task, prior to entering the serializer. The serializer saves the contents of
RB_Yield to the TQI entry for the current task, if required.
13-36 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Angel
The serializer maintains a task queue by linking together the elements of the
angel_TQ_Pool array. The task queue must contain an idle task entry. Each element
of the array is a Task Queue Item (TQI). A TQI contains task information such as:
• the register context for the task
• the current priority of the task
• the type of the task (for example, TP_Application)
• the task state (for example, TS_Blocked)
• the initial stack value for the task
• a pointer to the next lower-priority task.
The elements in the angel_TQ_Pool array are managed by routines within the
serializer and must not be modified externally.
Angel calls Angel_NewTask() to create new tasks. This function initializes a free TQI
with the values required to run the task. When the task is selected for execution,
Angel_SelectNextTask() loads the register context into the CPU. The context is
restored to the same TQI when:
When the debugger requests information about the state of the application registers, the
Angel debug agent retrieves the register values from the TQI for the application. The
application TQI is updated from the appropriate global register block when exceptions
cause Angel code to be run.
The application uses its own stack, and executes in either User or Supervisor mode.
Callbacks due to application requests to read or write from devices under control of the
Device Driver Architecture execute in User mode, and use the application stack.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 13-37
Angel
The following Angel stacks are simple stacks exclusively used by one thread of control.
This is ensured by disabling interrupts in the corresponding processor modes:
• IRQ stack
• FIQ stack
• UND stack
• ABT stack.
The User mode stack is also split into two cases, because the Application stack and
Angel stack are kept entirely separate. The Angel User mode stack is split into array
elements that are allocated to new tasks, as required. The application stack must be
defined by the application.
This section gives an example of processing a simple IRQ from start to finish, and
describes in more detail how Angel task management affects the receipt of data through
interrupts. Refer also to Angel communications architecture on page 13-71 for an
overview of Angel communications.
Figure 13-4 on page 13-39 shows the application running, when an interrupt request
(IRQ) is made that completes the reception of a packet.
13-38 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Angel
Appl IRQ 1
Angel ISR 2
Angel yes
Interrupt? Dev ISR
no
3
Complete yes
Request? Serialize Task New task yes
highest
priority?
Rx_Proc 6
4 no
no
Angel Return Save Content 5
no
Another task EDP?
Create new
task
yes
Select Next
Queue
callback 7
End Rx_Proc
8
Callback yes Data specific
next? callback Next task
no
Select
Another task Next Task
Appl
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 13-39
Angel
2. The Angel ISR saves the processor state in a register block, uses the GETSOURCE
macro to determine the interrupt source, and jumps to the handler. The processor
state is saved because this data is required by Angel_SerialiseTask().
3. The interrupt handler determines the cause of the IRQ. If the interrupt is not an
Angel interrupt it returns immediately.
If the interrupt is an Angel interrupt and the driver uses polled input, the handler
calls Angel_SerialiseTask() to schedule processing. If the driver does not
use polled input, the handler calls Angel_SerialiseTask() to schedule
processing if:
• the end of packet character is reached
• the end of request is reached for a raw device (determined by length)
• the ring buffer is empty (tx), or full (rx).
6. The new task executes in Supervisor mode. It reads the packet from the device
driver to create a proper ADP packet from the byte stream.
7. When the packet is complete, the task schedules a callback task to process the
newly arrived packet.
13-40 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Angel
Angel is designed to make porting to new hardware as easy as possible. However, there
are many configurable features of Angel and you must modify Angel code to support
your hardware.
In addition, there are Angel ports from other board manufacturers for their own
development boards. These are not distributed with the ARM Software Development
Toolkit.
You should select an existing version of Angel that has been ported to hardware that is
as similar as possible to your own. If you are not basing your Angel port on a port from
another board manufacturer it is recommended that you use the Angel PID port
provided with the ARM Software Development Toolkit. The most important hardware
features to consider when making this decision include:
Device drivers Writing device drivers is a large part of the porting process. If
possible, choose a version of Angel that supports the same, or very
similar communications hardware. This makes it simpler to
modify the device driver code.
Cache/MMU The PID and ARM evaluation boards do not have a cache or
MMU. If you are porting to hardware that is based on a third party
development board that includes a cache and MMU you should
consider using the Angel port from that manufacturer.
The following examples and recommendations refer to the Angel PID port, however, the
same general principles apply no matter which Angel port you select as a template.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 13-41
Angel
The Angel sources are distributed in a directory structure that separates the
target-dependent code, such as device drivers and board-specific setup code, from the
main generic code directory. There is a separate build directory for the specific build
information for each target. This directory contains the makefile or APM project file,
and is usually used as the output directory for object files and the final ROM image.
Figure 13-5 shows the directory structure for the Angel PID port.
Angel
Source
These steps are explained in more detail below, together with some recommendations
that might be useful when porting Angel to any new hardware.
13-42 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Angel
The first step in the porting process is to select a target template. If you are basing your
port on an ARM-supplied Angel port, it is recommended that you use the PID port as a
starting point.
The PID board is a complex system with a varied memory map comprising:
• SSRAM, SRAM, and DRAM
• ROM, and Flash memory
• two serial and one parallel communications channels
• two PC card slots.
There are also memory-mapped peripherals such as dual timers. The peripherals
conform to the ARM Reference Peripheral Specification. The system has a memory
remap facility.
After you have copied your template directory pair, you must set up the makefile or
APM project template to reflect your new directory structure. In addition you must set
a number of build options to suit your requirements.
Refer to Modifying the UNIX makefile on page 13-45 for information on modifying a
UNIX makefile or Modifying an APM project on page 13-49 for information on setting
up the ARM Project Manager project for your build.
When you have set up the makefile or APM project for your development directory
structure you should perform a trial build to ensure that the modifications are complete,
and that all necessary project build files have been copied correctly.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 13-43
Angel
The PID Angel port includes a number of target specific source files that you must
modify to support your hardware and environment. You should examine each of the
target specific files described in Modifying target-specific files on page 13-55.
Writing device drivers for your hardware is the major part of the porting procedure and
is completely target-dependent. Refer to Writing the device drivers on page 13-61 for
information on writing device drivers.
13-44 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Angel
Downloading Angel
After you have completed your Angel port you must download it to your hardware.
There are a number of methods you can use to do this. Refer to Downloading a new
version of Angel on page 13-65 for more information.
At various stages throughout the porting process you will need to debug your Angel
port. Only the initial stages of development can be debugged under the ARMulator
because the ARMulator environment does not support communications with peripheral
devices. Refer to Debugging your Angel port on page 13-66 for more information on
debugging Angel.
If you are using a command-line UNIX system, you must edit the appropriate makefile
when you copy an Angel template directory. If you are using APM, refer to Editing the
APM project directory structure on page 13-51.
The build directory is separate from the target source code directory. In the supplied
examples it has the same name as the target code directory with a .b extension. For
example, the build directory for the PID Angel port is angel/source/pid.b
You must modify the makefile so that it uses your directories, compiles and assembles
your source, and links your object files. This is described in Setting up the makefile,
below.
In addition to setting up the makefile for your new directory structure, you must set a
number of build options, either on the command-line or in the makefile, to provide
support for your hardware. The options include:
• Thumb support
• Angel data area and execution addresses
• endianness.
This is described in Setting command-line build options on page 13-46 and Editing
makefile build options on page 13-47.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 13-45
Angel
• copied the pid and pid.b template directory pair to a directory pair that is named
appropriately for your board.
At this stage, the directory structure for your board-specific files is similar to:
~/working_directory/angel/source/your_board
and
~/working_directory/angel/source/your_board.b
1. Open the appropriate makefile for your platform in a text editor. For example, if
you are working under Solaris, open your_board.b/gccsunos/Makefile.
2. Change all occurrences of the original directory name to the new directory name.
For example, if your port is based on the pid/pid.b directory pair, change all
occurrences of the pid directory to your_board.
Be careful with search and replace utilities because there are files named pid in
the target directories.
3. Set up the make parameters required. See Editing makefile build options below.
ENDIAN=BIG
This option builds a big-endian version of Angel. The objects and images
are stored in a sub-directory named big_rel. By default, the makefile
builds a little-endian Angel.
ETHERNET_SUPPORTED=1
This option enables ethernet support for the PID board. It includes the
ethernet drivers and the Fusion IP stack in the Angel build to enable
communications through the PC Card Ethernet Adapter. The default is 0
(no Ethernet support).
FUSION_BUILD=1
This option rebuilds the Fusion stack sources, if they are available.
13-46 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Angel
The Fusion stack binaries are supplied by ARM, under a license from
Pacific Softworks, with the Ethernet Upgrade Kit (No. KPI 0015A) for
the PID board. The fusion sources are available from ARM after you have
agreed a full source license with Pacific Softworks.
By default, the makefile does not rebuild Fusion stack sources.
The following PID build options are not available as command-line options. You must
edit the value of these options in the makefile. The most important options are ROADDR
and RWADDR. You must edit these to reflect the operational memory of your system.
THUMB_SUPPORT When set to 1 this builds Angel with support for debugging
Thumb code. If this is not set, the debugger does not support
Thumb state debugging. If Thumb code is encountered it
generally causes an undefined instruction trap.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 13-47
Angel
FIRST This option defines the object file that is linked at the beginning of
the ROM image. Valid values are:
FIRST = ’startrom.o(ROMStartup)’
The system can remap its memory map. ROM is
unmapped from 0 after reset. The first line of the
startup code is placed at the start of the ROM image.
The startup code copies the ARM exception vector
table to RAM at 0 after remap. This is the default.
FIRST = ’except.o(__Vectors)’
ROM is permanently mapped at 0. The ARM exception
vector table is placed at the beginning of the ROM
image.
ROADDR This defines the address of the Angel code at run time:
You can use this option to move Angel to RAM when ROM is
much slower than RAM. For example, the makefile for the PID
Angel port specifies an ROADDR in SRAM.
ROADDR is the address on which the compiler bases its
calculations for all the pc-relative instructions, such as branch
instructions.
Refer to Configuring where Angel runs on page 13-68 for more
information on ROADDR.
RWADDR This defines where Angel should store its read/write data. This is
the address of the data used by Angel at run time. You should
avoid setting this to 8000 if possible, because this is the default
application area.
Refer to Configuring where Angel runs on page 13-68 for more
information on RWADDR.
DEBUG If set to 1, this option enables debugging code within Angel.
13-48 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Angel
If you are using the ARM project manager on a Windows system, you must change the
project file when you copy an Angel template directory. If you are using UNIX, refer to
Editing makefile build options on page 13-47.
The build directory is separate from the target source code directory. In the supplied
examples it has the same name as the target code directory with a .b extension. The
APM projects are located in a subdirectory of the build directory. For example, the PID
project is located in c:\ARM250\Angel\Source\pid.b\Apm
The simplest way to use the PID Angel port as a template is to copy the entire Angel
directory structure to a working directory. If you want to change the names of the
directories to reflect the name of your board, you must modify the APM project file so
that it uses your directories, compiles and assembles your source, and links your object
files. This is described in Editing the APM project directory structure on page 13-51.
In addition to setting up the project file for your new directory structure, you must set a
number of build options. The options include:
• Thumb support
• Angel data area and execution addresses.
If you are using APM and have purchased the Angel Ethernet Kit, separate project files
are supplied to enable you to build Angel ROM Images with or without the Ethernet
drivers. Endianness is defined by the selected endianness of the APM environment.
When you have selected the Angel port that you want to base your own port on, you
must copy the required directories and files. The following instructions assume that you
are basing your port on the Angel PID port. Follow these steps to copy the Angel
template:
1. Copy the entire Angel directory and all subdirectories to your working directory.
It is recommended that you do not work in the installation Angel directory, by
default c:\ARM250\Angel, because this may cause problems if you reinstall the
Software Development Toolkit.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 13-49
Angel
2. In your working copy of the Angel directory, select Edit variables for
AngelPid.apj from the Project menu. The Edit Variable dialog is displayed
(Figure 13-6).
3. Change the $$ProjectName variable to the name of your port. The value given
here is used by APM to name the build output binaries.
4. Angel requires two files from the SDT installation C library directory:
• c:\ARM250\Cl\h_la_obj.s
• c:\ARM250\Cl\objmacs.s
5. This step is optional. You can rename the appropriate source and build directories
for your own port. For example, you can rename
working_directory\Angel\Sources\pid and
working_directory\Angel\Sources\pid.b as appropriate for your board.
You may need to do this if you have more than one project based on the PID port.
If you rename the pid and pid.b directories, you must make additional changes
to the project so that it will find the appropriate source files. Refer to Editing the
APM project directory structure on page 13-51 for detailed instructions.
If you have not renamed the directories, you can perform a trial build.
13-50 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Angel
If you renamed the pid and pid.b directories when you copied the Angel directory you
must ensure that the new directory paths are used to compile, assemble, and link your
sources. Follow these steps to configure the project template:
2. Select Edit Project Template… from the Project menu. The Project Template
Editor dialog is displayed (Figure 13-7).
3. Select Assemble from the list of build step patterns and click on the Edit…
button. The Edit Build Step Pattern dialog is displayed (Figure 13-8).
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 13-51
Angel
4. The Command Lines section of the dialog contains the command-line for the
assembler. The last part of the command line is:
{path|<path|-I><path>} <path><slash><file>.s
Change this to:
{path2|<path|-I><path>} <path><slash><file>.s
by adding the number 2 to the first path.
6. Repeat steps 3 and 4 for the build step patterns Assemble for ROM and Compile.
7. Select MakeLo from the list of build step patterns and click on the Edit… button.
The Edit Build Step Pattern dialog is displayed (Figure 13-9).
8. Change the Included Files and Command Lines sections of the dialog to reflect
the new directory structure. For example, if you have copied the complete Angel
directory structure and renamed the pid and pid.b directories, change pid to
your new directory name.
9. When you have finished editing the build steps, click Close to exit the Build Step
dialog box.
13-52 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Angel
11. Click on the Include Files tab and edit the list of include file directories to reflect
the new directory structure. Click OK to apply the changes.
12. Repeat steps 10 and 11 using the <asm> = tasm submenu to configure the
assembler.
13. Remove and re-add all target-specific source files to the project. These are the
files that are located in the renamed pid directory, such as devices.c and
makelo.c (see Figure 13-11 on page 13-54). In general you will have to replace
these files with your own code when porting Angel.
Select a file and press the delete key to remove it. Select Add files from the
Project menu to re-add the file to the Sources partition.
In addition, you must replace makelo.c in the Host Sources partition.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 13-53
Angel
14. The directory header in the APM window can be edited using the Edit Details
button. This is not required to build Angel.
The build variables for the APM project are the same as those defined in the UNIX
makefile. They are defined in either the project variables, or as preprocessor definitions
in the compiler configuration dialog. Refer to Editing makefile build options on page
13-47 for a description of the build options.
13-54 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Angel
Target-specific files are dependent on the target system you are porting Angel to. You
must modify these files for your system.
Most of the work in porting is carried out on the code in the target specific source
directory to set up the target and provide device drivers.
target.s This file provides important startup macros specific to the hardware. You
must check each macro in this file and change them for your board, if
necessary.
This file also contains the GETSOURCE macro. GETSOURCE is used to
identify which interrupt source has caused an interrupt. You must modify
this macro to suit the interrupt-driven devices and interrupt scheme used
by your hardware. Refer to target.s on page 13-56 for details.
makelo.c This is part of the Angel build environment. When built, makelo includes
a number of Angel header files and produces an assembly language .s
file that defines globals shared between C and assembly language
routines.
This enables assembly language and C modules to access global
constants without requiring separate copies for assembler use and for C
compiler use.
If you introduce new constants that need to be shared by C and assembly
language routines you must add them to makelo.c. Refer to makelo.c on
page 13-57 for details.
banner.h This declares what board Angel is running on, and with what options.
Refer to banner.h on page 13-58 for details.
devices.c This file #includes the headers for device drivers for the system. You
must modify this file if you add, remove, or rename any device drivers.
Refer to devices.c on page 13-58 for details.
devconf.h This is the main configuration file. It includes device declarations,
memory layout details, stack sizes, and interrupt source information (IRQ
or FIQ). You must check every item in this file to ensure that it is set up
correctly for your board. Refer to devconf.h on page 13-58 for details.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 13-55
Angel
Device Drivers
All other files in the target specific source directory are device driver
sources. You might need to modify these even if your board uses the same
communications chips as those supported by the port you are using as a
template. If you are using different communications hardware, you must
rewrite these files for your own hardware. Refer to Writing the device
drivers on page 13-61 for more information on writing device drivers.
target.s
This file defines the code in the macros called from the initialization and interrupt
routines in the main code in startrom.s and suppasm.s.
UNMAPROM This macro is called by the startrom.s ROM initialization code. The
macro is called in systems that use ROM remapping to ensure that the
ROM image is at 0 at reset. When the system initialization is complete, a
remap is called to map the ROM to its physical address, and map RAM
to 0.
This method is used in the PID board system where the memory
management system aliases the ROM from its physical address to 0, in
order to allow ROM-resident code to be available at reset.
STARTUPCODE
This macro is called from startrom.s for target specific startup. In the
PID example, the startup macros reset both the ramsize counter and the
interrupt controller.
INITMMU This macro initializes the MMU for processors that include an MMU.
The location of the pagetable is important to the operation of this code
and you must be specify it correctly.
If the system is operating in big-endian mode and the MMU is
responsible for the endianness of the core, it must be set up early to enable
to code to operate correctly.
INITTIMER This macro is not used by Angel. It is provided as a place holder to allow
you to initialize any timers required by your application. It is called after
interrupts are disabled and the processor is set to Supervisor mode. There
is no code included in the example because it does not make use of system
timers. Profiling support code contains its own timer initialization code.
13-56 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Angel
makelo.c
This file enables you to share variables and definitions between C and assembly
language sources. The makelo.c source file is compiled with armcc and executed
under armsd as part of the Angel build process. When executed, it reads the contents of
the C header files #included at the start of makelo.c and produces an assembler
header file named lolevel.s.
The assembler header file mirrors the C definitions in the #included C header files.
For example, the processor mode defined in arm.h, such as:
#define USRmode 0
Use a GET directive to include lolevel.s in any assembly language file that requires
access to C variables or definitions.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 13-57
Angel
To include your own C variables in the list contained in makelo.c, add lines in the
format:
fprintf(outfile, "Variable_Name\t\tEQU\t%d\n", Variable_Name);
banner.h
This header file contains macros that define the text that is displayed when the host and
target connect after initialization. You can modify this file to suit your target, and the
build options you use. Different ports can share components of this message by
including the file configmacros.h. You should take care not to advertise a feature in
the banner message that will not work correctly. The banner message is limited to 204
characters.
devices.c
This file defines the base address in memory for each available device. It enables C
pointers to access the operational registers in each device.
You must also define the interrupt handlers as the handler routine plus an optional
parameter. The parameter is used for handlers that service more than one source. In the
case of the PID, the same handler is responsible for the two serial ports and the parallel
port.
Serial drivers must conform to the generic function calls defined in devdriv.h. This
ensures that generic calls from the debug code and channels manager can access any
valid device driver, without requiring information about the peripheral being used.
devconf.h
This is the main configuration file for the target image. It sets up the Angel resources
for the specific target and defines the hardware configuration to Angel, including:
• a memory map of available memory
• interrupt operation
• the peripherals and devices available to Angel.
All systems require a similar devconf.h to that used for the PID. The following
explanation uses the PID devconf.h file as an example. It defines the following:
13-58 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Angel
Debug Method
The DEBUG_METHOD option is only applicable if DEBUG=1 is specified in
the makefile or APM project file.
The value of DEBUG_METHOD defines the channel that is used to pass
debug messages. Some options require specific equipment or software,
for example, pidulate, rombox, and e5 (see also Debugging your
Angel port on page 13-45).
The logadp option should not be used.
In general, the safest option is panicblk. The most useful option is
logterm, but this requires a spare serial port.
Use the #defines NO_LOG_INFO and NO_LOG_WARNING to increase
execution speed and reduce the size of images created with debug
enabled, when some or all debug messages are not required.
HANDLE_INTERRUPTS_ON_IRQ
Angel interrupt handlers will handle interrupts on IRQ
HANDLE_INTERRUPTS_ON_FIQ
Angel interrupt handlers will handle interrupts on FIQ.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 13-59
Angel
Note
Angel stack space is different from the application stack space. However,
Angel uses four words of application stack when it returns to the
application from an exception.
13-60 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Angel
Writing device drivers for your hardware is the main area of the porting operation, and
is completely application dependent. The device drivers provided with the PID Angel
port can provide a starting point, but in many cases you must completely recode the
source files. The simplest approach is to use the main functions defined in the PID code
and rewrite the underlying functionality.
For example, the Angel PID port controls the device through function pointers defined
between devclnt.h and devdriv.h. The main controlling functions are:
• the angel_DeviceControlFn()
• Transmit Control (ControlTx)
• Receive Control (ControlRx)
• Transmit Kick Start (KickStartFn)
• The interrupt handler.
These are discussed in more detail in the following sections.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 13-61
Angel
• Write either an interrupt service routine or a poll function that does input/output.
• Provide ring buffers that allow you to communicate with the rest of the code. You
must provide one transmit and one receive ring buffer.
Your device driver must be able to handle messages that are longer than 256 bytes in
order to handle memory write messages. The actual length of memory write messages
is determined by your Angel port. Refer to Download on page 13-29 for more
information.
Note
Raw device drivers that are purely interrupt driven must fit in with the interrupt scheme
described Example of Angel processing: a simple IRQ on page 13-38.
angel_DeviceControlFn
DC_RESET Device Reset. This provides device re-initialization to set the device into
a known operational state ready to accept input from the host at the
default setup.
DC_RECEIVE_MODE
Receive mode select. This sets the device into and out of receive mode.
13-62 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Angel
DC_SET_PARAMS
Set Device operational parameters. This sets the device parameters at
initialization. It is also used if the host needs to re-negotiate the
parameters, for example if the baud rate changes.
DC_RX_PACKET_FLOW
This control disables packet delivery when required, while still allowing
the device to read data:
1 Packet buffers not requested. Writing to the ring buffer is
allowed.
0 Normal operation.
When in operation, Angel defaults to the receive active state in order to enable quick
response to host messages. This function controls the transmit channel of the serial
driver, switching it on or off depending on the flag status set up in the calling routine.
Interrupt handlers
The interrupt handlers are generic for each peripheral. In the case of the PID board the
interrupt handler controls interrupts from each serial driver Tx and Rx in addition to the
parallel reads.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 13-63
Angel
• for the Tx case, it passes bytes from the internal Tx buffer to the Serial Tx FIFO
as long as there is space in the FIFO.
• for the Rx case, it passes the byte received at the Rx FIFO into the internal Rx
buffer, ready for Angel to unpack the message when the transfer is complete.
• for the parallel case, the parallel port is polled to pass the received data into the
memory location requested.
Refer to Example of Angel processing: a simple IRQ on page 13-38 for more
information on how Angel handles interrupts. Refer to Angel task management on page
13-31 for information on how Angel serializes communications tasks.
Note
Other system drivers (Ethernet/DCC) might not need the full operation functions
described above. They might need only a pure Rx/Tx control.
Polled devices
The registered read and write poll functions are called by the Angel_DeviceYield()
function. Angel ensures this function is called whenever communication with the host
is required. On each call, the device poll handler ensures that the device is serviced.
For a full Angel system, a hardware timer must be available for polled devices to work
because the timer interrupt is used to gain control of the processor and call
Angel_DeviceYield(). This call must be inserted at the end of the timer interrupt
handler for the port, because the timer itself is part of the port. For example:
/* See if it is time to call Angel_Yield yet */
if (++call_yield_count >= call_yield_every_n_irqs)
{
call_yield_count=0;
Angel_SerialiseTask(0,(angel_SerialisedFn)Angel_YieldCore,
NULL, empty_stack, &Angel_GlobalRegBlock[RB_Interrupted]);
}
13-64 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Angel
Angel can download a new version of itself. There are a number of methods you can use
to do this, depending on whether you are using armsd or ADW/ADU.
The best method is to download Angel to Flash, if your board supports it. This allows
you to replace your Angel as often as required, without losing the image at reset or
power down. The ARM PID board supports Flash. Refer to your board documentation
for more information on downloading to Flash.
If your board does not have Flash, and does have sufficient RAM, you can load Angel
to RAM and either run it in place, or relocate and run. If you are using Angel to replace
Angel with this method you cannot overwrite the currently executing Angel code.
Note
• Angel is not always capable of downloading a new copy of itself and then
restarting. Your board must contain sufficient spare RAM to copy the new Angel
into RAM before relocating it and running it. If you do not have sufficient RAM
you can use EmbeddedICE or Multi-ICE to download Angel, providing it has
been compiled to run from the download location.
• Angel is built to relocate a downloaded new Angel to the address that the new
Angel is built to execute from, and then to execute it. If you download a copy of
Angel that is built to run from ROM, it will fail.
See Configuring where Angel runs on page 13-68 for more information on
specifying the Angel execution address.
From armsd, use the loadagent command to download a new version of Angel. The
loadagent command cannot write to Flash. If you use loadagent, Angel must be
compiled to run from RAM.
In the ARM debuggers (ADW and ADU), select Flash Download from the File menu
to download a new version of Angel to Flash.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 13-65
Angel
You can use a number of methods to debug your Angel port. The method you choose
will depend on the stage of development you have reached, and the hardware available
to you.
Note
You should take debug requirements into consideration when designing your
development board. Your board should allow access to the full Data bus and Address
bus. In addition, general purpose outputs, such as programmable LEDs, can be useful
for debug purposes.
ARMulator You can debug the early stages of your Angel port under ARMulator.
Only the initial stages of the code can be debugged in ARMulator
because the ARMulator environment has no means of receiving
responses from peripherals. You can use programmable LEDs to assist
you in debugging under ARMulator.
Multi-ICE EmbeddedICE and Multi-ICE are valuable tools for debugging Angel
because they can operate before the basic Angel functionality is working.
For example, they can operate before your Angel device drivers are
functional.
These are the preferred option if your board uses an appropriate ARM
processor, such as the ARM7TDMI. Your processor must support the DI
debug extensions to work with an ICE solution.
Note
Specify DEBUG=1 to build a debugging version of Angel.
13-66 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Angel
You can configure the Angel stack positions by editing the value of:
#define Angel_StacksAreRelativeToTopOfMemory
in devconf.h.
By default, the Angel stacks are configured relative to the top of memory. This is the
recommended option. If Angel stacks are configured to start relative to the top of
memory then the Angel code searches for the top of contiguous memory and the stack
pointers are set at this location. This means that you can add memory to your system
without updating the memory map and rebuilding Angel. Refer to devconf.h on page
13-58 for more information.
You must define the memory map to allow the debugger to control illegal read/writes
using the checks in the PERMITTED macro. These should reflect the permitted access of
the system memory architecture. You must take care with systems that have access to
the full 4GB of memory, because the highest section of memory should equate to
0xffffffff when the base and size are defined as a sum, and it may wrap around to 0.
For example, if there is memory-mapped I/O at 0xffd00000 the definition should be:
#define IOBase (0xFFD00000)
#define IOSize (0x002fffff)
#define IOTop (IOBase + IOSize)
not:
#define IOBase (0xFFD00000)
#define IOSize (0x00300000)
#define IOTop (IOBase + IOSize)
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 13-67
Angel
The PID board has two timers available, and by default profiling and Ethernet are
configured to use the same timer. The PID board uses pc sampling for profiling. This
requires a fast interrupt. The interrupt service routine records where the program was
when it was interrupted. If you do not use profiling or Ethernet you can use the timer
for your application.
You can turn off profiling by setting a runtime debugger variable, but this does not free
the timer. In the Angel PID port, profiling is specified in the PROFILE entry of
devconf.h. You must recompile Angel to remove profiling support. Refer to devconf.h
on page 13-58 for more information.
You can chain your own exception handlers to the Angel exception handlers. Refer to
Chaining exception handlers on page 13-19 for more information.
Link addresses
The makefile for angel.rom contains two makefile macros that control the addresses
where Angel is linked:
RWADDR This defines the base address for read/write areas, such as dataseg and
bss (zero-initialized) areas, along with some assembler areas. Angel
requires approximately 24KB of free RAM for its read/write areas.
ROADDR This defines the base address for read-only areas. In general, read-only
areas are code areas. Angel requires between 50 and 100KB of RAM for
its read-only areas.
13-68 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Angel
ROM locations
Regardless of where you declare RWADDR and ROADDR to be, the ARM processor
requires the exception vector table to be located at zero. There are a number of situations
where this happens by default, for example when RWADDR is set to 0, or in ROM-at-zero
systems.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 13-69
Angel
When this does not happen by default, Angel explicitly copies everything in
AREA __Vectors from RWADDR to zero. All code within the __Vectors area must be
position-independent, because it is linked to run at ROADDR, not zero.
Angel requires one SWI in order to operate. The SWI is used to:
• change processor mode to gain system privileges
• make semihosting requests
• report an exception to the debugger.
The SWI passes a reason code in r0 to determine the type of request. Depending on the
SWI, additional arguments are passed in r1. Refer to Angel C library support SWIs on
page 13-77 more information.
The SWI number is different for ARM state and Thumb state. By default, the SWI
numbers used are:
If you want to use either of these SWI numbers for your system you can reconfigure the
SWI to use any of the available SWI numbers. If you change these values you must:
• Recompile the C library, specifying the new SWI value in the Angel definition
files. Refer to Retargeting the ANSI C library on page 4-6 of the ARM Software
Development Toolkit Reference Guide for more information.
13-70 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Angel
Figure 13-12 shows a conceptual model of the communication layers for Angel. In
practice, some layers might be combined.
Devices
ADP The Angel Debug Protocol channel. This consists of the Host ADP
channel (HADP) and Target ADP channel (TADP).
At the top level on the target, the Angel agent communicates with the debugger host,
and the user application can make use of semihosting support (CLIB).
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 13-71
Angel
All communications for debugging (ADP, BOOT, TDCC, CLIB) require a Reliable
channel between the target and the host. The Reliable communications and buffer
management layer is responsible for providing reliability, retransmissions, and
multiplexing/de-multiplexing for these channels. This layer must also handle buffer
management, because reliability requires retransmission after errors have occurred.
The device driver layer detects and rejects bad packets but does not offer reliability
itself.
If there are two or more debug devices (for example, serial and serial/parallel), the boot
agent must be able to receive messages on any device and then ensure that further
messages that come through the channels layer are sent to the correct (new) device.
When the debug agent detects a Reboot or Reset message, it listens to the other channels
using the device that received the message. All debug channels switch to use the newly
selected debug device.
During debugging, each channel is connected through the same device to one host.
Initially, Angel listens on all Angel-aware devices for an incoming boot packet, and
when one is received, the corresponding device is selected for further Angel use. Angel
listens for a reset message throughout a debugging session, so that it can respond to
host-end problems or restarts.
To support this, the channels layer provides a function to register a read callback across
all Angel-aware devices, and a function to set the default device for all other channel
operations.
The channels layer is responsible for multiplexing the various Angel channels onto a
single device, and for providing reliable communications over those channels. The
channels layer is also responsible for managing the pool of buffers used for all
transmission and reception over channels. Raw device I/O does not use the buffers.
Although there are several channels that could be in use independently (for example,
CLIB and HADP), the channel layer accepts only one transmission attempt at a time.
Channel restrictions
To simplify the design of the channels layer and to help ensure that the protocols
operating over each channel are free of deadlocks, the following restriction is placed on
the use of each channel.
13-72 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Angel
For a particular channel, all messages must originate from either the Host or the Target,
and responses can be sent only in the opposite direction on that channel. Therefore two
channels are required to support ADP:
• one for host originated requests (Read Memory, Execute, Interrupt Request)
• one for target originated requests (Thread has stopped).
Buffer management
Managing retransmission means that the channels layer must keep messages that have
been sent until they are acknowledged. The channel layer supplies buffers to channel
users who want to transmit, and then keeps transmitted buffers until acknowledged.
The number of available buffers might be limited by memory to less than the theoretical
maximum requirement of one for each channel and one for each Angel-aware device.
The buffers contain a header area sufficient to contain channel number and sequence
IDs, for use by the channels layer itself. Any spare bits in the channel number byte are
reserved as flags for future use.
Long buffers
Most messages and responses are short (typically less than 40 bytes), although some can
be up to 256 bytes long. However, there are some situations where larger buffers would
be useful. For example, if the host is downloading programs or configuration data to the
target, a larger buffer size reduces the overhead created by channel and device headers,
by acknowledgment packets and by the line turnaround time required to send each
acknowledgment (for serial links). For this reason, a long (target defined, suggested size
4KB) buffer is available for target memory writes, which are used for program
downloads.
Limited RAM
When RAM is unlimited, the easiest solution is to make all buffers large. There is a
mechanism that allows a single large buffer to be shared, because RAM in an Angel
system is not normally an unlimited resource.
When the device driver has read enough of a packet to determine the size of the packet
being received, it performs a callback asking for a suitably sized buffer. If a small buffer
is adequate, a small buffer is provided. If a large buffer is required, but is not available,
the packet is treated as a bad packet, and a resend request results.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 13-73
Angel
When sending data, the user of a channel must explicitly allocate a buffer before
requesting a write. Buffers must be released either by:
• Passing the buffer to one of the channel transmit functions in the case of reliable
data transmission. In this case, the channels code releases the buffer.
• Explicitly releasing it with the release function in the case of unreliable data
transmission.
Receive buffers must be explicitly released with the release function (see Figure 13-13).
alloc alloc
send send
release no release
13-74 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Angel
The length of the complete data packet is returned by the device driver layer. An overall
length field for the user data portion of the packet it not required, because the channel
header is fixed length.
Heartbeat mechanism
Heartbeats must be enabled for reliable packet transmission to work. Heartbeats work
only with the Software Development Toolkit version 2.11a (Angel 1.04, EmbeddedICE
2.07) and later.
The remote_a heartbeat software writes packets using at least the heartbeat rate, and
uses heartbeat packets to ensure this. It expects to see packets back using at least the
packet timeout rate, and signals a timeout error if this is violated.
Angel supports polled and asynchronous interrupt-driven devices, and devices that start
in an asynchronous mode and finish by polling the rest of a packet. At the boundary of
the device driver layer, the interface offers asynchronous (by callback) read and write
interfaces to Angel, and a synchronous interface to the application.
Refer to Writing the device drivers on page 13-61 for more information on device
drivers.
This is primarily a channels layer issue, but because the BOOT channel must listen on
all Angel-compatible devices, the channels layer must determine how many devices to
listen to for boot messages, and which devices those are.
To provide this statically, the devices layer exports the appropriate device table or tables,
together with the size of the tables.
Transmit queueing
Because the core operating mode is asynchronous and more than one thread can use a
device, Angel rejects all but the first request, returns a busy error message, and leaves
the user (channels or the user application) to retry later.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 13-75
Angel
Angel Interrupt handlers are installed statically, at link time. The Angel Interrupt
handler runs off either IRQ or FIQ. It is recommended that it is run off IRQ. The Angel
interrupt is defined in devconf.h. Refer to devconf.h on page 13-58 for more
information.
Control calls
Angel device drivers provide a control entry point that supports the enable/disable
transmit/receive commands, so that Angel can control application devices at critical
times. Refer to Writing the device drivers on page 13-61 for more information.
13-76 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Angel
Refer to The ANSI C library on page 4-5 of the ARM Software Development Toolkit
Reference Guide for more information on ARM C library support.
Angel uses a single SWI to request semihosting operations. By default, the Angel
semihosting SWI is:
• 0x123456 in ARM state
• 0xab in Thumb state.
You can configure the Angel SWI to any SWI number if you are developing an
operating system or application that uses these SWI numbers. Refer to the Configuring
Angel on page 13-67 for more information.
The semihosting operation type is passed in r0, rather than being encoded in the SWI
number. All other parameters are passed in a block that is pointed to by r1. The result is
returned in r0, either as an explicit return value or as a pointer to a data block. If no result
is returned, r0 is corrupted. Registers r1-r3 are preserved by Angel when an Angel
system call is made. See the description of each operation below.
In the following descriptions, the number in parentheses after the operation name (for
example 0x01) is the value r0 must be set to for this operation. If you are calling Angel
SWIs from assembly language code it is best to use the operation names that are defined
in arm.h. You can define the operation names with an EQU directive. For example:
SYS_OPEN EQU 0x01
SYS_CLOSE EQU 0x02
• Simple SWIs. These are SWIs such as EnterSVC and undefined SWIs. These
SWIs do not use the Angel serializer and do not store anything in the global
registers blocks. They can be treated like an APCS function call. Registers r0 to
r3 and r12 are corrupted.
• Complex SWIs. These are SWIs such as the C library support SWIs. These SWIs
use the serializer and the global register block, and they can take a significant
length of time to process. They can be treated as an APCS function call, but they
restore the registers they are called with before returning, except for r0 which
contains the return status.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 13-77
Angel
Table 13-3 gives a summary of the Angel semihosting SWIs. Refer to the descriptions
below for more detailed information.
SYS_READ (0x06) page 13-82 Read the contents of a file into a buffer.
SYS_READC (0x07) page 13-83 Read a byte from the debug channel.
SYS_ISTTY (0x09) page 13-84 Check whether a file is connected to an interactive device.
SYS_CLOCK (0x10) page 13-87 Number of centiseconds since support code started.
SYS_SYSTEM (0x12) page 13-88 Pass a command to the host command-line interpreter.
SYS_ERRNO (0x13) page 13-88 Get the value of the C library errno variable.
SYS_GET_CMDLINE (0x15) page 13-89 Get the command-line used to call the executable.
SYS_ELAPSED (0x30) page 13-91 Get the number of target ticks since support code started.
13-78 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Angel
Open a file on the host system. The file path is specified either as relative to the current
directory of the host process, or absolutely, using the path conventions of the host
operating system.
The ARM debuggers interpret the special path name :tt as meaning the console input
stream (for an open-read) or the console output stream (for an open-write). Opening
these streams is performed as part of the standard startup code for those applications
that reference the C stdio streams.
Entry
word 2 is an integer that specifies the file opening mode. Table 13-4 gives the
valid values for the integer, and their corresponding ANSI C fopen()
mode.
word 3 is an integer that gives the length of the string pointed to by word 1. The
length does not include the terminating null character that must be
present.
Table 13-4
mode 0 1 2 3 4 5 6 7 8 9 10 11
Return
On exit, r0 contains:
• a non-zero handle if the call is successful
• –1 if the call is not successful.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 13-79
Angel
Closes a file on the host system. The handle must reference a file that was opened with
SYS_OPEN.
Entry
Return
On exit, r0 contains:
• 0 if the call is successful
• –1 if the call is not successful.
Writes a character byte, pointed to by r1, to the debug channel. When executed under
an ARM debugger, the character appears on the display device connected to the
debugger.
Entry
Return
Writes a null-terminated string to the debug channel. When executed under an ARM
debugger, the characters appear on the display device connected to the debugger.
Entry
Return
13-80 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Angel
Writes the contents of a buffer to a specified file at the current file position. The file
position is specified either:
• explicitly, by a SYS_SEEK
• implicitly as one byte beyond the previous SYS_READ or SYS_WRITE request.
The file position is at the start of the file when the file is opened, and is lost when the
file is closed.
The file operation should be performed as a single action whenever possible. That is, a
write of 16KB should not be split into four 4KB chunks unless there is no alternative.
Entry
word 3 contains the number of bytes to be written from the buffer to the file.
Return
On exit, r0 contains:
• 0 if the call is successful
• the number of byte that are not written, if there is an error.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 13-81
Angel
Read the contents of a file into a buffer. The file position is specified either:
• explicitly, by a SYS_SEEK
• implicitly, as one byte beyond the previous SYS_READ or SYS_WRITE request.
The file position is at the start of the file when the file is opened, and is lost when the
file is closed.
The file operation should be performed as a single action whenever possible. That is, a
write of 16KB should not be split into four 4KB chunks unless there is no alternative.
Entry
word 3 contains the number of bytes to read to the buffer from the file.
word 4 is an integer that specifies the file mode. Table 13-4 on page 13-79 gives
the valid values for the integer, and their corresponding ANSI C
fopen() modes.
Return
On exit, r0 contains:
• 0 if the call is successful
• the number of bytes not read, if there is an error.
If the handle is for an interactive device (that is, SYS_ISTTY returns –1 for this handle),
a non-zero return from SYS_READ indicates that the line read did not fill the buffer.
13-82 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Angel
Reads a byte from the debug channel. The read is notionally from the keyboard attached
to the debugger.
Entry
Return
Determines whether the return code from another semihosting call is an error status or
not. This call is passed a parameter block containing the error code to examine.
Entry
Return
On exit, r0 contains:
• 0 if the status word is not an error indication
• a non-zero value if the status word is an error indication.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 13-83
Angel
Entry
Return
On exit, r0 contains:
• –1 if the handle identifies an interactive device
• 0 if the handle identifies a file
• a value other than –1 or 0 if an error occurs.
Seeks to a specified position in a file using an offset specified from the start of the file.
The file is assumed to be a byte array and the offset is given in bytes.
Entry
Return
On exit, r0 contains:
• 0 if the request is successful
• A negative value if the request is not successful. SYS_ERRNO can be used to
read the value of the host errno variable describing the error.
Note
The effect of seeking outside of the current extent of the file object is undefined.
13-84 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Angel
Entry
Return
On exit, r0 contains:
• the current length of the file object, if the call is successful
• –1 if an error occurs.
Entry
word 3 contains the length of the buffer. The length should be at least the value
of L_tmpnam on the host system.
Return
On exit, r0 contains:
• 0 if the call is successful
• –1 if an error occurs.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 13-85
Angel
Entry
word 1 points to a null-terminated string that gives the pathname of the file to be
deleted.
Return
On exit, r0 contains:
• 0 if the delete is successful
• a non-zero, host-specific error code if the delete fails.
Entry
Return
On exit, r0 contains:
• 0 if the rename is successful
• a non-zero, host-specific error code if the rename fails.
13-86 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Angel
Returns the number of centiseconds since the support code started executing.
Values returned by this SWI can be of limited use for some benchmarking purposes
because of communication overhead or other agent-specific factors. For example, with
the Multi-ICE debug agent the request is passed back to the host for execution. This can
lead to unpredictable delays in transmission and process scheduling.
This function should be used only to calculate time intervals (the length of time some
action took) by calculating the difference in the result on two occasions.
Entry
Return
On exit, r0 contains:
• the number of centiseconds since some arbitrary start point, if the call is
successful
• –1 if the call is unsuccessful (for example, because of a communications error).
Entry
Return
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 13-87
Angel
Passes a command to the host command-line interpreter. This SWI enables you to
execute a system command such as ls, or pwd. The terminal I/O is on the host, and is
not visible to the target.
Entry
Return
Returns the value of the C library errno variable associated with the host support for
the debug monitor. The errno variable can be set by a number of C library support
SWIs, including:
• SYS_REMOVE
• SYS_OPEN
• SYS_CLOSE
• SYS_READ
• SYS_WRITE
• SYS_SEEK.
Whether or not, and to what value errno is set is completely host-specific, except
where the ANSI C standard defines the behavior.
Entry
Return
13-88 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Angel
Entry
On entry, r1 points to a two word data block in which the command string and its length
are to be returned:
Return
On exit:
The debug agent might impose limits on the maximum length of the string that
can be transferred. However, the agent must be able to transfer a command-line
of at least 80 bytes.
In the case of the Angel debug monitor using ADP, the minimum is slightly more
than 200 characters.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 13-89
Angel
Returns the system heap parameters. The values returned are typically those used by the
Angel C library during initialization. These values are defined in the devconf.h header
file. Refer to Modifying target-specific files on page 13-55 for a description of
devconf.h.
The C library can override these values, but will do so only if __heap_base is defined
at link time. In this case the values of the following symbols are used:
• __heap_base
• __heap_limit
• __stack_base
• __stack_limit
This call returns sensible answers if EmbeddedICE is being used, but the values are
determined by the host debugger using the $top_of_memory debugger variable.
Entry
Return
The heap descriptor is a block of four words of data that contains the stack and heap
base and limit:
word 1 Heap Base.
word 2 Heap Limit.
word 3 Stack Base.
word 4 Stack Limit.
13-90 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Angel
Returns the number of elapsed target ticks since the support code started execution.
Ticks are defined by SYS_TICKFREQ. If the target cannot define the length of a tick,
it can supply SYS_ELAPSED.
Entry
Register r1 contains a pointer to a double word in which to put the number of elapsed
ticks. The first word is the least significant word. The last word is the most significant
word. This follows the convention used by the ARM compilers for the long long data
type.
Return
If the double word pointed to by r1 (low order word first) does not contain the number
of elapsed ticks, r1 is set to –1.
Entry
Exit
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 13-91
Angel
• The ReportException SWI. This SWI is used by the semihosting support code as
a way to report an exception to the debugger. It can be considered as a breakpoint
that starts in Supervisor mode rather than Undefined mode.
• The EnterSVC SWI. This SWI sets the processor to Supervisor mode.
Sets the processor to Supervisor (SVC) mode and disables all interrupts by setting both
interrupt mask bits in the new CPSR. Under Angel, the user stack pointer (r13_USR) is
copied to the Supervisor stack pointer (r13_SVC) and the I and F bits in the current
CPSR are set, disabling normal and fast interrupts.
Note
If you are debugging with an EmbeddedICE interface:
• the User mode stack pointer is not copied to the Supervisor stack pointer.
• the I and F bits of the CPSR are not set.
Entry
On entry, r0 contains 0x17. Register r1 is not used. The CPSR can specify User or
Supervisor mode.
Return
On exit, r0 contains the address of a function to be called to return to User mode. The
function has the following prototype:
void ReturnToUSR(void)
13-92 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Angel
Note
• If debugging with ARMulator or Multi-ICE, r0 is set to zero to indicate that no
function is available for returning to User mode.
If EnterSVC is called in User mode, this routine returns the caller to User mode and
restores the interrupt flags. If EnterSVC is not called in User mode, the action of this
routine is undefined.
If entered in User mode, the Supervisor stack is lost as a result of copying the user stack
pointer. The return to User routine restores r13_SVC to the Angel Supervisor mode
stack value, but this stack should not be used by applications.
After executing the SWI, the current link register will be r14_SVC, not r14_USR. If the
value of r14_USR is needed after the call, it should be pushed onto the stack before the
call and popped afterwards, as for a BL function call.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 13-93
Angel
This SWI can be called by an application to report an exception to the debugger directly.
The most common use is to report that execution has completed, using
ADP_Stopped_ApplicationExit.
Entry
The hardware exceptions are generated if the debugger variable $vector_catch is set
to catch that exception type, and the debug agent is capable of reporting that exception
type. Angel cannot report exceptions for interrupts on the vector it uses itself.
ADP_Stopped_BranchThroughZero 0x20000
ADP_Stopped_UndefinedInstr 0x20001
ADP_Stopped_SoftwareInterrupt 0x20002
ADP_Stopped_PrefetchAbort 0x20003
ADP_Stopped_DataAbort 0x20004
ADP_Stopped_AddressException 0x20005
ADP_Stopped_IRQ 0x20006
ADP_Stopped_FIQ 0x20007
13-94 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Angel
ADP_Stopped_BreakPoint 0x20020
ADP_Stopped_WatchPoint 0x20021
ADP_Stopped_StepComplete 0x20022
ADP_Stopped_RunTimeErrorUnknown *0x20023
ADP_Stopped_InternalError *0x20024
ADP_Stopped_UserInterruption 0x20025
ADP_Stopped_ApplicationExit 0x20026
ADP_Stopped_StackOverflow *0x20027
ADP_Stopped_DivisionByZero *0x20028
ADP_Stopped_OSSpecific *0x20029
Return
No return is expected from these calls. However, it is possible for the debugger to
request that the application continue by performing an RDI_Execute request or
equivalent. In this case, execution continues with the registers as they were on entry to
the SWI, or as subsequently modified by the debugger.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 13-95
Angel
13.9.1 How Angel, Fusion, and the PID hardware fit together
The Ethernet interface for the PID card is provided by an Olicom EtherCom PCMCIA
Ethernet card installed in either PCMCIA slot. The Olicom card uses an Intel i82595
Ethernet controller.
The UDP/IP stack is the Pacific Softworks Fusion product, ported to ARM and the
Angel environment. The drivers for PCMCIA and the Ethernet card have been
implemented, as has the Angel device driver to make the whole stack appear as an Angel
device. Figure 13-14 shows how the components fit together.
Angel
Angel
Ethernet driver
Fusion
sockets library
Fusion
UDP
Fusion
IP
i82595
controller
Olicom
card
pcmcia
manager
Ethernet
13-96 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Angel
Initialization
1. devclnt.c:angel_InitialiseDevices() calls
ethernet.c:ethernet_init()to open a socket.
2. fusion:socket() notices that the fusion stack has not been initialized. Fusion
stack initialization calls:
a. olicom.c:olicom_init() calls:
b. pcmcia.c:pcmcia_setup() detects Olicom card and calls:
c. olicom.c:olicom_card_handler() with a card insertion event and
then:
d. olicom.c:read_card_params() to register olicom_isr() with
pcmcia.c.
After initialization, the Angel side of the driver is implemented as a polling device. At
every call to Angel_Yield(), angel_EthernetPoll() is invoked, and
non-blocking recv() calls are made to the Fusion stack to see if data is waiting on any
of the sockets.
Outgoing packets are passed to the Fusion stack in a single step by calling sendto().
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. 13-97
Angel
Interrupt handling
The bottom of the Fusion stack is driven by interrupts from the Olicom card. Interrupts
are handled in the following sequence:
6. 82595.c routines control the i82595 chip and transfer packets in both directions
between Fusion buffers and the chip. Calls are made to Fusion functions as
appropriate.
Additionally, the Fusion stack can make calls to olicom_start() (to queue a new
packet for transmission), olicom_ioctl(), and olicom_updown() in response to
socket calls from the Angel Ethernet driver or as a result of packet processing.
13-98 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Appendix A
FlexLM License Manager
This appendix describes the use made by ARM Limited of FlexLM license management
software. You need to read this appendix and use FlexLM software only if you intend
to run any ARM licensed software, which at present is confined to UNIX-based
products.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. A-1
FlexLM License Manager
You must obtain a valid license file from ARM Limited before you can run licensed
ARM software. Obtaining your license file on page A-4 describes how to apply for your
license file.
You must specify one or more computers to act as a license server, on which license
management software runs. Any computer running FlexLM licensed software must
either be a license server or have access to a license server.
ARM Debugger for UNIX (ADU) is one example of software that requires a license
server before you can run it.
If you choose to use more than one, you must use three license server machines. These
communicate with one another, and co-ordinate the licensing. The advantage of this is
that if one of the license server machines fails to operate correctly the other two will
continue to allow licensed software to be used. This arrangement is known as a ‘3-server
redundant set’.
Remote license servers do not need to be running on the same hardware platform as the
software they are controlling.
A-2 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
FlexLM License Manager
License management software for various platforms is supplied on the CD-ROM of any
ARM licensed software (at present confined to UNIX-based products).
The following list shows the platforms supported, and the subdirectory containing the
appropriate software for each:
Solaris 2.5 flexlm/solaris
SunOS 4.1.x flexlm/sunos
HP-UX 9.x flexlm/hpux
Each directory contains the software in TAR file format, in a file called flexlm.tar.
Before applying for a license file you must install the FlexLM license management
software, as follows:
1. Copy the TAR file from the appropriate directory onto each license server
machine.
2. On each license server machine, unTAR the file using the command:
tar xvf flexlm.tar
3. When you have unTARed the software you need to run the makelinks.sh script.
Change into the directory containing the unTARed software and type:
./makelinks.sh
You need lmhostid when you complete your license request form.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. A-3
FlexLM License Manager
A-4 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
FlexLM License Manager
1. If you receive the license file by email you can either copy the license file section
out of the message, or save the entire message to disk. The license server ignores
all lines except those start with SERVER, VENDOR, or FEATURE.
2. If you received the license file by fax you will need to create a text file and key in
the information, using the editor of your choice. When data entry is complete, you
can use the lmchecksum utility to check that you typed everything in correctly.
Instructions for using lmchecksum are given under FlexLM license management
utilities, later in this appendix.
3. You may save the license file in any directory on each license server. It should,
however, be on a locally mounted file system.
4. You usually need to edit the VENDOR line of the license file on each license
server. The default license file sent you you contains:
VENDOR armlmd /opt/arm/flexlm/solaris
Change the text /opt/arm/flexlm/solaris so that it specifies the directory
that holds your license server software. Specifically, the directory that holds file
armlmd.
Full instructions for editing the license file can be found under Customizing your license
file, later in this appendix.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. A-5
FlexLM License Manager
where:
license_file_name
specifies the fully qualified pathname of the license file
logfile_name
specifies the fully qualifed pathname to a log file.
When you have started the license server, you can type:
cat logile_name
A-6 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
FlexLM License Manager
Assuming your license server is called enterprise, goto the machine where the ARM
Debugger is installed and type:
setenv ARMLMD_LICENSE_FILE @enterprise
You have only one license server and specified a TCP port (option 1)
Assuming your license server is called enterprise and you have specified TCP port
7117 in your license file, goto the machine where your licensed software is installed
and type:
setenv ARMLMD_LICENSE_FILE 7117@enterprise
You have only one license server and specified a TCP port (option 2)
Assuming your license file is called license.lic and is stored in the local directory
/opt/arm/licenses, type either one of the following two commands:
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. A-7
FlexLM License Manager
A-8 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
FlexLM License Manager
Although you must not change Feature lines, you may need to change the SERVER and
VENDOR lines in your license file.
You may need to change SERVER and VENDOR lines for the following reasons:
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. A-9
FlexLM License Manager
Feature lines describe the licenses that are available, and must not be altered. If they are
altered the license is invalidated, and the feature no longer operates.
Each Feature line specifies the feature name, the vendor daemon name, the feature
version, the expiration date of the license (a year of 0 means the license never expires),
the number of concurrent licenses available, and the license key.
A-10 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
FlexLM License Manager
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. A-11
FlexLM License Manager
The latest version of the FlexLM software will always work with vendor daemons built
using previous versions. Consequently you must always use the latest version of lmgrd
and the FlexLM utilities.
Note
The FlexLM software currently shipped by ARM is FlexLM version 6.0.
If you have multiple products using FlexLM you may encounter two situations:
• all the products use the same license server
• all the products use different license servers.
If the license files for every product contain exactly the same Server lines, ignoring
different TCP port numbers, then there are two possible solutions:
1. Start a separate lmgrd daemon for each license file. There are no real
disadvantages with this approach, as the separate daemons consume very little
system resources or CPU time.
2. Combine the the license files together. Take the the SERVER line from one of the
license files then add all of the other lines, that is the DAEMON/VENDOR and
FEATURE lines, to create a new license file.
You will need to store the new combined license file in
/use/local/flexlm/licenses/license.lic
or give its location via the LM_LICENSE_FILE environment variable.
Now start lmgrd using the new license file. Remember that you must use the
latest version of lmgrd that is used by any of the products. You can use the
command lmgrd -v or lmver lmgrd to find out the version of each lmgrd.
If the version of lmgrd is earlier than any of the vendor daemons, you see error
reports such as: Vendor daemon cannot talk to lmgrd (invalid data
returned from license server)
Leave a symbolic link to the new license file in all the locations which held the
original license files.
A-12 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
FlexLM License Manager
If all the products use different hosts to run the license managers, then you must keep
separate license files for each product.
Set the LM_LICENSE_FILE environment variable to point to the locations of all the
license files, for example:
setenv LM_LICENSE_FILE license_file1:license_file2:
...:license_filen
Note
FlexLM version 6.0 allows each software vendor to have an individual environment
variable for finding the license file for their products. The environment variable name
is xxx_LICENSE_FILE where xxx is the name of the vendor license daemon. In the
case of software from ARM Limited the vendor daemon is called ARMLMD, therefore the
environment variable for ARM software is ARMLMD_LICENSE_FILE. FlexLM version
6.0 vendor daemons always look for the vendor specific environment variable, ahead of
the LM_LICENSE_FILE environment variable.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. A-13
FlexLM License Manager
Installing FlexLM software on page A-3 describes how to install the software on your
(one or three) license server machines.
The installation process creates a series of hard links to make your usage of the license
management tools easier. Specifically it allows you to execute the utilities by using their
short names, for example you can type lmver instead of lmutil lmver.
All the license tools are actually contained within the single executable lmutil, the
behavior of which is determined by the value of its argv[0].
The lmdown, lmremove, and lmreread commands are privileged. If you started lmgrd
with the -p 2 switch then you must be a license administrator to run any of these three
utilities.
A license administrator is a member of the UNIX lmadmin group or, if that group does
not exist, a member of group 0.
-c license_file
operate on a specific license file.
lmchecksum
The lmchecksum utility performs a checksum of a license file. Use it to check for data
entry errors in your license file. lmcksum prints a line-by-line checksum for the file as
well as an overall file checksum. If the license file contains cksum=nn attributes, the
bad lines are indicated automatically.
This utility is particularly useful if you received your license by Fax and typed the file,
because of the possibility of data entry errors.
A-14 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
FlexLM License Manager
lmdiag
This utility allows you to check for problems, when you cannot check out a license.
-c license_file_list
Path to file(s) to check. If more than one file, use a colon separator.
-n Run in non-interactive mode.
feature Diagnose this feature only. If you do not specify a feature, all lines of the
license file are checked.
The lmdiag program first tries to check the feature. If this fails, the reason for failure
is printed.
If the check failed because lmdiag could not connect to the license server then you can
run extended connection diagnostics. These diagnostics try to check the validity of the
port number in the license file. lmdiag displays the port numbers of all ports that are
listening, and indicates which ones are lmgrd processes. If lmdiag finds the armlmd
daemon for the for feature being tested, it displays the correct port number to use in the
license file.
lmdown
lmdown [-c license_file_list] [-vendor name] [-q]
The program allows you to shut down gracefully all license daemons on all nodes (both
lmgrd and all vendor daemons).
-c license_file_list
Path to file(s) to be shut down. If more than one file, use a colon separator.
-vendor name
If you specify a vendor name, only that vendor daemon is shut down, and
lmgrd is not shut down.
-q Do not issue the Are you sure? prompt.
To stop and restart a single vendor daemon, use lmdown -vendor name, then
lmreread -vendor name.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. A-15
FlexLM License Manager
lmhostid
lmhostid
This program returns the correct host ID on any computer supported by FlexLM.
lmremove
This utility allows you to remove a single user license for a specific feature. For
example, when a user is running the software and the host crashes, the user license is
sometimes left checked out and unavailable to other users. lmremove frees the license
and makes it available to other users.
-c license_file_name
The full pathname of the license file to be used. If this is omitted the
LM_LICENSE_FILE environment variable is used instead.
feature The name of the feature the user has checked out.
user The name of the user.
host The name of the host the user was logged into.
display The name of the display where the user was working.
You can obtain the user, host, and display information from the output of lmstat
-a.
If the application is active when its license is removed by lmremove, it checks out the
license again at the next application heartbeat.
lmreread
This utility causes the license daemon to reread the license file, and start any new vendor
daemons that have been added. All the existing daemons are signalled to reread the
license file to check for any changes in their licensing information.
-vendor name
If you specify a vendor name, only that vendor daemon rereads the
license file. If the vendor daemon is not running, lmgrd starts it.
A-16 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
FlexLM License Manager
lmreread does not cause server host names or port numbers to be reread from the
license file. To make any changes to those items effective, you must restart lmgrd.
To stop and restart a single vendor daemon, use lmdown -vendor name, then
lmreread -vendor name.
lmstat
This utility helps you to monitor the status of all network licensing activities, including:
• which daemons are running
• users of individual features
• users of features served by specific daemons.
lmver
lmver [filename]
This utility reports the FlexLM version of a specific library or binary file.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. A-17
FlexLM License Manager
A Sometimes. You need to have the license file on your client machines
only when you are using the three-license server option.
In this situation you need to point the ARMLMD_LICENSE_FILE
environment variable at the local copy of the license file. Ensure that the
hostnames and TCP port numbers in the local license file are the same as
in the license server copies.
On a single-license server you can normally set
ARMLMD_LICENSE_FILE to contain the hostname of the server.
A-18 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
Index
The items in this index are listed in alphabetical order, with symbols and numerics appearing at the end. The
references given are to page numbers.
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. Index-1
component summary 13-7 status 13-29 Angel_TaskID() 13-33, 13-35
configuring 3-59, 13-67 ring buffers 13-62 angel_TQ_Pool 13-37
configuring run address 13-68 ROADDR 13-48 Angel_Wait() 13-33, 13-35, 13-36
configuring serial ports 13-59 RWADDR 13-48 Angel_Yield() 13-33, 13-34, 13-36,
configuring SWI numbers 13-70 semihosting support 13-3, 13-15, 13-64, 13-97
context switching 13-36 13-17 ANSI C 8-20
ControlRx 13-63 semihosting SWIs 13-77 header files 8-20
ControlTx 13-63 setting breakpoints 13-30 APCS
DEBUG 13-48 setting debug method 13-59 defined 6-3
debug agent interaction SWIs 13-92 stacks 13-10, 13-37 interworking ARM and Thumb 7-2,
debug method 13-59 stacks, setting up 13-60 7-13
Debug Monitor (ADM) 3-6 supervisor mode 13-19 register usage 6-10
Debug Protocol (ADP) 3-6 supervisor stack 13-17 APM
debug support 13-3 target-specific files 13-55 Angel project 13-43, 13-49
debugger functions 13-29 task management 13-5, 13-28, building C++ projects 2-53
debugging 13-45, 13-66 13-31, 13-37, 13-77 closing down 2-4
device configuration 13-44 task management functions 13-33 creating C++ projects 2-54
device driver layer 13-75 task priorities 13-31 desktop 2-16
downloading 13-25, 13-45, 13-61 task queue 13-37 generating source dependencies 2-9
downloading new versions of 13-65 Task Queue Items 13-36 interworking ARM and Thumb
enabling assertions 13-21 TDCC 13-24 7-25
Enter SVC mode 13-92 templates for porting 13-43 overview 2-2
Ethernet support 13-49, 13-96 Thumb debug communications partitions 2-25
exception handlers 13-68 channel 13-24 preferences 2-32
exception handling 13-5 timers 13-68 source files 2-35
exception vectors 13-9 undefined instruction 13-17 starting and stopping 2-4
full Angel 13-10 writing device drivers 13-61, 13-62 template location 2-53
hardware timers 13-64 angel.c ARMulator model 12-4 templates 2-42
heartbeat mechanism 13-75 angel.hex 13-11 using 2-4
initialization 13-27 angel.m32 13-11 using templates 2-54
initialization code 13-62 angel.rom 13-11, 13-68 viewing files 2-38
interrupt handlers 13-61, 13-63, Angel_BlockApplication() 13-33, Application heap, and Angel 13-60
13-98 13-34 AREA directive 5-11, 5-13
interrupt table 13-19 Angel_DeviceControlFn() 13-61 AREA directive (literal pools) 5-25
logging 13-66 Angel_DeviceYield() 13-64 Arguments, command line 3-46
makefile 13-43, 13-45 Angel_NewTask() 13-33, 13-37 ARM code
memory requirements 13-9 Angel_NextTask() 13-33, 13-34, interworking template 2-53
minimal Angel 13-12, 13-22 13-40 ARM core 3-5
minimal Angel initialization 13-28 Angel_QueueCallback() 13-33 ARM Debuggers for Windows and
planning development 13-16 Angel_SelectNextTask() 13-34, 13-37, UNIX, see ADW/ADU
polled devices 13-64 13-40 ARM licensed software A-1
porting 13-41 Angel_SerialiseTask() 13-32–13-33, ARM processors 3-5
prebuilt images 13-11 13-36, 13-37, 13-39, 13-40 ARM Project Manager, see APM
processor exception vectors 13-69 Angel_Signal() 13-33, 13-35 ARM Software Development Toolkit
profiling 13-68 angel_SWIreason_EnterSVC 13-92 (SDT) 3-1
programming restrictions 13-17 Angel_SWIreason_ReportException armasm 5-10
raw serial drivers 13-23 13-94 armcpp 2-54
Report Exception SWI 13-94 angel_SWIreason_ReportException armfast.c ARMulator model 12-3,
reporting memory and processor 13-94 12-20
Index-2 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
armflat.c ARMulator model 12-3, responsiveness 12-13 inline, see Inline assemblers
12-19 sample models mode changing 7-6
ARMLMD_LICENSE_FILE see also ARMulator models Assembly language
environment variable A-7 basic 12-3 Absolute maps 5-45
armmap.c ARMulator model 12-4, coprocessor 12-4 alignment 5-50
12-21 memory 12-3 and C++ 8-25
armpie.c ARMulator model 12-4 operating system 12-4 areas 5-13
armprof, see profiler SA-110 page table flags 12-15 base register 5-46
armsd SWIs 12-26 block copy 5-38
and Angel downloading 13-65 tracer 12-6 boolean constants 5-12
map files 11-9 user-configurable memory system calling from C 8-20
armsd.map file 11-9, 12-28 12-21 case rules 5-10
ARMulator 3-5, 3-6 windows hourglass 12-13 code size 5-55
overview 12-2 with ADW 12-13 comments 5-12
and Angel 13-66 yieding control to ADW 12-13 condition code suffixes 5-18
angel model 12-25 ARMulator functions conditional execution 5-17
armsd.map file 12-28 Tracer_Close 12-6 constants 5-12
armul.cnf file 12-28, 12-34 Tracer_Dispatch 12-6 data structures 5-45
ARM810 page table flags 12-15 Tracer_Flush 12-6 directives, see Directives, assembly
ARM940T page table flags 12-15 Tracer_Open 12-6 entry point 5-14
clock frequency 12-21 ARMulator models examples 5-2, 5-13, 5-15, 5-19,
configuration file, armul.cnf 12-6 angel.c 12-4 5-26, 5-28, 5-29, 5-32, 5-33,
configuring 3-57 armfast.c 12-3 5-38, 5-43, 5-55, 5-57
tracer 12-6 armflat.c 12-3 examples (Thumb) 5-16, 5-21,
under RDI 12-27 armmap.c 12-4 5-30, 5-33, 5-40
controlling using the debugger armpie.c 12-4 execution speed 5-55
12-27 bytelane.c 12-4 immediate constants (ARM) 5-22
dummy system coprocessor model dummymmu.c 12-4 inline, armasm differences 8-7
12-24 endianism 12-31 instructions, see Instructions,
emulation speed 12-13, 12-20 example.c 12-4, 12-29, 12-32, assembly
example 12-29, 12-34 12-34 interrupt handlers 9-28
flushing output to the tracer 12-6 noos.c 12-4 interworking ARM and Thumb 7-4,
functions, see ARMulator functions pagetab.c 12-3 7-21
initializing profiler.c 12-3 jump tables 5-29
MMU 12-15 stubs 12-5 labels 5-11
tracer 12-6 tracer.c 12-3, 12-4, 12-6 line format 5-10
instruction tracing 11-27 trickbox.c 12-4 line length 5-11
internal SWIs 12-26 validate.c 12-4 listing from debugger 4-3, 4-9
linking tracing code 12-6 winglass.c 12-3 literal pools 5-25
memory watchpoints 12-14 armul.cnf file 12-6, 12-28, 12-34 loading addresses 5-27
model stub exports 12-5 ARM740T protection unit loading constants 5-22
models, see ARMulator models page table model 12-17 local labels 5-11
page tables 12-15 ARM940T protection unit macros 5-42
profiler 12-12 page table model 12-17 maintenance 5-50
profiling 11-27 arm.h 13-57, 13-70, 13-77 maps 5-45
quitting from the tracer 12-6 asd in ADW/ADU 3-75 multiple register transfers 5-34
real time simulation 11-8 ASIC 3-5 see also STM, LDM
rebuilding with a new model 12-32 Assembler nesting subroutines 5-37
regular calls to the debugger 12-13 inline, armasm differences 8-7 numeric constants 5-12
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. Index-3
padding 5-50 Boolean constants, assembly language Calling
pc 5-5, 5-9, 5-11, 5-35, 5-37, 5-40 5-12 assembler from C++ 8-18
program counter 5-5, 5-9, 5-11, boot.s initialization file 10-26 C from assembly language 8-18
5-35, 5-37, 5-40 Branch instructions 5-6 C from C++ 8-18, 8-20
program-relative 5-11 scatter loading 10-32 C++ from assembler 8-25
program-relative maps 5-48 Branch instructions (Thumb) 5-8 C++ from assembly language 8-18
pseudo-instructions, see Breakpoints 4-6 language conventions 8-18
Pseudo-instructions, assembly and Angel 13-30 Calling SWIs 9-19
register-based Angel restrictions 13-30 Case rules, assembly 5-10
maps 5-47 data-dependent 3-5 Chaining exception handlers 9-39
register-relative address 5-11 MultiICE and EmbeddedICE 13-30 and Angel 13-19
relative maps 5-46 setting in ADW/ADU 3-27 Changing debugger variables 3-12
speed 5-55 setting, editing and deleting 3-26 Channel viewers, activating 3-49
stacks 5-36 simple 3-27 Channels
string constants 5-12 simple and complex 3-26 Angel channel restrictions 13-72
subroutine return 5-5 using 4-3 Characters, special 3-42
subroutines 5-15 window 3-18, 3-26 Class view window 3-64
symbols 5-52 Build log 2-13 Clock speeds 11-13
Thumb block copy 5-40 Build step 2-12 Closing
assembly language patterns 2-40, 2-48 ADW/ADU 3-10
using the APCS 6-2 Building APM 2-4
ASSERT directive 5-49, 5-59 an interworking image 2-53 Code
Assertions, and Angel debugging C++ projects in APM 2-53 ARM/Thumb 3-41
13-21 project output 2-10 density and interworking 7-2
ASSERT_ENABLED macro 13-21 variants of projects 2-12 size 5-19, 5-55
BX instruction 5-3, 5-6, 5-8, 5-16, 7-4, speed and setjmp() 11-19
8-8 Code size
B bit 0 usage 7-5 Dhrystone example 11-4
long range branching 7-5 measuring 11-3
B instruction (Thumb) 5-17 non-Thumb processors 7-5 reducing 11-16
Backtrace window 3-18, 3-33 without state change 7-5 reducing with short integers 11-17
Banked registers 9-3 bytelane.c ARMulator model 12-4 CODE16 directive 5-16, 7-4
banner.h 13-55 CODE32 directive 5-16, 7-4
Barrel shifter 5-7, 5-17 Collapsing project view 2-18
Barrel shifter (Thumb) 5-9 C Command line
Base classes arguments 3-46
in ADW/ADU 3-67 C debugger instructions 3-46
in ADW/ADU expressions 3-73 calling assembler 8-20 Command window 3-17
in mixed languages 8-19, 8-25 combining with assembler 6-2 Command-line
:BASE: operator 5-52 compiling 4-2 examples 4-2
Base register 5-46 linkage 8-18 tools 4-1
Benchmarks 11-2, 11-6 listing source 4-3, 4-9 Comments
Bit 0, use in BX instruction 7-5 using header files from C++ 8-16 assembly language 5-12
BL instruction 5-15, 8-7 C global variables from assembly inline assemblers 8-3
BL instruction (Thumb) 5-17 language 8-15 Communications
Blank templates 2-42 C library Angel communications architecture
Block copy, assembly language 5-38 and Angel 13-20 13-71
Block copy, (Thumb) 5-40 Angel SWIs 13-77 Compiler options
Call graph (profiling) 11-20, 11-21 latevia 2-24
Index-4 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
-MD- 2-9 C++ data types Debuggers
reading from a file 2-24 in mixed languages 8-19 downloading Angel 13-65
via 2-24 Debugging
Compiler, using 4-2 Angel 13-66
Complex D Angel assertions 13-21
breakpoint 3-26 decaof 2-39
watchpoint 3-29 Data abort decaxf 2-39
Concepts and terminology 3-7 exception 9-2 Deleting breakpoints 3-26
Condition code suffixes 5-18 handler 9-37, 9-43 Demon 1-6
Conditional execution (Thumb) 5-8, LDM 9-37 Destktop, APM 2-16
5-9 LDR 9-37 devclnt.c 13-97
Conditional execution, assembly 5-17, returning from 9-8 devclnt.h 13-61, 13-62
5-19 STM 9-37 devconf.h 13-29, 13-44, 13-57–13-58,
Configuring STR 9-37 13-67–13-69, 13-90
Angel 13-67 SWP 9-37 devdriv.h 13-58, 13-61
Angel run address 13-68 DATA directive 7-12 Device Data Control 13-60
ARMulator 3-57 Data maps, assembly 5-45 Device driver layer (Angel) 13-75
EmbeddedICE 3-60 Data processing instructions 5-6 Device drivers
Remote_A 3-59 Data processing instructions (Thumb) Angel 13-61
tools in APM 2-21 5-8 DeviceIdent structure 13-61
Console window 3-16 Data size, measuring 11-3 devices.c 13-55, 13-61
Constants, assembly 5-12 Data structure, assembly 5-45 devices.h 13-62
Constants, inline assemblers 8-5 Data types 8-19 Dhrystone
Context switch 9-32 DC_INIT 13-62 code size 11-4
and Angel 13-36 DC_RECEIVE_MODE 13-62 example 11-4
Controlling use of licensed software DC_RESET 13-62 map files 11-13
A-2 DC_RX_PACKET_FLOW 13-63 Directives, assembler
ControlRx 13-61, 13-63 DC_SET_PARAMS 13-63 ENTRY 10-6
ControlTx 13-61, 13-63 Debug agent 3-6 Directives, assembly language
Converting project format 2-31 Debug interaction SWIs 13-92 ALIGN 5-50
Coprocessors Debugger AREA 5-11, 5-13
ARMulator models 12-3, 12-4, breakpoints 4-6 AREA (literal pools) 5-25
12-24 closing down 3-10 ASSERT 5-49, 5-59
undefined instruction handlers 9-35 command line instructions 3-46 CODE16 5-16, 7-4
CPSR 5-5, 5-17, 9-5 debugger variables 4-9 CODE32 5-16, 7-4
interworking ARM and Thumb 7-2 executing a program 4-8 DATA 7-12
Crash Barrier 13-66 extra tools with C++ 3-63 END 5-14
Current program status register 5-5, .ini file 4-6 END (literal pools) 5-25
5-17 internals window 3-18 ENTRY 5-14
Customizing license file A-9 introduction to 3-2 IMPORT 8-15
Cycle counts program variables 4-9 MACRO 5-42
Dhrystone example 11-6 see also ADW/ADU MAP 5-45
displaying 11-6 single stepping 4-8 ROUT 5-11
C++ starting 3-9 # 5-45
asm 8-2 table formats in ADW/ADU 3-74 Disassembly
calling conventions 8-19 using 4-2, 4-6 mode 3-41
creating APM projects 2-54 watchpoints 4-7 window 3-21
menu 3-62 Debugger variables Display formats 3-38
string literal 8-2 viewing and changing 3-12 Download agent area 13-61
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. Index-5
dummymmu.c ARMulator model reentrant 9-23 F
12-4, 12-24 reset 9-34
DWARF 3-74 returning from 9-5 Fault address register 9-38
DWARF1 limitations 3-75 subroutines in 9-46 FEATURE line in license file A-9
SWI 9-14, 9-15, 9-16, 9-17, 9-43 File formats
Thumb 9-41 Intel 32-bit hex 10-35
E undefined instruction 9-35, 9-43 Intellec hex 10-35
Exceptions 9-2 Motorola 32-bit hex 10-35
Editing and Angel 13-19, 13-94 Files
breakpoints 3-26 data abort 9-2, 9-8 adding to project 2-8
project source files 2-19 entering 9-5 armsd.map 11-9, 12-28
ELF FIQ 9-2, 9-7 armul.cnf 12-6, 12-28, 12-34
converting to binary ROM formats initialization code for ROM images boot.s 10-26
10-34 10-6 init.s 10-13
file format 1-6 installing handlers 9-9 memory map 3-55
Embedded C library, ROM applications IRQ 9-2, 9-7 models.h 12-5
10-21 leaving 9-5 profiler.c 12-12
EmbeddedICE 3-5, 3-6 prefetch abort 9-2, 9-8 project 2-5
configuring 3-60 priorities 9-3 Finding a license file A-11
END directive 5-14 reporting in Angel 13-94 FIQ 9-2, 9-23
END directive (literal pools) 5-25 reset 9-2 and Angel 13-10, 13-18
ENTRY directive 5-14 response by processors 9-5 handler 9-7, 9-23, 9-43
Entry point, assembly 5-14 returning from 9-7, 9-43 registers 9-23
Environment variable SWI 9-2, 9-7 Flash download 3-48, 13-65
ARMLMD_LICENSE_FILE A-7 SWI handlers 9-14, 9-15, 9-16, 9-17 and Angel 13-25
errno, C library variable 13-88 undefined instruction 9-2, 9-7 Flat profile 11-20
Ethernet use of modes 9-3 FlexLM license management A-2
Angel support 13-25, 13-49 use of registers 9-3 installing A-3
Fusion IP stack for Angel 13-96 vector table 9-3, 9-9 multiple licenses A-12
Evaluating expressions 3-71 Executable image versions A-12
Examining APM template 2-53 Force building a project 2-12
memory 3-13, 3-40 Execution Formatting displayed variables 3-38
search paths 3-36 profile 11-20 FPA
source files 3-37 speed 5-19, 5-55, 7-2, 7-19, 9-23 undefined instruction handlers 9-35
variables 3-37 stopping 3-26, 3-34 Functions
example.c ARMulator model 12-4 window 3-15 call graph count 11-21
Exception handlers Exiting debugger 3-10 names window 3-22, 3-43
and Angel 13-19 Expanding project view 2-18 stepping in to 3-34
chaining 9-39 Expressions stepping out of 3-34
data abort 9-37, 9-43 evaluating, in ADW/ADU 3-71 Fusion IP stack 13-96
extending 9-39 formatting watches 3-69
FIQ 9-43 regular 3-42
installing 9-9 setting watches in ADW/ADU 3-66 G
installing from C 9-11 window 3-22
installing on reset 9-9 Extending exception handlers 9-39 GETSOURCE macro 13-40, 13-44,
interrupt 9-23 extern "C" 8-16, 8-18, 8-20 13-55, 13-57, 13-98
IRQ 9-43 E5 13-66 Global hierarchy, in ADW/ADU 3-64
nested 9-23 Global memory map file 3-55
prefetch abort 9-36, 9-43 Globals window 3-22
Index-6 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
H constants 8-5 PUSH (Thumb) 5-40
corrupted registers 8-3 STM 5-34, 5-48
Halfwords CPSR 8-6 STM (Thumb) 5-40
in load and store instructions 5-6 C, C++ expressions 8-5, 8-8 STR 5-45
reading and writing in ADW/ADU DC directives 8-6 SWI 8-7, 9-14
3-47 examples 8-10 SWIs
to reduce code size 11-17 floating point instructions 8-8 Thumb 9-44
HANDLE_INTERRUPTS_ON_FIQ instruction expansion 8-6 integer-like structures 6-14
13-39, 13-59 interrupts 8-10 Interrupt handlers 9-23
HANDLE_INTERRUPTS_ON_IRQ invoking 8-2 Angel 13-63
13-59 labels 8-3 Interrupts
Heartbeats (Angel) 13-75 LDM instruction 8-8 and Angel 13-39
Help, online 2-2, 3-2 long multiply 8-13 Angel Fusion stack 13-98
Hierarchy, project 2-26 MUL instruction 8-6 prioritization 9-30
High-level symbols 3-43 multiple lines 8-3 ROM applications 10-8
Host peripherals, accessing 3-5 operand expressions 8-5 source for Angel 13-59
physical registers 8-5, 8-8 interrupt.s 13-57
register corruption 8-7, 8-8 Interval
I restrictions 8-8 profiling 3-53
saving registers 8-9 Interworking ARM and Thumb 2-53,
Illegal address 9-2 sign extension 8-5 7-1
Image stacking registers 8-9 APCS 7-2, 7-13, 7-23
reducing size of 11-16 STM instruction 8-8 APM template 2-53, 7-25
reloading 3-11 storage declaration 8-6 assembly language 7-4, 7-21
stepping through 3-34 subroutine parameters 8-7 BX instruction 7-4
Immediate constants (ARM) 5-22 SWI instruction 8-7 C 7-16
implicit this 8-18 writing to pc 8-2, 8-5 C and C++ 7-13
IMPORT directive 8-15 # 8-5 C and C++ libraries 7-17, 7-19
:INDEX: operator 5-52 Inline strings 11-3 C libraries 7-28
Indicators, @ and ^ 3-43 Installing CODE16 directive 7-4, 7-25
Indirection 3-40 FlexLM A-3 CODE32 directive 7-4, 7-25
Initialization Instruction expansion 8-6 compatibility of options 7-13
Angel 13-62 Instruction set compiler command-line options
INITMMU macro 13-56 ARM 5-6 7-17
INITTIMER macro 13-56, 13-68 Thumb 5-8 compiling code 7-13
init.s initialization file 10-13 Instruction tracing 11-27 CPSR 7-2, 7-7
Inline assemblers 8-2 Instructions, assembly language data in Thumb code 7-12
accessing structures 8-15 ADD 5-52 detecting calls 7-18
ADR pseudo-instruction 8-7 BL 5-15, 8-7 duplicate functions 7-19
ADRL pseudo-instruction 8-7 BX 5-3, 5-16, 7-4 examples 7-7, 7-9, 7-16, 7-20, 7-21
ALU flags 8-6, 8-8 BX (Thumb) 5-8 exceptions 7-2
BL instruction 8-7 LDM 5-34, 5-48 function pointers 7-17
branches 8-3 LDM (Thumb) 5-40 image template 7-25
BX instruction 8-8 LDR 5-45 indirect calls 7-17
C global variables 8-15 MOV 5-22, 5-47 leaf functions 7-14
C variables 8-5, 8-9 MRS 5-7 mixed languages 7-21, 7-23
commas 8-8 MSR 5-7 modifying existing project 7-27
comments 8-3 MVN 5-22 MOV pc,lr 7-8
complex expressions 8-5 POP (Thumb) 5-40 non-Thumb processors 7-14
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. Index-7
procedure call standards 7-2 License management utilities A-14 list order 3-23
rules 7-17 lmchecksum A-14 Window 3-23
SPSR 7-2 lmdiag A-15
subroutines 7-8 lmdown A-15
TPCS 7-2 lmhostid A-16 M
UNIX 7-20 lmremove A-16
veneers 7-2, 7-13, 7-14, 7-15, 7-21 lmreread A-16 MACRO directive 5-42
-16 assembler option 7-25 lmstat A-17 Macros
IntHandlerID structure 13-61 lmver A-17 RegionInit 10-26, 10-30
Introduction to debugging 3-2 License server software A-6 makelo.c 13-55, 13-57, 13-58, 13-61
IRQ 9-23 Licensed software A-1 Managing projects, see APM
and Angel 13-10, 13-18 running A-7 Mangling symbol names 8-18, 8-20
Angel processing of 13-38 Licenses, multiple A-12 MAP directive 5-45
handler 9-7, 9-43 Line length, assembly language 5-11 Map files 11-9
IRQ exception 9-2 Link register 5-4, 5-15, 9-3 armsd.map 11-9
I/O devices, ROM applications 10-7 Linker attribute conflict 10-39 Dhrystone example 11-13
Linking format 11-10
and APM build steps patterns 2-12 Maps, assembly language
J and assembly language labels 5-11 absolute 5-45
and interworking 7-13, 7-18 program-relative 5-48
JTAG 3-5 and the AREA directive 5-13 register-based 5-47
Jump table 9-15, 9-44 Angel C libraries 13-20 relative 5-46
Jump tables, assembly 5-29 attribute conflicts 10-39 Matching strings 3-42
Jumps, and code speed 11-19 configuring in APM 2-21 Member functions in ADW/ADU
improving image size 11-16 expressions 3-72
introduction 4-4 Memory
K minimal Angel 13-23 displaying contents 4-3
the embedded C library 10-9, 10-39 examining 3-13, 3-40
KickStartFn() 13-63 Literal pools, assembly language 5-25 flash 3-48
lmchecksum utility A-14 map files 3-55
lmdiag utility A-15 simulating in map file 11-9
L lmdown utility A-15 window 3-23
lmhostid utility A-16 Memory management unit 10-7
Labels, assembly 5-11 lmremove utility A-16 Memory map
Labels, inline assemblers 8-6 lmreread utility A-16 Angel 13-60
LDM instruction 5-34, 5-48 lmstat utility A-17 configuring for Angel 13-67
Thumb 5-40 lmver utility A-17 layout 10-3
LDR loadagent command 13-61 organization of 10-3
instruction 5-45 Loading constants, assembly language RAM at address 0 10-3
pseudo-instruction 5-22, 5-25, 5-31 5-22 ROM at address 0 10-3
Leaf functions 7-14 Local labels, assembly language 5-11 Menu bar 3-8
Library Local memory map file 3-56 Menus
adw_cpp.dll 3-62 Locals window 3-22 C++ 3-62
License file Location of APM templates 2-53 window-specific 3-25
customizing A-9 Log of project building 2-13 MINIMAL_ANGEL macro 13-23,
finding A-11 Logic analyzers 13-47
obtaining A-4 debugging Angel 13-66 Mixed language programming
typical A-9 lolevel.s 13-57 interworking ARM and Thumb
License management questions A-18 Low-level symbols 3-43 7-21, 7-23
Index-8 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
models.h file 12-5 P porting
Mode, disassembly 3-41 Angel 13-41
Modifying debugger variables 3-12 Padding 5-50 choosing an Angel template 13-43
MOV instruction 5-22, 5-47 Page table model Power-up 9-2
MRS instruction 5-7 access permissions 12-16 Preferences, in APM 2-32
MSR instruction 5-7 ARM740T protection unit 12-17 Prefetch abort 9-2
Multi-ICE, debugging Angel 13-66 ARM810 flags 12-15 and Angel 13-5, 13-19, 13-20
Multiple register transfers 5-34 ARM940T flags 12-15 handler 9-36, 9-43
Multiple register transfers, see also ARM940T protection unit 12-17 returning from 9-8
STM, LDM bufferable (B) bit 12-16 Process control blocks 9-32
multiplication, returning a 64-bit result cacheable (C) bit 12-16 Processor exception vectors
6-16 contents 12-16 and Angel 13-69
MVN instruction 5-22 domain access control 12-15 Processor mode 5-4
domain field 12-16 and Angel stacks 13-37, 13-60
initializing the MMU 12-15 Processor time analysis 3-43
N physical base address 12-16 Processors
region size 12-16 clock speeds 11-13
Naming projects 2-29 regions in 12-16 responding to exceptions 9-5
Nested interrupts 9-24 SA-110 flags 12-15 Profiler 11-20, 12-12
Nested SWIs 9-18 translation faults 12-16 cache misses 12-12
Nesting subroutines, assembly language translation table base register 12-15 configuring under ARMulator
5-37 updateable (U) bit 12-16 12-12
Next line, stepping to 3-34 virtual base address 12-16 instruction counts 12-12
neXus 13-66 pagetab.c ARMulator model 12-3 profiling interval 12-12
non integer-like structures 6-16 Parameters (assembly macros) 5-42 profiler.c
noos.c ARMulator model 12-4 Partitions, in APM 2-25 ARMulator model 12-3
Numeric constants, assembly language passing structures 6-13 file 12-12
5-12 Paths, search 3-36 Profiling 3-43, 11-2, 11-20
Patterns, build step 2-40, 2-48 and Angel timers 13-59
PC sampling 11-21 call graph 11-20
O PCMCIA Ethernet card 13-96 collecting data 11-21
pc, assembly 5-37 creating report 11-22
Object library, APM template 2-53 pc, assembly language 5-5, 5-9, 5-11, execution profile 11-20
Olicom 13-96 5-35, 5-37, 5-40 flat 11-20
Online help, accessing 2-2, 3-2 Performance instruction tracing 11-27
Operand expressions, inline assemblers improving 11-16 interval, setting 3-53
8-5 measuring 11-6 sorts example 11-23
Operators in ADW/ADU expressions Peripherals, accessing 3-5 Program counter 5-9, 5-11, 5-35, 5-37,
3-72 PERMITTED macro 13-60, 13-67 5-40
Operators, assembly language PID board Program counter, assembly 5-5, 5-37
:BASE: 5-52 and Angel 13-14 Program image
:INDEX: 5-52 Angel device drivers 13-61 reloading 3-11
:AND: 5-50 Angel porting 13-41 stepping through 3-34
Optimization PMCIA, and Angel 13-59 Program-relative
and DWARF 3-75 Pointers address 5-11
and DWARF2 debug tables 3-75 data members 8-19 maps 5-48
Overloaded functions in ADW/ADU member functions 8-19 Project
expressions 3-72 Polled devices, and Angel 13-64 adding files to 2-8
POP instruction (Thumb) 5-40 building 2-10
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. Index-9
editing source files 2-19 Register-based maps 5-47 writing code for ROM 10-24, 10-28
expanding/collapsing view of 2-18 Register-relative address 5-11 Scope 5-11
files 2-5 Registers 5-4 Search paths
force building 2-12 displaying contents 4-3 viewing 3-36
format conversion 2-31 halting if changed 3-29 window 3-24
hierarchy 2-26 REMAP 10-4 Searching for license file A-11
manager (APM), see APM usage 6-10 Semihosting 13-3, 13-15, 13-17
naming 2-29 window 3-24 enabling and disabling 13-4, 13-15
sub-projects 2-4 Regular expressions 3-42 Semihosting SWIs 13-77
templates 2-25, 2-40 Relative maps 5-46 SYS_CLOCK 13-87
variables 2-27 Reloading an image 3-11 SYS_CLOSE 13-80
variants 2-28 REMAP register 10-4 SYS_ELAPSED 13-91
viewing 2-9 Remote debug information 3-41 SYS_ERRNO 13-88
window 2-16 Remote_A 3-6 SYS_FLEN 13-85
Properties of variables 3-39 configuring 3-59 SYS_GET_CMDLINE 13-89
Prototype statement 5-42 Reset exception 9-2 SYS_HEAPINFO 13-90
Pseudo-instructions, assembly language handler 9-34 SYS_ISERROR 13-83
ADR 5-27, 5-52 RESET vector 10-4 SYS_ISTTY 13-84
ADR (Thumb) 5-27 Return address 9-6 SYS_OPEN 13-79
ADRL 5-27, 5-52 Return instruction 9-6 SYS_READ 13-82
LDR 5-22, 5-25, 5-31 returning structures 6-13 SYS_READC 13-83
LDR (literal pools) 5-25 ROADDR (Angel) 13-27, 13-47, SYS_REMOVE 13-86
PUSH instruction (Thumb) 5-40 13-68, 13-69 SYS_RENAME 13-86
ROM SYS_SEEK 13-84
at address 0 10-3 SYS_SYSTEM 13-88
Q measuring requirements 11-4 SYS_TIME 13-87
writing code for 10-1 SYS_TMPNAM 13-85
Quitting ROMBase macro 13-69 SYS_WRITE 13-81
ADW/ADU 3-10 ROMulator 13-66 SYS_WRITEC 13-80
APM 2-4 ROUT directive 5-11 SYS_WRITEO 13-80
RTOS serlasm.s 13-33
and Angel 13-18 serlock 13-33
R and context switching 13-36 Server for license management A-2
Run to cursor 3-34 SERVER line in license file A-9
RAM Running licensed software A-7 setjmp()
at address 0 10-3 RWADDR (Angel) 13-27, 13-47, code speed 11-19
measuring requirements 11-4 13-68, 13-69 Setting
RB_ Angel register blocks 13-36 breakpoints 3-26
RDI (Remote Debug Interface) 3-6 environment variable A-7
log window 3-24, 3-41 S profiling interval 3-53
Real-time addresses 3-5 simple breakpoint 3-27
Real-time simulation 11-8 Saved program status register 5-5 simple watchpoint 3-29
References 8-19 Scatter load description file Short integers
RegionInit macro (scatter loading) examples 10-25, 10-29 to reduce code size 11-17
10-26, 10-30 Scatter loading Simple
Register access (Thumb) 5-9 assembly veneers 10-33 breakpoint 3-26, 3-27
Register banks 5-4 function pointers 10-32 watchpoint 3-29
Register-based long-distance branching 10-32 Simulation
symbols 5-52 range restrictions 10-32 real-time 11-8
Index-10 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
reducing time taken 11-15 Storage declaration, inline assemblers SYS_READ 13-82
Single stepping 3-5 8-6 SYS_READC 13-83
Soft reset 9-2 STR instruction 5-45 SYS_REMOVE 13-86
Software String constants, assembly language SYS_RENAME 13-86
development toolkit (SDT) 3-1 5-12 SYS_SEEK 13-84
licensed A-1 String copying SYS_SYSTEM 13-88
software FPA emulator assembler 8-20 SYS_TIME 13-87
undefined instruction handlers 9-35 Strings SYS_TMPNAM 13-85
Software interrupt, see SWIs specifying and matching 3-42 SYS_WRITE 13-81
Sorts profiling example 11-23 structure passing and returning 6-13 SYS_WRITEC 13-80
Source files Sub-projects 2-4 SYS_WRITEO 13-80
editing 2-19 Subroutines, assembly language 5-15
examining 3-37 Supervisor mode 9-17
in APM 2-35 and Angel 13-19 T
list window 3-24 entering from Angel 13-92
window 3-25 Supervisor stack 9-17 target.s 13-44, 13-55, 13-68, 13-69,
Special characters 3-42 suppasm.s 13-56, 13-57, 13-61, 13-98 13-98
Specifying strings 3-42 SWI exception 9-2 Task management
Sprintf() SWI instruction 8-7, 9-14 Angel 13-31, 13-77
as format string in ADW/ADU 3-70 Thumb 9-44 Task Queue Items 13-36
SPSR 5-5, 9-3, 9-5 SWIs tasm 5-10
interworking ARM and Thumb 7-2 Angel C library support SWIs 13-77 TDCC 13-59, 13-71
T bit 9-44 ARMulator 12-26 Templates
Stacks 5-4, 5-36, 9-3 calling 9-19 APM, location of 2-53
Angel 13-37 configuring for Angel 13-70 blank 2-42
initialization code for ROM images debug interaction SWIs 13-92 project 2-25, 2-40
10-7 handlers 9-14, 9-15, 9-16, 9-17, using APM 2-54
stack pointer 9-3 9-43 Terminology and concepts 3-7
supervisor 9-17 indirect 9-21 this, implicit 8-18
Starting returning from 9-7 Thumb
ADW/ADU 3-9 SYS_Write0 10-37 and scatter loading 10-33
APM 2-4 Thumb state 9-44 and __irq 9-24
license server software A-6 0x80 - 0x88 12-26 Angel breakpoint instruction 13-30
startrom.s 13-56 0x90 - 0x98 12-26 Angel SWI number 13-70
STARTUPCODE macro 13-56 Symbol names, mangling 8-18, 8-20 APM template 2-42
Statistics Symbols, high- and low-level 3-43 breakpoint setting 3-31
ARMulator 11-6 Symbols, register-based 5-52 BX instruction 5-16, 7-5
memory 11-12 System decoder 10-4 C libraries 7-19
Status bar 3-8 System mode 9-46 changing to Thumb state, example
Status flags 5-17 SYS_CLOCK 13-87 7-6
Stepping through an image 3-34 SYS_CLOSE 13-80 channel viewer 3-49
Steps, build 2-12 SYS_ERRNO 13-88 code for ROM applications 10-9
STM instruction 5-34, 5-48 SYS_FLEN 13-85 code, interworking template 2-53
Thumb 5-40 SYS_GET_CMDLINE 13-89 conditional execution 5-17
Stopping SYS_GET_ELAPSED 13-91 C++ APM template 2-53
ADW/ADU 3-10 SYS_GET_HEAPINFO 13-90 data in code areas 7-12
APM 2-4 SYS_ISERROR 13-83 debug communications channel
execution 3-34 SYS_ISTTY 13-84 3-49, 13-71
SYS_OPEN 13-79 direct loading 5-24
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. Index-11
disassembly mode 3-21, 3-41 enabling 12-8 changing contents of, in ADW/ADU
example assembly language 5-16 events 12-7, 12-8 3-70
exception handler 9-41 flushing output to the trace file 12-6 formatting watches 3-69
handling exceptions 9-41 idle cycles 12-7 halt if changed 3-29
inline assemblers 8-2 initializing 12-6 project 2-27
instruction set 5-8 output to the RDI log window 12-7 properties of 3-39
instruction set overview 5-8 quitting from 12-6 setting watches, in ADW/ADU
interworking libraries 7-19 source of trace data 12-7 3-66
interworking veneers and profiling trace file 12-7 viewing 3-37
restrictions 11-21 tracing options 12-7 $memstate 12-21
interworking with ARM 7-2, 7-8 unaccounted RDI access 12-7 $statistics 12-21
LDM and STM instructions 5-40 tracer.c ARMulator model 12-3, 12-4 Variants of projects 2-28
popping pc 5-37 Tracer_Close ARMulator function building 2-12
procedure call standard 6-11 12-6 Vector table 9-3, 9-9, 9-23, 9-41
return address 9-43 Tracer_Dispatch ARMulator function Vector table and caches 9-13
using duplicate function names 12-6 Vectors
7-19 Tracer_Flush ARMulator function exception 10-6
Time 12-6 RESET 10-4
analysis 3-43 Tracer_Open ARMulator function VENDOR line in license file A-9
Tool configuration in APM 2-21 12-6 Veneers, see Interworking
Toolbar 3-8 Tracing 11-27 View
Toolkit for software development 3-1 trickbox.c ARMulator model 12-4 menu 3-14
Tools for license management A-14 of project, expanding/collapsing
TPCS 6-11 2-18
interworking ARM and Thumb 7-2 U window 2-20
register names and usage 6-11 Viewing
TQI 13-36, 13-37 UDP/IP 13-96 code in ADW/ADU 3-65
Trace files Undefined instruction exception 9-2 debugger variables 3-12
address 12-10 Undefined instruction handler 9-7, files, in APM 2-38
disassembly 12-11 9-35, 9-43 memory 3-13, 3-40
event lines 12-9 Undefined symbols project 2-9
events 12-11 ROM code 10-37 search paths 3-36
instruction addresses 12-11 Unhandled ADP_Stopped exception source files 3-37
instruction lines 12-9, 12-11 13-94 variables 3-37
locked access 12-10 UNMAPROM macro 13-56, 13-69 watchpoints 3-29
memory access 12-10 User mode 9-3
memory cycles 12-10 Using
memory lines 12-9, 12-10 ADW/ADU with C++ 3-62 W
opcode 12-11 APM 2-4
opcode fetch 12-10 APM templates 2-54 Watch window, in ADW/ADU 3-66
output 12-9 APM with C++ 2-53 Watchpoints 4-7
read/write operations 12-10 the class view window 3-64 simple 3-29
return address 12-10 Utilities for license management A-14 simple and complex 3-26, 3-29
speculative instruction fetch 12-10 viewing 3-29
Tracer window 3-25
configuring under ARMulator 12-6 V Window
debug support 12-8 backtrace 3-18, 3-33
disabling 12-8 validate.c ARMulator model 12-4 breakpoints 3-18, 3-26
disassembling instructions 12-7 Variables command 3-17
Index-12 Copyright © 1997 and 1998 ARM Limited. All rights reserved. ARM DUI 0040D
console 3-16 Z
debugger internals 3-18
disassembly 3-21 Zero wait state memory system 12-19
execution 3-15
expression 3-22
function names 3-22, 3-43 Numerics
globals 3-22
locals 3-22 0-init data 11-4
low level symbols 3-23 64-bit
memory 3-23 integer addition 6-6
project 2-16 multiplication result 6-16
RDI log 3-24, 3-41
registers 3-24
search paths 3-24 Symbols
source file 3-25
source files list 3-24 # directive 5-45
view 2-20 $semihosting_enabled variable 13-4,
watch window 3-66 13-15
watchpoints 3-25 $top_of_memory debugger variable
winglass.c ARMulator model 12-3 13-90
Writing code for ROM 10-1 $vector_catch debugger variable 13-94
attribute conflict in linker 10-39 @ and ^ indicators 3-43
C library 10-9
common problems 10-37
converting ELF output 10-34
critical I/O devices 10-7
embedded C library 10-21
enabling interrupts 10-8
entry point 10-6
exception vectors 10-6
initialization 10-6
main function 10-9
memory for C code 10-8
MMU 10-7
processor mode 10-8
processor state 10-9
RAM at address 0 10-3
RAM variables 10-7
ROM at address 0 10-3, 10-10,
10-19
ROM at its base address 10-10
scatter loading 10-24, 10-28
execution regions 10-26, 10-30
variables 10-8
stack pointers 10-7
suitable output formats 10-35
SWI SYS_Write0 10-37
undefined symbols 10-37
undefined __main 10-39
ARM DUI 0040D Copyright © 1997 and 1998 ARM Limited. All rights reserved. Index-13