1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
|
/*********************************************************************************
* Lattice Semiconductor Corp. Copyright 2000-2008
*
* This is the hardware.c of ispVME V12.1 for JTAG programmable devices.
* All the functions requiring customization are organized into this file for
* the convinience of porting.
*********************************************************************************/
/*********************************************************************************
* Revision History:
*
* 09/11/07 NN Type cast mismatch variables
* 09/24/07 NN Added calibration function.
* Calibration will help to determine the system clock frequency
* and the count value for one micro-second delay of the target
* specific hardware.
* Modified the ispVMDelay function
* Removed Delay Percent support
* Moved the sclock() function from ivm_core.c to hardware.c
*********************************************************************************/
//#include <conio.h>
//unsigned char NOP = 0;
//#include "opcode.h"
#include <DataDef.h>
#include "include.h"
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <Utilities/delay.h>
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/gpio.h"
#include "Drivers/FPGA/Full_Vme/FPGA_Programming_Up.h"
#include "vmopcode.h"
#include "Drivers/FPGA/Full_vme/FPGA_Programming_Up.h"
extern FPGA_JTAG_GPIO FPGA_JTAG;
/********************************************************************************
* Declaration of global variables
*
*********************************************************************************/
unsigned char g_siIspPins = 0x00; /*Keeper of JTAG pin state*/
unsigned short g_usInPort = 0x379; /*Address of the TDO pin*/
unsigned short g_usOutPort = 0x378; /*Address of TDI, TMS, TCK pin*/
unsigned short g_usCpu_Frequency = 1000; /*Enter your CPU frequency here, unit in MHz.*/
/*********************************************************************************
* This is the definition of the bit locations of each respective
* signal in the global variable g_siIspPins.
*
* NOTE: Users must add their own implementation here to define
* the bit location of the signal to target their hardware.
* The example below is for the Lattice download cable on
* on the parallel port.
*
*********************************************************************************/
const unsigned char g_ucPinTDI = 0x01; /* Bit address of TDI */
const unsigned char g_ucPinTCK = 0x02; /* Bit address of TCK */
const unsigned char g_ucPinTMS = 0x04; /* Bit address of TMS */
const unsigned char g_ucPinENABLE = 0x08; /* Bit address of ENABLE */
const unsigned char g_ucPinTRST = 0x10; /* Bit address of TRST */
const unsigned char g_ucPinTDO = 0x40; /* Bit address of TDO*/
/***************************************************************
*
* Functions declared in hardware.c module.
*
***************************************************************/
void writePort( unsigned char a_ucPins, unsigned char a_ucValue );
unsigned char readPort();
void sclock();
void ispVMDelay( unsigned short a_usTimeDelay );
unsigned char calibration(void);
/********************************************************************************
* writePort
* To apply the specified value to the pins indicated. This routine will
* be modified for specific systems.
* As an example, this code uses the IBM-PC standard Parallel port, along with the
* schematic shown in Lattice documentation, to apply the signals to the
* JTAG pins.
*
* PC Parallel port pin Signal name Port bit address
* 2 g_ucPinTDI 1
* 3 g_ucPinTCK 2
* 4 g_ucPinTMS 4
* 5 g_ucPinENABLE 8
* 6 g_ucPinTRST 16
* 10 g_ucPinTDO 64
*
* Parameters:
* - a_ucPins, which is actually a set of bit flags (defined above)
* that correspond to the bits of the data port. Each of the I/O port
* bits that drives an isp programming pin is assigned a flag
* (through a #define) corresponding to the signal it drives. To
* change the value of more than one pin at once, the flags are added
* together, much like file access flags are.
*
* The bit flags are only set if the pin is to be changed. Bits that
* do not have their flags set do not have their levels changed. The
* state of the port is always manintained in the static global
* variable g_siIspPins, so that each pin can be addressed individually
* without disturbing the others.
*
* - a_ucValue, which is either HIGH (0x01 ) or LOW (0x00 ). Only these two
* values are valid. Any non-zero number sets the pin(s) high.
*
*********************************************************************************/
void writePort( unsigned char a_ucPins, unsigned char a_ucValue )
{
GPIO Gpio;
switch(a_ucPins)
{
case pinTCK:
Gpio.Port = FPGA_JTAG.GPO_TCK.Port;
Gpio.Pin = FPGA_JTAG.GPO_TCK.Pin;
break;
case pinTDI:
Gpio.Port = FPGA_JTAG.GPO_TDI.Port;
Gpio.Pin = FPGA_JTAG.GPO_TDI.Pin;
break;
case pinTMS:
Gpio.Port = FPGA_JTAG.GPO_TMS.Port;
Gpio.Pin = FPGA_JTAG.GPO_TMS.Pin;
break;
case pinENABLE: //always enabled
case pinTRST: //N/A
default:
return;
}
if(a_ucValue)
ROM_GPIOPinWrite(Gpio.Port, Gpio.Pin, Gpio.Pin); //Turn ON the requested GPIO
else
ROM_GPIOPinWrite(Gpio.Port, Gpio.Pin, 0); //Turn OFF the requested GPIO
}
/*********************************************************************************
*
* readPort
*
* Returns the value of the TDO from the device.
*
**********************************************************************************/
unsigned char readPort()
{
unsigned char ucRet = 0x00;
if(ROM_GPIOPinRead(FPGA_JTAG.GPI_TDO.Port, FPGA_JTAG.GPI_TDO.Pin))
ucRet = 0x01;
return ( ucRet );
}
/*********************************************************************************
* sclock
*
* Apply a pulse to TCK.
*
* This function is located here so that users can modify to slow down TCK if
* it is too fast (> 25MHZ). Users can change the IdleTime assignment from 0 to
* 1, 2... to effectively slowing down TCK by half, quarter...
*
*********************************************************************************/
void sclock()
{
unsigned short IdleTime = 0; //change to > 0 if need to slow down TCK
unsigned short usIdleIndex = 0;
IdleTime++;
for ( usIdleIndex = 0; usIdleIndex < IdleTime; usIdleIndex++ ) {
writePort( g_ucPinTCK, 0x01 );
}
for ( usIdleIndex = 0; usIdleIndex < IdleTime; usIdleIndex++ ) {
writePort( g_ucPinTCK, 0x00 );
}
}
/********************************************************************************
*
* ispVMDelay
*
*
* Users must implement a delay to observe a_usTimeDelay, where
* bit 15 of the a_usTimeDelay defines the unit.
* 1 = milliseconds
* 0 = microseconds
* Example:
* a_usTimeDelay = 0x0001 = 1 microsecond delay.
* a_usTimeDelay = 0x8001 = 1 millisecond delay.
*
* This subroutine is called upon to provide a delay from 1 millisecond to a few
* hundreds milliseconds each time.
* It is understood that due to a_usTimeDelay is defined as unsigned short, a 16 bits
* integer, this function is restricted to produce a delay to 64000 micro-seconds
* or 32000 milli-second maximum. The VME file will never pass on to this function
* a delay time > those maximum number. If it needs more than those maximum, the VME
* file will launch the delay function several times to realize a larger delay time
* cummulatively.
* It is perfectly alright to provide a longer delay than required. It is not
* acceptable if the delay is shorter.
*
* Delay function example--using the machine clock signal of the native CPU------
* When porting ispVME to a native CPU environment, the speed of CPU or
* the system clock that drives the CPU is usually known.
* The speed or the time it takes for the native CPU to execute one for loop
* then can be calculated as follows:
* The for loop usually is compiled into the ASSEMBLY code as shown below:
* LOOP: DEC RA;
* JNZ LOOP;
* If each line of assembly code needs 4 machine cycles to execute,
* the total number of machine cycles to execute the loop is 2 x 4 = 8.
* Usually system clock = machine clock (the internal CPU clock).
* Note: Some CPU has a clock multiplier to double the system clock for
the machine clock.
*
* Let the machine clock frequency of the CPU be F, or 1 machine cycle = 1/F.
* The time it takes to execute one for loop = (1/F ) x 8.
* Or one micro-second = F(MHz)/8;
*
* Example: The CPU internal clock is set to 100Mhz, then one micro-second = 100/8 = 12
*
* The C code shown below can be used to create the milli-second accuracy.
* Users only need to enter the speed of the cpu.
*
**********************************************************************************/
void ispVMDelay( unsigned short a_usTimeDelay )
{
if ( a_usTimeDelay & 0x8000 ) //millisecond
{
a_usTimeDelay &= ~0x8000;
if ( a_usTimeDelay <= 0 )
{
a_usTimeDelay = 1; //delay is 1 millisecond minimum
}
delayms(a_usTimeDelay);
}
else
{
if ( a_usTimeDelay <= 0 )
{
a_usTimeDelay = 1; //delay is 1 microsecond minimum
}
delayUs(a_usTimeDelay);
}
}
/*********************************************************************************
*
* calibration
*
* It is important to confirm if the delay function is indeed providing
* the accuracy required. Also one other important parameter needed
* checking is the clock frequency.
* Calibration will help to determine the system clock frequency
* and the loop_per_micro value for one micro-second delay of the target
* specific hardware.
*
**********************************************************************************/
unsigned char calibration(void)
{
unsigned char temp = 0;
//Apply 2 pulses to TCK.
writePort( pinTCK, 0x00 );
writePort( pinTCK, 0x01 );
writePort( pinTCK, 0x00 );
writePort( pinTCK, 0x01 );
writePort( pinTCK, 0x00 );
//Delay for 1 millisecond. Pass on 1000 or 0x8001 both = 1ms delay.
ispVMDelay(1);
//Apply 2 pulses to TCK
writePort( pinTCK, 0x01 );
writePort( pinTCK, 0x00 );
writePort( pinTCK, 0x01 );
writePort( pinTCK, 0x00 );
//Test pinTDI pinTMS
writePort( pinTDI, 0x01 );
writePort( pinTMS, 0x01 );
writePort( pinTMS, 0x00 );
writePort( pinTDI, 0x00 );
writePort( pinTMS, 0x00 );
temp = readPort();
return temp;
}
|