/* * (C) Copyright 2003 * Stefan Roese, esd gmbh germany, stefan.roese@esd-electronics.com * * SPDX-License-Identifier: GPL-2.0+ */ /***************************************************************************** * file: micro.c * abstract: This file contains the function, xsvfExecute(), * call for interpreting the XSVF commands. * Usage: Call xsvfExecute() to process XSVF data. * The XSVF data is retrieved by readByte() in ports.c * Remove the main function if you already have one. * Options: XSVF_SUPPORT_COMPRESSION * This define supports the XC9500/XL compression scheme. * This define adds support for XSDRINC and XSETSDRMASKS. * XSVF_SUPPORT_ERRORCODES * This define causes the xsvfExecute function to return * an error code for specific errors. See error codes below. * If this is not defined, the return value defaults to the * legacy values for backward compatibility: * 1 = success; 0 = failure. * Debugging: DEBUG_MODE (Legacy name) * Define DEBUG_MODE to compile with debugging features. * Both micro.c and ports.c must be compiled with the DEBUG_MODE * defined to enable the standalone main implementation in * micro.c that reads XSVF from a file. * History: v2.00 - Original XSVF implementation. * v4.04 - Added delay at end of XSIR for XC18v00 support. * Added new commands for CoolRunner support: * XSTATE, XENDIR, XENDDR * v4.05 - Cleanup micro.c but leave ports.c intact. * v4.06 - Fix xsvfGotoTapState for retry transition. * v4.07 - Update example waitTime implementations for * compatibility with Virtex-II. * v4.10 - Add new XSIR2 command that supports a 2-byte * IR-length parameter for IR shifts > 255 bits. * v4.11 - No change. Update version to match SVF2XSVF xlator. * v4.14 - Added XCOMMENT. * v5.00 - Improve XSTATE support. * Added XWAIT. *****************************************************************************/ #include #include #include #include "micro.h" #include "lenval.h" #include "ports.h" const unsigned char *xsvfdata; /*============================================================================ * XSVF #define ============================================================================*/ #define XSVF_VERSION "5.00" /***************************************************************************** * Define: XSVF_SUPPORT_COMPRESSION * Description: Define this to support the XC9500/XL XSVF data compression * scheme. * Code size can be reduced by NOT supporting this feature. * However, you must use the -nc (no compress) option when * translating SVF to XSVF using the SVF2XSVF translator. * Corresponding, uncompressed XSVF may be larger. *****************************************************************************/ #ifndef XSVF_SUPPORT_COMPRESSION #define XSVF_SUPPORT_COMPRESSION 1 #endif /***************************************************************************** * Define: XSVF_SUPPORT_ERRORCODES * Description: Define this to support the new XSVF error codes. * (The original XSVF player just returned 1 for success and * 0 for an unspecified failure.) *****************************************************************************/ #ifndef XSVF_SUPPORT_ERRORCODES #define XSVF_SUPPORT_ERRORCODES 1 #endif #ifdef XSVF_SUPPORT_ERRORCODES #define XSVF_ERRORCODE(errorCode) errorCode #else /* Use legacy error code */ #define XSVF_ERRORCODE(errorCode) ((errorCode==XSVF_ERROR_NONE)?1:0) #endif /* XSVF_SUPPORT_ERRORCODES */ /*============================================================================ * DEBUG_MODE #define ============================================================================*/ #define DEBUG_MODE #ifdef DEBUG_MODE #define XSVFDBG_PRINTF(iDebugLevel,pzFormat) \ { if ( xsvf_iDebugLevel >= iDebugLevel ) \ printf( pzFormat ); } #define XSVFDBG_PRINTF1(iDebugLevel,pzFormat,arg1) \ { if ( xsvf_iDebugLevel >= iDebugLevel ) \ printf( pzFormat, arg1 ); } #define XSVFDBG_PRINTF2(iDebugLevel,pzFormat,arg1,arg2) \ { if ( xsvf_iDebugLevel >= iDebugLevel ) \ printf( pzFormat, arg1, arg2 ); } #define XSVFDBG_PRINTF3(iDebugLevel,pzFormat,arg1,arg2,arg3) \ { if ( xsvf_iDebugLevel >= iDebugLevel ) \ printf( pzFormat, arg1, arg2, arg3 ); } #define XSVFDBG_PRINTLENVAL(iDebugLevel,plenVal) \ { if ( xsvf_iDebugLevel >= iDebugLevel ) \ xsvfPrintLenVal(plenVal); } #else /* !DEBUG_MODE */ #define XSVFDBG_PRINTF(iDebugLevel,pzFormat) #define XSVFDBG_PRINTF1(iDebugLevel,pzFormat,arg1) #define XSVFDBG_PRINTF2(iDebugLevel,pzFormat,arg1,arg2) #define XSVFDBG_PRINTF3(iDebugLevel,pzFormat,arg1,arg2,arg3) #define XSVFDBG_PRINTLENVAL(iDebugLevel,plenVal) #endif /* DEBUG_MODE */ /*============================================================================ * XSVF Type Declarations ============================================================================*/ /***************************************************************************** * Struct: SXsvfInfo * Description: This structure contains all of the data used during the * execution of the XSVF. Some data is persistent, predefined * information (e.g. lRunTestTime). The bulk of this struct's * size is due to the lenVal structs (defined in lenval.h) * which contain buffers for the active shift data. The MAX_LEN * #define in lenval.h defines the size of these buffers. * These buffers must be large enough to store the longest * shift data in your XSVF file. For example: * MAX_LEN >= ( longest_shift_data_in_bits / 8 ) * Because the lenVal struct dominates the space usage of this * struct, the rough size of this struct is: * sizeof( SXsvfInfo ) ~= MAX_LEN * 7 (number of lenVals) * xsvfInitialize() contains initialization code for the data * in this struct. * xsvfCleanup() contains cleanup code for the data in this * struct. *****************************************************************************/ typedef struct tagSXsvfInfo { /* XSVF status information */ unsigned char ucComplete; /* 0 = running; 1 = complete */ unsigned char ucCommand; /* Current XSVF command byte */ long lCommandCount; /* Number of commands processed */ int iErrorCode; /* An error code. 0 = no error. */ /* TAP state/sequencing information */ unsigned char ucTapState; /* Current TAP state */ unsigned char ucEndIR; /* ENDIR TAP state (See SVF) */ unsigned char ucEndDR; /* ENDDR TAP state (See SVF) */ /* RUNTEST information */ unsigned char ucMaxRepeat; /* Max repeat loops (for xc9500/xl) */ long lRunTestTime; /* Pre-specified RUNTEST time (usec) */ /* Shift Data Info and Buffers */ long lShiftLengthBits; /* Len. current shift data in bits */ short sShiftLengthBytes; /* Len. current shift data in bytes */ lenVal lvTdi; /* Current TDI shift data */ lenVal lvTdoExpected; /* Expected TDO shift data */ lenVal lvTdoCaptured; /* Captured TDO shift data */ lenVal lvTdoMask; /* TDO mask: 0=dontcare; 1=compare */ #ifdef XSVF_SUPPORT_COMPRESSION /* XSDRINC Data Buffers */ lenVal lvAddressMask; /* Address mask for XSDRINC */ lenVal lvDataMask; /* Data mask for XSDRINC */ lenVal lvNextData; /* Next data for XSDRINC */ #endif /* XSVF_SUPPORT_COMPRESSION */ } SXsvfInfo; /* Declare pointer to functions that perform XSVF commands */ typedef int (*TXsvfDoCmdFuncPtr)( SXsvfInfo* ); /*============================================================================ * XSVF Command Bytes ============================================================================*/ /* encodings of xsvf instructions */ #define XCOMPLETE 0 #define XTDOMASK 1 #define XSIR 2 #define XSDR 3 #define XRUNTEST 4 /* Reserved 5 */ /* Reserved 6 */ #define XREPEAT 7 #define XSDRSIZE 8 #define XSDRTDO 9 #define XSETSDRMASKS 10 #define XSDRINC 11 #define XSDRB 12 #define XSDRC 13 #define XSDRE 14 #define XSDRTDOB 15 #define XSDRTDOC 16 #define XSDRTDOE 17 #define XSTATE 18 /* 4.00 */ #define XENDIR 19 /* 4.04 */ #define XENDDR 20 /* 4.04 */ #define XSIR2 21 /* 4.10 */ #define XCOMMENT 22 /* 4.14 */ #define XWAIT 23 /* 5.00 */ /* Insert new commands here */ /* and add corresponding xsvfDoCmd function to xsvf_pfDoCmd below. */ #define XLASTCMD 24 /* Last command marker */ /*============================================================================ * XSVF Command Parameter Values ============================================================================*/ #define XSTATE_RESET 0 /* 4.00 parameter for XSTATE */ #define XSTATE_RUNTEST 1 /* 4.00 parameter for XSTATE */ #define XENDXR_RUNTEST 0 /* 4.04 parameter for XENDIR/DR */ #define XENDXR_PAUSE 1 /* 4.04 parameter for XENDIR/DR */ /* TAP states */ #define XTAPSTATE_RESET 0x00 #define XTAPSTATE_RUNTEST 0x01 /* a.k.a. IDLE */ #define XTAPSTATE_SELECTDR 0x02 #define XTAPSTATE_CAPTUREDR 0x03 #define XTAPSTATE_SHIFTDR 0x04 #define XTAPSTATE_EXIT1DR 0x05 #define XTAPSTATE_PAUSEDR 0x06 #define XTAPSTATE_EXIT2DR 0x07 #define XTAPSTATE_UPDATEDR 0x08 #define XTAPSTATE_IRSTATES 0x09 /* All IR states begin here */ #define XTAPSTATE_SELECTIR 0x09 #define XTAPSTATE_CAPTUREIR 0x0A #define XTAPSTATE_SHIFTIR 0x0B #define XTAPSTATE_EXIT1IR 0x0C #define XTAPSTATE_PAUSEIR 0x0D #define XTAPSTATE_EXIT2IR 0x0E #define XTAPSTATE_UPDATEIR 0x0F /*============================================================================ * XSVF Function Prototypes ============================================================================*/ int xsvfDoIllegalCmd( SXsvfInfo* pXsvfInfo ); /* Illegal command function */ int xsvfDoXCOMPLETE( SXsvfInfo* pXsvfInfo ); int xsvfDoXTDOMASK( SXsvfInfo* pXsvfInfo ); int xsvfDoXSIR( SXsvfInfo* pXsvfInfo ); int xsvfDoXSIR2( SXsvfInfo* pXsvfInfo ); int xsvfDoXSDR( SXsvfInfo* pXsvfInfo ); int xsvfDoXRUNTEST( SXsvfInfo* pXsvfInfo ); int xsvfDoXREPEAT( SXsvfInfo* pXsvfInfo ); int xsvfDoXSDRSIZE( SXsvfInfo* pXsvfInfo ); int xsvfDoXSDRTDO( SXsvfInfo* pXsvfInfo ); int xsvfDoXSETSDRMASKS( SXsvfInfo* pXsvfInfo ); int xsvfDoXSDRINC( SXsvfInfo* pXsvfInfo ); int xsvfDoXSDRBCE( SXsvfInfo* pXsvfInfo ); int xsvfDoXSDRTDOBCE( SXsvfInfo* pXsvfInfo ); int xsvfDoXSTATE( SXsvfInfo* pXsvfInfo ); int xsvfDoXENDXR( SXsvfInfo* pXsvfInfo ); int xsvfDoXCOMMENT( SXsvfInfo* pXsvfInfo ); int xsvfDoXWAIT( SXsvfInfo* pXsvfInfo ); /* Insert new command functions here */ /*============================================================================ * XSVF Global Variables ============================================================================*/ /* Array of XSVF command functions. Must follow command byte value order! */ /* If your compiler cannot take this form, then convert to a switch statement*/ TXsvfDoCmdFuncPtr xsvf_pfDoCmd[] = { xsvfDoXCOMPLETE, /* 0 */ xsvfDoXTDOMASK, /* 1 */ xsvfDoXSIR, /* 2 */ xsvfDoXSDR, /* 3 */ xsvfDoXRUNTEST, /* 4 */ xsvfDoIllegalCmd, /* 5 */ xsvfDoIllegalCmd, /* 6 */ xsvfDoXREPEAT, /* 7 */ xsvfDoXSDRSIZE, /* 8 */ xsvfDoXSDRTDO, /* 9 */ #ifdef XSVF_SUPPORT_COMPRESSION xsvfDoXSETSDRMASKS, /* 10 */ xsvfDoXSDRINC, /* 11 */ #else xsvfDoIllegalCmd, /* 10 */ xsvfDoIllegalCmd, /* 11 */ #endif /* XSVF_SUPPORT_COMPRESSION */ xsvfDoXSDRBCE, /* 12 */ xsvfDoXSDRBCE, /* 13 */ xsvfDoXSDRBCE, /* 14 */ xsvfDoXSDRTDOBCE, /* 15 */ xsvfDoXSDRTDOBCE, /* 16 */ xsvfDoXSDRTDOBCE, /* 17 */ xsvfDoXSTATE, /* 18 */ xsvfDoXENDXR, /* 19 */ xsvfDoXENDXR, /* 20 */ xsvfDoXSIR2, /* 21 */ xsvfDoXCOMMENT, /* 22 */ xsvfDoXWAIT /* 23 */ /* Insert new command functions here */ }; #ifdef DEBUG_MODE char* xsvf_pzCommandName[] = { "XCOMPLETE", "XTDOMASK", "XSIR", "XSDR", "XRUNTEST", "Reserved5", "Reserved6", "XREPEAT", "XSDRSIZE", "XSDRTDO", "XSETSDRMASKS", "XSDRINC", "XSDRB", "XSDRC", "XSDRE", "XSDRTDOB", "XSDRTDOC", "XSDRTDOE", "XSTATE", "XENDIR", "XENDDR", "XSIR2", "XCOMMENT", "XWAIT" }; char* xsvf_pzErrorName[] = { "No error", "ERROR: Unknown", "ERROR: TDO mismatch", "ERROR: TDO mismatch and exceeded max retries", "ERROR: Unsupported XSVF command", "ERROR: Illegal state specification", "ERROR: Data overflows allocated MAX_LEN buffer size" }; char* xsvf_pzTapState[] = { "RESET", /* 0x00 */ "RUNTEST/IDLE", /* 0x01 */ "DRSELECT", /* 0x02 */ "DRCAPTURE", /* 0x03 */ "DRSHIFT", /* 0x04 */ "DREXIT1", /* 0x05 */ "DRPAUSE", /* 0x06 */ "DREXIT2", /* 0x07 */ "DRUPDATE", /* 0x08 */ "IRSELECT", /* 0x09 */ "IRCAPTURE", /* 0x0A */ "IRSHIFT", /* 0x0B */ "IREXIT1", /* 0x0C */ "IRPAUSE", /* 0x0D */ "IREXIT2", /* 0x0E */ "IRUPDATE" /* 0x0F */ }; #endif /* DEBUG_MODE */ /*#ifdef DEBUG_MODE */ /* FILE* in; /XXX* Legacy DEBUG_MODE file pointer */ int xsvf_iDebugLevel; /*#endif /XXX* DEBUG_MODE */ /*============================================================================ * Utility Functions ============================================================================*/ /***************************************************************************** * Function: xsvfPrintLenVal * Description: Print the lenval value in hex. * Parameters: plv - ptr to lenval. * Returns: void. *****************************************************************************/ #ifdef DEBUG_MODE void xsvfPrintLenVal( lenVal *plv ) { int i; if ( plv ) { printf( "0x" ); for ( i = 0; i < plv->len; ++i ) { printf( "%02x", ((unsigned int)(plv->val[ i ])) ); } } } #endif /* DEBUG_MODE */ /***************************************************************************** * Function: xsvfInfoInit * Description: Initialize the xsvfInfo data. * Parameters: pXsvfInfo - ptr to the XSVF info structure. * Returns: int - 0 = success; otherwise error. *****************************************************************************/ int xsvfInfoInit( SXsvfInfo* pXsvfInfo ) { XSVFDBG_PRINTF1( 4, " sizeof( SXsvfInfo ) = %d bytes\n", sizeof( SXsvfInfo ) ); pXsvfInfo->ucComplete = 0; pXsvfInfo->ucCommand = XCOMPLETE; pXsvfInfo->lCommandCount = 0; pXsvfInfo->iErrorCode = XSVF_ERROR_NONE; pXsvfInfo->ucMaxRepeat = 0; pXsvfInfo->ucTapState = XTAPSTATE_RESET; pXsvfInfo->ucEndIR = XTAPSTATE_RUNTEST; pXsvfInfo->ucEndDR = XTAPSTATE_RUNTEST; pXsvfInfo->lShiftLengthBits = 0L; pXsvfInfo->sShiftLengthBytes= 0; pXsvfInfo->lRunTestTime = 0L; return( 0 ); } /***************************************************************************** * Function: xsvfInfoCleanup * Description: Cleanup the xsvfInfo data. * Parameters: pXsvfInfo - ptr to the XSVF info structure. * Returns: void. *****************************************************************************/ void xsvfInfoCleanup( SXsvfInfo* pXsvfInfo ) { } /***************************************************************************** * Function: xsvfGetAsNumBytes * Description: Calculate the number of bytes the given number of bits * consumes. * Parameters: lNumBits - the number of bits. * Returns: short - the number of bytes to store the number of bits. *****************************************************************************/ short xsvfGetAsNumBytes( long lNumBits ) { return( (short)( ( lNumBits + 7L ) / 8L ) ); } /***************************************************************************** * Function: xsvfTmsTransition * Description: Apply TMS and transition TAP controller by applying one TCK * cycle. * Parameters: sTms - new TMS value. * Returns: void. *****************************************************************************/ void xsvfTmsTransition( short sTms ) { setPort( TMS, sTms ); setPort( TCK, 0 ); setPort( TCK, 1 ); } /***************************************************************************** * Function: xsvfGotoTapState * Description: From the current TAP state, go to the named TAP state. * A target state of RESET ALWAYS causes TMS reset sequence. * All SVF standard stable state paths are supported. * All state transitions are supported except for the following * which cause an XSVF_ERROR_ILLEGALSTATE: * - Target==DREXIT2; Start!=DRPAUSE * - Target==IREXIT2; Start!=IRPAUSE * Parameters: pucTapState - Current TAP state; returns final TAP state. * ucTargetState - New target TAP state. * Returns: int - 0 = success; otherwise error. *****************************************************************************/ int xsvfGotoTapState( unsigned char* pucTapState, unsigned char ucTargetState ) { int i; int iErrorCode; iErrorCode = XSVF_ERROR_NONE; if ( ucTargetState == XTAPSTATE_RESET ) { /* If RESET, always perform TMS reset sequence to reset/sync TAPs */ xsvfTmsTransition( 1 ); for ( i = 0; i < 5; ++i ) { setPort( TCK, 0 ); setPort( TCK, 1 ); } *pucTapState = XTAPSTATE_RESET; XSVFDBG_PRINTF( 3, " TMS Reset Sequence -> Test-Logic-Reset\n" ); XSVFDBG_PRINTF1( 3, " TAP State = %s\n", xsvf_pzTapState[ *pucTapState ] ); } else if ( ( ucTargetState != *pucTapState ) && ( ( ( ucTargetState == XTAPSTATE_EXIT2DR ) && ( *pucTapState != XTAPSTATE_PAUSEDR ) ) || ( ( ucTargetState == XTAPSTATE_EXIT2IR ) && ( *pucTapState != XTAPSTATE_PAUSEIR ) ) ) ) { /* Trap illegal TAP state path specification */ iErrorCode = XSVF_ERROR_ILLEGALSTATE; } else { if ( ucTargetState == *pucTapState ) { /* Already in target state. Do nothing except when in DRPAUSE or in IRPAUSE to comply with SVF standard */ if ( ucTargetState == XTAPSTATE_PAUSEDR ) { xsvfTmsTransition( 1 ); *pucTapState = XTAPSTATE_EXIT2DR; XSVFDBG_PRINTF1( 3, " TAP State = %s\n", xsvf_pzTapState[ *pucTapState ] ); } else if ( ucTargetState == XTAPSTATE_PAUSEIR ) { xsvfTmsTransition( 1 ); *pucTapState = XTAPSTATE_EXIT2IR; XSVFDBG_PRINTF1( 3, " TAP State = %s\n", xsvf_pzTapState[ *pucTapState ] ); } } /* Perform TAP state transitions to get to the target state */ while ( ucTargetState != *pucTapState ) { switch ( *pucTapState ) { case XTAPSTATE_RESET: xsvfTmsTransition( 0 ); *pucTapState = XTAPSTATE_RUNTEST; break; case XTAPSTATE_RUNTEST: xsvfTmsTransition( 1 ); *pucTapState = XTAPSTATE_SELECTDR; break; case XTAPSTATE_SELECTDR: if ( ucTargetState >= XTAPSTATE_IRSTATES ) { xsvfTmsTransition( 1 ); *pucTapState = XTAPSTATE_SELECTIR; } else { xsvfTmsTransition( 0 ); *pucTapState = XTAPSTATE_CAPTUREDR; } break; case XTAPSTATE_CAPTUREDR: if ( ucTargetState == XTAPSTATE_SHIFTDR ) { xsvfTmsTransition( 0 ); *pucTapState = XTAPSTATE_SHIFTDR; } else { xsvfTmsTransition( 1 ); *pucTapState = XTAPSTATE_EXIT1DR; } break; case XTAPSTATE_SHIFTDR: xsvfTmsTransition( 1 ); *pucTapState = XTAPSTATE_EXIT1DR; break; case XTAPSTATE_EXIT1DR: if ( ucTargetState == XTAPSTATE_PAUSEDR ) { xsvfTmsTransition( 0 ); *pucTapState = XTAPSTATE_PAUSEDR; } else { xsvfTmsTransition( 1 ); *pucTapState = XTAPSTATE_UPDATEDR; } break; case XTAPSTATE_PAUSEDR: xsvfTmsTransition( 1 ); *pucTapState = XTAPSTATE_EXIT2DR; break; case XTAPSTATE_EXIT2DR: if ( ucTargetState == XTAPSTATE_SHIFTDR ) { xsvfTmsTransition( 0 ); *pucTapState = XTAPSTATE_SHIFTDR; } else { xsvfTmsTransition( 1 ); *pucTapState = XTAPSTATE_UPDATEDR; } break; case XTAPSTATE_UPDATEDR: if ( ucTargetState == XTAPSTATE_RUNTEST ) { xsvfTmsTransition( 0 ); *pucTapState = XTAPSTATE_RUNTEST; } else { xsvfTmsTransition( 1 ); *pucTapState = XTAPSTATE_SELECTDR; } break; case XTAPSTATE_SELECTIR: xsvfTmsTransition( 0 ); *pucTapState = XTAPSTATE_CAPTUREIR; break; case XTAPSTATE_CAPTUREIR: if ( ucTargetState == XTAPSTATE_SHIFTIR ) { xsvfTmsTransition( 0 ); *pucTapState = XTAPSTATE_SHIFTIR; } else { xsvfTmsTransition( 1 ); *pucTapState = XTAPSTATE_EXIT1IR; } break; case XTAPSTATE_SHIFTIR: xsvfTmsTransition( 1 ); *pucTapState = XTAPSTATE_EXIT1IR; break; case XTAPSTATE_EXIT1IR: if ( ucTargetState == XTAPSTATE_PAUSEIR ) { xsvfTmsTransition( 0 ); *pucTapState = XTAPSTATE_PAUSEIR; } else { xsvfTmsTransition( 1 ); *pucTapState = XTAPSTATE_UPDATEIR; } break; case XTAPSTATE_PAUSEIR: xsvfTmsTransition( 1 ); *pucTapState = XTAPSTATE_EXIT2IR; break; case XTAPSTATE_EXIT2IR: if ( ucTargetState == XTAPSTATE_SHIFTIR ) { xsvfTmsTransition( 0 ); *pucTapState = XTAPSTATE_SHIFTIR; } else { xsvfTmsTransition( 1 ); *pucTapState = XTAPSTATE_UPDATEIR; } break; case XTAPSTATE_UPDATEIR: if ( ucTargetState == XTAPSTATE_RUNTEST ) { xsvfTmsTransition( 0 ); *pucTapState = XTAPSTATE_RUNTEST; } else { xsvfTmsTransition( 1 ); *pucTapState = XTAPSTATE_SELECTDR; } break; default: iErrorCode = XSVF_ERROR_ILLEGALSTATE; *pucTapState = ucTargetState; /* Exit while loop */ break; } XSVFDBG_PRINTF1( 3, " TAP State = %s\n", xsvf_pzTapState[ *pucTapState ] ); } } return( iErrorCode ); } /***************************************************************************** * Function: xsvfShiftOnly * Description: Assumes that starting TAP state is SHIFT-DR or SHIFT-IR. * Shift the given TDI data into the JTAG scan chain. * Optionally, save the TDO data shifted out of the scan chain. * Last shift cycle is special: capture last TDO, set last TDI, * but does not pulse TCK. Caller must pulse TCK and optionally * set TMS=1 to exit shift state. * Parameters: lNumBits - number of bits to shift. * plvTdi - ptr to lenval for TDI data. * plvTdoCaptured - ptr to lenval for storing captured TDO data. * iExitShift - 1=exit at end of shift; 0=stay in Shift-DR. * Returns: void. *****************************************************************************/ void xsvfShiftOnly( long lNumBits, lenVal* plvTdi, lenVal* plvTdoCaptured, int iExitShift ) { unsigned char* pucTdi; unsigned char* pucTdo; unsigned char ucTdiByte; unsigned char ucTdoByte; unsigned char ucTdoBit; int i; /* assert( ( ( lNumBits + 7 ) / 8 ) == plvTdi->len ); */ /* Initialize TDO storage len == TDI len */ pucTdo = 0; if ( plvTdoCaptured ) { plvTdoCaptured->len = plvTdi->len; pucTdo = plvTdoCaptured->val + plvTdi->len; } /* Shift LSB first. val[N-1] == LSB. val[0] == MSB. */ pucTdi = plvTdi->val + plvTdi->len; while ( lNumBits ) { /* Process on a byte-basis */ ucTdiByte = (*(--pucTdi)); ucTdoByte = 0; for ( i = 0; ( lNumBits && ( i < 8 ) ); ++i ) { --lNumBits; if ( iExitShift && !lNumBits ) { /* Exit Shift-DR state */ setPort( TMS, 1 ); } /* Set the new TDI value */ setPort( TDI, (short)(ucTdiByte & 1) ); ucTdiByte >>= 1; /* Set TCK low */ setPort( TCK, 0 ); if ( pucTdo ) { /* Save the TDO value */ ucTdoBit = readTDOBit(); ucTdoByte |= ( ucTdoBit << i ); } /* Set TCK high */ setPort( TCK, 1 ); } /* Save the TDO byte value */ if ( pucTdo ) { (*(--pucTdo)) = ucTdoByte; } } } /***************************************************************************** * Function: xsvfShift * Description: Goes to the given starting TAP state. * Calls xsvfShiftOnly to shift in the given TDI data and * optionally capture the TDO data. * Compares the TDO captured data against the TDO expected * data. * If a data mismatch occurs, then executes the exception * handling loop upto ucMaxRepeat times. * Parameters: pucTapState - Ptr to current TAP state. * ucStartState - Starting shift state: Shift-DR or Shift-IR. * lNumBits - number of bits to shift. * plvTdi - ptr to lenval for TDI data. * plvTdoCaptured - ptr to lenval for storing TDO data. * plvTdoExpected - ptr to expected TDO data. * plvTdoMask - ptr to TDO mask. * ucEndState - state in which to end the shift. * lRunTestTime - amount of time to wait after the shift. * ucMaxRepeat - Maximum number of retries on TDO mismatch. * Returns: int - 0 = success; otherwise TDO mismatch. * Notes: XC9500XL-only Optimization: * Skip the waitTime() if plvTdoMask->val[0:plvTdoMask->len-1] * is NOT all zeros and sMatch==1. *****************************************************************************/ int xsvfShift( unsigned char* pucTapState, unsigned char ucStartState, long lNumBits, lenVal* plvTdi, lenVal* plvTdoCaptured, lenVal* plvTdoExpected, lenVal* plvTdoMask, unsigned char ucEndState, long lRunTestTime, unsigned char ucMaxRepeat ) { int iErrorCode; int iMismatch; unsigned char ucRepeat; int iExitShift; iErrorCode = XSVF_ERROR_NONE; iMismatch = 0; ucRepeat = 0; iExitShift = ( ucStartState != ucEndState ); XSVFDBG_PRINTF1( 3, " Shift Length = %ld\n", lNumBits ); XSVFDBG_PRINTF( 4, " TDI = "); XSVFDBG_PRINTLENVAL( 4, plvTdi ); XSVFDBG_PRINTF( 4, "\n"); XSVFDBG_PRINTF( 4, " TDO Expected = "); XSVFDBG_PRINTLENVAL( 4, plvTdoExpected ); XSVFDBG_PRINTF( 4, "\n"); if ( !lNumBits ) { /* Compatibility with XSVF2.00: XSDR 0 = no shift, but wait in RTI */ if ( lRunTestTime ) { /* Wait for prespecified XRUNTEST time */ xsvfGotoTapState( pucTapState, XTAPSTATE_RUNTEST ); XSVFDBG_PRINTF1( 3, " Wait = %ld usec\n", lRunTestTime ); waitTime( lRunTestTime ); } } else { do { /* Goto Shift-DR or Shift-IR */ xsvfGotoTapState( pucTapState, ucStartState ); /* Shift TDI and capture TDO */ xsvfShiftOnly( lNumBits, plvTdi, plvTdoCaptured, iExitShift ); if ( plvTdoExpected ) { /* Compare TDO data to expected TDO data */ iMismatch = !EqualLenVal( plvTdoExpected, plvTdoCaptured, plvTdoMask ); } if ( iExitShift ) { /* Update TAP state: Shift->Exit */ ++(*pucTapState); XSVFDBG_PRINTF1( 3, " TAP State = %s\n", xsvf_pzTapState[ *pucTapState ] ); if ( iMismatch && lRunTestTime && ( ucRepeat < ucMaxRepeat ) ) { XSVFDBG_PRINTF( 4, " TDO Expected = "); XSVFDBG_PRINTLENVAL( 4, plvTdoExpected ); XSVFDBG_PRINTF( 4, "\n"); XSVFDBG_PRINTF( 4, " TDO Captured = "); XSVFDBG_PRINTLENVAL( 4, plvTdoCaptured ); XSVFDBG_PRINTF( 4, "\n"); XSVFDBG_PRINTF( 4, " TDO Mask = "); XSVFDBG_PRINTLENVAL( 4, plvTdoMask ); XSVFDBG_PRINTF( 4, "\n"); XSVFDBG_PRINTF1( 3, " Retry #%d\n", ( ucRepeat + 1 ) ); /* Do exception handling retry - ShiftDR only */ xsvfGotoTapState( pucTapState, XTAPSTATE_PAUSEDR ); /* Shift 1 extra bit */ xsvfGotoTapState( pucTapState, XTAPSTATE_SHIFTDR ); /* Increment RUNTEST time by an additional 25% */ lRunTestTime += ( lRunTestTime >> 2 ); } else { /* Do normal exit from Shift-XR */ xsvfGotoTapState( pucTapState, ucEndState ); } if ( lRunTestTime ) { /* Wait for prespecified XRUNTEST time */ xsvfGotoTapState( pucTapState, XTAPSTATE_RUNTEST ); XSVFDBG_PRINTF1( 3, " Wait = %ld usec\n", lRunTestTime ); waitTime( lRunTestTime ); } } } while ( iMismatch && ( ucRepeat++ < ucMaxRepeat ) ); } if ( iMismatch ) { XSVFDBG_PRINTF( 1, " TDO Expected = "); XSVFDBG_PRINTLENVAL( 1, plvTdoExpected ); XSVFDBG_PRINTF( 1, "\n"); XSVFDBG_PRINTF( 1, " TDO Captured = "); XSVFDBG_PRINTLENVAL( 1, plvTdoCaptured ); XSVFDBG_PRINTF( 1, "\n"); XSVFDBG_PRINTF( 1, " TDO Mask = "); XSVFDBG_PRINTLENVAL( 1, plvTdoMask ); XSVFDBG_PRINTF( 1, "\n"); if ( ucMaxRepeat && ( ucRepeat > ucMaxRepeat ) ) { iErrorCode = XSVF_ERROR_MAXRETRIES; } else { iErrorCode = XSVF_ERROR_TDOMISMATCH; } } return( iErrorCode ); } /***************************************************************************** * Function: xsvfBasicXSDRTDO * Description: Get the XSDRTDO parameters and execute the XSDRTDO command. * This is the common function for all XSDRTDO commands. * Parameters: pucTapState - Current TAP state. * lShiftLengthBits - number of bits to shift. * sShiftLengthBytes - number of bytes to read. * plvTdi - ptr to lenval for TDI data. * lvTdoCaptured - ptr to lenval for storing TDO data. * iEndState - state in which to end the shift. * lRunTestTime - amount of time to wait after the shift. * ucMaxRepeat - maximum xc9500/xl retries. * Returns: int - 0 = success; otherwise TDO mismatch. *****************************************************************************/ int xsvfBasicXSDRTDO( unsigned char* pucTapState, long lShiftLengthBits, short sShiftLengthBytes, lenVal* plvTdi, lenVal* plvTdoCaptured, lenVal* plvTdoExpected, lenVal* plvTdoMask, unsigned char ucEndState, long lRunTestTime, unsigned char ucMaxRepeat ) { readVal( plvTdi, sShiftLengthBytes ); if ( plvTdoExpected ) { readVal( plvTdoExpected, sShiftLengthBytes ); } return( xsvfShift( pucTapState, XTAPSTATE_SHIFTDR, lShiftLengthBits, plvTdi, plvTdoCaptured, plvTdoExpected, plvTdoMask, ucEndState, lRunTestTime, ucMaxRepeat ) ); } /***************************************************************************** * Function: xsvfDoSDRMasking * Description: Update the data value with the next XSDRINC data and address. * Example: dataVal=0x01ff, nextData=0xab, addressMask=0x0100, * dataMask=0x00ff, should set dataVal to 0x02ab * Parameters: plvTdi - The current TDI value. * plvNextData - the next data value. * plvAddressMask - the address mask. * plvDataMask - the data mask. * Returns: void. *****************************************************************************/ #ifdef XSVF_SUPPORT_COMPRESSION void xsvfDoSDRMasking( lenVal* plvTdi, lenVal* plvNextData, lenVal* plvAddressMask, lenVal* plvDataMask ) { int i; unsigned char ucTdi; unsigned char ucTdiMask; unsigned char ucDataMask; unsigned char ucNextData; unsigned char ucNextMask; short sNextData; /* add the address Mask to dataVal and return as a new dataVal */ addVal( plvTdi, plvTdi, plvAddressMask ); ucNextData = 0; ucNextMask = 0; sNextData = plvNextData->len; for ( i = plvDataMask->len - 1; i >= 0; --i ) { /* Go through data mask in reverse order looking for mask (1) bits */ ucDataMask = plvDataMask->val[ i ]; if ( ucDataMask ) { /* Retrieve the corresponding TDI byte value */ ucTdi = plvTdi->val[ i ]; /* For each bit in the data mask byte, look for 1's */ ucTdiMask = 1; while ( ucDataMask ) { if ( ucDataMask & 1 ) { if ( !ucNextMask ) { /* Get the next data byte */ ucNextData = plvNextData->val[ --sNextData ]; ucNextMask = 1; } /* Set or clear the data bit according to the next data */ if ( ucNextData & ucNextMask ) { ucTdi |= ucTdiMask; /* Set bit */ } else { ucTdi &= ( ~ucTdiMask ); /* Clear bit */ } /* Update the next data */ ucNextMask <<= 1; } ucTdiMask <<= 1; ucDataMask >>= 1; } /* Update the TDI value */ plvTdi->val[ i ] = ucTdi; } } } #endif /* XSVF_SUPPORT_COMPRESSION */ /*============================================================================ * XSVF Command Functions (type = TXsvfDoCmdFuncPtr) * These functions update pXsvfInfo->iErrorCode only on an error. * Otherwise, the error code is left alone. * The function returns the error code from the function. ============================================================================*/ /***************************************************************************** * Function: xsvfDoIllegalCmd * Description: Function place holder for illegal/unsupported commands. * Parameters: pXsvfInfo - XSVF information pointer. * Returns: int - 0 = success; non-zero = error. *****************************************************************************/ int xsvfDoIllegalCmd( SXsvfInfo* pXsvfInfo ) { XSVFDBG_PRINTF2( 0, "ERROR: Encountered unsupported command #%d (%s)\n", ((unsigned int)(pXsvfInfo->ucCommand)), ((pXsvfInfo->ucCommand < XLASTCMD) ? (xsvf_pzCommandName[pXsvfInfo->ucCommand]) : "Unknown") ); pXsvfInfo->iErrorCode = XSVF_ERROR_ILLEGALCMD; return( pXsvfInfo->iErrorCode ); } /***************************************************************************** * Function: xsvfDoXCOMPLETE * Description: XCOMPLETE (no parameters) * Update complete status for XSVF player. * Parameters: pXsvfInfo - XSVF information pointer. * Returns: int - 0 = success; non-zero = error. *****************************************************************************/ int xsvfDoXCOMPLETE( SXsvfInfo* pXsvfInfo ) { pXsvfInfo->ucComplete = 1; return( XSVF_ERROR_NONE ); } /***************************************************************************** * Function: xsvfDoXTDOMASK * Description: XTDOMASK * Prespecify the TDO compare mask. * Parameters: pXsvfInfo - XSVF information pointer. * Returns: int - 0 = success; non-zero = error. *****************************************************************************/ int xsvfDoXTDOMASK( SXsvfInfo* pXsvfInfo ) { readVal( &(pXsvfInfo->lvTdoMask), pXsvfInfo->sShiftLengthBytes ); XSVFDBG_PRINTF( 4, " TDO Mask = "); XSVFDBG_PRINTLENVAL( 4, &(pXsvfInfo->lvTdoMask) ); XSVFDBG_PRINTF( 4, "\n"); return( XSVF_ERROR_NONE ); } /***************************************************************************** * Function: xsvfDoXSIR * Description: XSIR <(byte)shiftlen> * Get the instruction and shift the instruction into the TAP. * If prespecified XRUNTEST!=0, goto RUNTEST and wait after * the shift for XRUNTEST usec. * Parameters: pXsvfInfo - XSVF information pointer. * Returns: int - 0 = success; non-zero = error. *****************************************************************************/ int xsvfDoXSIR( SXsvfInfo* pXsvfInfo ) { unsigned char ucShiftIrBits; short sShiftIrBytes; int iErrorCode; /* Get the shift length and store */ readByte( &ucShiftIrBits ); sShiftIrBytes = xsvfGetAsNumBytes( ucShiftIrBits ); XSVFDBG_PRINTF1( 3, " XSIR length = %d\n", ((unsigned int)ucShiftIrBits) ); if ( sShiftIrBytes > MAX_LEN ) { iErrorCode = XSVF_ERROR_DATAOVERFLOW; } else { /* Get and store instruction to shift in */ readVal( &(pXsvfInfo->lvTdi), xsvfGetAsNumBytes( ucShiftIrBits ) ); /* Shift the data */ iErrorCode = xsvfShift( &(pXsvfInfo->ucTapState), XTAPSTATE_SHIFTIR, ucShiftIrBits, &(pXsvfInfo->lvTdi), /*plvTdoCaptured*/0, /*plvTdoExpected*/0, /*plvTdoMask*/0, pXsvfInfo->ucEndIR, pXsvfInfo->lRunTestTime, /*ucMaxRepeat*/0 ); } if ( iErrorCode != XSVF_ERROR_NONE ) { pXsvfInfo->iErrorCode = iErrorCode; } return( iErrorCode ); } /***************************************************************************** * Function: xsvfDoXSIR2 * Description: XSIR <(2-byte)shiftlen> * Get the instruction and shift the instruction into the TAP. * If prespecified XRUNTEST!=0, goto RUNTEST and wait after * the shift for XRUNTEST usec. * Parameters: pXsvfInfo - XSVF information pointer. * Returns: int - 0 = success; non-zero = error. *****************************************************************************/ int xsvfDoXSIR2( SXsvfInfo* pXsvfInfo ) { long lShiftIrBits; short sShiftIrBytes; int iErrorCode; /* Get the shift length and store */ readVal( &(pXsvfInfo->lvTdi), 2 ); lShiftIrBits = value( &(pXsvfInfo->lvTdi) ); sShiftIrBytes = xsvfGetAsNumBytes( lShiftIrBits ); XSVFDBG_PRINTF1( 3, " XSIR2 length = %d\n", (int)lShiftIrBits); if ( sShiftIrBytes > MAX_LEN ) { iErrorCode = XSVF_ERROR_DATAOVERFLOW; } else { /* Get and store instruction to shift in */ readVal( &(pXsvfInfo->lvTdi), xsvfGetAsNumBytes( lShiftIrBits ) ); /* Shift the data */ iErrorCode = xsvfShift( &(pXsvfInfo->ucTapState), XTAPSTATE_SHIFTIR, lShiftIrBits, &(pXsvfInfo->lvTdi), /*plvTdoCaptured*/0, /*plvTdoExpected*/0, /*plvTdoMask*/0, pXsvfInfo->ucEndIR, pXsvfInfo->lRunTestTime, /*ucMaxRepeat*/0 ); } if ( iErrorCode != XSVF_ERROR_NONE ) { pXsvfInfo->iErrorCode = iErrorCode; } return( iErrorCode ); } /***************************************************************************** * Function: xsvfDoXSDR * Description: XSDR * Shift the given TDI data into the JTAG scan chain. * Compare the captured TDO with the expected TDO from the * previous XSDRTDO command using the previously specified * XTDOMASK. * Parameters: pXsvfInfo - XSVF information pointer. * Returns: int - 0 = success; non-zero = error. *****************************************************************************/ int xsvfDoXSDR( SXsvfInfo* pXsvfInfo ) { int iErrorCode; readVal( &(pXsvfInfo->lvTdi), pXsvfInfo->sShiftLengthBytes ); /* use TDOExpected from last XSDRTDO instruction */ iErrorCode = xsvfShift( &(pXsvfInfo->ucTapState), XTAPSTATE_SHIFTDR, pXsvfInfo->lShiftLengthBits, &(pXsvfInfo->lvTdi), &(pXsvfInfo->lvTdoCaptured), &(pXsvfInfo->lvTdoExpected), &(pXsvfInfo->lvTdoMask), pXsvfInfo->ucEndDR, pXsvfInfo->lRunTestTime, pXsvfInfo->ucMaxRepeat ); if ( iErrorCode != XSVF_ERROR_NONE ) { pXsvfInfo->iErrorCode = iErrorCode; } return( iErrorCode ); } /***************************************************************************** * Function: xsvfDoXRUNTEST * Description: XRUNTEST * Prespecify the XRUNTEST wait time for shift operations. * Parameters: pXsvfInfo - XSVF information pointer. * Returns: int - 0 = success; non-zero = error. *****************************************************************************/ int xsvfDoXRUNTEST( SXsvfInfo* pXsvfInfo ) { readVal( &(pXsvfInfo->lvTdi), 4 ); pXsvfInfo->lRunTestTime = value( &(pXsvfInfo->lvTdi) ); XSVFDBG_PRINTF1( 3, " XRUNTEST = %ld\n", pXsvfInfo->lRunTestTime ); return( XSVF_ERROR_NONE ); } /***************************************************************************** * Function: xsvfDoXREPEAT * Description: XREPEAT * Prespecify the maximum number of XC9500/XL retries. * Parameters: pXsvfInfo - XSVF information pointer. * Returns: int - 0 = success; non-zero = error. *****************************************************************************/ int xsvfDoXREPEAT( SXsvfInfo* pXsvfInfo ) { readByte( &(pXsvfInfo->ucMaxRepeat) ); XSVFDBG_PRINTF1( 3, " XREPEAT = %d\n", ((unsigned int)(pXsvfInfo->ucMaxRepeat)) ); return( XSVF_ERROR_NONE ); } /***************************************************************************** * Function: xsvfDoXSDRSIZE * Description: XSDRSIZE * Prespecify the XRUNTEST wait time for shift operations. * Parameters: pXsvfInfo - XSVF information pointer. * Returns: int - 0 = success; non-zero = error. *****************************************************************************/ int xsvfDoXSDRSIZE( SXsvfInfo* pXsvfInfo ) { int iErrorCode; iErrorCode = XSVF_ERROR_NONE; readVal( &(pXsvfInfo->lvTdi), 4 ); pXsvfInfo->lShiftLengthBits = value( &(pXsvfInfo->lvTdi) ); pXsvfInfo->sShiftLengthBytes= xsvfGetAsNumBytes( pXsvfInfo->lShiftLengthBits ); XSVFDBG_PRINTF1( 3, " XSDRSIZE = %ld\n", pXsvfInfo->lShiftLengthBits ); if ( pXsvfInfo->sShiftLengthBytes > MAX_LEN ) { iErrorCode = XSVF_ERROR_DATAOVERFLOW; pXsvfInfo->iErrorCode = iErrorCode; } return( iErrorCode ); } /***************************************************************************** * Function: xsvfDoXSDRTDO * Description: XSDRTDO * Get the TDI and expected TDO values. Then, shift. * Compare the expected TDO with the captured TDO using the * prespecified XTDOMASK. * Parameters: pXsvfInfo - XSVF information pointer. * Returns: int - 0 = success; non-zero = error. *****************************************************************************/ int xsvfDoXSDRTDO( SXsvfInfo* pXsvfInfo ) { int iErrorCode; iErrorCode = xsvfBasicXSDRTDO( &(pXsvfInfo->ucTapState), pXsvfInfo->lShiftLengthBits, pXsvfInfo->sShiftLengthBytes, &(pXsvfInfo->lvTdi), &(pXsvfInfo->lvTdoCaptured), &(pXsvfInfo->lvTdoExpected), &(pXsvfInfo->lvTdoMask), pXsvfInfo->ucEndDR, pXsvfInfo->lRunTestTime, pXsvfInfo->ucMaxRepeat ); if ( iErrorCode != XSVF_ERROR_NONE ) { pXsvfInfo->iErrorCode = iErrorCode; } return( iErrorCode ); } /***************************************************************************** * Function: xsvfDoXSETSDRMASKS * Description: XSETSDRMASKS * * Get the prespecified address and data mask for the XSDRINC * command. * Used for xc9500/xl compressed XSVF data. * Parameters: pXsvfInfo - XSVF information pointer. * Returns: int - 0 = success; non-zero = error. *****************************************************************************/ #ifdef XSVF_SUPPORT_COMPRESSION int xsvfDoXSETSDRMASKS( SXsvfInfo* pXsvfInfo ) { /* read the addressMask */ readVal( &(pXsvfInfo->lvAddressMask), pXsvfInfo->sShiftLengthBytes ); /* read the dataMask */ readVal( &(pXsvfInfo->lvDataMask), pXsvfInfo->sShiftLengthBytes ); XSVFDBG_PRINTF( 4, " Address Mask = " ); XSVFDBG_PRINTLENVAL( 4, &(pXsvfInfo->lvAddressMask) ); XSVFDBG_PRINTF( 4, "\n" ); XSVFDBG_PRINTF( 4, " Data Mask = " ); XSVFDBG_PRINTLENVAL( 4, &(pXsvfInfo->lvDataMask) ); XSVFDBG_PRINTF( 4, "\n" ); return( XSVF_ERROR_NONE ); } #endif /* XSVF_SUPPORT_COMPRESSION */ /***************************************************************************** * Function: xsvfDoXSDRINC * Description: XSDRINC * ... * Get the XSDRINC parameters and execute the XSDRINC command. * XSDRINC starts by loading the first TDI shift value. * Then, for numTimes, XSDRINC gets the next piece of data, * replaces the bits from the starting TDI as defined by the * XSETSDRMASKS.dataMask, adds the address mask from * XSETSDRMASKS.addressMask, shifts the new TDI value, * and compares the TDO to the expected TDO from the previous * XSDRTDO command using the XTDOMASK. * Used for xc9500/xl compressed XSVF data. * Parameters: pXsvfInfo - XSVF information pointer. * Returns: int - 0 = success; non-zero = error. *****************************************************************************/ #ifdef XSVF_SUPPORT_COMPRESSION int xsvfDoXSDRINC( SXsvfInfo* pXsvfInfo ) { int iErrorCode; int iDataMaskLen; unsigned char ucDataMask; unsigned char ucNumTimes; unsigned char i; readVal( &(pXsvfInfo->lvTdi), pXsvfInfo->sShiftLengthBytes ); iErrorCode = xsvfShift( &(pXsvfInfo->ucTapState), XTAPSTATE_SHIFTDR, pXsvfInfo->lShiftLengthBits, &(pXsvfInfo->lvTdi), &(pXsvfInfo->lvTdoCaptured), &(pXsvfInfo->lvTdoExpected), &(pXsvfInfo->lvTdoMask), pXsvfInfo->ucEndDR, pXsvfInfo->lRunTestTime, pXsvfInfo->ucMaxRepeat ); if ( !iErrorCode ) { /* Calculate number of data mask bits */ iDataMaskLen = 0; for ( i = 0; i < pXsvfInfo->lvDataMask.len; ++i ) { ucDataMask = pXsvfInfo->lvDataMask.val[ i ]; while ( ucDataMask ) { iDataMaskLen += ( ucDataMask & 1 ); ucDataMask >>= 1; } } /* Get the number of data pieces, i.e. number of times to shift */ readByte( &ucNumTimes ); /* For numTimes, get data, fix TDI, and shift */ for ( i = 0; !iErrorCode && ( i < ucNumTimes ); ++i ) { readVal( &(pXsvfInfo->lvNextData), xsvfGetAsNumBytes( iDataMaskLen ) ); xsvfDoSDRMasking( &(pXsvfInfo->lvTdi), &(pXsvfInfo->lvNextData), &(pXsvfInfo->lvAddressMask), &(pXsvfInfo->lvDataMask) ); iErrorCode = xsvfShift( &(pXsvfInfo->ucTapState), XTAPSTATE_SHIFTDR, pXsvfInfo->lShiftLengthBits, &(pXsvfInfo->lvTdi), &(pXsvfInfo->lvTdoCaptured), &(pXsvfInfo->lvTdoExpected), &(pXsvfInfo->lvTdoMask), pXsvfInfo->ucEndDR, pXsvfInfo->lRunTestTime, pXsvfInfo->ucMaxRepeat ); } } if ( iErrorCode != XSVF_ERROR_NONE ) { pXsvfInfo->iErrorCode = iErrorCode; } return( iErrorCode ); } #endif /* XSVF_SUPPORT_COMPRESSION */ /***************************************************************************** * Function: xsvfDoXSDRBCE * Description: XSDRB/XSDRC/XSDRE * If not already in SHIFTDR, goto SHIFTDR. * Shift the given TDI data into the JTAG scan chain. * Ignore TDO. * If cmd==XSDRE, then goto ENDDR. Otherwise, stay in ShiftDR. * XSDRB, XSDRC, and XSDRE are the same implementation. * Parameters: pXsvfInfo - XSVF information pointer. * Returns: int - 0 = success; non-zero = error. *****************************************************************************/ int xsvfDoXSDRBCE( SXsvfInfo* pXsvfInfo ) { unsigned char ucEndDR; int iErrorCode; ucEndDR = (unsigned char)(( pXsvfInfo->ucCommand == XSDRE ) ? pXsvfInfo->ucEndDR : XTAPSTATE_SHIFTDR); iErrorCode = xsvfBasicXSDRTDO( &(pXsvfInfo->ucTapState), pXsvfInfo->lShiftLengthBits, pXsvfInfo->sShiftLengthBytes, &(pXsvfInfo->lvTdi), /*plvTdoCaptured*/0, /*plvTdoExpected*/0, /*plvTdoMask*/0, ucEndDR, /*lRunTestTime*/0, /*ucMaxRepeat*/0 ); if ( iErrorCode != XSVF_ERROR_NONE ) { pXsvfInfo->iErrorCode = iErrorCode; } return( iErrorCode ); } /***************************************************************************** * Function: xsvfDoXSDRTDOBCE * Description: XSDRB/XSDRC/XSDRE * If not already in SHIFTDR, goto SHIFTDR. * Shift the given TDI data into the JTAG scan chain. * Compare TDO, but do NOT use XTDOMASK. * If cmd==XSDRTDOE, then goto ENDDR. Otherwise, stay in ShiftDR. * XSDRTDOB, XSDRTDOC, and XSDRTDOE are the same implementation. * Parameters: pXsvfInfo - XSVF information pointer. * Returns: int - 0 = success; non-zero = error. *****************************************************************************/ int xsvfDoXSDRTDOBCE( SXsvfInfo* pXsvfInfo ) { unsigned char ucEndDR; int iErrorCode; ucEndDR = (unsigned char)(( pXsvfInfo->ucCommand == XSDRTDOE ) ? pXsvfInfo->ucEndDR : XTAPSTATE_SHIFTDR); iErrorCode = xsvfBasicXSDRTDO( &(pXsvfInfo->ucTapState), pXsvfInfo->lShiftLengthBits, pXsvfInfo->sShiftLengthBytes, &(pXsvfInfo->lvTdi), &(pXsvfInfo->lvTdoCaptured), &(pXsvfInfo->lvTdoExpected), /*plvTdoMask*/0, ucEndDR, /*lRunTestTime*/0, /*ucMaxRepeat*/0 ); if ( iErrorCode != XSVF_ERROR_NONE ) { pXsvfInfo->iErrorCode = iErrorCode; } return( iErrorCode ); } /***************************************************************************** * Function: xsvfDoXSTATE * Description: XSTATE * == XTAPSTATE; * Get the state parameter and transition the TAP to that state. * Parameters: pXsvfInfo - XSVF information pointer. * Returns: int - 0 = success; non-zero = error. *****************************************************************************/ int xsvfDoXSTATE( SXsvfInfo* pXsvfInfo ) { unsigned char ucNextState; int iErrorCode; readByte( &ucNextState ); iErrorCode = xsvfGotoTapState( &(pXsvfInfo->ucTapState), ucNextState ); if ( iErrorCode != XSVF_ERROR_NONE ) { pXsvfInfo->iErrorCode = iErrorCode; } return( iErrorCode ); } /***************************************************************************** * Function: xsvfDoXENDXR * Description: XENDIR/XENDDR * : 0 = RUNTEST; 1 = PAUSE. * Get the prespecified XENDIR or XENDDR. * Both XENDIR and XENDDR use the same implementation. * Parameters: pXsvfInfo - XSVF information pointer. * Returns: int - 0 = success; non-zero = error. *****************************************************************************/ int xsvfDoXENDXR( SXsvfInfo* pXsvfInfo ) { int iErrorCode; unsigned char ucEndState; iErrorCode = XSVF_ERROR_NONE; readByte( &ucEndState ); if ( ( ucEndState != XENDXR_RUNTEST ) && ( ucEndState != XENDXR_PAUSE ) ) { iErrorCode = XSVF_ERROR_ILLEGALSTATE; } else { if ( pXsvfInfo->ucCommand == XENDIR ) { if ( ucEndState == XENDXR_RUNTEST ) { pXsvfInfo->ucEndIR = XTAPSTATE_RUNTEST; } else { pXsvfInfo->ucEndIR = XTAPSTATE_PAUSEIR; } XSVFDBG_PRINTF1( 3, " ENDIR State = %s\n", xsvf_pzTapState[ pXsvfInfo->ucEndIR ] ); } else /* XENDDR */ { if ( ucEndState == XENDXR_RUNTEST ) { pXsvfInfo->ucEndDR = XTAPSTATE_RUNTEST; } else { pXsvfInfo->ucEndDR = XTAPSTATE_PAUSEDR; } XSVFDBG_PRINTF1( 3, " ENDDR State = %s\n", xsvf_pzTapState[ pXsvfInfo->ucEndDR ] ); } } if ( iErrorCode != XSVF_ERROR_NONE ) { pXsvfInfo->iErrorCode = iErrorCode; } return( iErrorCode ); } /***************************************************************************** * Function: xsvfDoXCOMMENT * Description: XCOMMENT * == text comment; * Arbitrary comment embedded in the XSVF. * Parameters: pXsvfInfo - XSVF information pointer. * Returns: int - 0 = success; non-zero = error. *****************************************************************************/ int xsvfDoXCOMMENT( SXsvfInfo* pXsvfInfo ) { /* Use the comment for debugging */ /* Otherwise, read through the comment to the end '\0' and ignore */ unsigned char ucText; if ( xsvf_iDebugLevel > 0 ) { putc( ' ' ); } do { readByte( &ucText ); if ( xsvf_iDebugLevel > 0 ) { putc( ucText ? ucText : '\n' ); } } while ( ucText ); pXsvfInfo->iErrorCode = XSVF_ERROR_NONE; return( pXsvfInfo->iErrorCode ); } /***************************************************************************** * Function: xsvfDoXWAIT * Description: XWAIT * If not already in , then go to . * Wait in for microseconds. * Finally, if not already in , then goto . * Parameters: pXsvfInfo - XSVF information pointer. * Returns: int - 0 = success; non-zero = error. *****************************************************************************/ int xsvfDoXWAIT( SXsvfInfo* pXsvfInfo ) { unsigned char ucWaitState; unsigned char ucEndState; long lWaitTime; /* Get Parameters */ /* */ readVal( &(pXsvfInfo->lvTdi), 1 ); ucWaitState = pXsvfInfo->lvTdi.val[0]; /* */ readVal( &(pXsvfInfo->lvTdi), 1 ); ucEndState = pXsvfInfo->lvTdi.val[0]; /* */ readVal( &(pXsvfInfo->lvTdi), 4 ); lWaitTime = value( &(pXsvfInfo->lvTdi) ); XSVFDBG_PRINTF2( 3, " XWAIT: state = %s; time = %ld\n", xsvf_pzTapState[ ucWaitState ], lWaitTime ); /* If not already in , go to */ if ( pXsvfInfo->ucTapState != ucWaitState ) { xsvfGotoTapState( &(pXsvfInfo->ucTapState), ucWaitState ); } /* Wait for microseconds */ waitTime( lWaitTime ); /* If not already in , go to */ if ( pXsvfInfo->ucTapState != ucEndState ) { xsvfGotoTapState( &(pXsvfInfo->ucTapState), ucEndState ); } return( XSVF_ERROR_NONE ); } /*============================================================================ * Execution Control Functions ============================================================================*/ /***************************************************************************** * Function: xsvfInitialize * Description: Initialize the xsvf player. * Call this before running the player to initialize the data * in the SXsvfInfo struct. * xsvfCleanup is called to clean up the data in SXsvfInfo * after the XSVF is played. * Parameters: pXsvfInfo - ptr to the XSVF information. * Returns: int - 0 = success; otherwise error. *****************************************************************************/ int xsvfInitialize( SXsvfInfo* pXsvfInfo ) { /* Initialize values */ pXsvfInfo->iErrorCode = xsvfInfoInit( pXsvfInfo ); if ( !pXsvfInfo->iErrorCode ) { /* Initialize the TAPs */ pXsvfInfo->iErrorCode = xsvfGotoTapState( &(pXsvfInfo->ucTapState), XTAPSTATE_RESET ); } return( pXsvfInfo->iErrorCode ); } /***************************************************************************** * Function: xsvfRun * Description: Run the xsvf player for a single command and return. * First, call xsvfInitialize. * Then, repeatedly call this function until an error is detected * or until the pXsvfInfo->ucComplete variable is non-zero. * Finally, call xsvfCleanup to cleanup any remnants. * Parameters: pXsvfInfo - ptr to the XSVF information. * Returns: int - 0 = success; otherwise error. *****************************************************************************/ int xsvfRun( SXsvfInfo* pXsvfInfo ) { /* Process the XSVF commands */ if ( (!pXsvfInfo->iErrorCode) && (!pXsvfInfo->ucComplete) ) { /* read 1 byte for the instruction */ readByte( &(pXsvfInfo->ucCommand) ); ++(pXsvfInfo->lCommandCount); if ( pXsvfInfo->ucCommand < XLASTCMD ) { /* Execute the command. Func sets error code. */ XSVFDBG_PRINTF1( 2, " %s\n", xsvf_pzCommandName[pXsvfInfo->ucCommand] ); /* If your compiler cannot take this form, then convert to a switch statement */ #if 0 /* test-only */ xsvf_pfDoCmd[ pXsvfInfo->ucCommand ]( pXsvfInfo ); #else switch (pXsvfInfo->ucCommand) { case 0: xsvfDoXCOMPLETE(pXsvfInfo); /* 0 */ break; case 1: xsvfDoXTDOMASK(pXsvfInfo); /* 1 */ break; case 2: xsvfDoXSIR(pXsvfInfo); /* 2 */ break; case 3: xsvfDoXSDR(pXsvfInfo); /* 3 */ break; case 4: xsvfDoXRUNTEST(pXsvfInfo); /* 4 */ break; case 5: xsvfDoIllegalCmd(pXsvfInfo); /* 5 */ break; case 6: xsvfDoIllegalCmd(pXsvfInfo); /* 6 */ break; case 7: xsvfDoXREPEAT(pXsvfInfo); /* 7 */ break; case 8: xsvfDoXSDRSIZE(pXsvfInfo); /* 8 */ break; case 9: xsvfDoXSDRTDO(pXsvfInfo); /* 9 */ break; #ifdef XSVF_SUPPORT_COMPRESSION case 10: xsvfDoXSETSDRMASKS(pXsvfInfo); /* 10 */ break; case 11: xsvfDoXSDRINC(pXsvfInfo); /* 11 */ break; #else case 10: xsvfDoIllegalCmd(pXsvfInfo); /* 10 */ break; case 11: xsvfDoIllegalCmd(pXsvfInfo); /* 11 */ break; #endif /* XSVF_SUPPORT_COMPRESSION */ case 12: xsvfDoXSDRBCE(pXsvfInfo); /* 12 */ break; case 13: xsvfDoXSDRBCE(pXsvfInfo); /* 13 */ break; case 14: xsvfDoXSDRBCE(pXsvfInfo); /* 14 */ break; case 15: xsvfDoXSDRTDOBCE(pXsvfInfo); /* 15 */ break; case 16: xsvfDoXSDRTDOBCE(pXsvfInfo); /* 16 */ break; case 17: xsvfDoXSDRTDOBCE(pXsvfInfo); /* 17 */ break; case 18: xsvfDoXSTATE(pXsvfInfo); /* 18 */ break; case 19: xsvfDoXENDXR(pXsvfInfo); /* 19 */ break; case 20: xsvfDoXENDXR(pXsvfInfo); /* 20 */ break; case 21: xsvfDoXSIR2(pXsvfInfo); /* 21 */ break; case 22: xsvfDoXCOMMENT(pXsvfInfo); /* 22 */ break; case 23: xsvfDoXWAIT(pXsvfInfo); /* 23 */ break; } #endif } else { /* Illegal command value. Func sets error code. */ xsvfDoIllegalCmd( pXsvfInfo ); } } return( pXsvfInfo->iErrorCode ); } /***************************************************************************** * Function: xsvfCleanup * Description: cleanup remnants of the xsvf player. * Parameters: pXsvfInfo - ptr to the XSVF information. * Returns: void. *****************************************************************************/ void xsvfCleanup( SXsvfInfo* pXsvfInfo ) { xsvfInfoCleanup( pXsvfInfo ); } /*============================================================================ * xsvfExecute() - The primary entry point to the XSVF player ============================================================================*/ /***************************************************************************** * Function: xsvfExecute * Description: Process, interpret, and apply the XSVF commands. * See port.c:readByte for source of XSVF data. * Parameters: none. * Returns: int - Legacy result values: 1 == success; 0 == failed. *****************************************************************************/ int xsvfExecute(void) { SXsvfInfo xsvfInfo; xsvfInitialize( &xsvfInfo ); while ( !xsvfInfo.iErrorCode && (!xsvfInfo.ucComplete) ) { xsvfRun( &xsvfInfo ); } if ( xsvfInfo.iErrorCode ) { XSVFDBG_PRINTF1( 0, "%s\n", xsvf_pzErrorName[ ( xsvfInfo.iErrorCode < XSVF_ERROR_LAST ) ? xsvfInfo.iErrorCode : XSVF_ERROR_UNKNOWN ] ); XSVFDBG_PRINTF2( 0, "ERROR at or near XSVF command #%ld. See line #%ld in the XSVF ASCII file.\n", xsvfInfo.lCommandCount, xsvfInfo.lCommandCount ); } else { XSVFDBG_PRINTF( 0, "SUCCESS - Completed XSVF execution.\n" ); } xsvfCleanup( &xsvfInfo ); return( XSVF_ERRORCODE(xsvfInfo.iErrorCode) ); } /***************************************************************************** * Function: do_cpld * Description: main function. * Specified here for creating stand-alone debug executable. * Embedded users should call xsvfExecute() directly. * Parameters: iArgc - number of command-line arguments. * ppzArgv - array of ptrs to strings (command-line arguments). * Returns: int - Legacy return value: 1 = success; 0 = error. *****************************************************************************/ int do_cpld(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { int iErrorCode; unsigned long duration; unsigned long long startClock, endClock; if (argc == 2) xsvfdata = (unsigned char *)simple_strtoul(argv[1], NULL, 16); else { #ifdef CONFIG_SYS_XSVF_DEFAULT_ADDR xsvfdata = (unsigned char *)CONFIG_SYS_XSVF_DEFAULT_ADDR; #else printf("Usage:\ncpld %s\n", cmdtp->help); return -1; #endif } iErrorCode = XSVF_ERRORCODE( XSVF_ERROR_NONE ); xsvf_iDebugLevel = 0; printf("XSVF Player v%s, Xilinx, Inc.\n", XSVF_VERSION); printf("Reading XSVF data @ %p\n", xsvfdata); /* Initialize the I/O. SetPort initializes I/O on first call */ setPort( TMS, 1 ); /* Execute the XSVF in the file */ startClock = get_ticks(); iErrorCode = xsvfExecute(); endClock = get_ticks(); duration = (unsigned long)(endClock - startClock); printf("\nExecution Time = %d seconds\n", (int)(duration/get_tbclk())); return( iErrorCode ); } U_BOOT_CMD( cpld, 2, 1, do_cpld, "program onboard CPLD", "" );