📄 hardware.c
字号:
/****************************************************************************
hardware.c for ispVME(tm) (ispVM(tm) Embedded)
Lattice Semiconductor Corp. Copyright 1998-2001.
When compiling it on MICROSOFT, the _inp() and _outp() parallel port
accessing functions are removed from the stdlib on VISUAL C++ compiler,
the library winmm.lib must be added to the library path for the program
to be compiled successfully. The winmm.lib can be added by:
Project->Settings->Link->Project Options:
type in winmm.lib
Even if this module is compiled successfully but it won't run on
Windows NT/2000/XP for those O/S no longer support _inp and _outp
functions. A device driver is required to access the parallel port.
When installing Lattice's ispVM System, the driver is also installed
on the PC if the O/S require a driver. In that case, a compiled
ispVME which can run on Windows NT/2000/XP can be requested from
Lattice.
This module function as a driver to covert commands and data into
electrical logic signals to program and verify the targeted In-System
Programming devices. The functional blocks:
ReadPort: Read a byte of data from the input port.
WritePort: Write a byte of data to the output port.
ispVMDelay: Wait for the specified mini-second or micro-second.
sclock: Toggle the TCK signal once.
ispVMClock: Toggle TCK signal the number of times as specified.
ispVMRead: Read number of bytes from the input port as
specified.
ispVMSend: Send the number of bytes to the output port as
specified.
ispVMStateMachine: Toggle TMS and TCK to step the BSCAN state machine
of the targeted devices to the JTAG state as
specified.
ispVMBypass: Put other devices in the daisy chain into bypass
mode.
ispVMStart: Connect the devices to the port and set JTAG state
machine of devices from unknown state to Test/Logic
Reset state.
ispVMEnd: Set JTAG state machine devices to Test/Logic Reset
state to put all devices into functional mode and
disconnect the devices from the port.
ispVMReadandSave: Support dynamic I/O.
ispVME for embedded applications where resources is a premium.
This is the scaled down version of the full ispVM target for embedded
applications. The total code size of this VM is less than 8K bytes.
Huffman encoding is used to minimize the Virtual Machine Format file size
without increasing the VM footprint and addtional RAM for decompression
is not required.
Typically only 100 bytes of RAM is required to hold one row of data when
processing the VMF file. The VM itself also need less than 100 bytes of
RAM to hold all the variables it needs.
Under no circumstances will it require more than 8000 bytes of RAM to
process a file. This maximum cap is achieved by splitting any SDR
constructs larger than 64000 bits in size into multiple SDR constructs
by the SVF2VME utility. The maximum cap can be easily reduced further by
modifying the SVF2VME utility to split the SDR constructs at smaller
blocks.
8.000 Howard Tang 3/6/00 convert form ispCODE7.c
9.000 Howard Tang 4/26/01 Add support to Header construct
HIR 32 TDI (00000000);
TIR 32 TDI (00000000);
HDR 32 TDI (00000000);
TDR 32 TDI (00000000);
for multiple devices in a single SVF
support.
v10.0 tnt 3/25/02 ispVMBypass function no longer issues SHIFTIR/SHIFTDR
and IRPAUSE/DRPAUSE to the state machine
1/15/04 Clock in last bit if cascade flag has been set.
**************************************************************************/
#include <stdio.h>
#include <windows.h>
#include <conio.h>
#include "hardware.h"
#include "vmedefinitions.h"
#include <time.h>
unsigned short siIspPins = 0x00; /*hold the current byte at OutPort*/
char cCurrentJTAGState = 0; /*hold the current state of JTAG state machine*/
extern unsigned char * OutMaskData, /*local RAM hold one row of MASK data*/
* InData, /*local RAM hold one row of TDI data*/
* OutData, /*local RAM hold one row of TDO data*/
* HIRData, /*local RAM hold SIR header*/
* TIRData, /*local RAM hold SIR trailer*/
* HDRData, /*local RAM hold SDR header*/
* TDRData, /*local RAM hold SDR trailer*/
* OutDMaskData; /*local RAM hold one row of DMASK data*/
extern unsigned short InPort;
extern unsigned short OutPort;
extern unsigned short Frequency;
extern unsigned short usFlowControl;
extern unsigned short usDataType;
extern unsigned short delayPercent;
/* JTAG state machine transistion tragetory table */
const struct iState {
unsigned char CurState; /* From this state */
unsigned char NextState; /* Step to this state */
unsigned char Pattern; /* The tragetory of TMS */
unsigned char Pulses; /* The number of steps */
} iStates[ 20 ] = {
{ RESET, RESET, 0xFC, 6 }, /* Transitions from RESET */
{ RESET, IDLE, 0x00, 1 },
{ RESET, DRPAUSE, 0x50, 5 },
{ RESET, IRPAUSE, 0x68, 6 },
{ IDLE, RESET, 0xE0, 3 }, /* Transitions from IDLE */
{ IDLE, DRPAUSE, 0xA0, 4 },
{ IDLE, IRPAUSE, 0xD0, 5 },
{ DRPAUSE, RESET, 0xF8, 5 }, /* Transitions from DRPAUSE */
{ DRPAUSE, IDLE, 0xC0, 3 },
{ DRPAUSE, IRPAUSE, 0xF4, 7 },
{ IRPAUSE, RESET, 0xF8, 5 }, /* Transitions from IRPAUSE */
{ IRPAUSE, IDLE, 0xC0, 3 },
{ IRPAUSE, DRPAUSE, 0xE8, 6 },
{ DRPAUSE, SHIFTDR, 0x80, 2 }, /* Extra transitions using SHIFTDR */
{ IRPAUSE, SHIFTDR, 0xE0, 5 },
{ SHIFTDR, DRPAUSE, 0x80, 2 },
{ SHIFTDR, IDLE, 0xC0, 3 },
{ IRPAUSE, SHIFTIR, 0x80, 2 }, /* Extra transitions using SHIFTIR */
{ SHIFTIR, IRPAUSE, 0x80, 2 },
{ SHIFTIR, IDLE, 0xC0, 3 }
};
/****************************************************************************
Function: writePort(unsigned char ucPins, unsigned char value)
Purpose:
To apply the specified value to the pins indicated. This routine will
likely be modified for specific systems. As an example, this code
is for the PC, as described below.
This routine uses the IBM-PC standard Parallel port, along with the
schematic shown in Lattice documentation, to apply the signals to the
programming loop.
PC Parallel port pin Signal name Port bit address
-------------------- ----------- ------------------
2 pinTDI 1
3 pinTCK 2
4 pinTMS 4
5 pinENABLE 8
6 pinTRST 16
7 pinCE 32
10 pinTDO 64
20 GND
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 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.
Returns: nothing.
*****************************************************************************/
void writePort( unsigned char a_ucPins, unsigned char a_ucValue )
{
if ( a_ucValue ) {
siIspPins = a_ucPins | siIspPins;
}
else {
siIspPins = ~a_ucPins & siIspPins;
}
_outp(OutPort, siIspPins );
}
/****************************************************************************
Function: readPort()
Purpose:
To get the value of the TDO pin from the input port.
This routine is specific to the PC parallel port setup, but can easily
be changed to address each user's hardware.
Parameters: none
Returns: The value of SDO, as a byte, with a value of either 0 or 1.
*****************************************************************************/
unsigned char readPort()
{
unsigned char ucRet;
if ( _inp( InPort ) & pinTDO ) {
ucRet = 0x01;
}
else {
ucRet = 0x00;
}
return ( ucRet );
}
/****************************************************************************
ispVMDelay
Users must devise their own timing procedures to ensure the specified
minimum delay is observed when using different platform.
The timing function used here is for PC only by hocking the clock chip.
*****************************************************************************/
void ispVMDelay( unsigned short a_usMicroSecondDelay )
{
unsigned short usiDelayTime = 0;
DWORD dwCurrentTime = 0;
DWORD dwStartTime = 0;
if ( a_usMicroSecondDelay & 0x8000 ) {
a_usMicroSecondDelay &= ~0x8000;
usiDelayTime = a_usMicroSecondDelay;
}
else {
usiDelayTime = a_usMicroSecondDelay / 1000;
if ( usiDelayTime <= 0 ) {
usiDelayTime = 1;
}
}
if ( delayPercent ) {
usiDelayTime = usiDelayTime * ( unsigned short ) ( 1 + ( delayPercent * 0.01 ) );
}
dwStartTime = time( NULL );
timeBeginPeriod( 1 );
dwCurrentTime = timeGetTime();
while ( ( dwStartTime = timeGetTime() - dwCurrentTime ) < ( DWORD ) ( usiDelayTime ) ){
}
timeEndPeriod( 1 );
}
/****************************************************************************
SCLOCK
This procedure apply a single pulse to TCK.
*****************************************************************************/
void sclock(void)
{
unsigned short IdleTime = 0;
unsigned short i;
if (Frequency >= 1000)
IdleTime = 0; /*in MHZ range, no delay*/
else
IdleTime = (unsigned short) (1000/Frequency + 1); /*delay the clock for 3K devices*/
IdleTime++;
for (i=0; i<IdleTime; i++) /* delay the clock by loop*/
writePort(pinTCK,0x01);
for (i=0; i<IdleTime; i++) /* delay the clock by loop */
writePort(pinTCK,0x00);
for (i=0; i<IdleTime; i++) /* delay the clock by loop */
writePort(pinTCK,0x00);
}
/****************************************************************************
* ispVMClocks
* This procedure apply the specified number of pulses to TCK.
*****************************************************************************/
void ispVMClocks( unsigned short Clocks)
{
unsigned short iClockIndex;
for ( iClockIndex = 0; iClockIndex < Clocks; iClockIndex++ ) {
sclock();
}
}
/****************************************************************************
This procedure takes care of the HIR,HDR,TIR,TDR for the purpose of
putting the other devices into Bypass mode. *
The Current State is checked to find out if it is at PauseDR or PauseIR. *
If it is at DRPAUSE, perform bypass register scan.
If it is at IRPAUSE, scan into instruction registers the bypass instruction.
4/26/01 Enhanced to support multiple devices in a single SVF file.
*****************************************************************************/
void ispVMBypass( char ScanType, unsigned short Bits )
{
unsigned short iIndex;
unsigned short iSourceIndex;
unsigned char cBitState;
unsigned char cCurByte;
unsigned char * pcSource;
if ( Bits <= 0 ) {
return;
}
switch ( ScanType ) {
case HIR:
pcSource = HIRData;
break;
case TIR:
pcSource = TIRData;
break;
case HDR:
pcSource = HDRData;
break;
case TDR:
pcSource = TDRData;
break;
default:
break;
}
iSourceIndex = 0;
cBitState = 0;
for ( iIndex = 0; iIndex < Bits - 1; iIndex++ ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -