Instructor's Manual MOTOR OLA Powe rPC E xci m e r Labo rato ry Manual Jose I. Quinones, Noel Serrano, Walter Guiot, Luis Narvaez, Eisen Montalvo Department of Electrical and Computer Engineering University of Puerto Rico-Mayaguez Chuck Corley PowerPC Applications Engineering Motorola Editor: Jose L. Cruz Rivera Department of Electrical and Computer Engineering University of Puerto Rico-Mayaguez VOLUME I 1 DISCLAIMERS 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 reserve the right to change or discontinue this product without notice. Information in this document is provided solely t o 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 product 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 b y 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 unauthorized application, customer shall indemnify and hold Motorola and IBM and their respective officers, employees, subsidiaries, 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 unauthorized 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 Employer. 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 Machines Corp. used by Motorola under license from International Business Machines Corp. International Business Machines Corp. is an Equal Opportunity/Affirmative Action Employer. 2 INTRODUCTION 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 assumed 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 (resident monitor program), keyboard input, assembly language programming, and linking assembly language to C code. There are also experiments on memory mapping and Flash ROM programming. Each lab experiment is structured as follows: Problem Statement, Objectives, Background Information, Procedure, Questions, and References. The Problem Statement provides a brief indication as to the tasks that will be performed. The Objectives section presents the specific educational objectives that will be met upon successful completion of the lab experiment. The Background information section presents a brief description of the theory behind the devices, instructions, 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. 3 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 standalone 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. 4 CONTENTS Experiment #1: Metaware Tutorial Write and compile a simple C program. Experiment #2: DINK Tutorial Download the program to Excimer and use some utilities. Experiment #3: Useful DINK Functions Write a program that will get input from KB and echo to display. Discuss various utilities of interest. Experiment #4: Excimer Memory Map Compile, download, and execute a C program which blinks the on-board LEDs 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. 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. Experiment #7: Introduction to Assembly Language Programming Write a simple assembly language program. Experiment #8: Linking Assembly Language and C code Link previous code fragments. 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 Corley, Motorola) Experiment #10: Dhrystone Benchmarking Write and debug a C program to count the integer number of cycles required to execute the Dhrystone benchmark. Experiment #11: Linpack Benchmarking Write and debug a C program to time in microseconds (floating point) the execution of the Linpack benchmark. Experiment #12: Cache Impact on Benchmark Metrics Write a single program to time the performance of Dhrystone and Linpack with the caches enabled and disabled. Experiment #13: Flash ROM Write a program that copies itself into Flash ROM and begins executing from there. 6 10 14 18 23 26 32 41 52 63 72 76 80 5 Experiment 1 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 remaining elements can be obtained by simply adding the last two numbers to get the next. For example, 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 6 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. Furthermore, 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 Fibonacci 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 7 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 specifies 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); 8 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. 9 Experiment 2 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. 10 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 Protocol Port Baud Rate Data Bits Parity Stop Bits RTS/CTS Value Serial COM1 9600 8 N 1 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. 11 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 information type help in the DINK prompt. Command Memory Display Registry Display Disassemble Trace Format md regdisp rx ds tr Breakpoint Assemble br as Description Displays the memory area specified by the hex address Displays the register specified by rx Disassemble the code starting at the specified address location Begin tracing a program at the specified address. To continue tracing type tr +. Sets a breakpoint at the specified address Provides you with the option of changing part of the assembly from the DINK Interface accessing it through the address of the code line. 12 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 assembly 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 13 Experiment 3 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 programmer 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 14 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(); 15 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 characters 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 characters 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 included 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 TBaseInit TBaseReadLower Address 0x39e0 0x3a04 Description Initializes the time base register Reads the lower half of the time base register 16 TBaseReadUpper CacheInhibit InvEnL1Dcache DisL1Dcache InvEnL1Icache DisL1Icache BurstMode 0x3a20 0x3a3c 0x3a5c 0x3aa4 0x3ac8 0x3b00 0x3bfc Reads the upper half of the time base register. Turns off the caches. Invalidate and Enable the L1 data cache. Disable L1 data cache. Invalidate and Enable the L1 instruction cache. Disable L1 instruction cache. 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. 17 Experiment 4 Excimer Memory Map Problem Statement: * This experiment requires the compilation, downloading, and execution of a C language program which blinks the Excimer Board's STATUS and ERROR Light Emitting Diodes (LEDs). (Contributed by Noel Serrano, Jose I. Quinones, Luis Navaez, 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 output 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. 18 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 devices. 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 clearing/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. 19 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 microprocessor 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 20 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 exactly 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*/ 21 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. 22 Experiment 5 LED Control from Keyboard Problem Statement: * This experiment requires the compilation, downloading, and execution of a C language program 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 Jose I. Quinones). 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. 23 Suggested Code: #include #define #define #define getchar dink_get_char putchar dink_write_char 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 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) 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; blink the Er- ); to blink the ); } 24 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 implementation 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. 25 Experiment 6 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 * 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 programs * 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 26 numerical value rather than as a string, your program has to convert the string characterby-character to a numerical value. And that is what scanf() does! It converts a string input 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. However 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 directive) 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 programs. 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 experiments may require more sophisticated substitute functions for scanf(), but this simple decimal input 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. 27 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 #define printf dink_printf 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 28 * * * * * */ new addresses being generated. Modification history: 21Oct98,My Created for ExcDemo 19Jan99,CJC Modified to run with my_scanf code. #define #define getchar dink_get_char 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 characters 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? */ 29 { 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 Excimer . * Programmers can write their own input/output routines or link in routines that are provided in the embedded system. 30 * 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 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: 31 Experiment 7 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 32 (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 33 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 34 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 contain 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. 35 Branch Instructions Set These instructions are commonly used with compare instructions. You place the branch after the compare, 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 - reserves space for a word in memory (d) .org
- starting address of the following code and/or data (e) .global