Home | Microprocessor | Labs Index |XUP-UNM V1000 Project|Workshops | Links & Datasheets | General Educational Material

 



About this lab

This lab is built on the first ML300-PPC405 lab. The primary goal is to introduce is to basic interrupt concepts in the ppc405 environment. For this purpose, we will add an interrupt controller and a programmable timer to the previous project. Most of our discussion in this lab will be centered at the software issues and development, more than the hardware, since we developed the basics in the first lab.

All the files are provided and the process of creation of the system is explained with detail. Several issues will be solved through the tutorial and references will be made to several Xilinx's documents. Please refer to the "links" section of this site to get the documents or links to them.

A printable version of this tutorial is available here. The final files for this tutorial are available here.

System requirements

This lab was developed using EDK 3.2.2 (the latest version up to now; Oct. 18), on a W2K Workstation and the ML300 development platform. The files provided respond to these specifications, however, the tutorial is meant to be easy to migrate to another development platform or future (and past) versions of EDK. If you find yourself in that situation and you find any trouble, please contact us. Also, if you success in migrating this tutorial, please send us your comments and anything you feel can be useful for us to improve this lab.

Think about working on a PIII 512Mb RAM at minimum. Also take in consideration that your workstation needs a parallel port (to configure the FPGA), a serial port (to make the connection with the hyperterminal) and a PS2 port (to power up the parallel IV cable). Most laptops don't have these ports anymore.
Some assumptions made

We did some assumptions in writing this tutorial. First of all, we are assuming you do have some basic knowledge on C, embedded systems, microprocessors, and VHDL. This save us the need in writing some details, but again, if you find any thing that you think should be explained in more detail, let us know!!.

System Description

The specification of our system is based on the system we built in the first ML300-PPC405 lab. We will detail the additions to that project in the following sections:

Adding a Timer to the system

The first step is to add a timer to our first simple project.

There different possibilities to this:

a.- Fixed Interval Timer (FIT_TIMER). As the name implies this is a peripheral that generates as strove signal at fixed intervals and is not attached to any bus. This is a small core, but it doesn't provide us with too much flexibility.

b.- OPB Timebase WDT. The TBWDT (TimeBase WatchDog Timer) is a peripheral that attaches to the OPB bus and basically provides a watchdog and a free running timebase counter. So, this is a strong possibility.

c.- OPB Timer/Counter: This is a more general core, a counter attached to the OPB. We will go for this one. If you decide to change it and use any of the other modules, the software changes are not complicated. We will try to cover that in the following sections.

The final structure of the system and it address map will be at follows:


Figure 1. System Block Diagram

The memory map is as shown is the next table:

Taking as starting point our first lab we can add the missing modules; go to XPS Add/Edit Cores and add the core "opb_timer" and configure its addresses as is shown in figure 2.


Figure 2. Adding the timer to the system

Take in consideration that a bigger memory map space allocated to any core; will reduce the FPGA resources required for decoding the address. A tight choice will increase the number of FPGA resources required for implementation and may adversely affect the maximum operating frequency of the system. Now let add the connection to the bus and the necessary ports as shown in figure 3 and 4.

Figure 3. Adding the bus connections

Figure 4. Adding ports

Here is something interesting. This is a special case, for the opb_intc component; the interrupt vector will be a concatenation of the locally defined interrupt signals and/or external interrupts. The position of the interrupt signal defines the priority. So, to add the interrupt signal of our timer to the interrupt controller we need to change the port as shown in figure 5.

Figure 5. Interrupt ports

No special parameters need to be setup this time. Well, this is about it on the hardware side; by clicking "Ok", XPS will show you the modified system. As before, we will generate the netlist by going to Tools/Generate Netlist in the XPS interface. Since the *.ucf file have not really change with respect to our first system, we can also proceed to the generation of the bitstream.

Developing the Software Design

As before, we need to specify the driver level for the core we added, we will use level 1. What is new for this project is that we will work with interrupts; that's why we need to configure the interrupt handling routine. Check figure 6. The interrupt parameter will not be enable if the interrupt pin of the core is not connected.

Figure 6. Configuring Timer options.

Let's check some basics: When working with peripherals, there are three principal I/O techniques: programmed I/O, in which I/O occurs under the direct and continuous control of the program requesting the I/O operation; interrupt-driven I/O, in which a program issues an I/O command and then continues to execute, until it is interrupted by the I/O hardware to signal the end of the I/O operation; and direct memory access (DMA), in which a specialized I/O processor takes over control of an I/O operation to move a large block of data [1].
Our timer doesn't really need to transfer data, but still there are two possibilities; a programmed or polled driven timer or a interrupt-driven timer. We will work with interrupt since it's the main point of this lab.
The C code for this lab is provided. Note that there is nothing really new on it since it's based on the first lab. What's new is the interrupt routine and the steps required to habilitate the interrupts and configure the timer.
The steps to enable the interrupts are standard in the sense that they probably won't change in the context of another program. The last three steps; XExc_Init() to setup the interrupt vector table; XExc_RegisterHandler() to register an exception handler for a specific exception; and XExc_mEnableExceptions() to enable the interrupts are necessary and explained in Chapter 28 of the EDK Documentation: Stand-Alone Board Support Package. The header file xexception_l.h for the exception handling API can be find in /ppc405/code/include in your project directory after you compile the libraries.
The C code provide was built on the examples provided with the drivers. Take a look at \EDK\sw\iplib\drivers\ . You will find a directory for each core. Look at tmrctr_v1_00_b\examples for instance; here you will find examples for the timer core. As we discussed earlier, the timer can be used as a polled-driven peripheral or an interrupt-driven peripheral. There is also a xtmrctr_low_level_example to describe timer instructions when you work with level 0 drivers.
Let's go back to our code. Every line is documented and it keeps a very close relation with the examples provided with the drivers. The code will display a "hello world" type message in the hyperterminal and it will also display a warning each time an interrupt occurs. The timer is setup to start counting at 0x1000000 in a countdown direction til zero. At zero the counter will raise an interrupt and reset its count to 0x1000000 and so on.
Well, now lets compile our code and add it to the bitstream by going in XPS to Tools/ Compile Program Sources and Tools/Update Bitstream. Careful! Check that the size of your program doesn't exceed the amount of memory we programmed in our FPGA. Now use the same procedure as before to program the board.

Debugging the program

The program will work, but still, it's a good idea to take a look at what's happening in the processor when handling an interrupt. In XPS go to Tools/XMD to open XMD. A windows as shown in figure 7 will open up.

Figure 7. XMD window


Check the register of the timer and the interrupt controller just to see have what you put in C code has been reflected in the configuration of the peripherals:

% mrd 0x60008100 8

to read 8 memory positions from the base address of the timer, check the values of the register with the datasheet of the timer and verify it with the values you configure in the C code. Here are some question for you to think about: Is the timer running? Remember that the processor is stopped and waiting for your instructions. Has the timer an interrupt raised right now?

% mrd 0x6000A200 8

to read 8 memory positions from the base address of the interrupt controller. Here are some more questions: Has the interrupt controller pending interrupts to attend? Check the values in the registers and compare it with the datasheet to figure out what is happening with the interrupt controller.


Now go to Tools/Software Debugger in XPS. A window similar to figure 8 will open up.
Go to "Run/Connect to Target" to connect the debugger to the PowerPC405 processor.


Figure 8. Software debug window


Once you are connected, check the stack and local variables. Try to understand at what point on the program you are. Then go one step further in the program and check how the variables are changing and how the interrupt is handled. Here are some questions for you, when the interrupt happens, do you go directly to your timer interrupt handling routine? What's the first step in handling the interrupt?. The software debugger should help you to figure this out.

By now the project is running, our hyperterminal console should look as shown in figure 9.

Figure 9. Hyperterminal view of the project

Our first interrupt based project is up and running. We'll use this lab to build the next lab in the sequence, a little bit more complex.

References:

[1] Computer Organization & Architecture, Designing for Performance; Stallings, 6th edition.

Disclaimer:

This document, the contents and the sample code, is provided AS IS without any expressed or implied warranty. By providing this design, code, or information as one possible implementation of this feature, application or standard, we are not making representation that this implementation is free from any claims of infringement, and you are responsible for obtaining any rights you may require for your implementation.

 

 


alnz | UNM - XUP