Professional Documents
Culture Documents
User Guide
R
R
"Xilinx" and the Xilinx logo shown above are registered trademarks of Xilinx, Inc. Any rights not expressly granted herein are reserved.
CoolRunner, RocketChips, Rocket IP, Spartan, StateBENCH, StateCAD, Virtex, XACT, XC2064, XC3090, XC4005, and XC5210 are
registered trademarks of Xilinx, Inc.
Platform Studio User Guide www.xilinx.com UG113 (v1.0) March 12, 2004
1-800-255-7778
Platform Studio User Guide
UG113 (v1.0) March 12, 2004
The following table shows the revision history for this document.
Version Revision
01/31/04 1.0 Initial Xilinx release for EDK 6.2i.
03/12/04 Updated for service pack release.
UG113 (v1.0) March 12, 2004 www.xilinx.com Platform Studio User Guide
1-800-255-7778
Platform Studio User Guide www.xilinx.com UG113 (v1.0) March 12, 2004
1-800-255-7778
R
Preface
Guide Contents
This manual contains the following chapters:
x Chapter 1, “Overview,” gives an overview of Platform Studio technology.
x Chapter 2, “Creating a Basic Hardware System in XPS,” contains a step-by-step
procedure to generate a simple hardware system for EDK-based designs.
x Chapter 3, “Writing Applications for a Platform Studio Design,” contains a step-by-
step procedure to generate software for EDK-based designs using Xilinx EDK6.2 and
Xilinx ISE 6.2 software.
x Chapter 4, “Using Xilkernel,” describes Xilkernel, a set of interfaces and functions that
allow context switching and resource sharing between applications.
x Chapter 5, “Using XilMFS,” describes XilMFS, a memory-based file system library.
x Chapter 6, “Simulation in EDK,” describes the HDL simulation flow using Xilinx EDK
and third party software.
x Chapter 7, “Debugging in EDK,” describes the basics of debugging a system designed
using EDK.
x Chapter 8, “Profiling Embedded Designs,” describes the steps to profile a program on
hardware using libxil profile library provided with EDK.
x Chapter 9, “System Initialization and Download,” describes the basics of system
initialization and download using the Xilinx Platform Studio tools.
x Chapter 10, “Creating a MicroBlaze Design,” guides you through the process of
finishing and testing a partially completed MicroBlaze system design using the
Embedded Development Kit (EDK).
x Chapter 11, “Creating a PowerPC Design,” guides you through the process of
finishing and testing a partially completed PowerPC system design using the
Embedded Development Kit (EDK).
Additional Resources
For additional information, go to http://support.xilinx.com. The following table lists
some of the resources you can access from this website. You can also directly access these
resources using the provided URLs.
Resource Description/URL
Tutorials Tutorials covering Xilinx design flows, from design entry to
verification and debugging
http://support.xilinx.com/support/techsup/tutorials/index.htm
Answer Browser Database of Xilinx solution records
http://support.xilinx.com/xlnx/xil_ans_browser.jsp
Application Notes Descriptions of device-specific design techniques and approaches
http://support.xilinx.com/apps/appsweb.htm
Data Sheets Device-specific information on Xilinx device characteristics,
including readback, boundary scan, configuration, length count,
and debugging
http://support.xilinx.com/xlnx/xweb/xil_publications_index.jsp
Problem Solvers Interactive tools that allow you to troubleshoot your design issues
http://support.xilinx.com/support/troubleshoot/psolvers.htm
Tech Tips Latest news, design tips, and patch information for the Xilinx
design environment
http://www.support.xilinx.com/xlnx/xil_tt_home.jsp
Conventions
This document uses the following conventions. An example illustrates each convention.
Typographical
The following typographical conventions are used in this document:
Conventions
Online Document
The following conventions are used in this document:
Chapter 1: Overview
Creating an Embedded Hardware System. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
Creating Software for the Embedded System . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
Software Libraries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
System Simulation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
System Debug and Verification . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
System Initialization and Download to the Board . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
Fast Download . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
Generating an ACE File. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
Advanced Topics: Embedded Processor System Design . . . . . . . . . . . . . . . . . . . . . . 16
VHDL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116
Verilog . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117
ModelSim . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118
VHDL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118
Verilog . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118
NcSim . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119
VHDL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119
Verilog . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119
Using SmartModels . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120
Accessing SmartModel’s Internal Signals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120
The lmcwin Command . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120
Viewing PowerPC Registers in ModelSim . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120
Bus Functional Simulation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
IBM® CoreConnect™ Toolkit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
Chapter 1
Overview
The Platform Studio User Guide is for users of the Embedded Development Kit (EDK). EDK
is a series of software tools for designing embedded processor systems on programmable
logic, and supports the IBM PowerPC™ hard processor core and the Xilinx MicroBlaze™
soft processor core. Platform Studio is the graphical user interface technology that
integrates the all the processes from design entry to design debug and verification. Users
are encouraged to use Platform Studio to perform their embedded system design tasks.
This document describes both simple and complex design tasks that a typical user would
go through. This chapter gives the user an overview of Platform Studio technology.
This chapter contains the following sections
x “Creating an Embedded Hardware System”
x “Software Libraries”
x “System Simulation”
x “System Debug and Verification”
x “System Initialization and Download to the Board”
x “Advanced Topics: Embedded Processor System Design”
Software Libraries
Platform Studio supports various software libraries that are included in the installation.
These libraries can be used to enhance application software as they provide specific
functions that are more coarse grained tasks than driver routines. Chapter 4, “Using
Xilkernel” describes the XilKernel library that provides functions for context switching
and resource sharing for multiple tasks. Chapter 5, “Using XilMFS” describes XilMFS, a
memory-based file system library for creating and managing files and directories in
Chapter 1: Overview
memory (RAM). Chapter 8, “Profiling Embedded Designs” describes the XilProfile library,
a software intrusive profiling technology to create Call Graph and Histogram information
for program optimization. This library can be used to find hotspots in the application
software and tune the application for better performance.
System Simulation
After a hardware embedded design is created and the software to run on the processor(s)
is written, design simulation can be done before verification of the design. Chapter 6,
“Simulation in EDK” describes all of the simulation options that are a part of Platform
Studio technology, and illustrates the steps required to simulate both the hardware and the
software running on the hardware.
Fast Download
The Fast Download section describes an innovative “fast” download for MicroBlaze
systems. This technique uses a unidirectional Fast Simplex Link (FSL) from the MicroBlaze
Debug Module to the processor.
detail the operation of the Base System Builder Wizard, that is used to create simple
systems quickly and efficiently. A development board with a Xilinx FPGA is required to
complete the process of design and download. Chapter 2 describes a MicroBlaze processor
system, and Chapter 3 describes a PowerPC processor system.
Chapter 1: Overview
Chapter 2
Overview
XPS is an IDE used to develop EDK-based system designs. A simple Hello World system is
used to demonstrate the flow involved in building a processor hardware system. The
hardware flow explained here is for the PowerPC405 processor embedded in Xilinx
Virtex-II Pro devices. The flow for the Xilinx MicroBlaze soft-core processor is similar. The
differences for creating a MicroBlaze system are illustrated.
Assumptions
This chapter assumes that the user:
x Has a basic understanding of processor and bus based systems
x Has a board on which to test the generated hardware
Steps
The steps involved in creating a hardware system for EDK using XPS are as follows:
1. Create a new XPS Project
2. Select a target board
3. Select the processor to be used
4. Configure the processor
5. Configure IO Interfaces
Steps
Steps
For MicroBlaze, the configuration page allows you to select the debug interface type,
whether you want any local data and instruction memory, and whether you want to enable
cache for MicroBlaze. Accept all the default values, as shown in Figure 2-5, and click Next.
Configure IO Interfaces
Based on the board you have selected, the BSB Wizard presents a list of external devices
present on the board. Every page in the wizard displays up to three devices. If there are
more than three, they are spread across multiple pages. By default, the wizard selects all
devices to be included in the design. For the purpose of creating a simple hardware system,
keep only one device, the RS232_Uart_1. Deselect other devices, as shown in Figure 2-6.
Steps
Clicking Next will bring you more Configure IO Interfaces pages. Deselect all the devices
shown on other pages and click Next until you reach the Add Internal Peripheral Page,
shown in Figure 2-7.
Figure 2-7. Additional peripherals can be added using the Add Peripherals button. For our
simple hardware system, however, we do not want to add any other internal peripherals.
Click Next.
For a MicroBlaze system, no internal peripheral is added by default. Do not add any
additional peripherals. Simply click Next.
Steps
Steps
Add/Edit Hardware Platform Specifications dialog box. The dialog box contains four tabs:
Peripherals, Bus Connections, Ports, and Parameters.
The Peripherals tab, shown in Figure 2-9, displays all the non-bus components in your
design along with their addresses. You can add or delete new components in this page.
Figure 2-9: Add/Edit Hardware Platform Specifications Dialog Box, Peripherals Tab
Click on the Bus Connections tab. It displays a matrix of buses and various peripherals
connected to that bus, as shown in Figure 2-10.
Figure 2-10: Add/Edit Hardware Platform Specifications Dialog Box, Bus Connections Tab
For further details on this dialog box, refer to the “Xilinx Platform Studio (XPS)” chapter in
the Embedded System Tools Guide. For a simple hardware system, we do not need to make
any modifications in the design. Just click Cancel.
Generate Bitstream
This brings you back into the main XPS environment. Now you are ready to implement the
design for the board. Select Tools o Generate Bitstream. This runs various tools which
take the hardware design and generate a bitstream for the FPGA. This bitstream is present
at implementation/system.bit.
This bitstream only contains the hardware information. To populate the bitstream with the
software for the processor, select Tools o Update Bitstream menu item. This option
generates the software and updates the bitstream with the software information. The
resulting bitstream is ready to be downloaded. It is present at
implementation/download.bit.
Steps
Chapter 3
Overview
XPS is an IDE used to develop EDK based system designs. A simple "Hello World"
example is used to demonstrate the flow involved in building EDK libraries, creating and
compiling applications, and debugging the application using debugger. The software flow
is processor independent and is applicable to both MicroBlaze and PowerPC405.
Assumptions
This chapter assumes that the user:
x Has created a valid EDK project for Hello World example
x Has created a valid hardware platform in the Hello World example project
x Is familiar with C programming language and using GNU tools
Steps
The following are the steps involved in generating software for EDK designs using XPS:
1. Configure Software settings
2. View and Set Project Options
3. Create EDK Software libraries
4. Open/Create your application(s)
The tree view of the project (displayed on the left side of the XPS main window) includes
references to a variety of project-related files. These are grouped together in the following
general categories.
Steps
x System BSP - This category defines the hardware platform used in the project. The
hardware platform includes processors, buses and peripherals. Double clicking
anywhere inside the category will bring up the Software settings dialog.
x Project Files - This category includes all project-specific files. The files include MHS
file, MSS file, PBD file, UCF file. For more information on these files, see the “Xilinx
Platform Studio (XPS)” chapter in the Embedded System Tools Guide.
x Project Options - This category includes all project-specific options. The options
include Device, Netlist, Implementation, HDL, Sim Model. For information on the
options, see the “Xilinx Platform Studio (XPS)” chapter in the Embedded System Tools
Guide.
You can configure software settings for an EDK project using the XPS GUI or by editing the
MSS file.
Right click on the processor name in the tree view shown above. In the pop-up menu,
select S/W settings.
This brings up the Software Settings Panel shown in the following picture. The top half of
this panel displays various devices in the hardware platform and the drivers assigned to
them. The bottom right side of the panel allows you to select an OS. By default, standalone
is selected. This means there is no operating system between the application software and
the hardware platform. The application software can still use the device drivers and some
basic libraries. Default drivers are assigned to the processor and each of the peripherals
present in the hardware platform. The pull-down menus on the Driver and Version
columns allow you to choose other applicable drivers and/or driver versions.
To configure processor and peripheral drivers, click on the Processor and Driver
Parameters tab. Similarly, use the Library/OS Parameters tab to configure libraries and
OS parameters. Once the software settings are configured click OK in the Software Setting
dialog box. This will create the software settings MSS file as shown in the right hand side
view of the XPS window below.
Steps
Set the appropriate Xilinx architecture, device, package and speed grades for which the
current project is targeted. If custom drivers are used in the system, specify the appropriate
path in the Peripheral Repository Directory section. By default the Hello World project
does not need an entry for this section. Click OK in the dialog box.
The software library for the Hello World project is created in this project area:
C:\Data\HelloWorld_Syste\microblaze_0\lib\libxil.a
The address map of the system is created in this header file:
C:\Data\HelloWorld_Syste\microblaze_0\include\xparameters.h
Steps
Right click on Software Projects to bring up a popup that says Add New Project. Click on
this to create a new software project for the processor in the system. This creates an empty
new project and allows you to enter a name for this project. Once you do this the tree view
is updated to show the new project (called hello_world_app in this example), as shown in
the following figure.
Add the following C file (named hello.c) as one of the sources to the hello_world_app.
/*-------------------------------------------------------------------
* Filename : hello.c
* Desc : Prints "Hello World" on the STDOUT device
* ----------------------------------------------------------------*/
#include "xparameters.h"
int main() {
xil_printf("Hello World \n");
}
First create the file hello.c using your favorite text editor. Then Right Click on the Sources
for Project hello_world_app and select Add File. This opens the file browser to select the
appropriate file. Select "hello.c" from the appropriate location.
Caution! Adding a source to your project does not cause any file to be copied. This action
simply adds the path and file name to the project data.
Steps
setting various compiler options. Choose the executable mode as shown in the following
figure.
Build Application(s)
Once you are done with creating the application and setting the options, you can right click
on the project name in the tree view and click on Build Project in the resulting popup to
create the executable. Alternatively, Select Tools o Compile Program Sources in XPS to
build all the applications.
download and execute the hello_world_app application, select Tools o Download in the
XPS main window. This downloads the bitstream onto the board. After downloading,
Hello World is displayed on the hyper terminal.
Steps
Next, you must set the debug options. In the compiler options dialog box shown above,
choose the Optimization tab. From the Optimization panel, under Debug Options, select
Create symbols for debugging (-g option) as shown in the figure below.
After setting the option, build the hello_world_app application as detailed earlier.
Download the bitstream and start XMD by selecting Tools o XMD. This should start up
the XMD debugger. Connect XMD to the board (see the “Xilinx Microprocessor Debugger
(XMD)” chapter in the Embedded System Tools Guide for more information). Once XMD is
connected to the board, select Tools o Software Debugger to start the GNU debugger.
This should pop up the following debugger window.
You can now download and debug the hello_world application using xmd and gdb (see
the “Xilinx Microprocessor Debugger (XMD)” chapter in the Embedded System Tools Guide
for more information).
Chapter 4
Using Xilkernel
Xilkernel is a set of interfaces and functions that allow context switching and resource
sharing between applications. Xilkernel is a low cost alternative to an RTOS (Real-Time
Operating System) in some use cases. The first sections of this chapter explain the
fundamental concepts of Xilkernel, followed by more sections illustrating how Xilkernel
functions can be incorporated into user applications. Later in the chapter, specific
examples targeting a particular board and device illustrate the configuration and usage of
Xilkernel functionality.
This chapter contains the following sections:
x “Xilkernel Concepts”
x “Getting Started with Xilkernel”
x “Using Xilkernel”
x “Xilkernel Design Examples”
Xilkernel Concepts
The following general concepts are key to understanding Xilkernel: Processes, Threads,
Context switching, Scheduling, Interprocess communication and Synchronization. These general
concepts are not explained in their entirety and detail in this chapter. However, a basic
introduction to each concept is provided. These concepts should be familiar to anyone
comfortable with Operating System technology, but Xilkernel introduces some additional
constraints in certain cases. Therefore, advanced users can skip introductory portions and
go directly to Xilkernel relevant parts. Some concepts are completely specific to Xilkernel.
These include Xilkernel configuration, bundled/separate-executable modes, block
memory allocation, system initialization, user-init functions, interrupt handling and
accessing standard libraries.
3. Timeslice3: Xilkernel stops Process B, saves its state, then restores the saved state of
Process A, and continues running Process A.
4. Timeslice4: Process A terminates, and Xilkernel restores the saved state of Process B,
and continues running Process B.
As a result of this sequence of operations, Process A and Process B appear to be running
concurrently. For example, an embedded system might have two applications that need to
run concurrently, where the first application continuously processes input packets and
outputs filtered data, while another application monitors user push-button inputs and
displays status on an LCD panel. Without Xilkernel, the two applications would have to be
combined into one giant application. With Xilkernel, each application becomes an
independent process, and can be developed and tested independently. A process can
perform several operations on itself or other processes, such as creating a new process,
yielding its time slice to another process, killing another process, waiting for another
process to finish, changing its own priority, and exiting.
In the context of Xilkernel, a thread is a special kind of process. The programming interface
for these threads is based on the widely used POSIX standard, now supported by the IEEE,
called pthreads. While other operating systems define a thread to be a light weight
process, a thread in Xilkernel is not very different from a regular process. Threads and
processes contend among each other for scheduling. Refer to the “Xilkernel” chapter in the
EDK OS and Libraries Reference Guide for the differences between threads and processes, the
details of their operation, as well as their life cycles. In further sections of this chapter, the
term process is used to encompass both processes and threads, while the term thread is used
in the context of thread-only operations. Xilkernel provides different scheduling
algorithms, one of which can be selected to best meet the needs of a particular combination
of applications. The simplest scheduling algorithm provided by Xilkernel is the round-
robin scheduler. This scheduler places all processes in a queue and assigns each time slice
to the next process in the queue. Xilkernel provides another scheduling algorithm called
the priority scheduler. The priority scheduler places processes in multiple queues, one for
each priority level. On each timer interrupt, the priority scheduler picks the first item in the
highest priority queue. Each process is assigned a fixed priority at the time it is created.
Some operating systems modify or increase the priority of a process if it is not picked to
run but Xilkernel does not. A process is picked to run only if it is ready to run and there are
no higher priority processes that are ready to run. Details of the scheduling algorithms are
described in the “Xilkernel” chapter in the EDK OS and Libraries Reference Guide.
Synchronization Constructs
When two processes try to access a shared resource such as a shared memory segment, it
might be necessary to provide exclusive access to the shared resource for a single process.
For example, if Process A is writing to a shared memory block, Process B should wait until
Process A is done, before it reads the same block. Similarly if Process B is reading a shared
memory block, Process A should wait until Process B is done, before it writes a new value
to the same block. The constructs that allow one to ensure this kind of constraints are
known as synchronization constructs. Semaphores and mutexes are the two constructs
provided by Xilkernel. In this example Process A and Process B could use semaphores to
ensure correct operation. Semaphores are much more advanced constructs than mutex
locks and provide a counting facility that can be used to co-ordinate tasks in much more
complex fashions. A mutex lock is essentially just a binary semaphore, but it may or may
not be implemented using a semaphore. In Xilkernel, mutex locks have an independent,
though similar, implementation from semaphores.
Here is an example scenario involving semaphores for coordinating accesses to a piece of
shared memory between two processes A and B. A uses semaphore X to signal B, while B
Xilkernel Concepts
uses semaphore A. Process A starts by creating semaphore X with an initial value of 0, and
Process B starts by creating a semaphore Y with an initial value of 0, and waits for
semaphore X. The wait operation blocks a process until a corresponding signal operation
releases it. Process A now writes to the shared memory and then signals semaphore X by
invoking the sem_post() function. Process A then waits on semaphore Y before writing
again. Meanwhile Process B which was waiting for semaphore X gets it and does the read
operation, and then signals semaphore Y, and waits again on semaphore X.
Mutexes are similar to semaphores, and they allow mutually exclusive access to a shared
resource. However, mutexes are defined only for threads in Xilkernel. The shared resource
may be a shared memory block as in the previous example, or it may be a peripheral device
such as a display device. A mutex is associated with the shared resource at software design
time. Then each thread that wants to access this resource first invokes a
pthread_mutex_lock() function on this mutex to obtain exclusive access. If the resource is not
available, the thread is blocked until the resource becomes available to it. Once the thread
obtains the lock, it performs the necessary functions with this resource and then unlocks
the resource using pthread_mutex_unlock().
Inter-Process Communication
Independently executing processes or threads can share information among themselves by
using standard mechanisms such as shared memory or message passing. By definition,
the data memory used by each process is distinct from the data memory used by other
processes. Consider a scenario in which you want to build a system in which Process A
reads data from a serial input device and stores it in memory, and Process B reads this data
from memory and computes some value, the data should be stored in a shared memory
segment. When you configure Xilkernel, as explained later, you can specify the number
and size of shared memory segments. Then Process A attaches to a named shared memory
segment, and writes data to it. Process B attaches to the same shared memory segment
using the same name and reads data from it.
Another technique to allow Process A and Process B to share data is message passing. In a
modified version of the previous example, Process A reads data from a serial device and
then creates a message containing this data. Process A sends the message to a message
queue, specifying a queue identifier. Process B then gets the message from a specified
message queue and retrieves the data in the message. The message passing routines are
higher level functions that use semaphores internally to provide a simple communication
mechanism between processes. Again, details of these functions are described in the
“Xilkernel” chapter in the EDK OS and Libraries Reference Guide.
The programming interface for shared memory and messages is based on the POSIX
standard, and is described in more detail in the “Xilkernel” chapter in the EDK OS and
Libraries Reference Guide.
running. The operating system then creates new processes for user applications. Xilkernel
works in this fashion when using the separate executable mode to configure processes.
Many embedded operating systems use a different mechanism that simplifies the
interaction with the operating system itself. In many cases, all the applications that will
ever run on an embedded system are known at the time the system is created. All these
applications reside in some kind of non-volatile memory. Push buttons or other simple
controls are used to start and stop different applications. In such situations, the operating
system kernel and the user applications are all bundled into one single executable file that
is loaded into memory. Xilkernel works in this fashion when using the kernel bundled
executable mode to configure processes. The default memory layout for Xilkernel used in
kernel bundled executable mode for MicroBlaze is as follows:
x 0x0 to 0x14 - reset vector, exception vector, interrupt vector (jump to start, exception
handler, interrupt handler)
x In executable mode:
i 0x18 - startup code, followed by application and Xilkernel code and data
x In xmdstub mode:
i 0x18 - 0x400 xmdstub code
i 0x400 - startup code followed by application and Xilkernel code and data
In the separate executable mode for MicroBlaze, the Xilkernel code and data are in the
same locations as in the kernel bundled executable mode described earlier, but each
application has its own elf file and has a different start address and a single contiguous
address range for its instructions and data. So application A might have a start address of
0x1000000 and its code and data have an address range of 0x10000000:0x10FFFFFF, while
application B might have a start address of 0x11000000 and its code and data have an
address range of 0x11000000:0x110FFFFF. Applications in the separate executable mode
must be compiled with the -xl-mode-xilkernel flag. The kernel bundled executables
and the Xilkernel executable for the kernel bundle mode must be compiled with either the
flag -xl-mode-xmstub or the flag -xl-mode-executable.
The PowerPC version of Xilkernel has a different memory layout dictated by the PowerPC
hardware requirements. The basic requirements for the PowerPC are a vectors section
starting on a 64KB address boundary, a boot section at 0xFFFFFFFC, and memory space for
other instruction and data sections. The default linker script for PowerPC Xilkernel defines
three sections - vecmem, codemem and datamem whose size and start address can be
configured by the user. Vecmem is the vectors section, and has a default size of 9KB and a
default start address of 0x0. Codemem is the memory for all the instructions, and it includes
the boot address 0xFFFFFFFC. The default start address is 0xFFFFD000 and the default size
is 12K. Datamem is the memory for all the data, with a default start address of 0x00002400
and a default size of 9K. For the separate executable mode, these memories are sufficient to
hold the default Xilkernel executable, and the applications with their own executable elf
files occupy separate non-overlapping memory regions. The kernel bundled mode
executable, and the Xilkernel executable in the separate executable mode should be
compiled with the top-level linker script provided with the Xilkernel sources
(linker_script.sh), while the applications in the separate executable mode must be
compiled with a different application level linker script. A sample script has been provided
under the test cases folder within the Xilkernel sources.This linker script will be discussed
later on.
Example application code for the kernel bundled executable mode:
#include <stdio.h>
/* various declarations and definitions go here */
Xilkernel Concepts
int app_main()
/* the entry point to the application should not be called main() */
/* this function name should not clash with any name in xilkernel code
or other apps */
/* this function name should be specified in the
kernel_bundled_process_table entry in the MSS file */
{
/* the application code goes here */
/* the application is allowed to create new processes and threads */
}
The kernel bundled executable mode kernel can still service separately compiled
executables, through a system call layer. This is akin to being a mixed executable mode.
Using Xilkernel
x OPB timer or Fixed Interval Timer (FIT) peripherals connected to the interrupt port of
the processor either directly or through an interrupt controller.
x Uart or Uartlite peripheral for input/output. (This is optional and is only used for
demonstration/debug purposes.)
Using Xilkernel
There are five steps to using Xilkernel with your applications.
1. Configure Xilkernel
2. Create your application(s)
3. Download Xilkernel and any separate applications
4. Debug your applications
5. Optional - Set up a boot loader to start Xilkernel and applications
Each of these steps is explained in more detail in the following sections.
Configuring Xilkernel
You can configure a software platform to include Xilkernel by using the XPS GUI or by
editing the MSS file. In the XPS GUI window click on the System tab in the middle-left
panel to bring up the hardware tree view. Then right click on the processor name in the tree
view shown below and select S/W Settings.
This brings up the Software Settings dialog box, shown following. The top half of this
dialog box displays various devices in the hardware platform and the drivers assigned to
them. The bottom right side of the dialog box allows you to select an OS. You can select
VxWorks, Standalone or Xilkernel. Select Xilkernel. If multiple versions of Xilkernel are
available, you can select an appropriate version. This chooses the OS for the software
platform of the selected processor.
Using Xilkernel
To further configure Xilkernel, click on the Library/OS Parameters tab at the top of the
panel. This brings up a panel that looks like this:
The Library/OS Parameters tab shows all the configurable parameters for Xilkernel. The
parameters are organized into categories and subcategories. For each parameter, the
parameter type, default value and a short explanation are shown. The default values are
already filled in, and you can change the values as needed. You can collapse or expand the
tree view by clicking on the + or - symbols on the left hand side. After setting all the
parameters click OK to save. You can always go back and change the saved values if you
want to.
Two parameters of special interest are the *_process_table parameters at the bottom of the
config_process category. The kernel_bundled_process_table parameter allows you to
provide a list of function names and priorities corresponding to the applications that are
bundled with the kernel executable. The separate_exec_process_table parameter allows
you to provide a list of start addresses and priorities corresponding to the separately
compiled applications that will be loaded into the kernel’s process table on startup. Note
that any application can create and kill arbitrary processes at run time, so the kernel’s
process table can change with time. Another point to note here is that at this point you have
not created any applications. Therefore, the start addresses and function names provided
here are based on what applications you plan to create. You can always come back to this
panel and change the process tables and other values after you actually create your
applications.
Using Xilkernel
Right click on Software Projects to bring up a popup that says Add New Project. Click on
this to create a new software project for your kernel application. This creates an empty new
project and allows you to enter a name for this project. Once you do this the tree view is
updated to show the new project (called kernel_bundled_app in this example), as shown in
the following figure.
Using Xilkernel
Now you have to set the compiler options correctly for the kind of application you want to
build. If this is a kernel bundled application, the kernel linker script and the -lxilkernel
options should be specified. You can do this by right clicking on the project name in the
tree view, and selecting Set Compiler Options on the popup. This opens up a window
with multiple tabbed panels for setting various compiler options. The linker script and -
lxilkernel options are set by clicking on the directories tab and entering the values as
shown in the following figure.
Note: Applications need __XMK__ to be defined when being compiled. Defining this flag makes
available certain definitions and declarations from the GNU include files that are required by both
Xilkernel and applications. Therefore, -D__XMK__ should accompany the compiler flags of any of
your applications.
Now you are ready to create your application source files. You can use your favorite text
editor or IDE to create your application. Then right click on Sources in the project tree
view, and click on Add File in the popup to add your source files. Once you are done with
this you can right click on the project name in the tree view and click on Build Project in
the resulting popup to create the executable that contains your kernel bundled application.
Using Xilkernel
x XPS allows you to use your elf file(s) to modify the BRAM contents in the bitstream. If
you do not care about this feature, you can simply use XMD to download your elf files
as described in the next section. If you want to initialize BRAM contents in the
bitstream, examine the XPS generated makefile to see how this can be done on the
command line.
scheme for sharing, using the basic semaphore, mutex, shared memory and other
interprocess communication primitives provided by Xilkernel.
For example, let the hardware system contain a UART for input and output, mapped to a
fixed base address. The software system consists of two applications bundled with
Xilkernel, and both applications want to use the UART driver. Since the applications and
Xilkernel are all bundled into a single executable file, there is a single copy of the device
driver. Unless Xilkernel and the two applications agree upon a scheme to send input data
from the UART to specific processes based on flags or some other mechanism, input from
the UART is fed to whichever process is running when the input arrives.
Within the design example folder, the MicroBlaze design example is located under the MB
folder, and the PowerPC example is located under the PPC folder. The Xilkernel
application sets are grouped under the code folder of each project folder. Each application
set is organized under a folder named ex<num>, where num is the example set number.
The design example applications are organized to be built outside of XPS. Each folder has
its own Makefile which is configured to build all the applications in each example set, in
their respective modes. Each application is coded in a single source C file.
The example application sets have been designed to illustrate all the features of Xilkernel
and the different modes in which applications can link with Xilkernel. Each application set
is available for both PowerPC and MicroBlaze. Xilkernel is loaded starting from the first
address in block ram in MicroBlaze (0x0) and 0xffff0000 in PowerPC systems. The PPC
Xilkernel needs a linker script to set up the vectors section which needs to be aligned at a
64KB boundary. Separate-executable applications are loaded starting from external
memory - 0xe000000 in the MicroBlaze system and 0xf8000000 in the PowerPC system.
Further description of the examples will focus on the MicroBlaze system. A separate
section will document the differences in the PowerPC examples, including the linker script
configuration.
Since the example applications include those that run from external memory, we will need
to use XMD to download the programs and execute them. Each of these design examples
has a simple startup program to print a welcome message and exit. Only this program is
used to initialize BRAM and execute on bitstream download.
The steps described below can be run completely from the XPS GUI, except for compiling
the example application sets. For this reason, it is recommended that you open a
console/shell session to key in the some compilation commands manually. The rest of the
tutorial does not use the GUI to illustrate each step. However you are recommended to try
the XPS GUI on your own, as it is offers an intuitive and easy interface.
You will need hyperterminal or some other terminal client connected to the serial port
through which the RS232 interface on the target board is connected. The session should be
configured for, 19200 baud, 8 data bits, no parity, 1 stop bit and no flow control. A sample
configuration window from hyperterminal is shown below.
END
The Xilkernel MSS specification needs to be enclosed within an OS block (highlighted in
green) as shown. The parameters in blue are required parameters. The os_name and
os_ver parameters combine to tell LibGen the folder name under which the OS’s source
files are to be located. The proc_instance parameter ties the OS to a particular processor
in the hardware system. In this case, it is tied to the processor whose instance name is
microblaze_0. Since the example applications use output and input from stdin and
stdout, we need to tell Xilkernel the instance names of the peripherals that are to be used for
standard inputs and outputs. In this case, we use the OPB Uartlite peripheral in the system,
named RS232, as the input-output device. Since all our examples work with processes and
threads, we set the config_process to true. The max_procs parameter controls the
maximum number of processes that can exist in the system and the corresponding number
of process context save structures that are allocated within the kernel statically. For example,
specifying max_procs to be 5 and assuming that each process context needs 120 bytes of
memory, a total of 600 bytes of memory for process contexts is allocated in the bss section of
the executable. The max_readyq controls the size of the ready queues in the system.
MicroBlaze systems require a systmr_spec parameter which specifies the timer device
that clocks the kernel and its type (there is support for the fit_timer and the opb_timer
devices in Xilkernel). The value of this parameter is a tuple which such as
(<instance_name>,<type>). FIT and PIT are the allowed type strings, corresponding to the
fit_timer and opb_timer, respectively. We use the system_timer device to clock Xilkernel
in this example. The parameter pit_interval configures the count down value that is
loaded onto a PIT timer if it is present in the system. This directly controls the amount of
CPU budget that each process is allocated when it is scheduled. Since we have multiple
interrupting sources in this system, we connect them through an interrupt controller.
Xilkernel supports the opb_intc interrupt controller. When interrupts are fed to the system
through the interrupt controller, the interrupt controller device must be specified with the
parameter sysintc_spec. The value of the parameter is the instance name of the
interrupt controller device.
All the parameters in the MSS file are translated into configuration directives and
definitions in header files. Specifically, for Xilkernel, os_config.h and config_init.h
are the generated header files that contain C-language equivalents of the specifications in
the MSS file. For the system timer device and system interrupt controller device
specifications, the header files contains definitions of base addresses of these devices,
which are in turn used by the Xilkernel code. These header files are generated under the
main processor include directory (microblaze_0/include in this example). Feel free to
take a look at how the MSS configuration translates to definitions in the header files.
The sched_type parameter controls the scheduling policy used by Xilkernel. The value 2
corresponds to the round-robin scheduling policy. The other supported policy is the
priority driven scheduling policy (value 3). Round-robin scheduling simplifies the
illustration of the various Xilkernel concepts.
The debug_mode parameter controls kernel debug message output. By default it is turned
off. Setting debug_mode to true, enables the macro DBG_PRINT in the Xilkernel code.
We set it to true in these examples to make available diagnostic messages from the kernel
available.
Example Set 1
Description
The following concepts of Xilkernel will be illustrated with example set 1:
i Configuring and building kernel bundled applications
i Processes
i Pthreads
i Dynamic thread creation
i Shared memory.
The example contains three different applications:
x A simple hello world application launched as a process.
x A pthread application creating multiple threads dynamically and joining with them.
x Aa shared memory application that tests the POSIX shared memory API.
All three applications are configured to be in kernel-bundled executable mode and are
created statically. On Xilkernel startup all the processes are created simultaneously. Round-
robin scheduling is used to time share the system between these three applications.
Configuring
The software specification for the system in example 1 is contained in the
system.mss.ex1 file contained in the project folder. Let us look at the relevant portions
of this software specification:
# Configure pthreads
PARAMETER config_pthread_support = true
PARAMETER max_pthreads = 5
# SHM specification
PARAMETER config_shm = true
PARAMETER shm_table = (100)
As explained in the description, the applications that form this example consist of a shared
memory application, a simple hello world application and a pthreads application. The first
step is to configure the kernel to include this functionality. The parameter
config_pthread_support is set to true to enable thread support in the system. The
maximum number of threads in the system is known to be 5, so that is also configured. In
this particular case, the number of threads need not have been configured since the default
value is also 5. Not specifying the max_pthreads parameter will cause it to default to the
MLD configured value. Look at the “Xilkernel” chapter in the EDK OS and Libraries
Reference Guide or xilkernel_v2_1_0.mld (present in the data/ folder of the xilkernel
sources) to get an idea of the available parameters and their configuration. The shared
memory segment needed by the shared memory application is configured in by the
config_shm parameter. The segment is also allocated within the kernel by the
shm_table parameter, which is an array, specifying the sizes of all the shared memory
segments that will be needed by the system. Recall that we want these three applications to
be bundled along with the kernel. The kernel_bundled_process_table parameter
specifies the starting function, priorities and stack sizes of all the processes that need to be
statically created. Similarly the kernel_bundled_pthread_table parameter is used to
statically create pthreads. However a stack size specification is not required as all the
threads that can ever execute in the system will already have a stack of configurable size,
pre-allocated. You need to modify the pthread_stack_size parameter to change the
amount of stack space allocated to threads. As part of Xilkernel's initialization, these
processes and threads would be created from the configuration directives files. Take a look
at the source code of these applications (code/ex1/*.c). Notice that these applications
do not have a main routine. This is because when bundled with the kernel, we want the
kernel's main routine to be the starting point of execution. A main, is therefore not allowed
in kernel bundled applications since it would conflict with the kernel's main routine.
Building
Copy over this example's MSS file, system.mss.ex1 to system.mss (cp -r
system.mss.ex1 system.mss). Clean and re-build the libraries using either the XPS
GUI or the command line. To build it using the GUI, select Tools o Generate Libraries
and BSPs. To build the libraries in the command line, enter
make -f system.make libsclean; make -f system.make libs
For this example, a xilkernel.elf file is not generated, since we have indicated that
there will be kernel bundled applications which will be linked in with Xilkernel. The kernel
sources are compiled and bundled into libxilkernel.a. This file gets generated in the
processor library folder (microblaze_0/lib). To build the applications, move to the
code/ex1 subfolder. In the shell, enter
make help
to view the available options. Enter
make all
to build all the applications and generates a single kernelbundle.elf containing all the
applications and the kernel. The example set Makefile illustrates how to link
applications with the kernel in kernel-bundle mode. The following compiler options are of
interest:
#
# Linker options for the kernel bundle.
#
LFLAGS = -xl-mode-executable -Wl,-defsym -Wl,_HEAP_SIZE=700
CFLAGS = -O2 -g -D__XMK__
The _HEAP_SIZE linker flag tells the linker how much heap space to allocate to the kernel
executable. There is an additional linker flag -xl-mode-executable. This corresponds
to the description in the “Code and Runtime Structure” section. You can use
-xl-mode-xmdstub as the linker flag, if you use XMDSTUB to debug your design. Of
special interest in the CFLAGS, is the definition of __XMK__. This is a special define that
must be used when compiling, both, Xilkernel and the applications that execute on
Xilkernel. This definition makes available other definitions in standard include files and is
required for proper compilation.
Downloading
Connect to the processor in the system using XMD. You can open up XMD either through
the XPS GUI (Tools o XMD), or by keying in xmd in the console. Connect to the processor
in the system with the mbconnect mdm command. Once you have connected to the
processor, download this example set. For your convenience, a batch script has been
provided in the file, dow-1.cmd. Once this step is complete, your application and
Xilkernel have been downloaded to appropriate locations in memory, based on the
information in the elf file(s). The download command gives you information about
where the various sections were downloaded. This sequence of steps is illustrated below,
Xilinx Microprocessor Debug (XMD) Engine
Xilinx EDK 6.2 Build EDK_Gm.9
Copyright (c) 1995-2002 Xilinx, Inc. All rights reserved.
XMD% mbconnect mdm
Executing
Once the download step is complete, the program counter of the processor points to the
start address of Xilkernel, since Xilkernel is the last of the programs to be downloaded.
Make sure you have hyperterminal connected as described earlier. Key in the following to
start the processor’s execution:
con
Stop the execution of the system after two of the applications terminate and the hello world
application continues in its infinite loop. This can be done by keying in the following in
XMD:
stop
The figure above shows output of the first two programs from the execution of Xilkernel.
The lines of output that start with XMK: are debug messages from the kernel. The kernel
starts out by initializing the hardware appropriately. This includes initializing the
interrupt controller and the PIT device so that it gets interrupted at the configured time
interval. Then Xilkernel performs a system initialization. This includes initializing data
structures inside the kernel, kernel flags and creating the statically specified processes and
threads. The threads and the processes are created in the same order that they were
specified in the MSS file. Therefore the hello world application gets to execute first (output
lines preceded by HELLOWORLD:). Since scheduling is round-robin, the kernel soon context
switches to the next process which is the shared memory application (output lines preceded
by SHM:). Let’s take a look at the flow of these two applications first.
hello_main()
{
int i = 0 ;
int pid;
pid = get_currentPID();
print("HELLOWORLD: My PID: ");
putnum(pid);
print ("\r\n");
As configured, the hello world application starts from the routine hello_main(). This is a
very simple application, that initially prints out a message which includes its own process
identifier. It uses the get_currentPID() system call to retrieve this value from inside the
kernel. The PID value of a process is useful for performing operations like, killing a
process, getting a process’s status, etc. The application then enters an infinite loop, printing
a message at regular intervals (snippet below).
while(1) {
print("HELLOWORLD: Hello World. Looping here
infinitely...\r\n");
Let us examine how the get_currentPID() system call is handled for this application, which
is a part of the kernel bundle. Take a look at the source code for get_currentPID() in the
following file under this user guide project folder:
microblaze_0/libsrc/xilkernel_v2_00_a/src/syscall/arch/microblaze/libprocess.c
int get_currentPID()
{
#ifdef KERNEL_BUNDLED_SYSCALL_LIBRARY
int ret;
xmk_enter_kernel();
ret = sys_get_currentPID();
xmk_leave_kernel();
return ret;
#else
JMP_SYSCALL_HANDLER( SC_Process_GetPID )
#endif
}
This is the system call wrapper code for get_currentPID(). It vectors control from the user
application to the actual system call, sys_get_currentPID(), in process.c. Since this
application is part of the kernel bundle, only the code that is conditional on
KERNEL_BUNDLED_SYSCALL_LIBRARY being defined, gets compiled. The other
conditional (grayed out) code is compiled, only when the application is in separate
executable mode. Also since the actual system call is within the symbolic scope of the
library wrapper, instead of vectoring the call, the system call function can be directly
invoked. The wrapper function proceeds to do this, but locks (xmk_enter_kernel()) and
unlocks (xmk_leave_kernel()) the kernel after the system call. This is because Xilkernel has
been designed to be monolithic and allows only one thread of control inside it at any
particular time.
Other system calls that you will see in the other applications in this example also follow the
same mechanism.
The shared memory application illustrates and tests all the POSIX shared memory
interfaces provided by Xilkernel. Upon encountering errors while testing a particular
interface, it sets a bit in an error string. The <sys/shm.h> header file needs to be included
to make available the standard declarations. Take a look at all the shm*() calls to get an idea
as to how the interface is used. Snippets of code from the shared memory application,
performing basic operations are explained below,
x Creating a shared memory segment of specified size and getting a handle to it.
shm_id1 = shmget(key, 100, IPC_CREAT);
Shared memory segments are created using the shmget() interface. A unique key is
used to identify the segment uniquely by all the sharing processes. The segment size
also needs to be specified. A successful call returns a unique positive number that
identifies the segment.
x Attaching to the shared memory segment and retrieving a C-language pointer to the
segment’s start address.
memptr = shmat(shm_id1, NULL, 0);
Attaching to the shared memory segment is done by using the shmat() interface. The
identifier of the segment to attach to is specified as the first parameter. The other two
parameters are unused currently. The system call returns a pointer to the start of the
shared memory segment.
x Retrieving statistics about the shared memory segment
shmctl(shm_id1, IPC_STAT, &shm_dat)
Any specified shared segment’s current statistics can retrieved using the shmctl()
system call. The statistics are written to the shm_dat structure which is of type shmid_ds.
Information such as the last process that performed an operation on this segment, the
process that created the segment, the number of attached processes, the size of the
segment etc. can be obtained.
x Detaching from the shared memory segment
shmdt(memptr2)
Detaches this process from the shared memory segment.
x Destroying the shared memory segment
shmctl(shm_id1, IPC_RMID, &shm_dat)
Destroying the shared memory segment is also done using the shmctl() API. The
requested operation is IPC_RMID, which indicates that the shared memory segment
should be removed.
Finally the program dumps out all the errors encountered so far (0x0 - no errors, in this
case).
The pthread application is the next application that is context switched into. Any
application that needs to use threads, has to include the pthread.h header file. The main()
routine in the pthread application creates three different threads dynamically, joins with
them and terminates. The output of the pthread application is shown in two parts below.
The pthread’s API implemented in Xilkernel is very close to the POSIX standards and
therefore this application in pthreads.c can be directly compiled using the compiler for
any POSIX operating system and executed on it, without any changes.
retval = pthread_attr_init(&attr);
This system call initializes an attributes structure pthread_attr_t that can be used,
optionally, to configure the created thread. It includes fields to specify the scheduling
priority and the detach state of the created thread. The pthread_attr_init system call inserts
default attributes in the attribute structure specified. The main thread changes the detach
state of the created threads. The default detach state specifies that the thread’s resources
will be reclaimed and the thread complete flushed from the system on the thread’s
termination. Specifying the detach state to be PTHREAD_CREATE_JOINABLE causes the
thread’s storage to be reclaimed only when another thread joins (explained further on) with
this. The system call to create a new thread dynamically is pthread_create().
retval = pthread_create(&tid1,&attr,thread_func1,&arg1);
At the end of the create system call, a new thread is created, starting from the function that
is specified in the call and this thread is put in the ready state, waiting to be scheduled in.
The system call returns the ID of the newly created thread in the location passed in as the
first parameter. The thread identifier is of type pthread_t. This thread identifier is different
from the process identifiers and should not be confused with it. This identifier must be
used in identifying the target of many thread operations. The first thread executes the body
of the thread_func1 routine. This routine prints out a message t1 some number of times
before terminating. It then terminates by invoking the following line of code,
pthread_exit(&ret);
Since this thread has been configured to be "joinable", the call to the pthread_exit() routine
suspends the calling thread without reclaiming resources and context switches to the next
schedulable process or thread. The exit routine takes a pointer argument, that points to a
return value data structure. This pointer argument can be reclaimed by any thread that
joins with this thread. The main thread, in fact, does this and prints out the return value in
hex. This call to pthread_exit() is not required at the end of a thread’s execution (except for
the main thread). Control returns from the thread function to a kernel-level wrapper, which
performs a call to the exit routine on behalf of the thread. The second and third,
dynamically created threads, choose this approach.
The second thread gets to execute next, since it was created after the first thread. This
thread prints out the message t2 some number of times and terminates.
The main thread "joins" with these two threads by using the pthread_join() interface.
retval = pthread_join(tid1,&retptr);
The target thread with which the join is to be performed, has to be specified in the call. The
main thread also passes in a location at which the return value pointer, if any, stored by the
target thread is saved. The join call, suspends the main thread, till the target thread
terminates and then it awakes the joining thread. The join call, releases the target thread’s
resources and then returns to the invoking thread. After joining with the first two threads,
the main thread retrieves its own thread identifier by:
main_tid = pthread_self();
This system call is useful if a thread needs to pass its own identifier to other threads that
work alongside. In our example, the third dynamic thread uses this identifier to try to join
with the main thread. The third thread, prints out a message t3, followed by its own
thread identifier, which was passed in as argument to the thread routine, some number of
times, before terminating. The main thread, launched this third thread, with detach state
set to PTHREAD_STATE_DETACHED. Therefore when the third thread terminates, its
resources will be automatically reclaimed, without requiring a join with it. The detach state
of a thread cannot be changed dynamically and can only be configured while the thread is
being created. The third thread tries to synchronize with the completion of the main thread
by performing a join. However it is possible that by the time this operation completes, the
main thread would have already terminated and thus detached. Joins to an already
terminated thread result in an error.
After all the threads in the pthreads application complete their execution, the only other
active process is the hello world application and it continues to execute in its infinite loop,
printing a message at regular intervals.
Notes
In the pthreads API, the pthread_join() and other pthread system calls such as pthread_self()
are valid and make sense only when invoked from within threads and not processes. This
is the reason why the body of main() was statically created to be a thread, since it makes
these pthread calls.
Example Set 2
The following concepts of Xilkernel will be illustrated with example set 2 -
x Separate executable mode of linking applications
x Dynamic process creation
x Semaphores
x Message queues
x Block memory allocation.
The example contains three different applications controlled by a statically created shell
application. The three applications that can be launched from the shell are:
x A producer-consumer application using the POSIX message queue API
x A threads application that uses semaphores to protect critical operations from other
threads
x A linked list application that uses the buffer memory allocation API.
The shell, again, illustrates dynamic process and thread creation.
Configuring
The software specification for the system in example 2 is contained in the
system.mss.ex2 file contained in the project folder. Let us look at the relevant portions
of this software specification:
# Configure pthreads
# Semaphore specification
PARAMETER config_sema = true
PARAMETER max_sem = 4
PARAMETER max_sem_waitq = 5
# MSGQ specification
PARAMETER config_msgq = true
PARAMETER num_msgqs = 1
PARAMETER msgq_capacity = 10
As explained in the description, the applications that form this example include a shell
configured as a separate executable. Using the shell you can launch three other
applications: a semaphore demo application, block memory allocation demo application,
and a producer consumer application demonstrating message queues. This MSS file
configures the kernel to include the required functionality. The parameter
config_pthread_support is set to true to enable thread support in the system. The
semaphore module and the message queue modules are turned on by setting the
corresponding parameters to true. The maximum number of semaphores and their wait
queue lengths are set to sufficient values with the max_sem and max_sem_waitq
parameters. A single message queue is configured in the system with a capacity for 10
messages. The parameter config_malloc enables the block memory allocation API. The
message queue module depends on both the semaphore and block memory allocation
modules. Each message queue uses two semaphores internally and uses block memory
allocation to allocate memory for messages in the queue. An important parameter while
using message queues and block memory allocation is the mem_table parameter. The
sizes and the count of all the blocks of memory that will be needed both by the user and the
kernel have to be configured in the table. For example, the tuple (4,30) indicates that the
block memory allocation API should be able to satisfy a maximum of 30 requests for 4 byte
blocks of memory. The shell application is configured to start from address 0xe000000. It
is also a thread. Therefore, Xilkernel is configured to statically create a process starting at
that address, with the separate_exec_pthread_table parameter.
Building
From the project directory, copy over this example’s MSS file, system.mss.ex2 to
system.mss (cp -r system.mss.ex2 system.mss). Clean and re-build the libraries
using either the XPS GUI or the command line. To build it using the GUI, select Tools o
Generate Libraries and BSPs. To build the libraries in the command line, enter:
make -f system.make libsclean; make -f system.make libs
For this example, a xilkernel.elf file is generated, since we have indicated that there
will be only separate executable applications. Therefore the kernel sources are compiled
into xilkernel.elf and separate executable applications link with the kernel dynamically
through the system call interface. This system call interface is built as a library
(libsyscall.a). This file gets generated in the processor library folder
(microblaze_0/lib). Separate executable applications link with this library to interface
with the kernel. To build the applications for this example, move to the code/ex2
subfolder. To view the available options, key in the following in the shell:
make help
To build all the 4 applications and generate the elf files for the separate executable
applications, key in the following:
make all
The example set Makefile illustrates how to link applications with the system call library.
The following compiler options are of interest:
#
# Linker options for the separate executables.
#
LFLAGSS = -xl-mode-xilkernel -Wl,-defsym -Wl,_HEAP_SIZE=500 -Wl,-defsym
-Wl,_TEXT_START_ADDR=$(SHELL_START_ADDRESS)
The -xl-mode-xilkernel option tells mb-gcc to use a different C-runtime (crt) file
when forming the final executable. This is because, the default crt is designed to initialize
the MicroBlaze exception and interrupt vector addresses in main memory. We do not want
this behavior when executing applications that run on Xilkernel, as Xilkernel would have
already set up this information. Apart from an optional heap size specification, these linker
flags also setup the starting address of the application. The linker flag snippet shown
above is for the shell application and hence it is configured to setup the start address of the
shell application to the required value.
Downloading
Connect to the processor in the system using XMD. You can open up XMD either through
the XPS GUI (Tools o XMD) or by keying in xmd in the console. Connect to the processor
in the system with the mbconnect mdm command. Once you have connected to the
processor, download this example set. For your convenience, a batch script has been
provided in the file, dow-2.cmd. Once this step is complete, your applications and
Xilkernel have been downloaded to appropriate locations in memory, based on the
information in the elf file(s). The download command gives you information about where
the various sections were downloaded. This sequence of steps is illustrated below.
Xilinx Microprocessor Debug (XMD) Engine
Xilinx EDK 6.2 Build EDK_Gm.9
Copyright (c) 1995-2002 Xilinx, Inc. All rights reserved.
XMD% mbconnect mdm
Version............................2.00.a
No of PC Breakpoints...............4
No of Read Addr/Data Watchpoints...2
No of Write Addr/Data Watchpoints..2
Instruction Cache Support..........off
Data Cache Support.................off
JTAG MDM Connected to Mircoblaze 1
Connected to MicroBlaze "mdm" target. id = 0
Starting GDB server for "mdm" target (id = 0) at TCP port no 1234
XMD% source dow-2.cmd
Program Executable Instruction Section(s):
Section(0): 0x0e000000-0x0e0010d8
Program Data Memory Section(s):
Section(0): 0x0e0010d8-0x0e00152a
Section(1): 0x0e001530-0x0e00184c
Section(2): 0x0e001850-0x0e001c50
Program Executable Instruction Section(s):
Section(0): 0x0e002000-0x0e002e84
Program Data Memory Section(s):
Section(0): 0x0e002e84-0x0e00314d
Section(1): 0x0e003150-0x0e0032a0
Section(2): 0x0e0032a0-0x0e0032a0
Section(3): 0x0e0032a0-0x0e0036b8
Program Executable Instruction Section(s):
Section(0): 0x0e004000-0x0e004b84
Program Data Memory Section(s):
Section(0): 0x0e004b84-0x0e004fb6
Section(1): 0x0e004fb8-0x0e004fb8
Section(2): 0x0e004fb8-0x0e0053f0
Program Executable Instruction Section(s):
Section(0): 0x0e006000-0x0e006e44
Program Data Memory Section(s):
Section(0): 0x0e006e44-0x0e00769a
Section(1): 0x0e0076a0-0x0e0076a0
Section(2): 0x0e0076a0-0x0e007ad0
Program Executable Instruction Section(s):
Section(0): 0x00000400-0x0000405c
Program Data Memory Section(s):
Section(0): 0x0000405c-0x0000429c
Section(1): 0x000042a0-0x000043e0
Section(2): 0x000043e0-0x00006a10
XMD%
The download command’s output shows the memory ranges onto which four applications
and the kernel are loaded. The start addresses of the four processes, shell, memory
example, semaphore example and producer-consumer example are 0xe000000, 0xe002000,
0xe004000, 0xe006000 respectively.
Executing
Once the download step is complete, the program counter of the processor points to the
start address of Xilkernel, since Xilkernel is the last of the programs to be downloaded.
Make sure you have hyperterminal connected as described earlier. Key in con to start the
processor’s execution. As configured, the shell starts execution as the only processes in the
system. The shell is a simple one, configured to recognize a few commands. For the
purpose of making the output of the applications in this example, easy to read, the output
has been reproduced from here on, instead of providing snapshots of the hyperterminal
session. Key in help in the hyperterminal shell prompt to view a list of available
commands. This produces a list of available options.
shell> help
List of commands
run <program_name> <prio>: Run the named program with priority
clear : Clear the screen
list : List the programs loaded for this example system
help : This help screen
exit : Exit this shell
The available commands are self-explanatory. Of interest are the list and run
commands. Key in list to take a look at the available programs that can be launched.
The shell throws up this list of available examples.
List of programs loaded in this example system
0xe002000 :llist.elf :Memory allocation example
0xe004000 :sem.elf :Semaphore example
0xe006000 :prodcon.elf :Producer consumer example using message queues
Let us take a look at the memory allocation example first. Key in run llist.elf 0 in
the hyperterminal session to launch the memory allocation example with priority zero.
The priority does not matter as we are doing round-robin scheduling in this system. Upon
keying in this command, the shell creates a new process using the process create
command.
pid = process_create (start_addr, prio);
This system call creates a new process starting at the specified address with the specified
priority. The process identifier of the newly created process is returned from the system call
and this can be used in other operations. The shell uses this process ID to periodically
retrieve the execution state of the process, and when it terminates, it produces the shell
prompt again and waits for input. The vectoring of the Xilkernel call to the actual system
call is different compared to the first example set, since the shell (and other processes) are
in separate executables. Here is a snippet from libprocess.c, which contains the system
call wrappers for the process module.
xmk_enter_kernel();
ret = sys_process_create (start, prio);
xmk_leave_kernel();
return ret;
#else
JMP_SYSCALL_HANDLER( SC_Process_Create )
#endif
}
Only the code in the #else part is conditionally compiled. The macro
JMP_SYSCALL_HANDLER loads a register with the number of the system call requested
(SC_Process_Create) and makes a "jump" to the microblaze exception vector address.
This vectors control to the soft interrupt handler, which locks the kernel, vectors the call to
the appropriate system call and unlocks the kernel upon return. The parameters to the
system call are passed on the stack, according to the EABI of MicroBlaze.
The shell retrieves the status of the created process by using the process_status() system call,
with the process identifier of the launched process.
The output from the execution of llist.elf is shown below:
LLIST: Sorted Linked List Implementation.
LLIST: Demonstrates memory allocation interfaces.
LLIST: Adding to list 10 statically defined elements....
( 0 1 2 3 4 5 6 7 8 9 )
LLIST: Deleting the list elements.. 0,5,9
LLIST: The list right now is,
( 1 2 3 4 6 7 8 )
LLIST: Adding to list 1535, 661, 2862 and 8.
LLIST: The list right now is,
( 1 2 3 4 6 7 8 8 661 1535 2862 )
LLIST: Done. Good Bye..
shell>
This is a linked list program which uses the dynamic block memory allocation interface of
Xilkernel. Every time it adds an element to the list, it invokes bufmalloc() with the requested
block memory size to get a pointer to a memory location. Every time it deletes an element,
it releases storage for that element by doing a buffree(). Recall that the memory for these
operations was configured in the MSS file using the mem_table parameter. The
application starts by adding some elements, then removing a few, then again adding a few
and then terminating. Of interest is the process_exit(), system call that is invoked when the
example terminates. This is required to indicate to the kernel that the processes’ storage can
be reclaimed. Control returns to the shell, which realizes through the process_status() call
when the linked list example terminates. You can execute the linked list example as many
times as you wish.
Let us execute the semaphore example next. The semaphore example requires the
semaphore.h header file to be included to make available standard declarations and
definitions. This application requires the body of main() to be a thread, so the shell launches
this and the producer consumer application as threads, using pthread_create() and waits for
them to terminate with pthread_join().
The system calls used in this example, of interest are the POSIX compliant semaphore calls.
x Creating a semaphore and getting a handle to it
sem_init (&protect, 1, 1)
The sem_init() system call creates a new semaphore inside the kernel and returns the
identifier of the created semaphore in the location passed as the first parameter. This
identifier is of type sem_t. The second argument is ignored. The third argument provides
the initial value of the semaphore.
x Performing a wait operation on the semaphore
sem_wait (&rzvous_1)
The wait operation blocks execution of the calling process until the semaphore is
successfully acquired. The semaphore’s value indicates the current state of the semaphore.
If the semaphore value is greater than zero, then the process decrements this value and
successfully acquires the semaphore. If it is less than or equal to zero, then the process
blocks.
x Performing a post operation on the semaphore
sem_post (&rzvous_1)
The post operation increments the value of the referenced semaphore. If the semaphore
value indicates that there are processes waiting to acquire the semaphore, then it unblocks
exactly one waiting process from the waiting queue. This queue is a priority queue when
scheduling is priority driven.
x Destroying the semaphore
sem_destroy (&protect)
This call deallocates the semaphore resources and removes it from the system. This call
fails if there are processes blocked on the semaphore.
The semaphore main thread initializes a total of three semaphores. Two of these, it uses as
flags to rendezvous with two dynamically created threads. i.e it creates these semaphores
with an initial value of 0. The created threads, as one of their first steps, do a sem_wait() on
these rendezvous semaphores. The main thread performs all the thread creation and
initialization operations and flags the threads off, by doing a post on both the threads. This
ensures that both the threads start their critical sections, as closely as possible.
The threads then contend for the console to do some message output operations. To
prevent the interleaving of the output on the console, they do this inside a critical section.
The protect semaphore is used to ensure mutual exclusion while executing in the critical
section. The protect semaphore has an initial value of 1. The threads do a sem_wait() to
acquire the semaphore and do a sem_post() to release it when they are out of the critical
section.
The two threads contend for a couple of times and then terminate. The main thread, which
was waiting to join with these two threads, now reclaims their resources, destroys the
semaphores, and terminates. Key in run sem.elf 0 in the hyperterminal shell prompt to
execute this example.
SEM: Spawning 1...
SEM: Returned TID: 00000002
SEM: Spawning 2..
SEM: Returned TID: 00000003
SEM: Rendezvousing with 1.
SEM: Rendezvousing with 2.
Thread 1: Doing sem_wait.
Thread 1: 00000000
Thread 1: 00000001
Thread 1: 00000002
Thread 1: 00000003
Thread 1: 00000004
Thread 1: 00000005
Thread 1: 00000006
Thread 1: 00000007
Thread 1: 00000008
Thread 1: 00000009
Thread 1: Doing sem_post.
Thread 1: Doing sem_wait.
Thread 1: 00000000
Thread 1: 00000001
Thread 1: 00000002
Thread 1: 00000003
Thread 1: 00000004
Thread 1: 00000005
Thread 1: 00000006
Thread 1: 00000007
Thread 1: 00000008
ThThread 2: Doing sem_wait.
read 1: 00000009
Thread 1: Doing sem_post.
Thread 2: 00000000
Thread 2: 00000001
Thread 2: 00000002
Thread 2: 00000003
Thread 2: 00000004
Thread 2: 00000005
Thread 2: 00000006
Thread 2: 00000007
Thread 2: 00000008
Thread 2: 00000009
Thread 2: Doing sem_post.
Thread 2: Doing sem_wait.
Thread 2: 00000000
Thread 2: 00000001
Thread 2: 00000002
Thread 2: 00000003
Thread 2: 00000004
Thread 2: 00000005
Thread 2: 00000006
Thread 2: 00000007
Thread 2: 00000008
Thread 2: 00000009
Thread 2: Doing sem_post.SEM: Successfully joined with thread 1. Return
value of
terminated thread: 00000064
You can execute the semaphore example as many times as you wish.
Let us execute the producer consumer example next. This application solves the producer
consumer problem using message queues. An application that uses message queues needs
to include the sys/ipc.h and sys/msg.h header files to make available standard
declarations. Let us look at the POSIX compliant message queue API that is used in this
example.
x Creating a message queue and getting a handle to it.
msgid = msgget (key, IPC_CREAT);
The msg_get() system call creates a new message queue inside the kernel and returns an
identifier to it. When obtaining a message queue, a unique key is used to identify the
message queue. Thus two threads, by agreeing upon a command key, can operate on the
same message queue and co-ordinate.
x Performing a blocking message send
PRODCON: Producer -- a
PRODCON: Producer -- b
PRODCON: Producer -- c
PRODCON: Producer -- d
PRODCON: Producer -- e
PRODCON: Producer -- f
PRODCON: Producer -- g
PRODCON: Producer -- h
PRODCON: Producer -- i
PRODCON: Producer -- j
PRODCON: Consumer -- Start !
PRODCON: Consumer -- a
PRODCON: Consumer -- b
PRODCON: Consumer -- c
PRODCON: Consumer -- d
PRODCON: Consumer -- e
PRODCON: Consumer -- f
PRODCON: Consumer -- g
PRODCON: Consumer -- h
PRODCON: Consumer -- i
PRODCON: Consumer -- j
PRODCON: Producer -- k
PRODCON: Producer -- l
PRODCON: Producer -- m
PRODCON: Producer -- n
PRODCON: Producer -- o
PRODCON: Producer -- p
PRODCON: Producer -- q
PRODCON: Producer -- r
PRODCON: Producer -- s
PRODCON: Producer -- t
PRODCON: Producer done !
PRODCON: Consumer -- k
PRODCON: Consumer -- l
PRODCON: Consumer -- m
PRODCON: Consumer -- n
PRODCON: Consumer -- o
PRODCON: Consumer -- p
PRODCON: Consumer -- q
PRODCON: Consumer -- r
PRODCON: Consumer -- s
PRODCON: Consumer -- t
PRODCON: Consumer -- Done. ERRORS (1 indicates error in corresponding
message):
00000000
PRODCON: Consumer -- Signalling main.
PRODCON: Consumer -- Doing other tests...Blocking on message queue
PRODCON: Successfully joined with producer. Return value of terminated
thread: 0
0000000
PRODCON: Starting other tests..
PRODCON: Trying to create a message queue with the same key.
PRODCON: EXCL mode...
PRODCON: Successfully failed :)
PRODCON: Retrieving msgid for already created msgQ.
PRODCON: Retrieving statistics from message queue.
PRODCON: MsgQ stats:
msg_qnum : 00000000
msg_qbytes : 00000064
msg_lspid : 00000003
msg_lrpid : 00000004
End Stats
PRODCON: Attempting to destroy message Q while a process is occupying
it.
PRODCON: Successfully removed message queue.
PRODCON: Consumer -- Great! Got Kicked out of msgrcv appropriately.
PRODCON: Consumer -- Terminating.
PRODCON: Successfully joined with consumer. Return value of terminated
thread: 0
0000000
PRODCON: Releasing misc resources..
PRODCON: Done !
Notes
x Since the semaphore and producer consumer examples are based on the POSIX API,
they should be completely portable onto a POSIX OS without any change.
x When you exit the shell, you will see an "Idle Task" executing. This idle task is
scheduled only when there are no other active tasks executing in the system. The
purpose of this idle task is to let the system continue operation, so that interrupts can
still be serviced, even if there are no tasks.
Example Set 3
The following concepts of Xilkernel will be illustrated with example set 3 -
i Mixed separate and kernel bundled executable modes
i Pthread mutex locks
i User level interrupt handling.
There are a total of three applications in this example set. They are; a shell configured
statically as a part of the kernel bundle; a separate executable user level interrupt handling
demo application and a separate executable mutex lock application. The shell dynamically
launches the other two applications. Again, round-robin scheduling is used to time-share
the system.
Configuring
The software specification for the system in example 3 is contained in the
system.mss.ex3 file contained in the project folder. Let us look at the relevant portions
of this software specification.
# Configure pthreads
PARAMETER config_pthread_support = true
PARAMETER max_pthreads = 8
Building
From the project directory, copy over this example’s MSS file, system.mss.ex3 to
system.mss (cp -r system.mss.ex3 system.mss). Clean and re-build the libraries
using either the XPS GUI or the command line. To build it using the GUI, select Tools o
Generate Libraries and BSPs. To build the libraries in the command line, key in
make -f system.make libsclean; make -f system.make libs
For this example, a xilkernel.elf file is not generated, since we have indicated that
there will be a kernel bundled application. Therefore the kernel sources are compiled into
libxilkernel.a and a kernel bundle is formed when the shell application links with the
library. The separate executable applications link with the kernel dynamically through the
system call interface. This system call interface is built as a library (libsyscall.a). These
libraries, again, get generated in the processor library folder (microblaze_0/lib). To
build the applications for this example, move to the code/ex3 subfolder. In the shell, key
in make help to view the available options. Key in make all to build the two
applications and generate the elf files for the separate executable applications and the
kernel bundle containing the shell application. The example set Makefile illustrates how to
link applications with the system call library and how the shell links with the kernel
bundle library, in the same fashion as the previous examples.
Downloading
Connect to the processor in the system using XMD. You can open up XMD either through
the XPS GUI (Tools o XMD), or by keying in xmd in the console. Connect to the processor
in the system using the mbconnect mdm command. Once you have connected to the
processor, download this example set. For your convenience, a batch script has been
provided in the file, dow-3.cmd. Once this step is complete, your applications and
Xilkernel have been downloaded to appropriate locations in memory, based on the
information in the elf file(s). The download command gives you information about where
the various sections were downloaded. This sequence of steps is illustrated in the below.
Xilinx Microprocessor Debug (XMD) Engine
Xilinx EDK 6.2 Build EDK_Gm.9
Copyright (c) 1995-2002 Xilinx, Inc. All rights reserved.
XMD% mbconnect mdm
Executing
Once the download step is complete, the program counter of the processor points to the
start address of Xilkernel, since Xilkernel is the last of the programs to be downloaded.
Make sure you have hyperterminal connected as described earlier. Key in con to start the
processor’s execution. As configured, the shell starts execution as the only processes in the
system. The shell is a simple one, configured to recognize a few commands. Key in help
in the hyperterminal shell prompt to view a list of available commands. This produces a
list of available options.
shell>help
List of commands
run<program_num>: Run the named program. For e.g. run0 loads the first
program.
clear : Clear the screen
The main() routine proceeds to register a handler with the interrupt controller to handle
interrupts from this device. The following system call is used to do that:
register_int_handler(id, timer_int_handler, NULL)
The first parameter is the zero-based identifier for the interrupt in question. In this
example system, it is 1. Registering the handler, does not enable it. A separate call is
required to enable the interrupts in the interrupt controller. This is done by the following
call:
enable_interrupt (id)
The timer interrupt handler prints out a message indicating that an interrupt has been
serviced. After servicing the interrupt five times, it disables the interrupt handling with the
interrupt controller. The main code meanwhile executes synchronously and terminates
after the five interrupts have been handled. It unregisters the handler before it terminates
by making the following call:
unregister_int_handler(id)
Key in run0 to launch this example. The output from this example is shown below. You
can execute this application as many times as you like.
INTCDEMO: Starting...
INTCDEMO: This demo will configure interrupts from the ’extra timer’
in the system. After handling N_INTR interrupts
asynchronously, the handlers are unregistered and the
demo terminates.
Let us execute the mutex demo application next. The following are some of the basic mutex
operations that are performed by this application.
x Initializing a mutex lock.
pthread_mutex_init (&mutex, NULL)
The pthread_mutex_init() system call creates a new mutex lock within the kernel and
returns the identifier of the mutex in the location passed as the first parameter. The
type of this mutex identifier is pthread_mutex_t. The initialization call requires a
second parameter, which gives a pointer to a mutex initialization attributes structure.
Since only the basic mutex types are supported, this parameter is unused and NULL or
an attribute initialized with pthread_mutexattr_init() should be passed in. There is an
alternative way to initialize the mutex lock statically, by assigning the value
PTHREAD_MUTEX_INITIALIZER to the pthread_mutex_t structure. This allows
the kernel to initialize the mutex lock, in a lazy fashion, whenever it gets operated on
for the first time.
x Performing a lock operation on the mutex
pthread_mutex_lock (&mutex)
This call locks the mutex for the calling process or thread and returns. If the mutex is
already locked, then the calling process or thread blocks until it is unblocked by some
mutex unlock operation.
x Performing a mutex unlock operation
pthread_mutex_unlock (&mutex)
This call unlocks the mutex, which must be currently locked by the calling process or
thread, and returns. If there are processes blocked on the mutex, this call unlocks
exactly one of them. If scheduling is priority driven, then it unlocks the highest-
priority process in the wait queue. If scheduling is round-robin, then it unlocks the first
process in the wait queue.
x Destroying the mutex lock
pthread_mutex_destroy (&mutex)
This call destroys the mutex lock. No consideration is given for blocked processes and
mutex lock and unlock state.
The mutex demo application basically, creates some configured number of threads (3
in this case). Each thread contends for a critical section in which it increments a global
variable. The main thread looks at this global variable to reach a particular value and
then proceeds to join with the threads. The threads use the lock and unlock primitives
to access the critical section. The threads also delay inside the critical section to
demonstrate contention by other threads. Key in run1 to start the mutex demo
application. The output is shown below:
MUTEX: Starting..
MUTEX: Launched four contending threads..
MUTEX: Waiting for threads to get past critical section...
MUTEX: Thread(0) starting...
MUTEX: Thread(0) contending...
MUTEX: Thread(0) in critical section..Will spend some time here.
MUTEX: Thread(1) starting...
MUTEX: Thread(1) contending...
MUTEX: Thread(2) starting...
MUTEX: Thread(2) contending...
MUTEX: Thread(0) mutex done...
MUTEX: Waiting for threads to get past critical section...
MUTEX: Thread(1) in critical section..Will spend some time here.
MUTEX: Thread(1) mutex done...
MUTEX: Thread(2) in critical section..Will spend some time here.
MUTEX: Thread(2) mutex done...
MUTEX: Destroying mutex lock...
MUTEX: Done. Good Bye !
PowerPC Examples
The same example sets that are available for MicroBlaze are available for PowerPC. The
examples follow the same configuration and organization in each set, as they do in the
MicroBlaze system. However there are some differences in the way that the applications
and the kernel get built. There are also slight differences in the debugging process and
some implications based on differences in the hardware. The flow through the example set
three is illustrated below, since it exercises both the separate and kernel bundle executable
modes.
Configuring
The software specification for the system in example 3 is contained in the
system.mss.ex3 file contained in the PowerPC project folder. Let us look at the relevant
portions of the software specification that differ from that of MicroBlaze.
PARAMETER proc_instance = ppc405_0
PARAMETER linker_script_specification = true
PARAMETER vec_mem_start = 0xffff0000
PARAMETER vec_mem_size = 16k
PARAMETER data_mem_start= 0xffff4000
PARAMETER data_mem_size = 20k
PARAMETER code_mem_start= 0xffff9000
PARAMETER code_mem_size = 28k
The processor instance parameter points to the only available PowerPC instance on the
board, named as ppc405_0. Xilkernel includes the sections for the exception vectors that
need to be setup for PowerPC, as a part of the executable image. This vectors section needs
to be aligned at a 64KB boundary in memory. Therefore, this must be configured
appropriately when linking the final executable image for Xilkernel, corresponding to the
available memory in the hardware and therefore we need a linker script for the kernel. The
parameters vec_mem_start and vec_mem_size allow the user to specify the starting
location in memory and the size of the vectors segment. Additionally, parameters
data_mem_start, data_mem_size, code_mem_start and code_mem_size allow
the user to place data and code sections, respectively, of the executable at appropriate
locations in memory. The provided MSS file has set values for these parameters to
sufficiently handle the resulting sections. To enable configuring these parameters, the
parameter linker_script_specification must be set to true, as above. The
configuration of the location and size of these segments, gets translated to the
linker_include.sh file, which gets generated in the Xilkernel source folder within
ppc405_0/libsrc/. Xilkernel, in turn, uses the parameters that are in this linker script
include file in its default kernel linker script and thus the final kernel executable gets
generated appropriately. This kernel linker script also groups libxil.a and libc.a
automatically for you, as standard libraries to be linked with Xilkernel.
The PPC MSS specification does not require a system timer specification parameter, as
there is a PIT timer present internally within the PowerPC processor that Xilkernel uses. If
you take a look at the hardware platform (system.mhs) for this design example, there will
be only one timer as compared to the two that can be found in the MicroBlaze design
example.
The rest of the parameters in the MSS specification are exactly the same as in MicroBlaze.
The system.mss.ex3 file again, configures the kernel for a shell application that forms a
part of the kernel bundle. Using the shell you can launch two other applications - a user-
level interrupts example and a mutex lock example configured as separate executables.
Building
From the project directory, copy over this example’s MSS file, system.mss.ex3 to
system.mss (cp -r system.mss.ex3 system.mss). Clean and re-build the libraries
using either the XPS GUI or the command line. To build it using the GUI and select Tools
o Generate Libraries and BSPs. To build the libraries in the command line, key in
make -f system.make libsclean; make -f system.make libs
For this example, a xilkernel.elf file is not generated, since we have indicated that
there will be a kernel bundled application. Therefore the kernel sources are compiled into
libxilkernel.a and a kernel bundle is formed when the shell application links with the
library. The separate executable applications link with the kernel dynamically through the
system call interface. This system call interface is built as a library (libsyscall.a). These
libraries, again, get generated in the processor library folder (ppc405_0/lib). To build
the applications for this example, move to the code/ex3 subfolder. In the shell, key in
make help to view the available options.
Key in make all to build the two applications and generate the elf files for the separate
executable applications and the kernel bundle containing the shell application. There are
some differences in the way applications get compiled on PowerPC, compared to
MicroBlaze. Firstly, in the kernel bundle mode, an application needs to be combined with
Xilkernel and therefore in this mode, care should be taken to move the various kernel
sections of the kernel bundle to appropriate locations in memory, in a similar fashion as
what we did when building the kernel separately. In essence, this means that the kernel
bundle application should use the default kernel linker script during the final link stage.
#
# Linker options for the kernel bundle
#
LFLAGS_KERNEL = -Wl,-defsym -Wl,_HEAP_SIZE=900 -Wl,-T
-Wl,../../ppc405_0/libsrc/xilkernel_v2_00_a/src/linker_script.sh
Correspondingly, the above linker flags are used to generate the kernel bundle. Notice how
the linker script is specified.
-Wl,-T -Wl,../../ppc405_0/libsrc/xilkernel_v2_00_a/src/linker_script.sh
The flag -Wl tells GCC to pass the option that follows to the linker. Each string of the
option is passed separately using a -Wl GCC option. The linker option for specifying the
linker script, thus boils down to
-T ../../ppc405_0/libsrc/xilkernel_v2_00_a/src/linker_script.sh
Hence, we use the kernel’s linker script, borrowing it from the kernel source code, to
compile kernel bundle applications.
Separate executable applications have a link step that is different. In MicroBlaze, we used
a special flag -xl-mode-xilkernel to tell GCC to build the application without the
usual boot sections (since Xilkernel would take care of the boot sections). However, there is
no such flag in PowerPC. Therefore, to avoid getting the boot section compiled in for each
separate executable application, we use a special linker script which uses the CRT section
as the startup code, instead of the boot section. Feel free to take a look at this linker script
which is present under each example folder. It is named as app_linker_script. You
can use this linker script as a template when building your own linker script for separate
executables. This linker script also groups libxil.a and libc.a automatically for you,
as standard libraries to be linked with your application, thus saving you the trouble of
mentioning libxil as a library that must be linked. The other linker option that is different
from MicroBlaze is the start address of the program. The symbol that must be defined is
_START_ADDR.. This can be seen in the following snippet.
# Linker options for the separate executables.
#
LFLAGS1 = -Wl,-defsym -Wl,_HEAP_SIZE=500 -Wl,-defsym
-Wl,_START_ADDR=$(PROG1_START_ADDRESS) -Wl,-T -Wl,./app_linker_script
LFLAGS2 = -Wl,-defsym -Wl,_HEAP_SIZE=500 -Wl,-defsym
-Wl,_START_ADDR=$(PROG2_START_ADDRESS) -Wl,-T -Wl,./app_linker_script
Downloading
Connect to the processor in the system using XMD. You can open up XMD either through
the XPS GUI (Tools oXMD), or by keying in xmd in the console. Connect to the processor
in the system with the ppcconnect command. Once you have connected to the processor,
download this example set. For your convenience, a batch script has been provided in the
file, dow-3.cmd. Once this step is complete, your applications and Xilkernel have been
downloaded to appropriate locations in memory, based on the information in the elf file(s).
The download command gives you information about where the various sections were
downloaded. This sequence of steps is illustrated below,
Xilinx Microprocessor Debug (XMD) Engine
Xilinx EDK 6.2 Build EDK_Gm.9
Copyright (c) 1995-2002 Xilinx, Inc. All rights reserved.
XMD% ppcconnect
Section(3): 0xf8001158-0xf800116c
Section(4): 0xf800116c-0xf800118c
Section(5): 0xf800118c-0xf8001190
Section(6): 0xf8001190-0xf8001194
Section(7): 0xf8001194-0xf80023a0
PC reset to 0xf8000000, Clearing MSR Register
Program Executable Instruction Section(s):
Section(0): 0xf8100000-0xf81015a4
Program Data Memory Section(s):
Section(0): 0xf81015a8-0xf81019f0
Section(1): 0xf81019f0-0xf81019f0
Section(2): 0xf81019f0-0xf8101e40
Section(3): 0xf8101e40-0xf8101e54
Section(4): 0xf8101e54-0xf8101e74
Section(5): 0xf8101e74-0xf8101e7c
Section(6): 0xf8101e7c-0xf8101e9c
Section(7): 0xf8101e9c-0xf81030d0
PC reset to 0xf8100000, Clearing MSR Register
Program Executable Instruction Section(s):
Section(0): 0xffff0000-0xffff20c4
Section(1): 0xffff9000-0xffffc730
Section(2): 0xffffc730-0xffffc740
Section(3): 0xfffffffc-0x00000000
Program Data Memory Section(s):
Section(0): 0xffff4000-0xffff4970
Section(1): 0xffff4970-0xffff49a0
Section(2): 0xffff49a0-0xffff49d4
Section(3): 0xffff49d4-0xffff49d4
Section(4): 0xffff49d4-0xffff73d0
PC reset to 0xfffffffc, Clearing MSR Register
XMD%
The download command’s output shows the memory ranges onto which two applications
and the kernel are loaded. The start addresses of the two separate executable processes,
interrupts demo and mutex example, are 0xf8000000, 0xf8100000 respectively.
Executing
Once the download step is complete, the program counter of the processor points to the
start address of Xilkernel, since Xilkernel is the last of the programs to be downloaded.
Make sure you have hyperterminal connected as described earlier. Key in con to start the
processor’s execution. As configured, the shell starts execution as the only processes in the
system. The shell is a simple one, configured to recognize a few commands. Key in help,
in the hyperterminal shell prompt to view a list of available commands. This produces a
list of available options.
shell>help
List of commands
run<program_num>: Run the named program. For e.g. run0 loads the first
program.
clear : Clear the screen
list : List the programs loaded for this example system
help : This help screen
exit : Exit this shell
shell>list
List of programs loaded in this example system
0xe000000 :intcdemo.elf : User-level interrupts example
0xe002000 :mutex.elf : Pthread mutex example
These applications are almost the same as their MicroBlaze counterparts and execute in
much the same fashion. The intcdemo.elf application is slightly different in the timer
device has a different base address and the interrupt ID of the timer device is zero. The way
the system calls work in kernel bundle mode and separate executable mode are very
similar to MicroBlaze, except that the PPC libraries use the PPC specific, sc instruction to
make a system call trap. Take a look at any of the PPC system call wrapper library source
files (lib*.c) in the Xilkernel sources. The system calls take the same flow depending on
whether they are configured for kernel bundle mode or separate executable mode. You can
execute the applications in this example set as many times as you wish.
Chapter 5
Using XilMFS
XilMFS is a memory-based file system library that can be used in standalone mode or
along with the Xilkernel library. You can use XilMFS functions to read and write files and
to create and manage directories and files in RAM. You can also use XilMFS to access read-
only files from read-only memory (ROM or Flash).
This chapter contains the following sections:
x “XilMFS Concepts”
x “Getting Started with XilMFS”
x “Using XilMFS”
XilMFS Concepts
XilMFS allows you to treat the RAM, ROM, Flash, or other memory in your system as a
collection of files, organized into directories and subdirectories as needed. You can create
and delete files from your program, allowing you to log information in a convenient
format. You can read data from files, allowing your software to be more data-driven.
XilMFS requires the use of BRAM or other external RAM for a read-write file system.
XilMFS works on MicroBlaze, PowerPC, and on the host platforms Solaris, Linux, and
PC/xygwin.
When XilMFS is used in conjunction with a Flash or ROM for a read-only file system, a separate
tool called mfsgen is used to create the read-only file system image. Mfsgen is bundled
along with the XilMFS libraries in source code form. Mfsgen is run on the host machine
(Solaris, Linux or PC/xygwin) to generate a file system image that can then be loaded into
the target memory.
For example, say you want your MicroBlaze or PowerPC target system to have a read-only
file system that contains a directory d1 which has two files a.txt and b.txt. You first
create the directory d1 and the files a.txt and b.txt somewhere on your host machine.
Then you run mfsgen to create a memory image file containing d1, a.txt, and b.txt.
Finally you download this memory image file to the target memory, and the XilMFS file
system is available for use.
x 8KB or larger BRAM or other memory connected to the processor over LMB or OPB,
with an appropriate memory controller (more or less memory may be needed
depending on how XilMFS is configured)
Using XilMFS
There are three steps to using XilMFS with your applications:
1. Configure XilMFS
2. Create your application
3. Optional - create a file system image on your host and download to target.
The following sections explain each of these steps in detail.
Configuring XilMFS
You can configure Xilkernel using the XPS GUI or by editing the MSS file. In the XPS GUI
window click on the System tab in the middle-left panel to bring up the hardware tree
view. Then right click on the processor name in the tree view shown in the following
picture to pop up a menu with S/W Settings as the first item. Click on S/W Settings.
Using XilMFS
This brings up the Software Platform Settings dialog box, shown below. The top half of this
dialog box displays various devices in the hardware platform and the drivers assigned to
them. The bottom right side of the dialog box allows you to select an OS. You can select
VxWorks, Standalone or Xilkernel. Select Standalone from the list.
Using XilMFS
Now click on the Library/OS Parameters tab at the top of the dialog box to configure
XilMFS (shown below).
The Library/OS parameters tab shows all the configurable parameters for XilMFS. For
each parameter, the parameter type, default value, and a short explanation are shown. The
default values are already filled in, and you can change them as needed. Collapse or
expand the tree view by clicking on the + or - symbols on the left hand side. After setting
all the parameters click OK to save. You can always go back and change the saved values
if you want to.
The base address and numbytes parameters allow you to indicate that a certain region of
memory starting at that base address and extending to numbytes bytes is reserved for
XilMFS.
Caution! The current version of the library generator and related tools does not verify that the
memory reserved for XilMFS is actually present in the hardware or whether this memory is used
by some other code or peripheral device.
When you are done with this panel, click OK. Then select Tools o Generate Libraries
and BSPs. This updates the standard Xilinx C libraries to be created, and the XilMFS
library functions are included in this library. You do not have to specify any additional
libraries in the compiler settings for your application. A file called mfs_config.h is
generated in the standard include area. You must include this file in your application code
to use XilMFS.
/*******************************************************************
*
* CAUTION: This file is automatically generated by libgen.
* Version: Xilinx EDK 6.2 EDK_Gm.10
* DO NOT EDIT.
*
* Copyright (c) 2003 Xilinx, Inc. All rights reserved.
*
* Description: MFS Parameters
*
*******************************************************************/
#ifndef _MFS_CONFIG_H
#define _MFS_CONFIG_H
#include <xilmfs.h>
#define MFS_NUMBYTES 100000
#define MFS_BASE_ADDRESS 0x10000000
#define MFS_INIT_TYPE MFSINIT_NEW
#endif
The first step in using XilMFS in your application code is to call the mfs_init_fs() function,
as shown below, using the parameters defined in mfs_config.h. After this you can
create a directory, open a file and write to it, and then open a file and read from it, as
shown. See the “LibXIL Memory File System” chapter in the EDK OS Libraries Reference
Guide for more information.
Using XilMFS
#include <stdio.h>
#include "mfs_config.h"
tmp = mfs_create_dir("testdir1");
mfs> ls -R testmfs
testmfs:
a.txt b.txt
Then run mfsgen to create the image and write the image to a file called image.mfs.
In this example, mfsgen is called with a block size of 10, resulting in a memory image size
of 5320 bytes, or 10 blocks, of which four are used to store the directory testmfs and the files
a.txt and b.txt.
Next, load this image file into memory at some suitable address, say 0x10000000. You can
use xmd to download data (see the “Xilinx Microprocessor Debugger (XMD)” chapter in
the Embedded System Tools Guide), or you can use some other tool to copy this data to
memory.
Finally, in your application, initialize the file system as follows:
mfs_init_fs(5320, 0x10000000, MFSINIT_ROM_IMAGE);
Now you are ready to use the file system in read-only mode. You can traverse directories,
open and close files and read files using the XilMFS functions in your application.
Note: Linux and Xygwin hosts are typically little-endian machines, while Solaris hosts and
MicroBlaze and PowerPC targets are big-endian. Mfsgen always creates an image in big-endian
format so it is readily usable on both MicroBlaze and PowerPC targets.
Chapter 6
Simulation in EDK
This chapter describes the basic HDL simulation flow using the Xilinx® EDK and third
party software. It includes the following sections:
x “Introduction”
x “EDK Simulation Basics”
x “Simulation Libraries”
x “Compiling Simulation Libraries”
x “Third Party Simulators”
x “Creating Simulation Models”
x “Memory Initialization”
x “Simulating a Basic System”
x “Submodule Simulation”
x “Using SmartModels”
x “Bus Functional Simulation”
Introduction
Increasing design size and complexity, as well as recent improvements in design synthesis
and simulation tools, have made HDL the preferred design language of most integrated
circuit designers. The two leading HDL synthesis and simulation languages today are
Verilog and VHDL. Both of these languages have been adopted as IEEE standards.
The two most common design methods used in both VHDL and Verilog logic designs are
behavioral and structural.
Structural design is a method by which a designer instantiates and utilizes predefined
components (or structures) and describes how they are to be connected together. For
example, a four-bit adder can be created by instantiating four one-bit adders and
connecting them together appropriately. The one-bit adder itself can be created by
instantiating and connecting the appropriate lower-level gates. A design that applies the
structural design method can be easily represented as a netlist that describes the
components used and their connections.
Behavioral design is a method by which a designer uses a much higher level of abstraction
than structural design. The design may contain high-level operations, such as a four-bit
addition operator (note this is not an adder as in structural), without having a knowledge
of how the design will be implemented. Synthesis tools then take these behavioral designs
and infer the actual gate structures and connections that are to be used, generating a netlist
description. As synthesis tools evolve, we will see more and more behavioral designs.
EDK IP components are designed with a mix of behavioral and structural descriptions. For
simplicity, we refer to these source descriptions only as behavioral, even though they have
some structural instantiations.
Functional Simulation
UG111_01_111903
Behavioral Simulation
EDK refers to pre-synthesis simulation as Behavioral Simulation. Behavioral simulation is
done from an HDL description of the design before it is synthesized to gates. This is the
quickest and least detailed HDL simulation method.
Behavioral simulation is used to verify the syntax and functionality without timing
information. The majority of the design development is done through behavioral
simulation until the required functionality is obtained. Errors identified early in the design
cycle are inexpensive to fix compared to functional errors identified during silicon debug.
Structural Simulation
EDK refers to post-synthesis simulation as Structural Simulation. After the behavioral
simulation is error-free, the HDL design is synthesized to gates and a purely structural
description of the design is generated. At this point, one can verify what the synthesis tool
did with the behavioral design. The post-synthesized structural simulation is a functional
simulation that can be used to identify initialization issues and to analyze don’t care
conditions. Timing information is not used at this simulation level. This method is slower
and has more details than behavioral simulation.
Xilinx tools have the ability to write out purely structural HDL netlists for a post-
synthesized design. These VHDL or Verilog netlists are written using UNISIM library
components, which describe all the low-level hardware primitives available in Xilinx
FPGAs.
Timing Simulation
EDK refers to post-implementation simulation as Timing Simulation. This is the same as
structural simulation, but with back-annotated timing information. Timing simulation is
important in verifying the operation of your circuit after the worst-case place and route
Simulation Libraries
(PAR) delays are calculated for your design. The back annotation process produces a netlist
of library components annotated in an SDF file with the appropriate block and net delays
from the place and route process. The simulation will identify any race conditions and
setup-and-hold violations based on the operating conditions for the specified functionality.
This simulation method is the slowest and is more detailed.
Simulation Libraries
EDK simulation netlists use low-level hardware primitives available in Xilinx FPGAs.
Xilinx provides simulation models for these primitives in the libraries listed below.
UNISIM Library
This is a library of functional models used for behavioral and structural simulation. It
contains default unit delays and includes all the Xilinx Unified Library components that
are inferred by most popular synthesis tools. The UNISIM library also includes
components that are commonly instantiated such as I/Os and memory cells.
You can instantiate the UNISIM library components in your design (VHDL or Verilog) and
simulate them during behavioral and structural simulation.
SIMPRIM Library
This is a library used for timing simulation. This library includes all of the Xilinx Primitives
Library components that are used by Xilinx implementation tools.
Timing simulation models generated by SimGen will instantiate SIMPRIM library
components.
XilinxCoreLib Library
The Xilinx CORE Generator is a graphical intellectual property design tool for creating
high-level modules like FIR Filters, FIFOs, CAMs as well as other advanced IP. You can
customize and pre-optimize modules to take advantage of the inherent architectural
features of Xilinx FPGA devices, such as block multipliers, SRLs, fast carry logic and on-
chip, single-port or dual-port RAM.
The CORE Generator HDL library models are used for behavioral simulation. You can
select the appropriate HDL model to integrate into your HDL design. The models do not
use library components for global signals.
EDK Library
All EDK IP components are written in VHDL. Some of the IP components distributed with
EDK have an encrypted source. EDK provides precompiled libraries of these that can be
used for behavioral simulation. Unecrypted EDK IP components can be compiled using
the COMPEDKLIB utility provided by Xilinx. COMPEDKLIB will deploy the encrypted
and unecrypted VHDL only compiled models into a common location.
Library Compilation
To compile your HDL libraries using compxlib, follow these steps (you need to have an
installation of the Xilinx implementation tools):
1. Run compxlib with -help option if you need to display a brief description for the
available options:
compxlib -help
2. The compxlib tool uses the following syntax:
compxlib -s <simulator> -f <family[:lib],<family[:lib],...|all>
[-l <language>]
[-o <compxlib_output_directory>]
[-w]
[-p <simulator_path>]
Note: Each simulator uses certain environment variables which must be set before invoking
compxlib. Consult your simulator documentation to ensure that the environment is properly set
up to run your simulator.
Note: Make sure you use the -p <simulator_path> option to point to the directory where the
modelsim executable is, if it is not in your path.
Usage
compedklib [ -h ] [ -s mti_se|mti_pe|ncsim ] [ -o output-dir-name ]
[ -lp repository-dir-name ] [ -X compxlib-output-dir-name ]
[ -E compedklib-output-dir-name ] [ -c core-name ]
Note: When running in a Xygwin command shel on a Windows PC, specify the command as
“compedklib.bat”.
This tool compiles the HDL in EDK pcore libraries for simulation using the simulators
supported by the EDK. Currently, the only supported simulator is MTI PE/SE.
To print the COMPEDKLIB online help to your monitor screen, type the following at the
command line:
compedklib -h
Other Details
You can supply multiple -X and -E arguments. The order is important. If you have the same
pcore in two places, the first one is used.
Some pcores are secure in that their source code is not available. In such cases, the
repository contains the compiled models. These are copied out into <compedklib-
output-dir-name>.
If your pcores are in your XPS project, you do not need to be concerned about Use Case 2.
XPS/SIMGEN will create the scripts to compile them.
If you have the MODELSIM environment variable set, the modelsim.ini file to which it
points is modified when this tool compiles the HDL sources for MTI SE/PE.
The execution log is available in compedklib.log.
All Xilinx EDK IP is written in VHDL, and behavioral model libraries are only available for
ModelSim SE/PE using VHDL at this time.
Setting Up SmartModels
SmartModels represent integrated circuits and system buses as black boxes that accept
input stimulus and respond with appropriate output behavior. Such behavioral models
provide improved performance over gate-level models, while at the same time protect the
proprietary designs created by semiconductor vendors. SmartModels connect to hardware
simulators through the SWIFT interface, which is integrated with over 30 commercial
simulators, including Synopsys VCS, Cadence Verilog-XL, Cadence NcSim, and Model
Technology ModelSim SE/PE (1).
The Xilinx Virtex-II Pro simulation flow uses Synopsys LMC models to simulate the IBM
PowerPC microprocessor and Rocket I/O multi-gigabit transceiver. LMC models are
simulator-independent models that are derived from the actual design and are therefore
accurate evaluation models. To simulate these models, a simulator that supports the
SWIFT interface must be used. The SmartModels are included in the ISE Implementation
Tools. The following steps outline how to set up the models. After setting up the
SmartModels, refer to “Third Party Simulators,” page 108 to setup your simulator to use
SmartModels.
Windows
On Windows, go to start o Control Panel o System. The “System Properties” dialog
box appears. Select the Advanced tab and click on Environment Variables. The
“Environment Variables” dialog box appears.
Set the variables to the following values (if not already set):
LMC_HOME %Xilinx%\smartmodel\nt\installed_nt
PATH %LMC_HOME%\bin;%LMC_HOME%\lib\pcnt.lib;%PATH%
Note: %PATH% represents what your PATH variable had before doing the changes. Make sure you
keep that.
Solaris
Set the following variables (if not already set):
Linux
Set the following variables (if not already set):
setenv LMC_HOME $XILINX/smartmodel/lin/installed_lin
setenv LD_LIBRARY_PATH $LMC_HOME/lib/x86_linux.lib:$LD_LIBRARY_PATH
setenv PATH $LMC_HOME/bin:${PATH}
Memory Initialization
Memory Initialization
Once a simulation model is created for a system, the software data must be included in the
memory simulation models for the system to run the program.
A C program that has been compiled to generate an executable file can be put inside the
simulation models. When running and debugging the software program in the simulator,
there will be several iterations of changes and compilation only of the C program and not
the hardware design. Creating this data inside the simulation models would be very
inefficient. If there are no hardware changes, there is no need to run any hardware creation
or implementation tools again.
EDK supports initialization of data in BRAM blocks. BRAM blocks are formed of several
BRAMs arranged and configured to create a memory of the size specified in the design.
The simulation models that Xilinx provides for these BRAMs use generics in the case of
VHDL and parameters in the case Verilog as means to initialize them with data.
If there is any program with which to initialize memory, EDK creates separate memory
initialization HDL files that include the data for the design.
VHDL Models
For VHDL simulation models, EDK generates a VHDL file that contains a configuration for
the system with all initialization values. For a design described in a file called system.mhs,
there will be a VHDL system configuration in the file system_init.vhd. The configuration in
this file maps the required generics for each of the BRAM blocks connected to a processor
in the system.
Verilog Models
For Verilog simulation models, EDK generates a Verilog file that contains an extra module
to be used along with the system with all initialization values. For a design described in a
file called system.mhs, there will be a VHDL system configuration in the file system_init.v.
This module does not have any ports and does not instantiate any other module. It only
contains a set of defparam statements to define the required parameters for each of the
BRAM blocks connected to a processor in the system.
timing/
Note: There will be other directories in your project directory, but these are not relevant for now.
Older hardware simulators used an interpreted technique. These kinds of simulators have
reasonable performance when simulating small designs but become inefficient as
hardware designs become larger and larger.
Modern hardware simulators use a compiled technique. They can either translate an HDL
representation and generate a C representation that is later translated to native machine
code by a C compiler, or they can directly generate native machine code. In either of these
cases, simulations runs much faster.
EDK 6.2 generates compile scripts for two compiled simulators: Model Technology’s
ModelSim and Cadence’s NcSim.
Structural Model
After a successfully generating structural simulation models, the simulation directory
contains the following files in the structural subdirectory:
peripheral_wrapper.[vhd|v]
Modular simulation files for each component.
system_name.[vhd|v]
The top level HDL file of the design.
system_name_init.[vhd|v]
Memory initialization file, if needed.
system_name.[do|sh]
Script to compile the HDL files and load the compiled simulation models in the
simulator.
Timing Model
After a successfully generating timing simulation models, the simulation directory
contains the following files in the timing subdirectory:
system_name.[vhd|v]
The top level HDL file of the design.
system_name.sdf
The Standard Delay Format file with the appropriate block and net delays from the
place and route process used only for timing simulation.
system_name_init.[vhd|v]
Memory initialization file, if needed.
system_name.[do|sh]
Script to compile the HDL files and load the compiled simulation models in the
simulator.
ModelSim
To simulate using ModelSim, do the following:
1. Compile the design
2. Load the design
3. Provide stimulus
4. Run simulation
# Load Design
vsim system
# Set Stimulus
force -freeze sim:/system/sys_clk 1 0, 0 {10 ns} -r 20 ns
force -freeze sim:/system/sys_reset 1
force -freeze sim:/system/sys_reset 0 100 ns, 1 {200 ns}
# Run simulation
run 2 us
To run this script, on ModelSim’s command prompt type:
ModelSim> do run.do
NcSim
To simulate using ModelSim, you need to do the following:
1. Compile the design
2. Elaborate the design
3. Load the design
4. Provide stimulus
5. Run simulation
VHDL
To elaborate the design type:
> ncelab system:structure
If the design has any memories to be initialized, type:
> ncelab system_conf
Verilog
To elaborate the design type:
> ncelab system glbl
If the design has any memories to be initialized, type:
> ncelab system_conf system glbl
Submodule Simulation
In certain cases, the EDK design will not be the top-level of your design. This will be the
case when you instantiate it in a higher level design for synthesis or when you instantiate
the EDK design in a testbench for simulation. In either case, the design hierarchy is
modified, and the EDK design is pushed one level down the hierarchy. This section
describes instantiating simulation models in testbenches or higher level systems.
VHDL
You can instantiate an EDK design in a testbench or higher level design using the following
syntax:
entity <testbench name> is
end <testbench name>;
Submodule Simulation
<generics>
)
port map (
<ports>
);
end <testbench architecture>;
For example, if the design name is “system”, you will write in a VHDL file (for example,
tb.vhd) the following code:
entity tb is
end tb;
architecture STRUCTURE of tb is
mysystem: system
port map (
sys_clk => my_clk,
sys_rst => my_rst
);
end STRUCTURE;
configuration tb_conf of tb is
for STRUCTURE
for mysystem: system
use configuration work.system_conf;
end for;
end tb_conf;
You should also include all the other components, signals, or stimulus generation code in
the same file.
The EDK system configuration (system_conf in this case) defines all the memory
initialization definitions for your design. If this configuration is not used, there will be no
data in any memory blocks. If the design has no memory blocks to be initialized, you can
omit the usage of the configuration.
Verilog
You can instantiate an EDK design in a testbench or higher level design using the following
syntax:
module <testbench name> ();
<design name>
<design name>
(
.<port1> (),
.<port2> (),
);
endmodule
For example, if the design name is “system”, you will write in a Verilog file (for example,
tb.v) the following code:
module tb();
system_conf
system_conf();
system
system
(
.sys_clk (my_clk),
.sys_rst (my_rst)
);
endmodule
You should also include all the other components, signals or stimulus generation code in
the same file.
The configuration module (system_conf in this case) is a module that has all the memory
initialization parameter definitions for your design. If this module is not instantiated, there
will be no data in any memory blocks. If the design has no memory blocks to be initialized,
you can omit the configuration module instantiation.
ModelSim
This provides partial instructions on how to compile, load, and simulate using ModelSim.
For a more extensive explanation, refer to the section “Simulating a Basic System,” or to
your ModelSim documents.
VHDL
To compile the tb.vhd file, type:
ModelSim> vcom -93 -work work tb.vhd
To load the testbench:
ModelSim> vsim tb_conf
Or if there are no memory blocks to initialize, type:
ModelSim> vsim tb
To simulate, type:
VSIM> run 100
Verilog
To compile the tb.v file, type:
ModelSim> vlog -incr -work work tb.v
Submodule Simulation
NcSim
This section provides partial instructions on how to compile, load, and simulate using
NcSim. For a more extensive explanation, refer to section “Simulating a Basic System,” or
to your NcSim documents.
VHDL
To compile the tb.vhd file, type:
nclaunch> ncvhdl -v93 -work work tb.vhd
To elaborate it:
nclaunch> ncelab tb_conf
Or if there are no memory blocks to initialize, type:
nclaunch> ncelab tb:structure
To load the testbench:
nclaunch> ncsim tb_conf
If there are no memory blocks to initialize:
nclaunch> ncsim tb
To simulate, type:
ncsim> run 100
Verilog
To compile the tb.v file, type:
nclaunch> ncvlog -update -work work tb.v
To elaborate it:
nclaunch> ncelab tb glbl
To load the testbench:
nclaunch> ncsim tb glbl
To simulate, type:
ncsim> run 100
Using SmartModels
Chapter 7
Debugging in EDK
This chapter describes the basics in debugging a system designed using EDK. This
includes Software debugging using XMD and GDB as well as Hardware debugging using
the Chipscope Pro cores and Chipscope Analyzer tool. This chapter is organizes into the
following sections.
x “Introduction”
x “Debugging PowerPC Software”
i “Hardware setup for PowerPC Debugging Using a JTAG Cable”
i “Software setup for PowerPC Debugging”
i “Advanced PowerPC Debugging Tips”
x “Debugging MicroBlaze Software”
i “Hardware setup for MDM-based Debugging using JTAG (hw-based)”
i “Software setup for MDM-based Debugging”
i “Hardware setup for xmdstub-based Debugging using JTAG (sw-based)”
i “Software setup for xmdstub-based debugging”
i “Using Serial cable for xmdstub debugging”
x “Hardware Debugging Using Chipscope Pro”
i “Instantiating Chipscope Pro Cores in an EDK Design”
i “Steps involved in using Chipscope Pro Analyzer with an EDK design”
i “Using Chipscope PLB IBA and VIO cores”
i “Advanced Chipscope Debugging tips”
Introduction
A significant percentage of the design cycle of complex processor systems is spent in
debugging and verification. This includes debugging of software running on processors
and verification of on-chip bus transactions and hardware logic. Since time-to-market is a
key factor in most designs, appropriate tools are needed for both these time-consuming
tasks. EDK provides IP cores to access processors, buses and random logic in a users
design (inside the FPGA) and software tools to visualize and control these blocks.
BEGIN jtagppc_cntlr
PARAMETER INSTANCE = jtagppc_0
PARAMETER HW_VER = 1.00.b
PORT DBGC405DEBUGHALT_1 = DBGC405DEBUGHALT
PORT JTGC405TRSTNEG_All = JTGC405TRSTNEG
PORT JTGC405TCK_All = JTGC405TCK
PORT JTGC405TDI_1 = JTGC405TDI
PORT JTGC405TMS_All = JTGC405TMS
PORT C405JTGTDO_Last = C405JTGTDO
For more information about the JTAGPPC connection, refer the PPC405 JTAG port section
of the PowerPC 405 Block Reference Guide. For more information about MHS files and
making port connections in Platform Studio, refer the Embedded Systems Tools Reference
Guide.
3. Connect GDB to XMD’s GDB server TCP port “1234” and debug the program locally
(hostname=localhost) or remotely (hostname = IP addr).
4. For help in using GDB, select Help->Help Topics from the GDB GUI.
.....
BEGIN microblaze
PARAMETER INSTANCE = microblaze_0
PARAMETER HW_VER = 2.00.a
PARAMETER C_DEBUG_ENABLED = 1
PARAMETER C_NUMBER_OF_PC_BRK = 2
PARAMETER C_NUMBER_OF_RD_ADDR_BRK = 1
PARAMETER C_NUMBER_OF_WR_ADDR_BRK = 1
BUS_INTERFACE DOPB = mb_opb
BUS_INTERFACE IOPB = mb_opb
BUS_INTERFACE DLMB = dlmb
BUS_INTERFACE ILMB = ilmb
PORT CLK = sys_clk_s
PORT DBG_CAPTURE = DBG_CAPTURE_s
PORT DBG_CLK = DBG_CLK_s
PORT DBG_REG_EN = DBG_REG_EN_s
PORT DBG_TDI = DBG_TDI_s
PORT DBG_TDO = DBG_TDO_s
PORT DBG_UPDATE = DBG_UPDATE_s
END
BEGIN opb_mdm
PARAMETER INSTANCE = debug_module
PARAMETER HW_VER = 1.00.c
PARAMETER C_MB_DBG_PORTS = 1
PARAMETER C_USE_UART = 1
PARAMETER C_UART_WIDTH = 8
PARAMETER C_BASEADDR = 0x80002000
PARAMETER C_HIGHADDR = 0x800020ff
BUS_INTERFACE SOPB = mb_opb
PORT OPB_Clk = sys_clk_s
PORT DBG_CAPTURE_0 = DBG_CAPTURE_s
PORT DBG_CLK_0 = DBG_CLK_s
PORT DBG_REG_EN_0 = DBG_REG_EN_s
PORT DBG_TDI_0 = DBG_TDI_s
PORT DBG_TDO_0 = DBG_TDO_s
PORT DBG_UPDATE_0 = DBG_UPDATE_s
END
.....
Figure 7-2: MHS snippet for a MicroBlaze system with Hardware debug over JTAG
1 05026093 8 XC18V04
2 0123e093 10 XC2VP4
Assuming, Device No: 2 contains the MicroBlaze system
Connected to the JTAG MicroBlaze Debug Module (MDM)
No of processors = 1
3. Connect GDB to XMD’s GDB server TCP port “1234” and debug the program locally
(hostname=localhost) or remotely (hostname = IP addr).
4. For help in using GDB, select Help->Help Topics from the GDB GUI.
BEGIN opb_mdm
PARAMETER INSTANCE = debug_module
PARAMETER HW_VER = 1.00.c
PARAMETER C_MB_DBG_PORTS = 0
PARAMETER C_USE_UART = 1
PARAMETER C_UART_WIDTH = 8
PARAMETER C_BASEADDR = 0x80002000
PARAMETER C_HIGHADDR = 0x800020ff
BUS_INTERFACE SOPB = mb_opb
PORT OPB_Clk = sys_clk_s
END
.....
Figure 7-3: MHS snippet for xmdstub-based debugging using MDM
Figure 7-4: Setting xmdstub parameter using Software Settings dialog in XPS
BEGIN PROCESSOR
PARAMETER DRIVER_NAME = cpu
PARAMETER DRIVER_VER = 1.00.a
PARAMETER HW_INSTANCE = microblaze_0
PARAMETER COMPILER = mb-gcc
PARAMETER ARCHIVER = mb-ar
PARAMETER XMDSTUB_PERIPHERAL = debug_module
END
Figure 7-5: MSS snippet for xmdstub-based debugging
BEGIN chipscope_icon
PARAMETER INSTANCE = chipscope_icon_0
PARAMETER HW_VER = 1.00.a
PARAMETER C_SYSTEM_CONTAINS_MDM = 1 # Needed if opb_mdm is also present
PARAMETER C_NUM_CONTROL_PORTS = 1
PORT control0 = opb_iba_control
END
BEGIN chipscope_opb_iba
PARAMETER INSTANCE = chipscope_opb_iba_0
PARAMETER HW_VER = 1.00.a
PARAMETER C_DATA_UNITS = 1
PARAMETER C_CONTROL_UNITS = 1
PARAMETER C_WRDATA_UNITS = 1
PARAMETER C_RDDATA_UNITS = 1
PARAMETER C_ADDR_UNITS = 1
BUS_INTERFACE MON_OPB = mb_opb
PORT OPB_Clk = sys_clk_s
PORT chipscope_icon_control = opb_iba_control
END
Figure 7-7: Connecting the OPB IBA to the OPB as a Bus Analyzer
Figure 7-8: Connecting the ICON “control” Signals to the OPB IBA
Platgen and the Tcl wrappers for the Chipscope cores would have created the signals (.cdc)
file based on the design parameters in the following directory:
<EDK Project Directory>/implementation/<OPB IBA instance name>_wrapper/<OPB
IBA instance name>.cdc
Ex: If the instance name of the OPB IBA in your design is chipscope_opb_iba_0 then,
<Project>/implementation/chipscope_opb_iba_0_wrapper/chipscope_opb_iba_0.cdc
will be the Chipscope signals (.cdc) file that will have to be imported into the Analyzer.
6. Now, you can use the Chipscope Analyzer to monitor the bus transactions
For more information on using the Chipscope Analyzer, refer the Chipscope Pro Users
Guide.
Chapter 8
Assumptions
This chapter assumes that the user:
x is familiar with EDK and has built systems with XPS.
x is familiar with debugging applications using XMD.
x is familiar with C programming and has used GNU tools.
Tool Requirements
Program profiling requires the following tools in EDK:
x Xilinx Platform Studio (XPS)
x EDK GNU tools
x Library generator (LibGen)
x Xilinx Microprocessor Debugger (XMD).
x opb_timer peripheral is needed for MicroBlaze.
Features
LibXil Profile library has the following features:
x Provides Histogram (flat profile) and Call Graph information.
i Histogram: Shows how much time the program spent in each function and how
many times the function was called.
i Call Graph: Shows for each function, which functions called it, which other
functions it called and how many times.
x Profiling parameters are configurable, Sampling Frequency, Histogram Binsize and
Timer to use.
x Memory location and size to store profiling is flexible and configurable based on
program requirements.
######################################################################
#
****************************************************************
** Memory Requirements for Profiling (Microblaze)
** Executable: microblaze_0/code/executable.elf
** Histogram BinSize: 4
****************************************************************
Program Text Size........................3176
No. of Func. Calls.......................23
No. of Func. Ptr. Calls..................0
MicroBlaze Configuration :
--------------------------
Version............................2.00.a
No of PC Breakpoints...............4
No of Read Addr/Data Watchpoints...1
No of Write Addr/Data Watchpoints..1
Instruction Cache Support..........off
Data Cache Support.................off
****************************************************************
** Profiling Memory Test
** Executable: microblaze_0/code/executable.elf
** Memory Allocated: 856
** Profile Type: PROFILE_FUNCPTR
** Histogram BinSize: 4
****************************************************************
Flat profile:
granularity: each sample hit covers 16 byte(s) for 9.41% of 0.00 seconds
-----------------------------------------------
<spontaneous>
[9] 3.5 0.00 0.00 _program_clean [9]
0.00 0.00 16/160 strcmp [3]
-----------------------------------------------
0.00 0.00 16/16 Proc_2 [8]
[10] 0.0 0.00 0.00 16 Func_2 [10]
-----------------------------------------------
0.00 0.00 16/16 Func_3 [6]
[11] 0.0 0.00 0.00 16 malloc [11]
-----------------------------------------------
1 main [19]
[19] 0.0 0.00 0.00 0+1 main [19]
1 main [19]
-----------------------------------------------
Index by function name
Chapter 9
Assumptions
This chapter assumes that the user:
x Has created an EDK project.
x Has created a hardware system and a software application in this EDK project.
x Has used the ISE tools to create a bitstream for the hardware, and the EDK compiler
tools to create an ELF file for the application.
Introduction
System initialization and download consists of updating the hardware bitstream with
BRAM initialization data, downloading this modified bitstream to the FPGA, and
initializing external memories if necessary. There are several methods available to do this.
The user must pick the appropriate method depending on the application and the stage of
the project.
If the entire software application is contained within FPGA BRAM blocks and no external
memories need to be initialized, the system can be initialized by updating the bitstream.
Refer to the “Initialize Bitstreams with Application(s)” section for more details.
If a part of the software application resides in external memory, XMD can be used to
download the software application after the FPGA has been programmed with the
bitstream. Refer to the “Downloading an Application Using XMD” section for more
details. To ensure that the processor does not enter a bad state in the time between
download of the bitstream and download of the application, a bootloop must be used.
Refer to the “Initialize Bitstreams with Bootloops” section for more information on
bootloops.
Another way to initialize the system is using System ACE. System ACE CF configures
devices using Boundary-Scan (JTAG) instructions and a Boundary-Scan Chain. System
ACE CF is a two-chip solution that requires the System ACE CF controller and either a
CompactFlash card or one-inch Microdrive disk drive technology as the storage medium.
Refer to the “Generating ACE Files” section for more details. A bootloader may also be
used as the mechanism to load the application from some nonvolatile memory into
processor memory and execute it. Refer to the “Bootloaders” section for more details.
Bitstream Initialization
Bootloaders
Bootloaders are small software programs that reside in internal BRAM memory. They are
executed when the processor comes out of reset. A bootloader should set up registers and
copy the main application program from external nonvolatile memory (usually flash
memory) into internal BRAM memory as well as external nonvolatile memory. Once the
application has been copied, the bootloader executes it by branching to the entry point of
the application. Usually, all interrupts are turned off when the bootloader is executing. The
application is responsible for all interrupt handling.
System ACE
The System ACE solution can be used to download software through JTAG in a similar
way to the debugger. This way a single System ACE controller can be augmented to
contain both the bitstream and software initialization data. Refer to the “Generating a
System ACE File” section of this chapter for more information.
Assumptions
This chapter assumes that the user:
x Has created an EDK project (hardware and software) using the Xilinx Platform Studio
(XPS).
x Is familiar with debugging a program using XMD/GDB.
Tool Requirements
Fast download on MicroBlaze is supported on IP and tools of the following or later
versions:
x microblaze 2.10.a
x opb_mdm 2.00.a
x xmd EDK 6.2
x mb-gdb EDK 6.2
Steps
The following steps are performed for EDK designs, using XPS:
1. Building the hardware: Connecting the FSL bus interface between MicroBlaze and the
opb_mdm module.
2. Downloading the program using XMD/GDB.
Cores in XPS. For more information refer Chapter 2, “Creating a Basic Hardware System
in XPS”.
BEGIN opb_mdm
PARAMETER INSTANCE = debug_module
PARAMETER HW_VER = 2.00.a
PARAMETER C_MB_DBG_PORTS = 1
PARAMETER C_USE_UART = 1
PARAMETER C_UART_WIDTH = 8
BEGIN fsl_v20
PARAMETER INSTANCE = download_link
PARAMETER HW_VER = 1.00.b
PARAMETER C_EXT_RESET_HIGH = 0
PORT SYS_Rst = sys_rst
PORT FSL_Clk = sys_clk
END
Note: Only the Slave FSL Interface (SFSL0) of MicroBlaze should be used for Fast Download. Fast
Download will not work if any other FSL Interface is connected to the opb_mdm FSL Interface.
XMD%
Note: When XMD is used for generation of a System ACE file, XMD does not read the config word
from MDM, i.e., XMD will not know if the MFSL0 Interface is available on MDM. When the MHS file is
not available, XMD cannot verify the FSL connection. In these cases, XMD can be forced to use the
fast download methodology by entering the command xforce_use_fsl_dow after the connection
is established. For more information refer to the “Xilinx Microprocessor Debugger (XMD)” chapter in
the Embedded System Tools Guide.
Note: For the Xilinx Parallel Cable, the default JTAG clock speed is set to 5 Mhz. The speed can be
changed by setting the XIL_IMPACT_ENV_LPT_SETCLOCK_VALUE environment variable in the
shell. The allowed values are 10000000, 5000000, 2500000, 1250000, and 625000 (Hz).
Assumptions
This chapter assumes that the user:
x Is familiar with debugging programs using XMD and is familiar with XMD
commands.
x Is familiar with general hardware and software system models in EDK.
x Has a basic understanding of TCL scripts.
Tool Requirements
Generating an ACE file requires the following tools:
x genace.tcl (MicroBlaze support in EDK 6.2)
x xmd
x iMPACT (from ISE)
GenACE Features
x Supports PowerPC and MicroBlaze with MDM targets
x ACE file generation from hardware (Bitstream) and software (ELF/data) files.
x Initialize external memories on PowerPC and MicroBlaze systems.
x Supports Single/Multiple FPGA device systems.
GenACE Model
The System ACE files generated support the System ACE CF family of configuration
solutions. System ACE CF configures devices using Boundary-Scan (JTAG) instructions
and a Boundary-Scan Chain. System ACE CF is a two-chip solution that requires the
System ACE CF controller, and either a CompactFlash card or one-inch Microdrive disk
drive technology as the storage medium. The System ACE file is generated from a Serial
Vector Format (SVF) file. An SVF file is a text file that contains both programming
instructions and configuration data to perform JTAG operations.
XMD and iMPACT generate SVF files for software and hardware system files respectively.
Basically, the set of JTAG instructions and data used to communicate with the JTAG chain
on board is written out as an SVF file, i.e., the instructions and data to perform operations
like configuring FPGA using iMPACT, connecting to processor target, downloading
program, and running the program from XMD are captured in an SVF file format. The SVF
file is converted to an ACE file and written to the storage medium. These operations are
then performed by the System ACE controller to achieve the determined operation.
The following is the sequence of operations using iMPACT and XMD for a simple
hardware and software configuration, that gets translated into ACE file.
1. Download bitstream using iMPACT. The bitstream (download.bit) contains system
configuration and bootloop code.
2. Bring the device out of reset, causing the Done pin to go high. (This starts the Processor
system.)
3. Connect to the Processor using XMD.
4. Download multiple data files to BRAM or External memory.
5. Download multiple executable files to BRAM or External memory. The PC will point
to the start location of the last downloaded ELF file.
6. Continue execution from the PC instruction address.
The flow for generating System ACE files is bit o svf, elf o svf, binary data o svf and svf
o ace file. The genace.tcl scripts allows to perform the following operations.
Usage
xmd genace.tcl -jprog -target mdm -hw implementation/download.bit
-elf executable1.elf executable2.svf -data image.bin 0xfe000000
-board auto -ace system.ace
-jprog
-target mdm
-hw implementation/download.bit
-elf executable1.elf executable2.svf
-data image.bin 0xfe000000
-ace system.ace
-board user
-configdevice devicenr 1 idcode 0x5026093 irlength 8 partname XC18V04
-configdevice devicenr 2 idcode 0x123e093 irlength 10 partname XC2VP4
-debugdevice devicenr 2 cpunr 1
Note: The board option in the above options file has been changed from auto to user. The
genace.opt file should not have a blank line, the parser would error out.
# xmd_elf2svf file
#puts "xconnect Done..\n\n"
set tgt 1 <= Note: The Target has been changed to Processor 2
set a "xconnect $target_type -cable type xilinx_svffile fname
-jprog
-target ppc_hw
-hw implementation/download.bit
-elf executable2.elf
-ace fpga2.ace
-board user
-configdevice devicenr 1 idcode 0x123e093 irlength 10 partname XC2VP4
-configdevice devicenr 2 idcode 0x123e093 irlength 10 partname XC2VP4
-debugdevice devicenr 2 cpunr 1 <= Note: The change in Devicenr
This will generate the file fpga2.svf.
2. Concatenate the files in the following order: fpga1.svf and fpga2.svf to
final_system.svf.
3. Finally, generate the ACE file by calling impact -batch svf2ace.scr. The
following SCR file should be used:
svf2ace -wtck -d -i final_system.svf -o final_system.ace
quit
Related Information
Adding a New Device to the JTAG Chain
An XMD supported device list is located at $XILINX_EDK/data/deviceid.lst. If XMD
detects a device as “UNKNOWN” in the JTAG chain, the IR length of the device has to be
specified manually by the user. This can be done in the following ways:
x Edit the deviceid.list.
Add a new entry for the device to the deviceid.lst. XMD would then support the
device. User has to add entry to all 3 sections in the list file. For more details refer the
deviceid.lst file.
x Provide a GenACE OPT file with options.
The user can specify the -configdevice and -debugdevice option in the options file.
x Edit genace.tcl file.
Add a new board type in genace.tcl. Specify the xmd_options, jtag_fpga_position and
jtag_devices values for the board. Refer to the genace.tcl file in EDK installation at
$XILINX_EDK/data/genace.tcl for more details.
CF Device Format
For the System ACE controller to read the CF device the following steps should be
performed:
1. Format the CF device as FAT 16.
2. Create a Xilinx.sys file in the root directory. This file contains the directory structure to
use by the ACE controller. Copy the generated ACE file to the appropriate directory.
For more information refer to the “iMPACT” section of the ISE documentation.
Chapter 10
System Requirements
You must have the following software installed on your PC to complete this tutorial:
x Windows 2000 SP2/Windows XP
x EDK 6.2 or later
x ISE 6.2i or later
Note: This tutorial can be completed on Linux or Solaris, but the screenshots and directories
illustrated in this tutorial are based on the Windows Platform.
Hardware Requirements
In order to download the completed processor system, you must have the following
hardware:
x Memec Design Virtex-II Pro Development Board (2VP7 FG456 -6)
x Xilinx Parallel Cable 4 used to program and debug the device
x Serial Cable
Note: It should be noted that other hardware can be used with this tutorial. However, the completed
design has only been verified on the board specified above. The following design changes are
required:
x Update pin assignments in the system.ucf file
x Update board JTAG chain specified in the download.cmd
i OPB_UARTLITE
DLMB Bus
OPB_BRAM_IF
OPB_GPIO OPB_GPIO OPB_UARTLITE
ILMB Bus _CNTLR
OPB BRAM
X10149
Note: For more information on the MHS file, refer to the “Microprocessor Hardware
Specification (MHS)” chapter in the Embedded System Tools Guide.
x Microprocessor Software Specification (MSS) file
Note: For more information on the MSS file, refer to the “Microprocessor Software
Specification (MSS)” chapter in the Embedded System Tools Guide.
XPS supports the software tool flows associated with these software specifications.
Additionally, you can use XPS to customize software libraries, drivers, and interrupt
handlers, and to compile your programs.
Starting XPS
1. To open XPS, select the following:
Start o Programs o Xilinx Embedded Development Kit o Xilinx Platform Studio
2. Select File o New Project o Base System Builder (BSB) to open the Create New
Project Using BSB Wizard dialog box shown in Figure 10-2.
Figure 10-2: Create New Project Using Base System Builder Wizard
3. Use the Project File Browse button to browse to the edk_tutorial_mb folder shown in
Figure 10-3. Click Open to create the system.xmp file.
MHS File
The Microprocessor Hardware Specification (MHS) file describes the following:
x Embedded processor: either the soft core MicroBlaze processor or the hard core
PowerPC (only available in Virtex-II Pro devices)
x Peripherals and associated address spaces
x Buses
x Overall connectivity of the system
The MHS file is a readable text file that is an input to the Platform Generator (the hardware
system building tool). Conceptually, the MHS file is a textual schematic of the embedded
system. To instantiate a component in the MHS file, you must include information specific
to the component.
MPD File
Each system peripheral has a corresponding MPD file. The MPD file is the symbol of the
embedded system peripheral to the MHS schematic of the embedded system. The MPD
file contains all of the available ports and hardware parameters for a peripheral. The
tutorial MPD file is located in the following directory:
%XILINX_EDK/hw/XilinxProcessorIPLib/pcores/<peripheral_name>/data
Note: For more information on the MPD and MHS files, refer to the “Microprocessor Peripheral
Description (MPD)” and “Microprocessor Hardware Specification (MHS)” chapters in the Embedded
System Tools Guide.
EDK provides two methods for creating the MHS file. Base System Builder Wizard and the
Add/Edit Cores Dialog assist you in building the processor system which is defined in the
MHS file. This tutorial will illustrate the Base System Builder.
2. Click Next. Select the processor to be used in your system, as shown below:
3. Click Next. You will now specify several processor options as shown in Figure 10-6:
- XMD with S/W Debug stub: Selecting this mode of debugging interface
introduces a software intrusive debugging. There is a 400 byte stub which is
located at 0x00000000. This stub communicates with the debugger on the host
through the JTAG interface of the OPB MDM module.
- On-Chip H/W Debug module: When the H/W debug module is selected, an
OPB MDM module is included in the hardware system. This introduces
hardware intrusive debugging with no software stub required. This is the
recommended way of debugging for MicroBlaze system.
- No Debug: No debug is turned on.
Note: For more information about the Xilinx Microprocessor Debugger (XMD), refer to
the Xilinx Microprocessor Debugger (XMD) chapter in the Embedded System Tools
Guide.
- Users can also specify the size of the local instruction and data memory. You
can also specify the use of a cache.
5. Click Next. Select each of the peripheral available as shown in Figure 10-7.
Note: The Baud Rate for the UARTLite must be updated to 11520.
6. Click Next. Click on Add Peripheral. Add a 16KB OPB BRAM IF CNTLR as shown in
Figure 10-8.
7. Click Next. You will now customize the cache settings as shown in Figure 10-9. This
will cache instructions stored in the opb_bram_if_cntlr_1 and the SDRAM. No data
will be cacheable, only instructions.
8. Using the Software Configuration dialog box as shown in Figure 10-10, specify the
following software settings:
i Standard Input o RS232
i Standard Output o RS232
i Instruction o ilmb_cntlr
i Data o dlmb_cntlr
i Stack/Heap o dlmb_cntlr
9. Click Next. The completed system including the memory map will be displayed as
shown in Figure 10-10. Currently the memory map can not be changed or updated in
the BSB. If you want to change the memory map you can do this in XPS.
3. In the Project Options dialog box, select the Hierarchy and Flow tab.
4. Select the following options:
b. Create a new directory named proj_nav_proj in the root XPS project directory by
using the right mouse button and selecting New o Folder from the pop-up menu.
c. Select this directory and click Open.
Note: Verify that the Project Navigator project is created in the root directory to ensure that
it is not deleted when you clean up the XPS project.
5. Click OK.
6. In XPS, select the following to create a Project Navigator project in the directory
previously specified:
Tools o Export to ProjNav
7. Open the Project Navigator project XPS just created.
1. Select Project o Add Source to add the system.ucf file included in the data directory.
2. If the system.bmm file has not been added to the project, select Project o Add Source
to add the system.bmm file in the implementation directory.
3. Select system.vhd in the Source Window.
4. Right click on Generate Programming File in the Process Window and select
Properties.
5. Under the Startup options tab, select JTAG Clock for FPGA Start-up Clock.
6. Click OK.
7. Double click Generate Programming File in the Process Window to generate the
uninitialized bit file.
There are two major parts to software design, configuring the BSP and writing the software
applications. The configuration of the BSP includes the selection of device drivers and
libraries.
1. In XPS, select Project o Software Platform Settings. This will open the Software
Platform Settings dialog box as shown in Figure 10-14.
The Software Platform Settings dialog box contains three tabs. Each of these tabs is
used to control all aspects of the BSP creation.
2. The Software Platform tab allows the user to select the following:
i Drivers: The driver and driver version for each peripheral can be selected. It
should be noted that the driver version is not related to the peripheral version.
i Libraries: Select the Xilinx libraries used in the software applications.
i Kernel and Operating Systems: Select the Kernel or Operating System to be used.
The following Operating Systems are supported:
- Standalone
- Xilinx MicroKernel
3. No changes are required on this tab. Select the Processor and Driver Parameters tab as
shown below. This tab allows the user to configure several Processor and Driver
Parameters. No changes are required.
5. Configure the Library/OS Parameters tab as shown in Figure 10-16. This allows the
RS232 peripheral to be used for standard IO functions like print, printf, scanf, etc.
6. Click OK.
7. In XPS, select Tools o Generate Libraries and BSPs to run LibGen and create the
BSP which includes device drivers, libraries, configures the STDIN/STDOUT, and
Interrupt handlers associated with the design.
8. LibGen creates the following directories in the ppc405_0:
i code: contains the compiled and linked application code in an ELF file
i include: contains the header files for peripherals included in the design (such as
xgpio.h and xuartlite.h)
i lib: contains the library files (such as libc.a and libxil.a)
i libsrc: contains the source files used to create libraries
Note: For more information on these files, refer to the Embedded System Tools Guide.
In EDK 6.2, XPS provides the ability for the user to create multiple software projects. These
projects can include source files, header files, and linker scripts.
Unique software projects allows the designer to specify the following options for each
software project:
i Specify compiler options
i Specify which projects to compile
i Specify which projects to downloaded
i Build entire projects
Software application code development can be managed by selecting the Applications tab
as shown in Figure 10-17. The Base System Builder (BSB) generates a sample application
which tests a subset of the peripherals included in the design.
17. Add the DeviceId to the function call so that it looks as follows:
XGpio_Initialize(&gpio, XPAR_LEDS_48BIT_DEVICE_ID);
18. Using the documentation specify the direction of the GPIO data as an output.
19. Now that the peripheral has been initialized and the direction of the data has been
specified, code a simple while loop to count from 1 to 16. Each value should be written
to the GPIO.
20. An example of the function can be found below:
while(1) {
XGpio_DiscreteWrite(&gpio, j);
j++;
/* Insert some delay so you can see the LEDs changing */
for (k = 0; k < 10000000; k++);
if (j > 16)
j = 0;
}
21. In order to use these new functions, an additional header file must be included,
include the gpio.h header file.
22. The completed code shown below can be used as example:
/*
* Xilinx EDK 6.2
*
* This file is a sample test application
*
* This application is intended to test and/or illustrate some
* functionality of your system. The contents of this file may
* vary depending on the IP in your system and may use existing
* IP driver functions. These drivers will be generated in your
* XPS project when you run the "Generate Libraries" menu item
* in XPS.
*
* Your XPS project directory is at: C:\edk_tutorial_mb
*/
#include "xgpio.h"
/*
* Routine to write a pattern out to a GPIO
* which is configured as an output
* PARAMETER C_ALL_INPUTS = 0
*/
void WriteToGPOutput(Xuint32 BaseAddress, int gpio_width) {
int i=0, j=0, k=0;
int numTimes = 5;
/*
* Routine to read data from a GPIO
* which is configured as an input
* PARAMETER C_ALL_INPUTS = 1
*/
Xuint32 ReadFromGPInput(Xuint32 BaseAddress) {
Xuint32 data = XGpio_mGetDataReg(BaseAddress);
return data;
}
//====================================================
XGpio gpio;
int j = 0;
int k = 0;
WriteToGPOutput(XPAR_LEDS_4BIT_BASEADDR, 4);
{
Xuint32 data = ReadFromGPInput(XPAR_PUSH_BUTTONS_3BIT_BASEADDR);
xil_printf("Data read from Push_Buttons_3Bit: 0x%x\n", data);
}
{
Xuint32 data = ReadFromGPInput(XPAR_DIP_SWITCHES_8BIT_BASEADDR);
xil_printf("Data read from DIP_Switches_8Bit: 0x%x\n", data);
}
}
else {
xil_printf("FAILED!\n");
}
}
XGpio_Initialize(&gpio, XPAR_LEDS_4BIT_DEVICE_ID);
XGpio_SetDataDirection(&gpio, 0);
while(1) {
XGpio_DiscreteWrite(&gpio, j);
j++;
if (j > 16)
j = 0;
Linker Scripts
A linker script is required to tell the GNU linker where to place the code. A linker script
was written by the Base System Builder (BSB) using the information you provided when
specifying the project for this tutorial.
1. Double click on TestAppLinkScr to open the linker script for the TestApp Project.
Examine the contents of the file.
Tutorial Test Question:
At what address will the .text section be placed? ______________________
At what address will the .data section be placed? ______________________
2. Save and close the file.
10. Once the device is configured, the hyperterminal should look like the following figure:
11. As the message states, data was read from the DIP switch, the push button switches
and then several memory tests were performed.
5. Configure the Target Selection dialog box to match Figure 10-20. Click OK.
6. In GDB, select File o Open File.
7. Select executable.elf in the inst_microblaze/code directory.
Tutorial Test Questions:
Do you see the C code or the assembly code? _________________________________
Why can you not see the C code? ______________________________________
8. In GDB, select File o Exit.
9. In XPS, select Options o Compiler Options.
10. In the microblaze instance inst_microblaze dialog box, select the Optimization tab.
11. Select Create symbols for debugging (-g option).
12. Click OK.
13. Perform the following steps:
i recompile the code
i load the new executable.elf into GDB
Tutorial Test Question:
Do you see the C code? ________ If you do not see the C code, repeat steps 9-13.
14. Select Run o Run
There is an automatic breakpoint at main. GDB allows you to single step the C or
assembly code. This is an exercise to help you learn how to run GDB.
Note: The default values displayed in the Registers Window are in hex, while the values displayed
in the Source Window are in decimal.
15. Once you have determined the error, recompile the code and download it through
GDB.
Chapter 11
System Requirements
You must have the following software installed on your PC to complete this tutorial:
x Windows 2000 SP2 or Windows XP
x EDK 6.2 or later
x ISE 6.2i or later
Note: This tutorial can be completed on Linux or Solaris, but the screenshots and directories
illustrated in this tutorial are based on the Windows Platform.
Hardware Requirements
In order to download the completed processor system, you must have the following
hardware:
x Memec Design Virtex-II Pro Development Board (2VP7 FG456 -6)
x Xilinx Parallel Cable 4 used to program and debug the device
x Serial Cable
Note: It should be noted that other hardware can be used with this tutorial. However, the completed
design has only been verified on the board specified above. To use another board, the following
design changes are required:
x Update pin assignments in the system.ucf file
x Update board JTAG chain specified in the download.cmd
PROC_SYS
RESET
X9934
Starting XPS
1. To open XPS, select the following:
Start o Programs o Xilinx Embedded Development Kit o Xilinx Platform Studio
2. Select File o New Project o Base System Builder to open the Create New Project
dialog box shown in the following figure:
3. Use the Project File Browse button to browse to the edk_tutorial_ppc folder. Click
Open to create the system.xmp file as shown in the following figure:
MHS File
The Microprocessor Hardware Specification (MHS) file describes the following:
x Embedded processor: either the soft core MicroBlaze processor or the hard core
PowerPC (only available in Virtex-II Pro devices)
x Peripherals and associated address spaces
x Buses
x Overall connectivity of the system
The MHS file is a readable text file that is an input to the Platform Generator (the hardware
system building tool). Conceptually, the MHS file is a textual schematic of the embedded
system. To instantiate a component in the MHS file, you must include information specific
to the component.
MPD File
Each system peripheral has a corresponding MPD file. The MPD file is the symbol of the
embedded system peripheral to the MHS schematic of the embedded system. The MPD
file contains all of the available ports and hardware parameters for a peripheral. The
tutorial MPD file is located in the following directory:
%XILINX_EDK/hw/XilinxProcessorIPLib/pcores/<peripheral_name>/data
Note: For more information on the MPD and MHS files, refer to the “Microprocessor Peripheral
Description (MPD)” and “Microprocessor Hardware Specification (MHS)” chapters in the Embedded
Systems Tool Guide.
EDK provides two methods for creating the MHS file. Base System Builder Wizard and the
Add/Edit Cores Dialog assist you in building the processor system which is defined in the
MHS file. This tutorial will illustrate the use of the Base System Builder.
2. Click Next. Select the processor to be used in your system, as shown below:
3. Click Next. You will now specify several processor options as shown in Figure 11-6:
- Processor Clock Frequency: This is the frequency of the clock driving the
PowerPC clock pins. This is generated using a DCM.
- Bus Clock Frequency: This is the frequency of the clock driving all
components connected to a bus. You can not currently specify unique bus
frequencies. This can be done in XPS.
i PowerPC 405 Processor Engine Settings:
- JTAG Debug Interface: Allows the user to specify how the Processor JTAG
interface should be connected.
- On-Chip Memory: Allows the user to specify the amount of BRAM memory
to be used for the OCM space.
5. Click Next. Select each of the peripheral available as shown in Figure 11-7.
6. Click Next. Click on Add Peripheral. Add a 16KB OPB BRAM IF CNTLR as shown in
Figure 11-8.
7. Using the Software Configuration dialog box, specify the following software settings:
i Standard Input o RS232
i Standard Output o RS232
i Instructions o SDRAM_8Mx32
i Data o opb_bram_if_cntlr_1
i Stack/Heap o plb_bram_if_cntlr_1
8. Click Next. The completed system including the memory map will be displayed as
shown in Figure 11-10. Currently the memory map can not be changed or updated in
the BSB. If you want to change the memory map you can do this in XPS.
3. In the Project Options dialog box, select the Hierarchy and Flow tab. The following
dialog box is displayed:
b. Create a new directory named proj_nav_proj in the root XPS project directory by
using the right mouse button and selecting New o Folder from the pop-up menu.
c. Select this directory and click Open.
Note: Verify that the Project Navigator project is created in the root directory to ensure that
it is not deleted when you clean up the XPS project.
5. Click OK.
6. In XPS, select the following to create a Project Navigator project in the directory
previously specified:
Tools o Export to ProjNav
3. If the system.bmm file has not been added to the project, select Project o Add Source
to add the system.bmm file in the implementation directory.
4. Select system.vhd in the Source Window.
5. Right click on Generate Programming File in the Process Window and select
Properties.
6. Under the Startup options tab, select JTAG Clock for FPGA Start-up Clock.
7. Click OK.
8. Double click Generate Programming File in the Process Window to generate the
uninitialized bit file.
There are two major parts to software design, configuring the BSP and writing the software
applications. The configuration of the BSP includes the selection of device drivers and
libraries.
The Software Platform Settings dialog box contains three tabs. Each of these tabs is used to
control all aspects of the BSP creation.
2. The Software Platform tab allows the user to select the following:
i Drivers: The driver and driver version for each peripheral can be selected. It
should be noted that the driver version is not related to the peripheral version.
i Libraries: Select the Xilinx libraries used in the software applications.
i Kernel and Operating Systems: Select the Kernel or Operating System to be used.
The following Operating Systems are supported:
- Standalone
- VxWorks 5.4/VxWorks 5.5
- Monta Vista Linux
- Xilinx MicroKernel
Note: Only the BSP is generated for the Operating System. In order to use the generated BSP
the user must have a valid installation of VxWorks/Tornado and Monta Vista Linux Development
tools.
3. No changes are required on this tab. Select the Processor and Driver Parameters tab
as shown below. This tab allows the user to configure several Processor and Driver
Parameters. Specify the parameters to match the following:
i Processor Parameters:
- CORE_CLOCK_FREQ_HZ = 300000000
5. Configure the Library/OS Parameters tab as shown in Figure 11-15. This allows the
RS232 peripheral to be used for standard IO functions like print, printf, scanf, etc.
6. Click OK.
7. In XPS, select Tools o Generate Libraries and BSPs to run LibGen and create the
BSP which includes device drivers, libraries, configures the STDIN/STDOUT, and
Interrupt handlers associated with the design.
8. LibGen creates the following directories in the ppc405_0:
i code: contains the compiled and linked application code in an ELF file
i include: contains the header files for peripherals included in the design (such as
xgpio.h and xuartlite.h)
i lib: contains the library files (such as libc.a and libxil.a)
i libsrc: contains the source files used to create libraries
Note: For more information on these files, refer to the Embedded System Tools Guide.
In EDK 6.2, XPS provides the ability for the user to create multiple software projects. These
projects can include source files, header files, and linker scripts.
Unique software projects allow the designer to specify the following options for each
software project:
i Specify compiler options
i Specify which projects to compile
i Specify which projects to downloaded
i Build entire projects
Software application code development can be managed by selecting the Applications tab
as shown in Figure 11-16. The Base System Builder (BSB) generates a sample application
which tests a subset of the peripheral included in the design. The TestApp.c written by the
BSB does not include an interrupt handler for the Programmable Interrupt Timer. This
section walks you through the process of creating the PIT handler. Additionally, you will
fix an error in the program in the “Downloading and Debugging the Software Design”
section.
2. Examine the contents of the file. Notice that it performs basic read and write tests to via
the different GPIO ports.
3. You will now write the PIT Interrupt Handler and enable the non-critical interrupts.
4. Select the following:
Start o Programs o Xilinx Embedded Development Kit o EDK Documentation
5. Select Documents.
6. Select Embedded System Tools to open est_guide.pdf.
7. Scroll down until you find the PowerPC Interrupt Management section.
8. When utilizing interrupts in the PowerPC several steps must be completed.
a. Initialize the exception handler
b. Register the interrupt handler
c. Initial the PIT timer and specify any parameters
d. Enable the PIT interrupt
9. Create a new function called “init_pit” to perform all of these functions. An example of
the function can be found below:
//====================================================
// Setup and Initialize the PIT Timer
void init_pit() {
10. In order to use these functions, the xexception_l.h header file must be included.
Include this file in TestApp.c.
11. Write a simple Interrupt Handler which increments a variable called hit_the_pit each
time the interrupt handler is called. An example is shown below:
/*
* Interrupt service routine for the timer. This is registered using
* XExc_RegisterHandler function. This is associated with Periodic
* Interval Timer (PIT) Interrupt.
*
* The baseaddr_p pointer points to 0x00000000, because PIT is
* an internal exception.
*/
hit_the_pit = hit_the_pit + 1;
12. Now that both the Interrupt handler and the init_pit functions are complete they can
be included in the main function. You should also write some simple code to test the
number of times a PIT interrupt has occurred. The completed code shown below can
be used as an example:
/*
* Xilinx EDK 6.2
*
* This file is a sample test application
*
* This application is intended to test and/or illustrate some
* functionality of your system. The contents of this file may
* vary depending on the IP in your system and may use existing
* IP driver functions. These drivers will be generated in your
* XPS project when you run the "Generate Libraries" menu item
* in XPS.
*
* Your XPS project directory is at:
* C:\Insight_2VP7_FG456\edk_tutorial_ppc
*/
Xuint32 hit_the_pit = 0;
/*
* Routine to write a pattern out to a GPIO
* which is configured as an output
* PARAMETER C_ALL_INPUTS = 0
*/
void WriteToGPOutput(Xuint32 BaseAddress, int gpio_width) {
int i=0, j=0, k=0;
int numTimes = 5;
XGpio_mSetDataReg(BaseAddress, j);
j = j << 1;
for (k=0; k<10000000; k++) {
; //wait
}
}
numTimes--;
}
}
/*
* Routine to read data from a GPIO
* which is configured as an input
* PARAMETER C_ALL_INPUTS = 1
*/
Xuint32 ReadFromGPInput(Xuint32 BaseAddress) {
Xuint32 data = XGpio_mGetDataReg(BaseAddress);
return data;
}
/*
* Interrupt service routine for the timer. This is registered using
* XExc_RegisterHandler function. This is associated with Periodic
* Interval Timer (PIT) Interrupt.
*
* The baseaddr_p pointer points to 0x00000000, because PIT is an
* internal exception.
*/
hit_the_pit = hit_the_pit + 1;
//====================================================
// Setup and Initialize the PIT Timer
void init_pit() {
//====================================================
int main (void) {
print("-- Entering main() --\n ");
while(1) {
WriteToGPOutput(XPAR_LEDS_4BIT_BASEADDR, 4);
{
Xuint32 data = ReadFromGPInput(XPAR_PUSH_BUTTONS_3BIT_BASEADDR);
xil_printf("Data read from Push_Buttons_3Bit: 0x%x\n ", data);
}
{
Xuint32 data = ReadFromGPInput(XPAR_DIP_SWITCHES_8BIT_BASEADDR);
xil_printf("Data read from DIP_Switches_8Bit: 0x%x\n", data);
}
if(hit_the_pit == 5) {
print(" Hit the Pit Five times\n");
hit_the_pit = 0;
}
}
print("-- Exiting main() --\n");
return 0;
}
Linker Scripts
A linker script is required to tell the GNU linker where to place the code. A linker script
was written by the Base System Builder (BSB) using the information you provided when
specifying the project for this tutorial.
1. Double click on TestAppLinkScr to open the linker script for the TestApp Project.
Examine the contents of the file.
Tutorial Test Question:
At what address will the .text section be placed? ______________________
At what address will the .data section be placed? ______________________
2. Since no interrupts where utilized in the original design, the .vectors section has been
commented out. Remove the comments.
3. Remove the comments around the ivector PT_LOAD; command.
4. Assign the .vectors to the plb_bram_if_cntlr_1 memory space. An example is shown
below:
.vectors :
{
*(.vectors)
} > plb_bram_if_cntlr_1 : ivector
7. Close objdump.
TCL/Terminal Interface
JTAG
PPC405 Debug
Port
PowerPC System
X9936
Note: A GDB server was started for the PowerPC target on a local TCP port numbered 1235.
4. In XPS, select Tools o Software Debugger to open the GDB interface.
5. In GDB, select File o Target Settings to display the Target Selection dialog box.
6. Configure the Target Selection dialog box to match the following figure:
7. Click Ok.
8. In GDB, select File o Open File.
9. Select executable.elf in the TestApp directory.
Tutorial Test Questions:
Do you see the C code or the assembly code? _________________________________
Why can you not see the C code? ______________________________________
10. In GDB, select File o Close.
11. In XPS, select the Applications Tab.
12. Right-Click on Project:TestApp and select Set Compiler Options.
13. In the Set compiler settings for the project: TestApp dialog box, select the Optimization
tab.
14. Select Create symbols for debugging (-g option).
15. Click OK.
16. Perform the following steps:
i recompile the code
i load the new executable.elf into GDB
Tutorial Test Question:
Do you see the C code? ________ If you do not see the C code, repeat steps 11-16.
17. Select Run o Run
There is an automatic breakpoint at main. GDB allows you to single step the C or
assembly code. This is an exercise to help you learn how to run GDB.
Note: The default values displayed in the Registers Window are in hex, while the values displayed
in the Source Window are in decimal.
18. Once you have determined the error, recompile the code and download it through
GDB.