847 lines
48 KiB
HTML
847 lines
48 KiB
HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
|
"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd">
|
|
<html lang="en">
|
|
<head>
|
|
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
|
|
<title>GPIF</title>
|
|
<meta name="generator" content="BBEdit 6.0">
|
|
<script language="JavaScript">
|
|
<!--
|
|
function na_preload_img()
|
|
{
|
|
var img_list = na_preload_img.arguments;
|
|
if (document.preloadlist == null)
|
|
document.preloadlist = new Array();
|
|
var top = document.preloadlist.length;
|
|
for (var i=0; i < img_list.length; i++) {
|
|
document.preloadlist[top+i] = new Image;
|
|
document.preloadlist[top+i].src = img_list[i+1];
|
|
}
|
|
}
|
|
|
|
function na_change_img_src(name, nsdoc, rpath, preload)
|
|
{
|
|
var img = eval((navigator.appName.indexOf('Netscape', 0) != -1) ? nsdoc+'.'+name : 'document.all.'+name);
|
|
if (name == '')
|
|
return;
|
|
if (img) {
|
|
img.altsrc = img.src;
|
|
img.src = rpath;
|
|
}
|
|
}
|
|
|
|
// -->
|
|
</script>
|
|
</head>
|
|
<body bgcolor="#FFFFFF" OnLoad="na_preload_img(false, 'images/cp-01.gif', 'images/cp-02.gif', 'images/cp-03.gif');">
|
|
|
|
|
|
<table border="0" cellpadding="0" cellspacing="0" width="90%" align="center">
|
|
<tr valign="top">
|
|
<td colspan="1" align="left" width="744">
|
|
|
|
<p align="center"><font face="verdana, arial, helvetica, sans-serif" size="2" color="#000000"><B><a name="SingleXactions"></a>Implementing Single Transactions</B></font>
|
|
</td>
|
|
</tr>
|
|
|
|
<tr valign="top">
|
|
<td colspan="1" align="left" width="744">
|
|
|
|
<p>
|
|
<font face="verdana, arial, helvetica, sans-serif" size="1" color="#000000">As previously mentioned, the simplest GPIF waveforms to produce are the single read and single
|
|
write waveforms. Performing this
|
|
function first not only enhances the initial user experience with the design, but also allows the design to be in fairly good shape, fairly quickly. Of
|
|
course, for high bandwidth applications the natural migration is then to create FIFO read and write transactions.
|
|
But, the implementation of single
|
|
transactions is the right place to start. The
|
|
first section discusses the single transaction waveforms implemented using GPIF Designer and the next section
|
|
covers the firmware that triggers them.<br>
|
|
|
|
</font><font face="Verdana,Arial" size="1" color="#000000"><br></font> <p align="center"><font face="Verdana" size="1"><img src="images/SingleBlkDiag.gif" width="432" height="327" border="0"> <br>Figure
|
|
12. GPIF Designer Block Diagram</font></p>
|
|
<p>
|
|
<font face="Verdana" size="1">The GPIF Designer makes creating GPIF waveform
|
|
descriptors easy. Rather than having to know each bit of the waveform
|
|
descriptor opcode bytes in detail to create a waveform, the GPIF
|
|
Designer allows you to “draw” each waveform and export the waveform
|
|
descriptors to a self-contained file, typically called gpif.c. When
|
|
you open GPIF Designer, it will present you with a block diagram
|
|
view of the physical interconnect as shown in <i>Figure 12</i>. You can
|
|
then use the block diagram view to name the individual</font><font face="Verdana,Arial" size="1" color="#000000">
|
|
</font><font face="Verdana" size="1">CTLx lines and
|
|
RDYn signals. These names propagate into the waveform tabs, allowing
|
|
you to personalize each waveform and determine which signals are
|
|
being manipulated. You can also use the block diagram to configure
|
|
the clock properties of IFCLK, select different package types, and
|
|
label the external slave device.<br><br><b><a name="WaveformDescriptors"></a></b>We
|
|
can see that the naming conventions are consistent with the hardware
|
|
set-up. The single write waveform (waveform 1) is shown below in
|
|
<i>Figure 13</i>.<br></font>
|
|
</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td colspan="1" align="center" height="387" width="744">
|
|
<p align="center"><font face="Verdana" size="1"><img src="images/singlewr.gif" width="432" height="327" border="0"><br> Figure
|
|
13. Single Write waveform in GPIF Designer<br></font></p>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="1" align="center" width="744">
|
|
<p align="left"><font face="Verdana" size="1">For the single write
|
|
waveform, data is written to the external FIFO in S0 by making CTL0
|
|
a logic LOW (WEN is asserted) and placing data on the bus (Activate
|
|
Data) for one IFCLK cycle (Wait 1). At 48 MHz, one IFCLK cycle is
|
|
20.83 ns. With the IFCLK output inverted, this provides enough set-up
|
|
and hold time for the data.</font></p>
|
|
<p align="left"><font face="Verdana" size="1">S1 is a decision-point
|
|
state that forces an unconditional branch to the IDLE state, which
|
|
terminates the waveform (no activity occurs in the IDLE state).
|
|
A decision point state allows you to pick, at most, two terms to
|
|
evaluate a logical expression. Based on the results of that evaluation,
|
|
you can control the next state the waveform goes to. See the FX2
|
|
Technical Reference Manual for more information on decision point
|
|
states. Also in S1, CTL0 is a logic HIGH (WEN is de-asserted), and
|
|
the data bus is tri-stated (De-activate Data).</font></p>
|
|
<p align="left"><font face="Verdana" size="1">Every time a single
|
|
write waveform is initiated, the GPIF engine will cycle through
|
|
S0, S1, and then IDLE (S7).<br><br>The single read waveform (waveform 0)
|
|
is very similar to the single write waveform. The single read waveform
|
|
is shown in <i>Figure 14</i>.<br></font></p>
|
|
<p align="left"><font face="Verdana" size="1"> </font></p>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="1" align="center" width="744">
|
|
<p align="center"><font face="Verdana" size="1"><img src="images/singlerd.gif" width="432" height="327" border="0"><br>Figure
|
|
14. Single Read waveform in GPIF Designer</font></p>
|
|
<p align="left"><font size="1" face="Verdana">For the single read
|
|
waveform, CTL1 starts off as a logic LOW in S0 (REN asserted) for
|
|
one IFCLK cycle. This is to account for a t ENS set-up time for
|
|
the external FIFO before OE (CTL2) is asserted. S1 then asserts
|
|
OE, and in S2 the data bus is sampled (Activate Data) and an unconditional
|
|
branch to the IDLE state is taken to terminate the waveform (no
|
|
activity occurs in the IDLE state).</font></p>
|
|
<p align="left"><font size="1" face="Verdana">Note that the data
|
|
bus is sampled in S2 when it would be tempting to sample it in S1.
|
|
At the beginning of S1, the data is not yet available from the external
|
|
FIFO, therefore the GPIF has to “catch” the data at the beginning
|
|
of S2. This is why the data bus is sampled in S2 instead of S1.</font></p>
|
|
<p align="left"><font size="1" face="Verdana">Every time a single
|
|
read waveform is initiated, the GPIF engine will cycle through S0,
|
|
S1, S2, and then IDLE (S7). Notice that waveforms 2 and 3 are unused
|
|
for the single transaction example, but will be used later for the
|
|
FIFO transaction example.<br></font></p>
|
|
<p align="left"><font size="1" face="Verdana"> </font></p>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="1" align="center" height="13" width="744">
|
|
<p align="left"><font face="Verdana" size="1"><b><a name="FW"></a>Single Transaction
|
|
Firmware</b></font></p>
|
|
</td>
|
|
</tr>
|
|
<tr valign="top">
|
|
<td colspan="1" align="left" width="744">
|
|
<p>
|
|
<font face="verdana, arial, helvetica, sans-serif" size="1" color="#000000">After the single transaction waveforms were implemented in the GPIF Designer, the next step was to integrate the USB portion of the
|
|
overlying firmware with the GPIF Designer output to perform write and read operations to and from the external FIFO. To do this a firmware frameworks project
|
|
was copied and the code that performed the external FIFO operations was added to the TD_Poll() function within FX2_extsyncfifo.c (note that periph.c was
|
|
renamed to something more meaningful here). Endpoint and GPIF register initialization is performed in the TD_Init() function, which is also within
|
|
FX2_extsyncfifo.c.<br><br><a name="Files"></a>When the user opens up the Keil uVision2 project for the FIFO example, the following should be the list of files shown in the Project Window: </font> </td>
|
|
</tr>
|
|
|
|
<tr valign="top">
|
|
<td colspan="1" align="center" width="744">
|
|
|
|
<font face="verdana, arial, helvetica, sans-serif" size="1" color="#000000">
|
|
<img src="images/keil.gif" width="253" height="140" align="center" border="0" ismap usemap="#keil_map"><br>
|
|
</font>
|
|
<ul>
|
|
<p align="left"><font face="verdana, arial, helvetica, sans-serif" size="1" color="#000000">The
|
|
contents of these files is as follows: <br>
|
|
</font></p>
|
|
</ul>
|
|
|
|
</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td colspan="1" align="center" height="15" width="744">
|
|
<ul>
|
|
<p align="left"><font face="Verdana" size="1"><b>fw.c</b><br>Firmware
|
|
frameworks which handles USB requests and calls the task dispatcher
|
|
TD_Poll(). </font></p>
|
|
</ul>
|
|
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="1" align="center" height="15" width="744">
|
|
<ul>
|
|
<p align="left"><font face="Verdana" size="1"><b>Ezusb.lib</b><br>Collection
|
|
of functions that handle suspend, resume, I2C operations, etc. </font></p>
|
|
</ul>
|
|
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="1" align="center" height="15" width="744">
|
|
<ul>
|
|
<p align="left"><font face="Verdana" size="1"><b>USBJmpTb.OBJ</b><br>Interrupt
|
|
vector jump table for USB (INT2) and GPIF/Slave FIFO (INT4)
|
|
interrupt sources. </font></p>
|
|
</ul>
|
|
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="1" align="center" height="15" width="744">
|
|
<ul>
|
|
<p align="left"><font face="Verdana" size="1"><b>dscr.a51</b><br>Device
|
|
descriptor tables for the FIFO example which report EP2OUT and
|
|
EP6IN as the available endpoints for the FX2 device. </font></p>
|
|
</ul>
|
|
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="1" align="center" height="15" width="744">
|
|
<ul>
|
|
<p align="left"><font face="Verdana" size="1"><b>FX2_to_extsyncFIFO.c</b><br>Main
|
|
user application code where TD_Poll() and TD_Init() can be found.
|
|
The user will mainly be modifying this particular file and will
|
|
not need to touch fw.c. </font></p>
|
|
</ul>
|
|
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="1" align="center" height="15" width="744">
|
|
<ul>
|
|
<p align="left"><font face="Verdana" size="1"><b>gpif.c</b><br>File
|
|
that contains the GPIF waveform descriptor tables that implement
|
|
the Single/FIFO GPIF transaction waveform behavior.<br> </font></p>
|
|
</ul>
|
|
|
|
</td>
|
|
</tr>
|
|
<tr valign="top">
|
|
<td colspan="1" align="left" width="744">
|
|
|
|
<ul>
|
|
<font face="verdana, arial, helvetica, sans-serif" size="1" color="#000000"><B><a name="TD_Init("></a>TD_Init( )</B>
|
|
</font>
|
|
</ul>
|
|
|
|
</td>
|
|
</tr>
|
|
|
|
<tr valign="top">
|
|
<td colspan="1" align="left" width="744">
|
|
<ul>
|
|
|
|
<p>
|
|
<font face="verdana, arial, helvetica, sans-serif" size="1" color="#000000">The first task at hand was to setup the endpoints appropriately for this example. The following code switches the CPU clock
|
|
speed to 48MHz (since at power-on default it is 12MHz), and sets up EP2 as an OUT endpoint, 4x buffered of size 512, and EP6 as an IN endpoint, also
|
|
4x buffered of size 512. This setup utilizes the maximum allotted 4KB FIFO space. It also sets up the FIFOs for manual mode, word wide operation and
|
|
goes through a FIFO reset and arming sequence to ensure that they are ready for data operations.<br>
|
|
</font>
|
|
</ul>
|
|
|
|
</td>
|
|
</tr>
|
|
|
|
<tr valign="top">
|
|
<td colspan="1" align="left" width="744">
|
|
<blockquote>
|
|
<ul>
|
|
<font face="verdana, arial, helvetica, sans-serif" size="1" color="#000000"><font color="#339933">// set the CPU clock to 48MHz</font><br>
|
|
CPUCS = ((CPUCS & ~bmCLKSPD) | bmCLKSPD1);<br>
|
|
<font color="#666666">SYNCDELAY</font>;<br>
|
|
<br>
|
|
EP2CFG = <font color="#0000CC">0xA0</font>; <font color="#339933">// EP2OUT, bulk, size 512, 4x buffered</font><br>
|
|
<font color="#666666">SYNCDELAY</font>;<br>
|
|
EP4CFG = <font color="#0000CC">0x00</font>; <font color="#339933">// EP4 not valid</font><br>
|
|
<font color="#666666">SYNCDELAY</font>;<br>
|
|
EP6CFG = <font color="#0000CC">0xE0</font>; <font color="#339933">// EP6IN, bulk, size 512, 4x buffered</font><br>
|
|
<font color="#666666">SYNCDELAY</font>;<br>
|
|
EP8CFG = <font color="#0000CC">0x00</font>; <font color="#339933">// EP8 not valid</font><br>
|
|
<font color="#666666">SYNCDELAY</font>;<br>
|
|
<br>
|
|
EP2FIFOCFG = <font color="#0000CC">0x01</font>; <font color="#339933">// manual mode, disable PKTEND zero length send, word ops</font><br>
|
|
<font color="#666666">SYNCDELAY</font>;<br>
|
|
EP6FIFOCFG = <font color="#0000CC">0x01</font>; <font color="#339933">// manual mode, disable PKTEND zero length send, word ops</font><br>
|
|
<font color="#666666">SYNCDELAY</font>;<br>
|
|
<br>
|
|
FIFORESET = <font color="#0000CC">0x80</font>; <font color="#339933">// set NAKALL bit to NAK all transfers from host</font><br>
|
|
<font color="#666666">SYNCDELAY</font>;<br>
|
|
FIFORESET = <font color="#0000CC">0x02</font>; <font color="#339933">// reset EP2 FIFO</font><br>
|
|
<font color="#666666">SYNCDELAY</font>;<br>
|
|
FIFORESET = <font color="#0000CC">0x06</font>; <font color="#339933">// reset EP6 FIFO</font><br>
|
|
<font color="#666666">SYNCDELAY</font>;<br>
|
|
FIFORESET = <font color="#0000CC">0x00</font>; <font color="#339933">// clear NAKALL bit to resume normal operation</font><br>
|
|
<font color="#666666">SYNCDELAY</font>;<br>
|
|
<br>
|
|
<font color="#339933">// out endpoints do not come up armed</font><br>
|
|
<font color="#339933">// since EP2OUT is quad buffered we must write dummy byte counts four times</font><br>
|
|
<br>
|
|
EP2BCL = <font color="#0000CC">0x80</font>; <font color="#339933">// arm EP2OUT by writing byte count w/skip.</font><br>
|
|
<font color="#666666">SYNCDELAY</font>;<br>
|
|
EP2BCL = <font color="#0000CC">0x80</font>;<br>
|
|
<font color="#666666">SYNCDELAY</font>;<br>
|
|
EP2BCL = <font color="#0000CC">0x80</font>;<br>
|
|
<font color="#666666">SYNCDELAY</font>;<br>
|
|
EP2BCL = <font color="#0000CC">0x80</font>;<br>
|
|
<font color="#666666">SYNCDELAY</font>;<br>
|
|
<br>
|
|
GpifInit (); <font color="#339933">// initialize GPIF registers</font><br>
|
|
<br></font>
|
|
</ul>
|
|
|
|
</blockquote>
|
|
</font>
|
|
</td>
|
|
</tr>
|
|
|
|
<tr valign="top">
|
|
<td colspan="1" align="left" width="744">
|
|
|
|
<ul>
|
|
<font face="verdana, arial, helvetica, sans-serif" size="1" color="#000000"><B><a name="IFCONFIG"></a>IFCONFIG Register</B><br>
|
|
|
|
</font>
|
|
</ul>
|
|
|
|
</td>
|
|
</tr>
|
|
|
|
<tr valign="top">
|
|
<td colspan="1" align="left" width="744">
|
|
<ul>
|
|
|
|
<p>
|
|
<font face="verdana, arial, helvetica, sans-serif" size="1" color="#000000">TD_Init then calls the function GPIFInit() that resides in gpif.c. GPIFInit() is where the loading of the GPIF waveform
|
|
descriptor table into on-chip memory takes place and other GPIF registers get setup. An important register, IFCONFIG, also gets setup here to define
|
|
how the physical interface operates. Table 2 goes through the reasoning behind the setup of the IFCONFIG register for this example.
|
|
Note that all these bit assignments were made, automatically
|
|
by GPIF Designer as a consequence of the Block Diagram configuration.<br><br>
|
|
</font>
|
|
</ul>
|
|
|
|
</td>
|
|
</tr>
|
|
|
|
<tr valign="top">
|
|
<td colspan="1" align="center" width="744">
|
|
<table align="center" border="1" cellspacing="0" width="90%" bordercolordark="white" bordercolorlight="black">
|
|
<tr>
|
|
<td width="38" height="15">
|
|
<p align="center"><font face="Verdana" size="1"><b>Bit
|
|
#</b></font></p>
|
|
</td>
|
|
<td width="79" height="15">
|
|
<p align="center"><font face="Verdana" size="1"><b>Bit
|
|
Label</b></font></p>
|
|
</td>
|
|
<td width="547" height="15">
|
|
<p align="center"><font face="Verdana" size="1"><b>Contents
|
|
/ Description</b></font></p>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td width="38" height="13">
|
|
<p align="center"><font face="Verdana" size="1">7</font></p>
|
|
</td>
|
|
<td width="79" height="13">
|
|
<p align="center"><font face="Verdana" size="1">IFCLKSRC</font></p>
|
|
</td>
|
|
<td width="547" height="13"> <p align="left"><font face="Verdana" size="1">Set
|
|
to 1 to run the GPIF using the internal clock source</font></p>
|
|
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td width="38">
|
|
<p align="center"><font face="Verdana" size="1">6</font></p>
|
|
</td>
|
|
<td width="79">
|
|
<p align="center"><font face="Verdana" size="1">3048MHz</font></p>
|
|
</td>
|
|
<td width="547">
|
|
<p><font face="Verdana" size="1">Set to 1 to run the
|
|
internal clock source for the GPIF at 48MHz.</font></p>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td width="38">
|
|
<p align="center"><font face="Verdana" size="1">5</font></p>
|
|
</td>
|
|
<td width="79">
|
|
<p align="center"><font face="Verdana" size="1">IFCLKOE</font></p>
|
|
</td>
|
|
<td width="547">
|
|
<p><font face="Verdana" size="1">Set to 1 to turn on
|
|
the IFCLK output to drive the WCLK and RCLK inputs of
|
|
the external FIFO.</font></p>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td width="38">
|
|
<p align="center"><font face="Verdana" size="1">4</font></p>
|
|
</td>
|
|
<td width="79">
|
|
<p align="center"><font face="Verdana" size="1">IFCLPOL</font></p>
|
|
</td>
|
|
<td width="547">
|
|
<p><font face="Verdana" size="1">Set to 1 to invert
|
|
the IFCLK output to the external FIFO. This allows enough
|
|
setup time for the external FIFO.</font></p>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td width="38">
|
|
<p align="center"><font face="Verdana" size="1">3</font></p>
|
|
</td>
|
|
<td width="79">
|
|
<p align="center"><font face="Verdana" size="1">ASYNC</font></p>
|
|
</td>
|
|
<td width="547">
|
|
<p><font face="Verdana" size="1">Set to 0 to operate
|
|
the GPIF at the highest rate (sync mode).</font></p>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td width="38">
|
|
<p align="center"><font face="Verdana" size="1">2</font></p>
|
|
</td>
|
|
<td width="79">
|
|
<p align="center"><font face="Verdana" size="1">GSTATE</font></p>
|
|
</td>
|
|
<td width="547">
|
|
<p><font face="Verdana" size="1">Set to 1 to turn on
|
|
the debug outputs of the state machine. PE[2:0] displays
|
|
the states the GPIF engine cycles through during each
|
|
transaction (Note: PE[2:0] are only available on the
|
|
100- and 128-pin packages).</font></p>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td width="38">
|
|
<p align="center"><font face="Verdana" size="1">1</font></p>
|
|
</td>
|
|
<td width="79">
|
|
<p align="center"><font face="Verdana" size="1">IFCFG1</font></p>
|
|
</td>
|
|
<td width="547">
|
|
<p><font face="Verdana" size="1">Set to 1 to put the
|
|
FX2 part into GPIF mode (internal master).</font></p>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td width="38">
|
|
<p align="center"><font face="Verdana" size="1">0</font></p>
|
|
</td>
|
|
<td width="79">
|
|
<p align="center"><font face="Verdana" size="1">IFCFG0</font></p>
|
|
</td>
|
|
<td width="547">
|
|
<p><font face="Verdana" size="1">Set to 0 to put
|
|
the FX2 part into GPIF mode (internal master).</font></p>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
<p><font face="verdana, arial, helvetica, sans-serif" size="1" color="#000000">Table 2. IFCONFIG register bit settings for FIFO example<br>
|
|
<br>
|
|
</font></p>
|
|
|
|
</td>
|
|
</tr>
|
|
|
|
<tr valign="top">
|
|
<td colspan="1" align="left" width="744">
|
|
<ul>
|
|
|
|
<p>
|
|
<font face="verdana, arial, helvetica, sans-serif" size="1" color="#000000">The next thing TD_Init() does is it resets the external FIFO by pulsing PA2. This ensures that the external FIFO is at a
|
|
ground-zero state before commencing data operations. The following code does the trick:<br>
|
|
|
|
</font>
|
|
</ul>
|
|
|
|
</td>
|
|
</tr>
|
|
|
|
<tr valign="top">
|
|
<td colspan="1" align="left" width="744">
|
|
|
|
<p>
|
|
<blockquote>
|
|
<ul>
|
|
<font face="verdana, arial, helvetica, sans-serif" size="1" color="#000000"><font color="#339933">// reset the external FIFO</font><br>
|
|
<br>
|
|
OEA |= <font color="#0000CC">0x04</font>; <font color="#339933">// turn on PA2 as output pin</font><br>
|
|
IOA |= <font color="#0000CC">0x04</font>; <font color="#339933">// pull PA2 high initially</font><br>
|
|
IOA &= <font color="#0000CC">0xFB</font>; <font color="#339933">// bring PA2 low</font><br>
|
|
<font color="#666666">EZUSB_Delay (<font color="#0000CC">1</font>)</font>; <font color="#339933">// keep PA2 low for ~1ms, more than enough time</font><br>
|
|
IOA |= <font color="#0000CC">0x04</font>; <font color="#339933">// bring PA2 high</font><br>
|
|
</font>
|
|
</ul>
|
|
|
|
</blockquote>
|
|
|
|
</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td colspan="1" align="center" height="15" width="744">
|
|
<ul>
|
|
|
|
<p align="left">
|
|
<font face="verdana, arial, helvetica, sans-serif" size="1" color="#000000">A vendor command was also setup in the DR_VendorCmnd() function so that the user could reset the external FIFO at any time by
|
|
performing a vendor request of 0xB2 from the EZ-USB Control Panel. </font>
|
|
</ul>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="1" align="center" height="15" width="744">
|
|
|
|
<ul>
|
|
<p align="left"><font face="verdana, arial, helvetica, sans-serif" size="1" color="#000000"><B><a name="Triggering"></a>Triggering GPIF Single Transactions</B><br></font>
|
|
</ul>
|
|
</td>
|
|
</tr>
|
|
<tr valign="top">
|
|
<td colspan="1" align="left" width="744">
|
|
<ul>
|
|
|
|
<p>
|
|
<font face="verdana, arial, helvetica, sans-serif" size="1" color="#000000">In order for the data transfers to occur across the physical interface, the CPU needs to trigger the GPIF waveforms by accessing
|
|
the registers XGPIFSGLDATH, XGPIFSGLDATLX, and XGPIFSGLDATLNOX.<br><br> In order to trigger a GPIF Single Word Write transaction, the user writes to the XGPIFSGLDATAH< and XGPIFSGLDATLX in the following manner:<br><br>
|
|
XGPIFSGLDATH = <font color="#999999"><</font>word_value<font color="#999999">></font> >> <font color="#0000CC">8</font>;<br>
|
|
XGPIFSGLDATLX = <font color="#999999"><</font>word_value<font color="#999999">></font> <font color="#339933">// trigger GPIF<br><br></font>This effectively setups the MSB and LSB of the word value to be transferred, and the sheer act of writing to the XGPIFSGLDATLX register fires
|
|
off the Single Word Write transaction. To make things a little neater to follow in TD_Poll(), the following function was defined which basically
|
|
accepts a word value as an input argument and performs the GPIF Single Word Write transaction:<br></font>
|
|
<ul>
|
|
<p> <font face="verdana, arial, helvetica, sans-serif" size="1" color="#000000"><font color="#339933">// reset the external FIFO</font><br>
|
|
<font color="#990000">void</font> GPIF_SingleWordWrite( WORD gdata )<br>
|
|
{<br>
|
|
<font color="#990000">while</font>( !( GPIFTRIG & <font color="#0000CC">0x80</font> ) ) <font color="#339933">// poll GPIFTRIG.7 Done bit</font><br>
|
|
{<br>
|
|
;<br>
|
|
}<br>
|
|
|
|
<font color="#339933">// using registers in XDATA space</font><br>
|
|
XGPIFSGLDATH = gdata;<br>
|
|
XGPIFSGLDATLX = gdata >> <font color="#0000CC">8</font>; <font color="#339933">// trigger GPIF Single Word Write transaction</font><br>
|
|
}</font></p>
|
|
</ul>
|
|
<p><font face="verdana, arial, helvetica, sans-serif" size="1" color="#000000">This function also checks to see if the GPIF is in the IDLE state (GPIFTRIG.7 is set if GPIF is IDLE) before it launches the transaction. This is
|
|
something that is necessary before launching any GPIF transaction. Note that the access to the single transaction registers is swapped here because
|
|
the endpoint buffer is organized as a FIFO. The swapping ensures that the first byte in the endpoint buffer is written out FD[7:0], and the second
|
|
byte is written out FD[15:8].<br>
|
|
<br>
|
|
In order to trigger a GPIF Single Word Read transaction, the user performs a dummy read from the XGPIFSGLDATX register. The word value just read will
|
|
be contained in the registers XGPIFSGLDATH and XGPIFSGLDATLNOX. <br><br>To make things a little neater to follow in TD_Poll(), the following function was defined which basically accepts a word pointer for the
|
|
destination variable as an input argument and performs the GPIF Single Word Read transaction:</font></p>
|
|
<ul>
|
|
<p><font face="verdana, arial, helvetica, sans-serif" size="1" color="#000000"><font color="#990000">void</font> GPIF_SingleWordRead( WORD xdata *gdata )<br>
|
|
{<br>
|
|
<font color="#990000">static</font> BYTE g_data = <font color="#0000CC">0x00</font>; <font color="#339933">// dummy variable</font><br>
|
|
<br>
|
|
<font color="#990000">while</font>( !( GPIFTRIG & <font color="#0000CC">0x80</font> ) ) <font color="#339933">// poll GPIFTRIG.7 Done bit</font><br>
|
|
{<br>
|
|
;<br>
|
|
}<br>
|
|
<br>
|
|
<font color="#339933">// using register in XDATA space</font><br>
|
|
g_data = XGPIFSGLDATLX; <font color="#339933">// dummy read to trigger GPIF Single Word Read transaction</font><br>
|
|
<br>
|
|
<font color="#990000">while</font>( !( GPIFTRIG & <font color="#0000CC">0x80</font> ) ) <font color="#339933">// poll GPIFTRIG.7 Done bit</font><br>
|
|
{<br>
|
|
;<br>
|
|
}<br>
|
|
<br>
|
|
<font color="#339933">// using register(s) in XDATA space, retrieve word just read from external FIFO</font><br>
|
|
*gdata = ( ( WORD )XGPIFSGLDATLNOX << <font color="#0000CC">8</font> ) | ( WORD )XGPIFSGLDATH;<br>
|
|
}</font></p>
|
|
</ul>
|
|
<p><font face="verdana, arial, helvetica, sans-serif" size="1" color="#000000">This function first checks to see if the GPIF is IDLE and then performs a dummy read from XGPIFSGLDATLX to fire off the GPIF Single Word Read
|
|
transaction. Then, another check is performed before accessing the registers that contain the word value.<br>
|
|
<font color="#339933"> </font></font></p>
|
|
|
|
</ul>
|
|
|
|
</td>
|
|
</tr>
|
|
|
|
<tr valign="top">
|
|
<td colspan="1" align="left" width="744">
|
|
|
|
<p>
|
|
|
|
<ul>
|
|
<font face="verdana, arial, helvetica, sans-serif" size="1" color="#000000"><B><a name="TD_Poll()"></a>TD_Poll()</B><br>
|
|
</font>
|
|
</ul>
|
|
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="1" align="center" height="15" width="744">
|
|
<ul>
|
|
|
|
<p align="left">
|
|
<font face="verdana, arial, helvetica, sans-serif" size="1" color="#000000">The TD_Poll() function is where the main application code resides. The firmware here calls the functions GPIF_SingleWordWrite() and
|
|
GPIF_SingleWordRead to send and receive data from EP2OUT and EP6IN, respectively.<br><br>Code that handles USB OUT transfers</font>
|
|
<ul>
|
|
<p align="left"><font face="verdana, arial, helvetica, sans-serif" size="1" color="#000000"><font color="#990000">if</font>(!(EP2468STAT & bmEP2EMPTY) && (EXTFIFONOTFULL))<br>
|
|
{<br>
|
|
<font color="#339933">// if host sent data to EP2OUT AND external FIFO is not full</font><br>
|
|
<br>
|
|
Tcount = (EP2BCH << <font color="#0000CC">8</font>) + EP2BCL; <font color="#339933">// load transaction count with EP2 byte count</font><br>
|
|
Tcount /= <font color="#0000CC">2</font>; <font color="#339933">// divide by 2 for word wide transaction</font><br>
|
|
Source = (WORD *)(&EP2FIFOBUF);<br>
|
|
<font color="#990000">for</font>( i = <font color="#0000CC">0x0000</font>; i < Tcount; i++ )<br>
|
|
{<br>
|
|
<font color="#339933">// transfer data from EP2OUT buffer to external FIFO</font><br>
|
|
GPIF_SingleWordWrite (*Source);<br>
|
|
Source++;<br>
|
|
}<br>
|
|
EP2BCL = <font color="#0000CC">0x80</font>; <font color="#339933">// re-arm EP2OUT</font><br>
|
|
}</font></p>
|
|
</ul>
|
|
<p align="left"><font face="verdana, arial, helvetica, sans-serif" size="1" color="#000000">The first thing the OUT handling code does is it checks to see if the host sent data to EP2OUT, and if the external FIFO is not full by accessing the
|
|
GPIFREADYSTAT register (EXTFIFONOTEMPTY is a macro for GPIFREADYSTAT & bmBIT0).<br><br>If both conditions are met, the word variable Tcount is setup appropriately. Since each GPIF Single Word Write transaction sends an entire word to
|
|
the external FIFO, the number of transactions is always half the number of bytes actually contained within the endpoint buffer.<br><br>A for loop then calls the GPIF_SingleWordWrite function and indexes through the endpoint buffer values, sending a word out to the external FIFO
|
|
at a time. The last step then is to re-arm the endpoint buffer so that the next USB data packet can be accepted</font><font face="Verdana" size="1">.</font></p>
|
|
|
|
<p align="left">
|
|
<font face="verdana, arial, helvetica, sans-serif" size="1" color="#000000">Code that handles USB IN transfers </font>
|
|
<ul>
|
|
|
|
|
|
<p align="left"><font face="verdana, arial, helvetica, sans-serif" size="1" color="#000000"><font color="#990000">if</font>(in_enable) <font color="#339933">// if IN transfers are enabled</font><br>
|
|
{<br>
|
|
<font color="#990000">if</font>(!(EP2468STAT & bmEP6FULL) && (EXTFIFONOTEMPTY))<br>
|
|
{<br>
|
|
<font color="#339933">// if EP6IN is not full AND there is data in the external FIFO</font><br>
|
|
<br>
|
|
Destination = (WORD *)(&EP6FIFOBUF);<br>
|
|
<font color="#990000">for</font>( i = <font color="#0000CC">0x0000</font>; i < Tcount; i++ )<br>
|
|
{<br>
|
|
<font color="#339933">// transfer data from external FIFO to EP6IN buffer</font><br>
|
|
GPIF_SingleWordRead (Destination);<br>
|
|
Destination++;<br>
|
|
}<br>
|
|
Tcount *= <font color="#0000CC">2</font>; <font color="#339933">// multiply by 2 to obtain byte count value</font><br>
|
|
EP6BCH = MSB(Tcount);<br>
|
|
<font color="#666666">SYNCDELAY</font>;<br>
|
|
EP6BCL = LSB(Tcount); <font color="#339933">// arm EP6IN to send data to the host</font><br>
|
|
<font color="#666666">SYNCDELAY</font>;<br>
|
|
}<br>
|
|
}</font>
|
|
</ul>
|
|
<p align="left"><font face="verdana, arial, helvetica, sans-serif" size="1" color="#000000">Another vendor command (0xB3) is setup to enable the IN transfers to occur. Otherwise, the code will just sit there and not process the INs. The
|
|
reason for the in_enable flag is so that the user can test each read and write operation independently. Otherwise, after the OUT handling code, the
|
|
IN is processed immediately. This is also useful for debugging purposes with the logic analyzer. It allows the user to capture each read/write
|
|
operation relatively easily.<br><br>If the in_enable flag is set, the code will fall through and check if the EP6IN endpoint buffer is not full, and if the external FIFO is not empty
|
|
(The CPU can check the status of the RDY signals by accessing the GPIFREADYSTAT register, so EXTFIFONOTEMPTY is a macro for GPIFREADYSTAT & bmBIT1).<br><br>If both conditions are met, a for loop then calls the GPIF_SingleWordRead function and indexes through the endpoint buffer values, receiving a word from
|
|
the external FIFO at a time. The last step then is to re-arm the endpoint buffer so that the next USB data packet can be accepted. Since each GPIF
|
|
Single Word Read transaction receives an entire word from the external FIFO, the number of transactions is always half the number of bytes actually
|
|
contained within the endpoint buffer.<br><br> </font></p>
|
|
|
|
</ul>
|
|
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="1" align="center" height="15" width="744">
|
|
|
|
<p align="left"><font face="verdana, arial, helvetica, sans-serif" size="1" color="#000000"><B><a name="Running"></a>Running the example for GPIF Single Transactions<br> </B></font> </td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="1" align="center" height="15" width="744">
|
|
|
|
<p align="left">
|
|
<font face="verdana, arial, helvetica, sans-serif" size="1" color="#000000">Now that the user understands how this FIFO example works, the bulk loop back function can be exercised by performing the steps discussed in this section.<br><br>Step 1: Download the firmware using the EZ-USB Control Panel</font>
|
|
<ul>
|
|
<p align="left"><font face="verdana, arial, helvetica, sans-serif" size="1" color="#000000">a)
|
|
Unzip the "FX2_extsyncFIFO GPIF Single Transactions.zip" package in the C:\Cypress\Usb\Examples\FX2 directory.<br></font></p>
|
|
<p align="left"><font face="verdana, arial, helvetica, sans-serif" size="1" color="#000000">b)
|
|
After the user plugs-in the FX2 board, launch the EZ-USB Control Panel and ensure that the selected target is FX2.<br></font></p>
|
|
<p align="left"><font face="verdana, arial, helvetica, sans-serif" size="1" color="#000000">c)
|
|
Then, press the "Download" button and select the FX2_extsyncFIFO.hex file. The FX2 board renumerates as a Cypress EZ-USB Sample Device and LED0 should come up flashing.<br></font></p>
|
|
<p align="left"><font face="verdana, arial, helvetica, sans-serif" size="1" color="#000000">d)
|
|
Perform a "Get Pipes" and "Get Dev" to verify one more time that the firmware is up and running. The user should then see the following screen shown below:</font></p>
|
|
</ul>
|
|
|
|
|
|
<ul>
|
|
<p align="left"><A onClick="na_change_img_src('image2', 'document', 'images/cp-01.gif', true);"><img src="images/cp-01.gif" width="488" height="400" align="center" border="0" name="image2"></A> </ul>
|
|
|
|
|
|
<p><font face="verdana, arial, helvetica, sans-serif" size="1" color="#000000"><br> </font></p>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="1" align="center" height="15" width="744">
|
|
|
|
<p align="left">
|
|
<font face="verdana, arial, helvetica, sans-serif" size="1" color="#000000"><a name="Step2"></a>Step 2: Setup bulk IN transfer and send 512 bytes to the external FIFO<br></font>
|
|
<ul>
|
|
<p align="left"><font face="verdana, arial, helvetica, sans-serif" size="1" color="#000000">a)
|
|
On the same line as the "BulkTrans" button, select Endpoint 6 IN as the "Pipe" and specify a "Length" of 512 bytes. Then click the
|
|
"BulkTrans" button. This will setup a bulk IN transfer of 512 bytes to read that amount from the external FIFO. Select View -> Pending Ops to
|
|
see the pending bulk IN transfer.<br></font></p>
|
|
<p align="left"><font face="verdana, arial, helvetica, sans-serif" size="1" color="#000000">b)
|
|
On the same line as the "FileTrans.." button, select Endpoint 2 OUT as the "Pipe". Press the "FileTrans.." button and select the 512_count.hex
|
|
file. Click on "Open" and this action will send out 512 bytes out to the external FIFO (the data stream is a ramp). <br></font></p>
|
|
<p align="left"><font face="verdana, arial, helvetica, sans-serif" size="1" color="#000000">c)
|
|
Even though 512 bytes have been written into the external FIFO the IN transfer is not processed. This is because the in_enable flag in the firmware has not yet been set to TRUE.<br></font></p>
|
|
</ul>
|
|
|
|
|
|
<ul>
|
|
<p align="left"><A onClick="na_change_img_src('image1', 'document', 'images/cp-02.gif', true);"><font face="verdana, arial, helvetica, sans-serif" size="1" color="#000000"><img src="images/cp-02.gif" width="441" height="400" align="center" border="0" name="image1"></font></A> </ul>
|
|
|
|
|
|
<p> </p>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="1" align="center" height="15" width="744">
|
|
|
|
<p align="left">
|
|
<font face="verdana, arial, helvetica, sans-serif" size="1" color="#000000"><a name="Step3"></a>Step 3: Complete IN transfer to read back 512 bytes from the external FIFO<br>
|
|
<br>
|
|
In order to complete the pending IN transfer and read back 512 bytes from the external FIFO, the in_enable flag must be set to TRUE (remember that
|
|
this allows the INs to be processed in the TD_Poll routine). To set the flag, on the same line as the "Vend Req" button, enter a value of 0xb3 in the
|
|
"Req" field. Then click the "Vend Req" button. The user should now see the 512 bytes read back from the external FIFO displayed in the window.<br></font>
|
|
<ul>
|
|
|
|
<p align="left"><A onClick="na_change_img_src('image3', 'document', 'images/cp-03.gif', true);"><img src="images/cp-03.gif" width="449" height="400" border="0" name="image3"></A></p>
|
|
</ul>
|
|
<p align="center"> </p>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="1" align="center" height="15" width="744">
|
|
|
|
<p align="left">
|
|
<font face="verdana, arial, helvetica, sans-serif" size="1" color="#000000">The bulk loop back function can also be exercised by running the bulkloop.exe utility supplied with the EZ-USB development kit software. After
|
|
downloading the firmware, launch the bulkloop.exe utility found in the C:\Cypress\Usb\Bin sub-directory. The user should setup the parameters
|
|
according to the following screen:</font>
|
|
<p align="left"><img src="images/bulkexe.gif" width="544" height="361" border="0"></p>
|
|
|
|
<p align="left">
|
|
<font face="verdana, arial, helvetica, sans-serif" size="1" color="#000000">Prior to clicking the "Start" button to commence the bulk loop back transfers, the user should perform the 0xb3 vendor request to set the in_enable flag
|
|
to TRUE. By clicking the "Start" button, the user should see the "Pass" counter increment as each loop back transfer is exercised. Clicking on the "Stop"
|
|
button will end the loop back transfers. The data values are also checked by the bulkloop utility on each pass, so the user should see the "Error" count
|
|
increment if any data value does not match. The application will also stop on any error if the "Stop on Error" checkbox is selected.<br>
|
|
<br>
|
|
|
|
<font face="verdana, arial, helvetica, sans-serif" size="1" color="#666666"><b>Debug Tip: </b><br>
|
|
While running this example and at any time during GPIF development, the user is strongly encouraged to connect a logic analyzer to the relevant signals
|
|
on the development kit headers. Monitoring the GPIF bus transactions aids debug sessions tremendously, and is essential for anyone seriously interested
|
|
in writing GPIF firmware. The next topic presents the waveforms the user should see on the logic analyzer as the example is run. An HP1660C Logic
|
|
Analyzer was used to capture the waveforms.<br></font></font>
|
|
<p align="left"><font face="verdana, arial, helvetica, sans-serif" size="1" color="#000000"><font face="verdana, arial, helvetica, sans-serif" size="1" color="#666666"> </font></font></p>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="1" align="center" height="15" width="744">
|
|
|
|
<p align="left"><font face="verdana, arial, helvetica, sans-serif" size="1" color="#000000"><B><a name="AnalyzerWaves"></a>Logic Analyzer Waveforms<br> </B></font> </td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="1" align="center" height="15" width="744">
|
|
|
|
<ul>
|
|
<p align="left"><font face="verdana, arial, helvetica, sans-serif" size="1" color="#000000"><B><a name="SingleWr"></a>Single Write Waveform<br></B></font>
|
|
<ul>
|
|
<p align="left"><font face="verdana, arial, helvetica, sans-serif" size="1" color="#000000"><img name="law" src="images/sWrite.gif" width="432" height="290" align="center" border="0"></font> </p>
|
|
</ul>
|
|
|
|
</ul>
|
|
<ul>
|
|
|
|
<p align="left">
|
|
<font face="verdana, arial, helvetica, sans-serif" size="1" color="#000000">The waveform above shows the timing generated by the GPIF engine for the Single Write waveform as defined by the GPIF tool. All the essential signals
|
|
are presented here, including GSTATE[2:0], which displays the states the GPIF engine cycles through as it performs the Single Write transaction.<br><br></font><font face="verdana, arial, helvetica, sans-serif" size="1" color="#666666"><b>Debug Tip: </b><br>
|
|
<br>
|
|
Bringing out the GSTATE signals to the logic analyzer headers allows the user to correlate between the waveforms generated by the GPIF tool, and
|
|
the actual waveforms generated on the physical interface. This also aids the debugging process because the user can see the immediate effect of
|
|
changing the waveform behavior in the GPIF tool</font><font face="verdana, arial, helvetica, sans-serif" size="1" color="#000000">.</font><font face="verdana, arial, helvetica, sans-serif" size="1" color="#666666"><br><br></font><font face="verdana, arial, helvetica, sans-serif" size="1" color="#000000">As expected from the GPIF tool output, S0 places the data on the bus (PORTB is FD[7:0] and PORTD is FD[15:8]), and asserts CTL0 (connected to the
|
|
external FIFO's WEN/ line). This effectively writes the 16-bit data value into the external FIFO. Note here that enough data setup time to the
|
|
rising edge of IFCLK is provided, since the minimum data setup time for the external FIFO is 4 ns (see CY4265 datasheet). S1 is a decision point
|
|
state that unconditionally branches to the IDLE state to terminate the transaction. Without the unconditional branch, the GPIF engine would
|
|
sequentially move through the remaining states until the IDLE state (S7) is reached. <br>
|
|
<br>
|
|
For every word written out in a bulk OUT transfer, the user should see the GPIF engine cycle through S0, S1, and S7. To capture the waveform, the
|
|
user should trigger the logic analyzer on the falling edge of CTL0. A sampling rate of 4 ns will give the user the same resolution shown in the
|
|
waveform above.<br>
|
|
</font><font face="verdana, arial, helvetica, sans-serif" size="1" color="#666666"> </font>
|
|
</ul>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="1" align="center" height="15" width="744">
|
|
|
|
<ul>
|
|
<p align="left"><font face="verdana, arial, helvetica, sans-serif" size="1" color="#000000"><B><a name="SingleRd"></a>Single Read Waveform<br><br> </B></font>
|
|
<ul>
|
|
<p align="left"><font face="verdana, arial, helvetica, sans-serif" size="1" color="#000000"><img name="law" src="images/sRead.gif" width="432" height="290" align="center" border="0"><B> <br></B></font>
|
|
</ul>
|
|
<p align="left">
|
|
<font face="verdana, arial, helvetica, sans-serif" size="1" color="#000000">The waveform above shows the timing generated by the GPIF engine for the Single Read waveform as defined by the GPIF tool. All the essential signals
|
|
are presented here, including GSTATE[2:0], which displays the states the GPIF engine cycles through as it performs the Single Read transaction<B>.</B><br><br>As expected from the GPIF tool output, S0 asserts CTL1 (connected to the external FIFO's REN/ line), S1 asserts CTL2 (connected to the external
|
|
FIFO's OE/ line), and S2 samples the data bus (PORTB is FD[7:0] and PORTD is FD[15:8]). This effectively reads the 16-bit data value into the
|
|
external FIFO. Note here that enough data setup time to the rising edge of IFCLK is provided, since the minimum data setup time for the external
|
|
FIFO is 4 ns (see CY4265 datasheet). S2 is a decision point state that unconditionally branches to the IDLE state to terminate the transaction.
|
|
Without the unconditional branch, the GPIF engine would sequentially move through the remaining states until the IDLE state (S7) is reached. <br>
|
|
<br>
|
|
For every word read out from the external FIFO in a bulk IN transfer, the user should see the GPIF engine cycle through S0, S1, S2, and S7. To
|
|
capture the waveform, the user should trigger the logic analyzer on the falling edge of CTL1. A sampling rate of 4 ns will give the user the same
|
|
resolution shown in the waveform above.<br>
|
|
</font>
|
|
</ul>
|
|
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="1" align="center" height="15" width="744">
|
|
<p> </p>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="1" align="center" height="15" width="744">
|
|
<p> </p>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="1" align="center" height="15" width="744">
|
|
<p> </p>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="1" align="center" height="15" width="744">
|
|
<p> </p>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="1" align="center" height="15" width="744">
|
|
<p> </p>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="1" align="center" height="15" width="744">
|
|
<p> </p>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
|
|
</font>
|
|
</body>
|
|
</html>
|