⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hardware.c

📁 在嵌入式系统中对Lattice CPLD软件升级时所需的VME文件生成所需源代码。
💻 C
📖 第 1 页 / 共 2 页
字号:
/****************************************************************************
              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 + -