1
MM
MMOO
OOTT
TTOO
OORR
RROO
OOLL
LLAA
AA
PP
PPoo
ooww
wwee
eerr
rrPP
PPCC
CC
EE
EExx
xxcc
ccii
iimm
mmee
eerr
rr
LL
LLaa
aabb
bboo
oorr
rraa
aatt
ttoo
oorr
rryy
yy
MM
MMaa
aann
nnuu
uuaa
aall
ll
Jose I. Quiñones, Noel Serrano, Walter Guiot, Luis Narváez, Eisen Montalvo
Department of Electrical and Computer Engineering
University of Puerto Rico-Mayagüez
Chuck Corley
PowerPC Applications Engineering
Motorola
Editor: José L. Cruz Rivera
Department of Electrical and Computer Engineering
University of Puerto Rico-Mayagüez
VOLUME I
Instructor’s Manual
2
Motorola Inc. 1999
Portions hereof International Business Machines Corp. 1991–1995. All rights reserved.
This document contains information on a new product under development by Motorola and IBM. Motorola and IBM re-
serve the right to change or discontinue this product without notice. Information in this document is provided solely to
enable system and software implementers to use PowerPC microprocessors. There are no express or implied copyright or
patent licenses granted hereunder by Motorola or IBM to design, modify the design of, or fabricate circuits based on the
information in this document. The PowerPC 60x microprocessors embody the intellectual property of Motorola and of
IBM. However, neither Motorola nor IBM assumes any responsibility or liability as to any aspects of the performance,
operation, or other attributes of the microprocessor as marketed by the other party or by any third party. Neither Motorola
nor IBM is to be considered an agent or representative of the other, and neither has assumed, created, or granted hereby any
right or authority to the other, or to any third party, to assume or create any express or implied obligations on its behalf.
Information such as data sheets, as well as sales terms and conditions such as prices, schedules, and support, for the prod-
uct may vary as between parties selling the product. Accordingly, customers wishing to learn more information about the
products as marketed by a given party should contact that party. Both Motorola and IBM reserve the right to modify this
manual and/or any of the products as described herein without further notice.
NOTHING IN THIS MANUAL, NOR IN ANY OF THE ERRATA SHEETS, DATA SHEETS, AND OTHER SUPPORTING
DOCUMENTATION, SHALL BE INTERPRETED AS THE CONVEYANCE BY MOTOROLA OR IBM OF AN EXPRESS
WARRANTY OF ANY KIND OR IMPLIED WARRANTY, REPRESENTATION, OR GUARANTEE REGARDING THE
MERCHANTABILITY OR FITNESS OF THE PRODUCTS FOR ANY PARTICULAR PURPOSE.
Neither Motorola nor IBM assumes any liability or obligation for damages of any kind arising out of the application or
use of these materials. Any warranty or other obligations as to the products described herein shall be undertaken solely by
the marketing party to the customer, under a separate sale agreement between the marketing party and the customer. In the
absence of such an agreement, no liability is assumed by Motorola, IBM, or the marketing party for any damages, actual or
otherwise. “Typical” parameters can and do vary in different applications. All operating parameters, including “Typicals,”
must be validated for each customer application by customer’s technical experts. Neither Motorola nor IBM convey any
license under their respective intellectual property rights nor the rights of others. Neither Motorola nor IBM makes any
claim, warranty, or representation, express or implied, that the products described in this manual are designed, intended, or
authorized for use as components in systems intended for surgical implant into the body, or other applications intended
to support or sustain life, or for any other application in which the failure of the product could create a situation where
personal injury or death may occur. Should customer purchase or use the products for any such unintended or unauthor-
ized application, customer shall indemnify and hold Motorola and IBM and their respective officers, employees, subsidi-
aries, affiliates, and distributors harmless against all claims, costs, damages, and expenses, and reasonable attorney fees
arising out of, directly or indirectly, any claim of personal injury or death associated with such unintended or unauthor-
ized use, even if such claim alleges that Motorola or IBM was negligent regarding the design or manufacture of the part.
Motorola and are registered trademarks of Motorola, Inc. Motorola, Inc. is an Equal Opportunity/Affirmative Action Em-
ployer. IBM and IBM logo are registered trademarks, and IBM Microelectronics is a trademark of International Business
Machines Corp. The PowerPC name, PowerPC logotype, and PowerPC 601 are trademarks of International Business Ma-
chines Corp. used by Motorola under license from International Business Machines Corp. International Business Ma-
chines Corp. is an Equal Opportunity/Affirmative Action Employer.
DIS CLAIM ERS
3
This laboratory manual contains 13 lab experiments for the PowerPC Excimer Board presented in
an increasing order of complexity. The experiments range from memory mapping problems and
system benchmarking to integer to floating point number representation conversion. It is as-
sumed that the student has a basic understanding of C and assembly languages. There is a natural
progression in the lab experiments leading up to the Dhrystone and Linpack benchmarking of the
PowerPC603e that forms the basis of the Excimer board. Specifically, the experiments guide the
student through the following topics: code compilation, code download, DINK functions (resi-
dent monitor program), keyboard input, assembly language programming, and linking assembly
language to C code. There are also experiments on memory mapping and Flash ROM program-
ming.
Each lab experiment is structured as follows: Problem Statement, Objectives, Background Infor-
mation, Procedure, Questions, and References. The Problem Statement provides a brief indica-
tion as to the tasks that will be performed. The Objectives section presents the specific educa-
tional objectives that will be met upon successful completion of the lab experiment. The Back-
ground information section presents a brief description of the theory behind the devices, instruc-
tions, functional units, and/or methods to be followed in the conduction of the experiment. The
Procedure section presents a step-by-step guide to the experiment. The Questions section seeks
to guide the student through a meaningful analysis of what he/she has performed as part of the
experiment. Finally, the References section presents additional references with material that is
useful for the experiment at hand. In addition to these sections, the Instructor’s Manual contains
a Results and a Troubleshooting section.
INT RODUC TION
4
This laboratory manual contains experiments designed to familiarize students with the PowerPC
architecture via the Excimer Laboratory Board. The lab manual is not meant to serve as a stand-
alone textbook on the PowerPC instruction set architecture (ISA), but rather is designed as a
companion to any PowerPC book or technical reference. Each experiment is designed so that
students will end up with a significant number of useful subroutines that can be used in other
more complex programming problems. Additional references to the PowerPC architecture and
the Excimer board may be found at http://www.motorola.com/SPS/PowerPC/teksupport.
5
Experiment #1: Metaware Tutorial
Write and compile a simple C program.
6
Experiment #2: DINK Tutorial
Download the program to Excimer and use some utilities.
10
Experiment #3: Useful DINK Functions
Write a program that will get input from KB and echo to display. Discuss various utilities of interest.
14
Experiment #4: Excimer Memory Map
Compile, download, and execute a C program which blinks the on-board LEDs
18
Experiment #5: LED Control from PC Keyboard
Write and debug a C program to turn the on-board LEDs on and off for varying integer counts.
23
Experiment #6: A Simple Scanf Function for Excimer
Develop a C function for taking character input from the terminal emulator’s keyboard attached to Excimer
through the serial port and converting number characters to decimal values used in other programs.
26
Experiment #7: Introduction to Assembly Language Programming
Write a simple assembly language program.
32
Experiment #8: Linking Assembly Language and C code
Link previous code fragments.
41
Experiment #9: Converting Integers to Floating Point
Develop an assembly language subroutine to convert the 64 bit integer value read from the PowerPC time
base facility to a 64 bit (double) floating point number representing seconds. (Contributed by Chuck Cor-
ley, Motorola)
52
Experiment #10: Dhrystone Benchmarking
Write and debug a C program to count the integer number of cycles required to execute the Dhrystone
benchmark.
63
Experiment #11: Linpack Benchmarking
Write and debug a C program to time in microseconds (floating point) the execution of the Linpack bench-
mark.
72
Experiment #12: Cache Impact on Benchmark Metrics
Write a single program to time the performance of Dhrystone and Linpack with the caches enabled and dis-
abled.
76
Experiment #13: Flash ROM
Write a program that copies itself into Flash ROM and begins executing from there.
80
CONTENTS
6
Metaware Tutorial
Problem Statement:
In this experiment the student will develop and compile a C program that will calculate the
first 12 Fibonacci Numbers using the Metaware PowerPC compiler. (Contributed by Noel
Serrano).
Objectives:
Upon completion of this laboratory experience, students will be able to:
write, debug and compile a C program using the Metaware and Code Warrior compilers
write a recursive function that will generate the first 12 Fibonacci Numbers
Background Information:
This experiment is designed to take you through the major steps required to implement a simple
algorithm for the generation of the first 12 Fibonacci numbers using the Metaware compilers for
the Excimer board. The Metaware compiler facilitates code writing, debugging, and optimization.
More information on the compiler may be obtained from www.metaware.com .
The Fibonacci sequence represents a series that has as its first two elements 0 and 1. The re-
maining elements can be obtained by simply adding the last two numbers to get the next. For ex-
ample, the first 12 Fibonacci Numbers (the first element in the sequence, 0, is not included) are:
1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89
Experiment
1
7
The Fibonacci numbers arose from the solution to the following problem posed in the year 1225:
Suppose we have one pair of rabbits that can produce another pair of productive offspring when
they reach the age of 1 month and that each successive pair of offspring can do the same. Fur-
thermore, assume the rabbits never die. How many rabbits will there be after n months? The
solution is as follows: If after n months there are kn pairs of rabbits, the number of pairs in month
n+ 1 will be kn plus the number of new pairs born. However, since new pairs are only born to
pairs at least 1 month old, there will be kn-1 new pairs, that is kn+1 = kn + kn-1, which is simply
the rule for generating the Fibonacci Numbers. More information on the fascinating world of Fi-
bonacci Numbers and their applications can be found in
http://pass.maths.org.uk/issue3/fibonacci/index.html .
Procedure:
1. Write a C language program that will calculate the first 12 Fibonacci numbers.
Hint: Use a recursive function.
2. To be able to print the numbers in the DINK32 interface (this will be discussed in more
detail in future experiments) you will need to add the following code to your program to
redefine the default printf function with the one provided by DINK. Also the printf
function should contain only one variable.
#define printf dink_printf
unsigned long (*dink_printf)() = (unsigned long (*)())) 0x6270;
3. Type your program to a text file using notepad or edit and save it in the directory you
have chosen to contain your code.
4. Compile the C code with the hcppc command included with the Metaware C compiler
using the following command on the DOS command prompt :
hcppc –Hppc603 –c file.c
8
Note: “file.c” stands for the C code file. You may name your C code file as you wish, but
remember to use the chosen name in the hcppc command. The result from this command
will be “file.o”, which is the object file. For more information about the options of the
compiler type hcppc -h.
5. Link the object files using ldppcl command to invoke the linker program included with
Metaware C compiler using the following command on the DOS Command Prompt:
ldppc –B start_addr=70000 –xm file.o
Note: “file.o” is the object file generated in the last step. The object file will be named exactly as
you named the C code file.) The result from this step will be the file “a.hex”, the file that will be
later downloaded to the Excimer board. The –B start_addr=70000 is an option that speci-
fies where does your code is going to be paced in the memory of the Excimer Board. For more
information about the linker type ldppc -h.
References:
Metaware High C/C++ Compiler – http://www.metaware.com
Suggested Code:
int fibonacci(int x);
#define printf dink_printf
unsigned long (*dink_printf)() = (unsigned long (*)()) 0x6270;
main()
{
int fib_no = 0, index = 0;
while (index < 12)
{
fib_no = fibonacci(index);
printf("Fibonacci number for index %d is", index);
9
printf(" %d\n", fib_no);
index++;
}
return 0;
}
int fibonacci(int number)
{
switch (number)
{
case 0 :
return 1;
case 1 :
return 1;
default :
return (fibonacci(number-1) + fibonacci(number-2));
}
}
Troubleshooting:
If the student is not able to:
Print to the DINK 32 interface: verify that the address of the pointer address matches that of
the DINK version in use. This can be done through an st command in DINK and verifying
that the address for printf matches the one provided in this manual.
10
DINK Tutorial
Problem Statement:
This experiment is designed to introduce the student to the DINK interface. A tutorial on
how to download code to the Excimer board and some useful DINK debugging utilities are
also presented. (Contributed by Noel Serrano).
Objectives:
Upon completion of this laboratory experience, students will be able to:
download their programs to the Excimer board using the DINK interface.
debug the programs using the DINK built-in debugging tools.
Background Information:
The Excimer board contains a debugging interface called DINK. This interface enables you to
connect to the evaluation board through a serial cable using a terminal program. This enables the
developer to have continuous communication with the evaluation board, allowing insight into the
board’s state at all time. The terminal screen of your program should look like this.
Experiment
2
11
Figure 1. DINK32 on terminal client
More information on DINK can be found at
www.mot.com/SPS/PowerPC/teksupport/teklibrary/index.html.
Procedure:
1. First make sure you have your evaluation board connected using the serial cable provided to
serial port 1 (COM1). Open your terminal client and configure it to connect through COM1
using the following parameters.
Parameter Value
Protocol Serial
Port COM1
Baud Rate 9600
Data Bits 8
Parity N
Stop Bits 1
RTS/CTS Enabled
Turn on the evaluation board and press Connect on your terminal client. You should be able
to see the initialization window with the DINK32_603e >> prompt as presented in the figure
shown below (see step 4).
2. Compile the program you created on experiment number one using the Metaware compiler.
12
3. Now you are ready to download your program to the Excimer board for execution. To do so
first go to the terminal client running the DINK32 interface and type dl –k. This command
will expect to receive data from the keyboard serial port (COM1). Now proceed to send the
file from the terminal client. This can be done by selecting a command like Send Text File or
Send ASCII (this can vary from one terminal client to the other). Now browse for the a.hex
created in the directory where you compiled your program.
4. Run your program by typing go 70000 in the DINK32 program. If your code is correct
and if you have been successful in downloading the code you should get an output like the
following.
Hint: The table below presents some useful commands in case you need to debug your program,
view memory or register contents, and/or ser breakpoints for program tracing. For more informa-
tion type help <command> in the DINK prompt.
Command Format Description
Memory Display md <addr> Displays the memory area specified by the hex address
Registry Display regdisp rx Displays the register specified by rx
Disassemble ds <addr> Disassemble the code starting at the specified address location
Trace tr <addr> Begin tracing a program at the specified address. To continue
tracing type tr +.
Breakpoint br <addr> Sets a breakpoint at the specified address
Assemble as <addr> Provides you with the option of changing part of the assembly
from the DINK Interface accessing it through the address of
the code line.
13
References:
[1] Motorola, Designing a Minimal PowerPC System, PowerPC Application Note: AN1769/D,
1998.
Conclusions:
Students should be able to note that:
DINK works similarly to other evaluation board environments
DINK provides functionality that enables the user to modify the memory, registers, and as-
sembly code
DINK provides breakpoint and trace capabilities for debugging purposes
Troubleshooting:
If the student is not able to communicate with the DINK:
verify the connections to COM1 port and board
check for correct settings on terminal client
14
Useful DINK Functions
Problem Statement:
In this experiment the student is introduced to a set of useful functions that are contained
within the DINK 32 Interface. (Contributed by Noel Serrano).
Objectives:
Upon completion of this laboratory experience, students will be able to:
work with more advanced DINK functions and use them on future laboratories.
Background Information:
The DINK 32 interface provides a set of functions that facilitate the development of programs
for the Excimer board. Among the functions included in DINK are some that allow the program-
mer to capture data from the keyboard and to print to the screen. Other functions control parts
of the Excimer board configuration like enabling the timer, cache, etc.
This laboratory will give you and overview of a basic set of these functions and will teach you
how to access them in your C programs. There is a command included in DINK that display a
list of all these functions with their branch labels and corresponding addresses. The command is
st and the corresponding output will look like this.
DINK32_603e >>st
Experiment
3
15
Current list of DINK branch labels:
KEYBOARD: 0x0
get_char: 0x1e4c4
write_char: 0x5eb4
TBaseInit: 0x39e0
TBaseReadLower: 0x3a04
TBaseReadUpper: 0x3a20
CacheInhibit: 0x3a3c
InvEnL1Dcache: 0x3a5c
DisL1Dcache: 0x3aa4
InvEnL1Icache: 0x3ac8
DisL1Icache: 0x3b00
BurstMode: 0x3bfc
RamInCBk: 0x3c3c
RamInWThru: 0x3c7c
dink_loop: 0x55e8
dink_printf: 0x6270
Current list of USER branch labels:
DINK32_603e >>
All these functions can be accessed through your C code by casting a function that will point to
the address in DINK. The code that defines the function would look like the following example
for the printf function.
#define printf dink_printf
unsigned long (*dink_printf)() = (unsigned long (*)()) 0x6270;
In the following section we present examples of three DINK functions.
a) get_char This function enables the programmer to capture characters from the keyboard
through the DINK interface. The get_cahr function can be accessed by using the following code:
#define getchar dink_get_char
unsigned long (*dink_get_char)() = (unsigned long (*)()) 0x1e4c4;
This will enable you to capture characters from the keyboard. The syntax for reading character
from the keyboard would be:
char LED;
LED = getchar();
16
b) write_char This function enables the programmer to display characters on the terminal
screen that is running DINK. The write_char function can be accesed by using the following
code.
#define writechar dink_write_char
unsigned long (*dink_write_char)() = (unsigned long (*)())0x5eb4;
This will enable you to output characters to the screen. The sysntax for displaying single charac-
ters from the keyboard would be:
char LED = ‘N’;
LED = writechar(LED);
c) dink_printf –This functions provide the programmer the option of displaying a string of char-
acters on the DINK interface and also provide the user the ability of including a runtime variable,
either char or integer, on this string. It is done by using the dink_printf function using the same
syntax as in C.
#define printf dink_printf
unsigned long (*dink_printfr)() = (unsigned long (*)())0x6270;
This will enable you to print any message on the DINK and also include any of the variables in-
cluded in your code. The DINK printf function can only include one variable per statement
not like in C which it can contain any number of variables.
printf("Fibonacci number for index %d is", index);
There are other important functions that can be used to control many aspects of the Excimer
board. These are briefly described in the table below and explained in details in the included
DINK manuals.
Functions Address Description
TBaseInit 0x39e0 Initializes the time base register
TBaseReadLower 0x3a04 Reads the lower half of the time base register
17
TBaseReadUpper 0x3a20 Reads the upper half of the time base register.
CacheInhibit 0x3a3c Turns off the caches.
InvEnL1Dcache 0x3a5c Invalidate and Enable the L1 data cache.
DisL1Dcache 0x3aa4 Disable L1 data cache.
InvEnL1Icache 0x3ac8 Invalidate and Enable the L1 instruction cache.
DisL1Icache 0x3b00 Disable L1 instruction cache.
BurstMode 0x3bfc Sets up burst mode.
References:
[1] Motorola, Designing a Minimal PowerPC System, PowerPC Application Note: AN1769/D,
1998.
Suggested Code:
/* This section of code can be used to define any of the DINK functions in a C language program.
The user will only need to modyfy the address and function name. */
#define function_name dink_function_name
unsigned long (*dink_function_name)() = (unsigned long (*)()) hex_addr;
Troubleshooting:
If the student is not able to access the DINK functions:
verify the casting is correct.
verify that he/she is using the correct hex address.
18
Excimer Memory Map
Problem Statement:
This experiment requires the compilation, downloading, and execution of a C language pro-
gram which blinks the Excimer Board’s STATUS and ERROR Light Emitting Diodes (LEDs).
(Contributed by Noel Serrano, José I. Quiñones, Luis Naváez, Walter Guiot, and Gunther
Costas).
Objectives:
Upon completion of this laboratory experience, students will be able to:
write and compile a C program
download and execute PowerPC Assembly object code
locate the LEDs within the Excimer’s memory map
apply the methodology needed to turn on and off the LEDs
Background Information:
The PowerPC family of microprocessors is based on a memory mapped input/output scheme.
Under this scheme, an input port can be thought of as read-only memory location, while an out-
put port can be treated like a write-only memory location. The microprocessor’s address bus is
used to select the peripheral device (port location), the data bus is used to transmit or receive
data to/from the device, and the Transfer Type signals are used to convey the directionality of
the information transfer.
Experiment
4
19
The memory map for the Excimer Board is shown in Figure 2. The memory map indicates that
out of a total of 232 = 4GB addressable locations, the Excimer Board allocates 230 = 1GB each to
Static RAM, Fast I/O devices, Slow I/O devices and Flash ROM [1]. Of course, the Excimer
board only uses a fraction of the memory locations allocated for each type of memory and de-
vices. The Excimer Board is configured with 512 KBs of SRAM, 4MBs of Flash ROM, and
some LED indicators. For example, there’s a STATUS LED located at 0x40200000, while an
ERROR LED is specified at 0x40600000.
STATIC RAM
0x0000_0000 0x3FFF_FFFF
FAST I/O
0x4000_0000 0x7FFF_FFFF
STATUS LED: 0x4020_0000
ERROR LED: 0x4060_0000
SLOW I/O
0x8000_0000 0xBFFF_FFFF
FLASH ROM
0xC000_0000 0xFFFF_FFFF
Figure 1: Excimer's Memory Map.
In this experiment you are required to write a C program that will blink (repeatedly turn on and
off) the STATUS and ERROR LEDs alternatively. The LEDs are turned on/off by clear-
ing/setting BIT 3 (fourth least significant bit) of these locations. The reason for this negative
logic is that the LEDs are connected in a common anode configuration, as shown in Figure 2 for
the case of a seven segment LED display.
20
Figure 2: Common Anode LED configuration. LEDs will turn ON when the cathode is at ground
level (Excimer Output asserted low)
To successfully blink an LED, you must carefully select the delay timing. Remember that the mi-
croprocessor may turn the LED on and off so quickly that you will not see the blinking effect.
Since your program will be written in C, a simple “for” loop instruction may do the job.
For (counter=0;counter <= parameter; counter++);
Note: counter must be declared as unsigned long in the program. The value parameter will define
the delay time.
There are other ways to accomplish a time delay, for example using the PowerPC’s internal timer
register. These techniques will be demonstrated in the successive experiments.
Procedure:
1. Write a simple C code that alternatively blinks the Status and Error LEDs ten times.
2. Compile the C code with the hcppc command included with the Metaware C compiler using
the following command on the DOS command prompt :
hcppc –Hppc603 –c file.c
21
Note: File.c” stands for the C code file. You may name your C code file as you wish, but
remember to use the chosen name in the hcppc command. The result from this command
will be “file.o”, which is the object file.
3. Link the object files using ldppcl command to invoke the linker program included with
Metaware C compiler using the following command on the DOS Command Prompt:
ldppc –B start_addr=70000 –xm file.o
Note: “File.o” is the object file generated in the last step. The object file will be named ex-
actly as you named the C code file.) The result from this step will be the file “a.hex”.
4. Run the DINK32 application on your Windows 95 or NT terminal. Download the “a.hex”
file, which resulted from the last step. To do so, write DL –k on the DINK monitor. On the
terminal it will appear, “Set to Keyboard Port”. Press Transfer->Send Text File on
the communication terminal’s menu. Find your a.hex” file and select it. The file will be
downloaded to the Excimer board.
5. Execute the program by writing “go 70000” on the terminal.
6. Observe the behavior of the on-board LED’s. What happens if you decrease/increase the
value of parameter in your FOR loop statement?
References:
[1] Motorola, Designing a Minimal PowerPC System, PowerPC Application Note: AN1769/D,
1998.
Suggested Code:
/* This program will blink the status and Error LEDs alternatively
ten times. After that, both LEDs will be shut down. 0xfffff will
cause a visible delay in a 300MHz PowerPC*/
22
Main ()
{
unsigned long count;
int loop;
for (loop = 0 ; loop <= 10; loop++)
{
*(char *) (0x40200000) = 0x00; //turn on status
*(char *) (0x40600000) = 0x08; //turn off error
for(count = 0; count <= 0xfffff; count ++);
*(char *) (0x40200000) = 0x08; //turn off status
*(char *) (0x40600000) = 0x00; //turn on error
for(count = 0; count <= 0x1fffff; count ++);
}
*(char *) (0x40600000) = 0x08;
}
Conclusions:
Students should be able to note that:
The speed, which drives the PowerPC microprocessor, is very fast and thus a blinking effect
might not be perceived.
For different loop parameters, the LED will remain ON or OFF for a different time period.
The LED’s are configured as Common Anode (negative terminal connected together).
Troubleshooting:
If the student is not able to turn ON or OFF the LED check that:
the address being written to is either 0x40600000 or 0x40200000.
a suitable value for the time delay loop has been defined.
the student has compiled, linked and downloaded the program correctly.
23
LED Control from Keyboard
Problem Statement:
This experiment requires the compilation, downloading, and execution of a C language pro-
gram which blinks the Excimer Board’s ERROR Light Emitting Diode (LEDs) the number of
times specified by the user input. (Contributed by Noel Serrano and José I. Quiñones).
Objectives:
Upon completion of this laboratory experience, students will be able to:
use the DINK functions presented in experiment #3
print to the DINK 32 interface
capture single characters from the keyboard and echo them to the DINK 32 interface
Procedure:
1. Write a C program that will blink the on board LED’s based on user input. The program
should ask the user which LED he wants to blink and how many times.
Hint: To create this program use the program you created in the previous experiment and the
Useful DINK Functions.
References:
[1] Motorola, Designing a Minimal PowerPC System, PowerPC Application Note: AN1769/D,
1998.
Experiment
5
24
Suggested Code:
#include <stdio.h>
#define getchar dink_get_char
#define putchar dink_write_char
#define printf dink_printf
void blink_leds(int addr, int i);
unsigned long (*dink_get_char)() = (unsigned long (*)()) 0x1e4c4;
unsigned long (*dink_write_char)(char) = (unsigned long (*)(char)) 0x5eb4;
unsigned long (*dink_printf)() = (unsigned long (*)()) 0x6270;
main()
{
int decimal_no;
char LED;
char number;
do
{
printf ("\nSelect the LED you want to blink:\n");
printf ("\tS - Press S for the Status LED\n");
printf ("\tE - Press E for the Error LED\n");
printf ("\tQ - Press Q to Quit\n");
LED = getchar(); /* Read typed Character */
if (LED == 'E' || LED == 'e')
{
printf ("\nEnter the number of times (1-9) to blink the Er-
ror LED: ");
do{ /* is it a number??? */
number = getchar();
}while ( !((number >= '0') && (number <= '9')) );
putchar(number); /* echo typed character */
decimal_no = number - 48;
blink_leds(0x40600000, decimal_no);
}
else if (LED == 'S' || LED == 's')
{
printf ("\nEnter the number of times (1-9) to blink the
Status LED: ");
do{
number = getchar();
}while ( !((number >= '0') && (number <= '9')) );
putchar(number);
decimal_no = number -48;
blink_leds(0x40200000, decimal_no);
}
} while ( LED != 'Q' && LED != 'q' ); /* X or x */
return 0;
}
25
void blink_leds(int addr, int i)
{
unsigned long count;
int loop;
for (loop = 0 ; loop < i; loop++)
{
*(char *) (addr) = 0x00; //turn on error
for(count = 0; count <= 0xfff00; count ++);
*(char *) (addr) = 0x08; //turn off error
for(count = 0; count <= 0xfff00; count ++);
}
*(char *) (0x40600000) = 0x08;
}
Conclusions:
Students should be able to note that:
a PowerPC Excimer Board program can obtain data from a user via the Keyboard.
the getchar function is not useful in cases you need more than character as input, so an im-
plementation of a scanf function would be useful.
Troubleshooting:
If the student is not able to:
Access DINK 32 interface functions: use the st command to verify that the address for the
DINK functions matches the ones provided in this manual.
Blink the LEDs: verify the memory mapping for each of the LEDs.
26
A simple scanf function for Excimer
Problem Statement:
In this experiment the student will develop a C function for taking character input from the terminal
emulator’s keyboard attached to Excimer through the serial port and converting number characters
to decimal values used in other programs. (Contributed by Chuck Corley, Motorola)
Objectives:
Upon completion of this laboratory experience, students will be able to:
substitute the getchar and putchar equivalent functions available in DINK for the same functions
normally found in <stdio.h>
recognize the ASCII character values returned from getchar() and echo them back via putchar()
convert digit characters input through the keyboard into decimal integer values for use in other pro-
grams
utilize DINK’s print output function to display the resulting decimal value
Background Information:
Texts on programming describe how to get input for a program. For example, The Waite Group’s New
C Primer Plus [1] says:
The C library contains several input functions, and scanf() is the most general of them,
for it can read a variety of formats. Of course, input for the keyboard is text because the
keys generate text characters: letters, digits, and punctuation. When you desire to enter,
say, the integer 2002, you type the characters 2 0 0 and 2. If you want to store that as a
Experiment
6
27
numerical value rather than as a string, your program has to convert the string character-
by-character to a numerical value. And that is what scanf() does! It converts a string in-
put into various forms: integers floating-point numbers, characters, and C strings.
It is the inverse of printf(), which converts integers, floating-point numbers, characters,
and C strings to text that is to be displayed on the screen. Like printf(), scanf() uses a
control string followed by a list of arguments. The control string indicates into which
formats the input is to be converted.
The DINK software on Excimer provides input and output functions that save the programmer from
having to interact directly with the duart that receives input and sends output to the terminal. How-
ever these functions are not at the level of a complex function like scanf(). Nevertherless, many of the
C programs that we desire to run on Excimer call the scanf() function because of it’s widespread use.
In this experiment, you will write your own function my_scanf() and substitute it (by a #define direc-
tive) for any scanf() function that the compiler may encounter in programs intended for Excimer.
Likewise you will define dink_printf() to substitute for printf() and link dink_printf() into your pro-
grams. Then you will have input and output functions for use in other programs.
To keep my_scanf() simple we will assume that the only control string for converting inputs is the %d
or decimal format. Your my_scanf() function should accept a control string as an argument but then
ignore it and return a decimal value to the second (and last) argument in the functional call. Later ex-
periments may require more sophisticated substitute functions for scanf(), but this simple decimal in-
put routine will be widely applicable.
Eximer’s dink_printf() does accept a control string but it ignores floating-point and character formats.
It will only print decimal numbers (%d), hexadecimal numbers (%x), and strings (%s) and then only one
such format per printf statement.
28
Procedure:
1. Write a C language program which asks the user to input a number through the keyboard and then
outputs the number input as a positive decimal number.
2. In a separate file write a C program my_scanf(char, int) which reads characters from the keyboard,
echoes those that are digits, and at the carriage return assigns a decimal value to the second argument
of my_scanf().
Hint: While ignoring non-digit characters may be an acceptable simplification, you may want to check
for backspace or delete characters and take the appropriate action if the user attempts to correct his
numerical input.
3. Write a header file which equates the function name scanf to my_scanf and printf to dink_printf. In
the header file equate dink_printf to the address where it is stored in RAM as revealed by DINK’s
symtab (symbol table) command. Include this header file in your test program.
Example:
/* File - support.h
* Equates functions used in Excimer Exercise to equivalent
* functions defined in DINK or in my_scanf.c
* NOTE: If DINK function addresses change because DINK changes,
* addresses here must be changed accordingly.
*
* Modification history:
* 19Jan99,CJC Original
*/
#define printf dink_printf
#define scanf my_scanf
extern void my_scanf(const char *, ...);
unsigned long (*dink_printf)() = (unsigned long (*)()) 0x6368;
4. Your my_scanf() function will use getchar() and putchar(). Write a header file equates these to
DINK’s get_char and write_char. Write a header file which equates dink_get_char() and
dink_write_char() to the addresses where they are stored in RAM as revealed by DINK’s symtab
(symbol table) command. . Include this header file in the my_scanf.c program.
Example:
/* File - excimer.h
* Provides the addresses of functions defined in DINK on the Excimer
* board and used by programs. The addresses of the functions are
* taken from the xref.txt file generated by the linker.
* When a new version of DINK is downloaded to the target, make sure
* the functions' addresses are changed accordingly to match with the
29
* new addresses being generated.
*
* Modification history:
* 21Oct98,My Created for ExcDemo
* 19Jan99,CJC Modified to run with my_scanf code.
*/
#define getchar dink_get_char
#define putchar dink_write_char
/* Addresses of DINK functions. */
unsigned long (*dink_get_char)() = (unsigned long (*)()) 0x1e5e4;
unsigned long (*dink_write_char)(char) = (unsigned long (*)(char)) 0x5fac;
5. Link your input/output test program and my_scanf program.
6. Download the resulting S-record file to Excimer, execute it, confirm that it echoes only digit charac-
ters and returns the correct decimal value to your program at the carriage return.
References:
[1] The Waite Group’s New C Primer Plus (1990: Howard W. Sams & Co, Carmel, IN)
Suggested Code:
/* file "testscanf.c"
* A test harness for Excimer Experiment to prove out
* my_scanf() function.
* Modification History:
* 990121 CJC Original
*/
#include "support.h"
void main(void)
{
int decimal_no;
printf ("Enter a decimal number: ");
scanf("%d", &decimal_no);
printf ("\nDecimal number is: %d \n", decimal_no);
/* file "support.c"
* Defines an alternative to the scanf function provided by
* stdio.h for use when running the Dhrystone benchmarks on DINK.
* Created: 990119 CJC
* Modified:
*/
#include "excimer.h"
void my_scanf(char *fmt, int *v)
{
char ch;
int no_runs = 0;
while ((ch = getchar()) != 0xd) /* Carriage return? */
{
if ( (ch == 0x7f) || (ch == 0x8)) /* Delete? */
30
{
putchar(0x8); /* Backspace */
putchar(0x20); /* Overprint a space. */
putchar(0x8); /* Backspace */
/* Assume modulo arithmetic to subtract last digit added. */
no_runs = no_runs / 10;
} else
if ( (ch >= '0') && (ch <= '9')) /* A digit? */
{
putchar(ch); /* Echo it and */
/* Accumulate the value. */
no_runs = (no_runs * 10) + (ch - 48);
/* ASCII character - 48 equals the digit. */
}
}
*v = no_runs; /* Assign second Arg the value. */
}
/* file “makefile” */
SUPPORT =
SUPPORTOPT =
OPTLEV = -O1
CPU = 603
TARGFLAGS = -Hppc$(CPU)
CC = c:\sw\metaware\hcppc\bin\hcppc -Ic:\sw\metaware\hcppc\inc \
-Hnocopyr -c -nofsoft $(OPTLEV) $(TARGFLAGS)
AS = c:\sw\metaware\hcppc\bin\asppc -c -big_si
LKOPT = -Bbase=0x70000 -xm -e main -Bnoheader -Bhardalign \
-xo=$(@) -q -Qn -Cglobals -Csections -Csymbols -Ccrossref \
> $(@D)\xref.txt
LINK = c:\sw\metaware\hcppc\bin\ldppc $(LKOPT)
testscanf.src: testscanf.o my_scanf.o
$(LINK) testscanf.o my_scanf.o \
c:\sw\metaware\hcppc\lib\be\fp\libmw.a
testscanf.o: testscanf.c
$(CC) testscanf.c -o testscanf.o $(SUPPORTOPT)
my_scanf.o: my_scanf.c
$(CC) my_scanf.c -o my_scanf.o $(SUPPORTOPT)
Conclusions:
Students should be able to note that:
Characters are received from the keyboard as bytes of ASCII encoded information.
Input/Output functions normally available in standard C libraries for a given computer may not be
available or may exist in different, simpler forms on a small, embedded evaluation system like Exci-
mer .
Programmers can write their own input/output routines or link in routines that are provided in the
embedded system.
31
Hard-coding addresses of embedded routines is a dangerous way of linking code if the routines are
relocated by DINK revisions.
Troubleshooting:
If the student is not able to:
Get started. Suggest that the student develop and debug the C program on the host computer by
including <stdio.h> before substituting the DINK routines and downloading to Excimer. This
should clarify the ASCII encoding of digits and conversion to a decimal number.
Recognize the carriage return character. Eximer will be in a continous loop of accepting and echoing
input. Additional printf() statements which output each character as it is read in will reveal the
value provided by the duart for the carriage return character.Troubleshooting:
32
Introduction to Assembly Language Programming
Problem Statement:
In this experiment the student is introduced to the PowerPC instruction set architecture through the
development of an assemblylLanguage routine. (Contributed by Eisen Montalvo-Ruiz)
Objectives:
Upon completion of this laboratory experience, students will be able to:
write and compile an assembly language subroutine
use Metaware Assembler directives
understand the instruction set and the register set of the PowerPC
Background Information:
PowerPC Register Set
The PowerPC architecture has two levels of privileges, the user mode, and the supervisor mode. In
the supervisor mode all registers are available to the programmer, while in the user mode only a
subset of the registers are available. We are going to focus on the user mode for this laboratory.
Tin the user mode the available PowerPC registers include 32 General Purpose Registers (GPRs),
32 Floating-Point Registers (FPRs), a Condition Register (CR), a Floating-Point Status and
Condition Register (FPSCR), the XER register, the Link Register (LR) and the Count Register
Experiment
7
33
(CTR). In addition, there are two read-only registers, associated with the Time Base Facility (TBU
and TBL).
The GPRs are used to manipulate integer data. They come in two sizes, according to the
implementation of processor. 32-bit GPRs for the 32-bit PowerPC and 64-bits for the 64-bit
PowerPC. They are used as source and destination registers in the integer instructions.
The FPRs are used with floating-point instructions. They are 64 bits wide independently of the
implementation, and can manipulate single- and double floating-point data. Related to these
registers is the FPSCR. It contains all floating-point exception signal bits, excluding summary bits,
exception summary bits, exception enable bits, and rounding control bits.
The CR is a 32-bit register, divided into eight 4-bit fields. This register contains the results of
certain arithmetic operations and provides a way for testing and branching. The XER register
indicates overflows and carry conditions for integer operations. The LR register and the CTR
register are like the GPRs, their size depends on the implementation. The LR supplies the branch
target address for the Branch Conditional to Link Registers instructions. The CTR holds a loop
count that can be decremented during execution of appropriately coded branch instructions.
The Time Base Facility consists of a 64-bit register, divided in two 32-bit registers, Time Base
Upper (TBU) and Time Base Lower (TBL). These registers will be used in a future laboratory,
where you will learn more about them.
PowerPC Instruction Set
The PowerPC Instruction Set is very powerful and extensive. It contains around 200 instructions,
excluding suffices. We don’t have the space to cover all of them. For now, we are going to work
with the Integer Arithmetic, Load and Store, and Flow Control instructions. A general description
34
of the format of the instructions will be given. More information can be obtained from the PowerPC
programming references.
Integer Instruction Set
(a) Integer Arithmetic Instructions
You can add, subtract, multiply, and divide integer numbers. You can use immediate values and
registers. Also, register to register instructions are available. A general description of the format
of the instructions follows.
1. Immediate Values
opcode rD, rA, SIMM - where rD is the destination register, rA is the source register and
SIMM is a Signed Immediate value.
2. Register to Register
opcode rD, rA, rB - where rD is the destination register and rA and rB are the source
registers.
(b) Integer Compare Instructions
These instructions can be used in conjunction with the branch instructions to control the flow
of a program. They affect the CR, such that the branch instructions can choose their target
address based on what happened in the previous instruction. Of course, they could be used
only for comparing.
1. Immediate Values
opcode rA, SIMM - where rA is the register you want to compare to a Signed
Immediate value
2. Register to Register
opcode rA, rB - where rA is the register you want to compare to register
35
rB
Load and Store Instruction Set
Load and Store instructions allow data movement between memory and register locations. They
have three addressing modes. In anyone of them, if you use r0, the address calculation will use
zero instead of the value in rA.
(a) Register Indirect with Immediate Index Addressing
opcode rD, SIMM(rA) - if loading then rD is the destination register. It will con-
tain the value that is stored in the memory address that is
the sum of SIMM and the value in the register rA. If
storing then the memory address that is the sum of SIMM
with the value in register rA, will contain the value stored
in register rD.
(b) Register Indirect with Index Addressing
opcode rD, rA, rB - if loading then rD is the destination register. It will contain
the value that is stored in the memory address that is the sum of
the value in register rA and the value in the register rB. If storing
then the memory address that is the sum of the value in register
rA with the value in register rB, will contain the value stored in
register rD.
(c) Register Indirect Addressing
opcode rD, rA - if loading then rD is the destination register. It will contain the
value that is stored in the memory address that is the value in the
register rA. If storing then the memory address that is the value
in register rA will contain the value stored in register rD.
36
Branch Instructions Set
These instructions are commonly used with compare instructions. You place the branch after the com-
pare, using the result of it to make the decision.
opcode label - where label is the address of the code where you want to
branch to. The assembler takes care of translating the label to
the address.
Metaware Assembler Directives
The assembler directives are instructions to the assembler on how to configure data and where to
put the code and data in memory. The most useful are:
(a) .text – identifies where the code section starts.
(b) .data – mark the start of the data section
(c) .word <value> – reserves space for a word in memory
(d) .org <address> – starting address of the following code and/or data
(e) .global <label> – makes this routine a public one.
You can put comments in any line, but they must begin with a “!”. In addition, you can use labels
for branching. They must end with a semicolon and must be at the beginning of the line, with or
without code in the same line.
Metaware Assembly Compilation
For compiling your code using Metaware, you must go through two steps. First compile the code
using asppc, the Metaware Assembler.
asppc –o filename.o filename.s
The extension of yo
37
ur file must be *.s. In this way the Assembler recognizes the file. The –o option tells the assembler
the name of the object file. If you don’t use it, the default name is the same as the code file with *.o
as the extension.
The second step is to convert the object to Motorola S3 record and to set again the address of the
code and data section.
elf2hex –p .text:0x70000,.data:0x70100 –o filename.hex –xm filename.o
The p option is used to tell where the section of the file starts in memory. In this case, .text
section will start in address 0x70000 and the .data section in 0x70100. The –o option is the name of
the output file. The xm tells the program to generate a Motorola S3 record and filename.o is the
file of the object file.
Procedure:
1. Write an assembly language routine that multiplies 2 3x3 Matrices.
Remember:
=
ijii
j
j
ijii
j
j
ijii
j
j
ccc
ccc
ccc
bbb
bbb
bbb
aaa
aaa
aaa
...
...........
...
...
...
...........
...
...
...
...........
...
...
21
22221
11211
21
22221
11211
21
22221
11211
di
mens
i
on.matr
i
x t
h
e
i
sn w
h
ere,
*
...
**
2211 njinjijiij
b
a
b
a
b
aC +++=
Hint:
Set the start of the matrices in memory, so you know where the code has to look for the data. Also,
make it flexible, so you can change the size of the matrices without making changes in your code.
38
References:
[1] Motorola, PowerPC Microprocessor Family: The Programming Environments for 32-Bit
Microprocessors, MPCFPE32B/AD, Rev 1, 1/97.
Suggested Code:
!file "matmult.s"
! Assembly Language program to multiply 2 3x3 matrices
! EMR 990321
!
! Register usage:
! r9 – Pointer to start of data section
! r12 – miscellaneous
! r5 - i
! r10 – j
! r11 – k
! r7 - Pointer to row in matrix
! r8 - Pointer to column in matrix
! r5 - holds temporary result of calculations
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! CODE Section !
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
.org 0x60000
.text
.global mat_mult
mat_mult:
addic r5, r0, 0 !Clear R5
lis r9, 6 !Load immediate shifted to R9
addi r9, r9, 208 !Pointer to data section
lwz r12, 108(r9) !Load n
cmpw r5, r12 !If R5>=R12 then ...
bge exit !goto exit, else ...
another_i:
addi r10, r0, 0 !Clear R10
lis r9, 6 !Load immediate shifted to R9
addi r9, r9, 208 !Pointer to data section
lwz r12, 108(r9) !Load n
cmpwi r12, 0 !If R12<=0 then ...
ble incr_i !goto incr_i, else ...
another_j:
addi r11, r0, 0 !Clear R11
lis r9, 6 !Load immediate shifted to R9
addi r9, r9, 208 !Pointer to data section
39
lwz r12, 108(r9) !Load n
cmpwi r12, 0 !If R12<=0 then ...
ble incr_j !goto incr_j, else ...
another_k:
mulli r7, r5, 12 !Pointer to row of A using i
slwi r12, r11, 2 !Pointer to col of A using k
add r12, r12, r7 !Pointer to Aik
lis r9, 6 !Load immediate shifted to R9
addi r9, r9, 208 !Pointer to data section
lwzx r6, r12, r9 !Load Aik to R6
mulli r12, r11, 12 !Pointer to row of B using k
slwi r8, r10, 2 !Pointer to col of B using j
add r12, r8, r12 !Pointer to Bkj
add r12, r12, r9 !Add start address of data section
lwz r12, 36(r12) !Load Bkj
mullw r6, r12, r6 !Aik*Bkj
add r12, r8, r7 !R12=i+j
add r8, r12, r9 !Pointer Cij
lwz r12, 72(r8) !Load Cij
add r12, r12, r6 !Cij+=Aik*Bkj
stw r12, 72(r8) !Store Cij
incr_k:
addi r11, r11, 1 !Increment k
lwz r12, 108(r9) !Load n
cmpw r12, r11 !If R12>R11 then ...
bgt another_k !goto another_k, else ...
incr_j:
addi r10, r10, 1 !Increment j
lis r9, 6 !Load immediate shifted to R9
addi r9, r9, 208 !Pointer to data section
lwz r12, 108(R9) !Load n
cmpw r12, r10 !If R12>R10 then ...
bgt another_j !goto another_j, else ...
incr_i:
addi r5, r5, 1 !Increment i
lis r9, 6 !Load immediate shifted to R9
addi r9, r9, 208 !Pointer to data section