summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Daniel <cd@maintech.de>2012-05-17 22:47:51 +0200
committerChristian Daniel <cd@maintech.de>2012-05-17 22:47:51 +0200
commit5dcfd6a1568a40a5331c0cc8963c0f920858b27c (patch)
treeae2a8dfa646d2b04abefdfd14d46a4a6fea07421
parentc46bad77e52425448b0c67d915b31b6bd1ee8024 (diff)
added DFU functionality for the FPGA - crudely removed stuff from the loader to make it fit into the 16k
-rw-r--r--firmware/usb-dfu-project/hardware.c226
-rw-r--r--firmware/usb-dfu-project/hardware.h11
-rw-r--r--firmware/usb-dfu-project/main.c136
-rw-r--r--firmware/usb-dfu-project/opcode.h135
-rw-r--r--firmware/usb-dfu-project/slimpro.c1255
5 files changed, 1747 insertions, 16 deletions
diff --git a/firmware/usb-dfu-project/hardware.c b/firmware/usb-dfu-project/hardware.c
new file mode 100644
index 0000000..999e3f5
--- /dev/null
+++ b/firmware/usb-dfu-project/hardware.c
@@ -0,0 +1,226 @@
+/**************************************************************
+*
+* Lattice Semiconductor Corp. Copyright 2008
+*
+*
+***************************************************************/
+
+
+/**************************************************************
+*
+* Revision History of hardware.c
+*
+*
+* 09/11/07 NN type cast all the mismatch variables
+***************************************************************/
+
+#include <stdio.h>
+#include <unistd.h>
+#include "opcode.h"
+#include "hardware.h"
+
+/*************************************************************
+* *
+* EXTERNAL FUNCTION *
+* *
+*************************************************************/
+
+extern void ispVMStateMachine( char a_cNextState );
+
+/*************************************************************
+* *
+* READPORT *
+* *
+* INPUT: *
+* None. *
+* *
+* RETURN: *
+* Returns the bit read back from the device. *
+* *
+* DESCRIPTION: *
+* This function is used to read the TDO pin from the *
+* input port. *
+* *
+* NOTE: This function should be modified in an embedded *
+* system! *
+* *
+*************************************************************/
+
+int readPort()
+{
+ uint32_t value;
+
+ value = *((volatile uint32_t*)(0x400e0e00 + 0x3c));
+
+ if(value & (1 << 6))
+ return 1;
+ else return 0;
+}
+
+/*************************************************************
+* *
+* WRITEPORT *
+* *
+* INPUT: *
+* a_ucPins: a byte to indicate which pin will be *
+* depending on the value. *
+* *
+* a_ucValue: the value to determine of the pin above *
+* will be written out or not. *
+* *
+* RETURN: *
+* None. *
+* *
+* DESCRIPTION: *
+* 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. *
+* *
+* NOTE: This function should be modified in an embedded *
+* system! *
+* *
+*************************************************************/
+
+void writePort( unsigned int a_ucPins, unsigned int a_ucValue )
+{
+ uint32_t value = 0;
+
+ if(a_ucPins & pinTDI)
+ value |= (1 << 8);
+ if(a_ucPins & pinTCK)
+ value |= (1 << 7);
+ if(a_ucPins & pinTMS)
+ value |= (1 << 5);
+
+ if(a_ucValue)
+ *((volatile uint32_t*)(0x400e0e00 + 0x30)) = value;
+ else *((volatile uint32_t*)(0x400e0e00 + 0x34)) = value;
+}
+
+/*************************************************************
+* *
+* ISPVMDELAY *
+* *
+* INPUT: *
+* a_uiDelay: delay in milliseconds *
+* *
+* RETURN: *
+* None. *
+* *
+* DESCRIPTION: *
+* The user must implement a delay to observe a_uiDelay, *
+* where a_uiDelay is the number of milliseconds that must *
+* pass before data is read from in_port. Since platforms and*
+* processor speeds vary greatly, this task is left to the *
+* user. This subroutine is called upon to provide a delay *
+* from 1 millisecond to a few hundreds milliseconds each time*
+* That is the reason behind using unsigned long integer in *
+* this subroutine. It is OK to provide longer delay than *
+* required. It is not acceptable if the delay is shorter than*
+* required. *
+* *
+* Note: user must re - implement to target specific hardware.*
+* *
+* Example: Use the for loop to create the microsecond delay. *
+* Loop 1K times to produce the milliseconds delay. *
+* *
+* Let the CPU clock (system clock) be F Mhz. *
+* *
+* Let the for loop represented by the 2 lines of *
+* machine code: *
+* LOOP: DEC RA; *
+* JNZ LOOP; *
+* Let the for loop number for one microsecond be L. *
+* Lets assume 4 system clocks for each line of *
+* machine code. *
+* Then 1 us = 1/F (microseconds per clock) *
+* x (2 lines) x (4 clocks per line) x L*
+* = 8L/F *
+* Or L = F/8; *
+* *
+* Convert the unit in microseconds to *
+* milliseconds. *
+* L = F/8 x 1000; *
+* Lets assume the CPU clock is set to 48MHZ. The C *
+* code then is: *
+* *
+* unsigned int F = 48; //MHZ. *
+* unsigned int L = F/8; //microseconds. *
+* unsigned int index, m; *
+* *
+* *
+* if (L < 1) L = 1; //minimum is i microsecond. *
+* for (index=0; index < a_uiDelay * L; index++) *
+* { *
+* //loop 1K times to produce milliseconds delay *
+* for (m=0; m<1000; m++); //milliseconds *
+* } *
+* return 0; *
+* *
+* *
+*************************************************************/
+
+/* the unit of a_uiDelay is milliseconds */
+void ispVMDelay( unsigned int a_uiDelay )
+{
+ // yes, this is more or less calibrated - cd
+ volatile int i, j;
+ for(i = 0; i < a_uiDelay; i++) {
+ for(j = 0; j < 5000; j++)
+ asm("nop");
+ }
+}
+
+/*************************************************************
+* *
+* ENABLEHARDWARE *
+* *
+* INPUT: *
+* None. *
+* *
+* RETURN: *
+* None. *
+* *
+* DESCRIPTION: *
+* This function is called to enable the hardware. *
+* *
+* NOTE: This function should be modified in an embedded *
+* system! *
+* *
+*************************************************************/
+
+void EnableHardware()
+{
+ ispVMStateMachine(RESET);
+}
+
+/*************************************************************
+* *
+* DISABLEHARDWARE *
+* *
+* INPUT: *
+* None. *
+* *
+* RETURN: *
+* None. *
+* *
+* DESCRIPTION: *
+* This function is called to disable the hardware. *
+* *
+* NOTE: This function should be modified in an embedded *
+* system! *
+* *
+*************************************************************/
+
+void DisableHardware()
+{
+ ispVMStateMachine(RESET);
+}
+
+
diff --git a/firmware/usb-dfu-project/hardware.h b/firmware/usb-dfu-project/hardware.h
new file mode 100644
index 0000000..e343605
--- /dev/null
+++ b/firmware/usb-dfu-project/hardware.h
@@ -0,0 +1,11 @@
+#ifndef INCLUDE_HARDWARE_H
+#define INCLUDE_HARDWARE_H
+
+#include <stdint.h>
+
+const uint8_t* g_ispAlgo;
+size_t g_ispAlgoSize;
+const uint8_t* g_ispData;
+size_t g_ispDataSize;
+
+#endif // INCLUDE_HARDWARE_H
diff --git a/firmware/usb-dfu-project/main.c b/firmware/usb-dfu-project/main.c
index b7e47de..5e01092 100644
--- a/firmware/usb-dfu-project/main.c
+++ b/firmware/usb-dfu-project/main.c
@@ -62,6 +62,8 @@
#include "dfu_desc.h"
+#include "opcode.h"
+
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
/*----------------------------------------------------------------------------
@@ -104,12 +106,12 @@ static void ISR_Vbus(const Pin *pPin)
/* Check current level on VBus */
if (PIO_Get(&pinVbus))
{
- TRACE_INFO("VBUS conn\n\r");
+ //TRACE_INFO("VBUS conn\n\r");
USBD_Connect();
}
else
{
- TRACE_INFO("VBUS discon\n\r");
+ //TRACE_INFO("VBUS discon\n\r");
USBD_Disconnect();
}
}
@@ -133,7 +135,7 @@ static void VBus_Configure( void )
}
else
{
- TRACE_INFO("discon\n\r");
+ //TRACE_INFO("discon\n\r");
USBD_Disconnect();
}
}
@@ -209,7 +211,7 @@ void USBDCallbacks_RequestReceived(const USBGenericRequest *request)
void USBDDriverCallbacks_InterfaceSettingChanged(unsigned char interface,
unsigned char setting)
{
- TRACE_INFO("DFU: IfSettingChgd(if=%u, alt=%u)\n\r", interface, setting);
+ //TRACE_INFO("DFU: IfSettingChgd(if=%u, alt=%u)\n\r", interface, setting);
}
#define BOOT_FLASH_SIZE (16 * 1024)
@@ -233,8 +235,8 @@ static const struct flash_part flash_parts[] = {
.size = AT91C_IRAM_SIZE,
},
[ALTIF_FPGA] = {
- .base_addr = AT91C_IFLASH1,
- .size = AT91C_IFLASH1_SIZE,
+ .base_addr = 0,
+ .size = 16*1024*1024, // really no limit
},
};
@@ -242,11 +244,13 @@ static const struct flash_part flash_parts[] = {
int USBDFU_handle_upload(uint8_t altif, unsigned int offset,
uint8_t *buf, unsigned int req_len)
{
+ return -EINVAL;
+#if 0
struct flash_part *part;
void *end, *addr;
uint32_t real_len;
- TRACE_INFO("DFU: handle_upload(%u, %u, %u)\n\r", altif, offset, req_len);
+ //TRACE_INFO("DFU: handle_upload(%u, %u, %u)\n\r", altif, offset, req_len);
if (altif > ARRAY_SIZE(flash_parts))
return -EINVAL;
@@ -265,6 +269,94 @@ int USBDFU_handle_upload(uint8_t altif, unsigned int offset,
LED_Clear(USBD_LEDOTHER);
return real_len;
+#endif
+}
+
+extern unsigned short g_usDataType;
+
+static uint8_t fpgaBuf[1024];
+static uint fpgaBufStart; // file offset of first byte in buffer
+static uint fpgaBufEnd;
+static uint fpgaBufFill;
+static uint fpgaBufRPtr;
+static uint fpgaPushedAddr;
+
+short int ispProcessVME();
+void EnableHardware();
+
+void fpgaPushAddr()
+{
+ fpgaPushedAddr = fpgaBufRPtr;
+}
+
+void fpgaPopAddr()
+{
+ printf("*");
+ fpgaBufRPtr = fpgaPushedAddr;
+}
+
+uint8_t fpgaGetByte()
+{
+ uint8_t res = fpgaBuf[fpgaBufRPtr - fpgaBufStart];
+ fpgaBufRPtr++;
+
+ return res;
+}
+
+static int fpgaFlash(unsigned int offset, const uint8_t* buf, unsigned int len)
+{
+ int i;
+
+ if(offset == 0) {
+ for(i = 0; i < len; i++)
+ fpgaBuf[i] = buf[i];
+ fpgaBufStart = 0;
+ fpgaBufEnd = len;
+ fpgaBufFill = len;
+ fpgaBufRPtr = 0;
+
+ *((uint32_t*)(0x400e0410)) = (1 << 11);
+ *((uint32_t*)(0x400e0e00 + 0x44)) = (1 << 5) | (1 << 6) | (1 << 7) | (1 << 8);
+ *((uint32_t*)(0x400e0e00 + 0x60)) = (1 << 5) | (1 << 6) | (1 << 7) | (1 << 8);
+ *((uint32_t*)(0x400e0e00 + 0x54)) = (1 << 5) | (1 << 6) | (1 << 7) | (1 << 8);
+ *((uint32_t*)(0x400e0e00 + 0x10)) = (1 << 5) | (1 << 7) | (1 << 8);
+ *((uint32_t*)(0x400e0e00 + 0x00)) = (1 << 5) | (1 << 6) | (1 << 7) | (1 << 8);
+
+ if(fpgaGetByte())
+ g_usDataType = COMPRESS;
+ else g_usDataType = 0;
+
+ EnableHardware();
+ } else {
+ for(i = 0; i < len; i++)
+ fpgaBuf[fpgaBufFill + i] = buf[i];
+ fpgaBufEnd += len;
+ fpgaBufFill += len;
+ }
+/*
+ printf("\n\rs:%d,e:%d,f:%d,r:%d,p:%d\n",
+ fpgaBufStart, fpgaBufEnd, fpgaBufFill, fpgaBufRPtr, fpgaPushedAddr);
+*/
+ while(fpgaBufEnd - fpgaBufRPtr > 192) {
+ if((i = ispProcessVME()) < 0)
+ return -1;
+ }
+
+ if(fpgaBufFill > 384) {
+ uint moveby = fpgaBufFill - 384;
+ uint movelen = fpgaBufFill - movelen;
+
+ for(i = 0; i < movelen; i++)
+ fpgaBuf[i] = fpgaBuf[i + moveby];
+ fpgaBufStart += moveby;
+ fpgaBufFill -= moveby;
+/*
+ printf("\n\rs:%d,e:%d,f:%d,r:%d,p:%d\n",
+ fpgaBufStart, fpgaBufEnd, fpgaBufFill, fpgaBufRPtr, fpgaPushedAddr);
+*/
+ }
+
+ return 0;
}
/* DFU callback */
@@ -286,14 +378,13 @@ int USBDFU_handle_dnload(uint8_t altif, unsigned int offset,
end = part->base_addr + part->size;
if (addr + len > end) {
- TRACE_ERROR("Cannot write beyond end of DFU partition %u\n\r", altif);
+ TRACE_ERROR("Write beyond end (%u)\n\r", altif);
g_dfu.status = DFU_STATUS_errADDRESS;
return DFU_RET_STALL;
}
switch (altif) {
case ALTIF_APP:
- case ALTIF_FPGA:
/* SAM3U Errata 46.2.1.3 */
SetFlashWaitState(6);
LED_Set(USBD_LEDOTHER);
@@ -302,13 +393,26 @@ int USBDFU_handle_dnload(uint8_t altif, unsigned int offset,
/* SAM3U Errata 46.2.1.3 */
SetFlashWaitState(2);
if (rc != 0) {
- TRACE_ERROR("Error during write of DFU partition %u\n\r", altif);
+ TRACE_ERROR("Write error (%u)\n\r", altif);
+ g_dfu.status = DFU_STATUS_errPROG;
+ return DFU_RET_STALL;
+ }
+ break;
+
+ case ALTIF_FPGA:
+ LED_Set(USBD_LEDOTHER);
+ rc = fpgaFlash(offset, buf, len);
+ LED_Clear(USBD_LEDOTHER);
+ /* SAM3U Errata 46.2.1.3 */
+ if (rc != 0) {
+ TRACE_ERROR("FPGA error (ofs %d)\n\r", fpgaBufRPtr);
g_dfu.status = DFU_STATUS_errPROG;
return DFU_RET_STALL;
}
break;
+
default:
- TRACE_WARNING("Write to DFU partition %u not implemented\n\r", altif);
+ TRACE_WARNING("Not implemented (%u)\n\r", altif);
g_dfu.status = DFU_STATUS_errTARGET;
break;
}
@@ -330,11 +434,11 @@ void dfu_drv_updstatus(void)
*----------------------------------------------------------------------------*/
extern void USBD_IrqHandler(void);
-
+/*
static const char *rst_type_strs[8] = {
"General", "Backup", "Watchdog", "Softare", "User", "5", "6", "7"
};
-
+*/
int main(void)
{
volatile uint8_t usbConn = 0;
@@ -342,12 +446,12 @@ int main(void)
TRACE_CONFIGURE(DBGU_STANDARD, 115200, BOARD_MCK);
- printf("-- USB DFU Test %s --\n\r", SOFTPACK_VERSION);
+// printf("-- USB DFU Test %s --\n\r", SOFTPACK_VERSION);
printf("-- %s\n\r", BOARD_NAME);
- printf("-- Compiled: %s %s --\n\r", __DATE__, __TIME__);
+// printf("-- Compiled: %s %s --\n\r", __DATE__, __TIME__);
rst_type = (RSTC_GetStatus() >> 8) & 0x7;
- printf("-- Reset type: %s --\n\r", rst_type_strs[rst_type]);
+ //printf("-- Reset type: %s --\n\r", rst_type_strs[rst_type]);
chipid_to_usbserial();
diff --git a/firmware/usb-dfu-project/opcode.h b/firmware/usb-dfu-project/opcode.h
new file mode 100644
index 0000000..6ee4d8e
--- /dev/null
+++ b/firmware/usb-dfu-project/opcode.h
@@ -0,0 +1,135 @@
+
+/**************************************************************
+*
+* Revision History of opcode.h
+*
+*
+* 09/11/07 NN Updated to support version 1.3
+* This version supported new POLING STATUS LOOP opcodes
+* for Flash programming of the Lattice FPGA devices
+* #define LOOP = 0x58
+* #define ENDLOOP = 0x59
+***************************************************************/
+
+
+/*************************************************************
+* *
+* LATTICE CABLE DEFINTIONS. *
+* *
+* Define these only if the lattice cable is being used. *
+* *
+*************************************************************/
+
+#define pinTDI 1
+#define pinTCK 2
+#define pinTMS 4
+#define pinENABLE 8
+#define pinTRST 16
+#define pinCE 32
+#define pinTDO 64
+
+/*************************************************************
+* *
+* ERROR DEFINITIONS *
+* *
+*************************************************************/
+
+#define ERR_VERIFY_FAIL -1
+#define ERR_FIND_ALGO_FILE -2
+#define ERR_FIND_DATA_FILE -3
+#define ERR_WRONG_VERSION -4
+#define ERR_ALGO_FILE_ERROR -5
+#define ERR_DATA_FILE_ERROR -6
+#define ERR_OUT_OF_MEMORY -7
+
+/*************************************************************
+* *
+* DATA TYPE REGISTER BIT DEFINITIONS *
+* *
+*************************************************************/
+
+#define SIR_DATA 0x0001 /*** Current command is SIR ***/
+#define SDR_DATA 0x0002 /*** Current command is SDR ***/
+#define TDI_DATA 0x0004 /*** Command contains TDI ***/
+#define TDO_DATA 0x0008 /*** Command contains TDO ***/
+#define MASK_DATA 0x0010 /*** Command contains MASK ***/
+#define DTDI_DATA 0x0020 /*** Verification flow ***/
+#define DTDO_DATA 0x0040 /*** Verification flow ***/
+#define COMPRESS 0x0080 /*** Compressed data file ***/
+#define COMPRESS_FRAME 0x0100 /*** Compressed data frame ***/
+
+/*************************************************************
+* *
+* USED JTAG STATE *
+* *
+*************************************************************/
+
+#define RESET 0x00
+#define IDLE 0x01
+#define IRPAUSE 0x02
+#define DRPAUSE 0x03
+#define SHIFTIR 0x04
+#define SHIFTDR 0x05
+#define DRCAPTURE 0x06
+
+/*************************************************************
+* *
+* VME OPCODE DEFINITIONS *
+* *
+* These are the opcodes found in the VME file. Although *
+* most of them are similar to SVF commands, a few opcodes *
+* are available only in VME format. *
+* *
+*************************************************************/
+
+#define STATE 0x10
+#define SIR 0x11
+#define SDR 0x12
+#define TCK 0x1B
+#define WAIT 0x1A
+#define ENDDR 0x02
+#define ENDIR 0x03
+#define HIR 0x06
+#define TIR 0x07
+#define HDR 0x08
+#define TDR 0x09
+#define TDI 0x13
+#define CONTINUE 0x70
+#define TDO 0x14
+#define MASK 0x15
+#define LOOP 0x58
+#define ENDLOOP 0x59
+#define LCOUNT 0x66
+#define LDELAY 0x67
+#define LSDR 0x68
+#define ENDSTATE 0x69
+#define ENDVME 0x7F
+
+/*************************************************************
+* *
+* Begin future opcodes at 0xA0 to avoid conflict with Full *
+* VME opcodes. *
+* *
+*************************************************************/
+
+#define BEGIN_REPEAT 0xA0
+#define END_REPEAT 0xA1
+#define END_FRAME 0xA2
+#define DATA 0xA3
+#define PROGRAM 0xA4
+#define VERIFY 0xA5
+#define DTDI 0xA6
+#define DTDO 0xA7
+
+/*************************************************************
+* *
+* Opcode for discrete pins toggling *
+* *
+*************************************************************/
+#define signalENABLE 0x1C /*assert the ispEN pin*/
+#define signalTMS 0x1D /*assert the MODE or TMS pin*/
+#define signalTCK 0x1E /*assert the SCLK or TCK pin*/
+#define signalTDI 0x1F /*assert the SDI or TDI pin*/
+#define signalTRST 0x20 /*assert the RESET or TRST pin*/
+#define signalTDO 0x21 /*assert the RESET or TDO pin*/
+#define signalCableEN 0x22 /*assert the RESET or CableEN pin*/ \ No newline at end of file
diff --git a/firmware/usb-dfu-project/slimpro.c b/firmware/usb-dfu-project/slimpro.c
new file mode 100644
index 0000000..b1b70de
--- /dev/null
+++ b/firmware/usb-dfu-project/slimpro.c
@@ -0,0 +1,1255 @@
+/**************************************************************
+*
+* Lattice Semiconductor Corp. Copyright 2008
+*
+*
+***************************************************************/
+
+
+/**************************************************************
+*
+* Revision History of slim_pro.c
+*
+*
+* 09/11/07 NN Updated to support version 1.3
+* This version supported new POLING STATUS LOOP opcodes (LOOP and ENDLOOP)
+* for Flash programming of the Lattice FPGA devices
+* 09/11/07 NN type cast all the mismatch variables
+***************************************************************/
+
+
+#include <utility/trace.h>
+#include "opcode.h"
+#include "hardware.h"
+
+#define xdata
+#define reentrant
+
+/*************************************************************
+* *
+* PROTOTYPES *
+* *
+*************************************************************/
+
+uint8_t fpgaGetByte();
+unsigned int ispVMDataSize();
+short int ispVMShiftExec(unsigned int a_uiDataSize);
+short int ispVMShift(char a_cCommand);
+void ispVMStateMachine(char a_cNextState);
+void ispVMClocks(unsigned int a_usClocks);
+void ispVMBypass(unsigned int a_siLength);
+void sclock();
+short int ispVMRead(unsigned int a_uiDataSize);
+void ispVMSend(unsigned int a_uiDataSize);
+void ispVMLCOUNT(unsigned short a_usCountSize);
+void ispVMLDELAY();
+/*************************************************************
+* *
+* EXTERNAL FUNCTION *
+* *
+*************************************************************/
+
+extern void ispVMDelay(unsigned int a_usDelay);
+extern int readPort();
+extern void writePort(unsigned int a_ucPins, unsigned int a_ucValue);
+
+/*************************************************************
+* *
+* GLOBAL VARIABLES *
+* *
+*************************************************************/
+static int g_iMovingAlgoIndex = 0; /*** variable to hold the current index in the algo array ***/
+static int g_iMovingDataIndex = 0; /*** variable to hold the current index in the data array ***/
+unsigned short g_usDataType = 0x0000; /*** data type register used to hold information ***
+ **** about the algorithm and data ***/
+static unsigned char g_cEndDR = 0; /*** used to hold the ENDDR state. ***/
+static unsigned char g_cEndIR = 0; /*** used to hold the ENDIR state. ***/
+static short int g_siHeadDR = 0; /*** used to hold the header data register ***/
+static short int g_siHeadIR = 0; /*** used to hold the header instruction register ***/
+static short int g_siTailDR = 0; /*** used to hold the trailer data register ***/
+static short int g_siTailIR = 0; /*** used to hold the trailer instruction register ***/
+
+static int g_iMainDataIndex = 0; /*** forward - only index used as a placed holder in the data array ***/
+static int g_iRepeatIndex = 0; /*** Used to point to the location of REPEAT data ***/
+static int g_iTDIIndex = 0; /*** Used to point to the location of TDI data ***/
+static int g_iTDOIndex = 0; /*** Used to point to the location of TDO data ***/
+static int g_iMASKIndex = 0; /*** Used to point to the location of MASK data ***/
+static unsigned char g_ucCompressCounter = 0; /*** used to indicate how many times 0xFF is repeated ***/
+
+static short int g_siIspPins = 0x00; /*** holds the current byte to be sent to the hardware ***/
+static char g_cCurrentJTAGState = 0; /*** holds the current state of JTAG state machine ***/
+
+static int g_iLoopIndex = 0;
+static int g_iLoopMovingIndex = 0; /*** Used to point to the location of LOOP data ***/
+static int g_iLoopDataMovingIndex = 0;
+
+static unsigned short g_usLCOUNTSize = 0;
+static unsigned char g_ucLDELAYState = IDLE;
+static unsigned short int g_ucLDELAYTCK = 0;
+static unsigned short int g_ucLDELAYDelay = 0;
+static unsigned short int m_loopState = 0;
+
+/*************************************************************
+* *
+* EXTERNAL VARIABLES *
+* *
+* If the algorithm does not require the data, then *
+* declare the variables g_pucDataArray and g_iDataSize *
+* as local variables and set them to NULL and 0, *
+* respectively. *
+* *
+* Example: *
+* xdata unsigned char * g_pucDataArray = NULL; *
+* xdata int g_iDataSize = 0; *
+* *
+*************************************************************/
+
+xdata const struct iState
+{
+ /*** JTAG state machine transistion table ***/
+ unsigned char CurState; /*** From this state ***/
+ unsigned char NextState; /*** Step to this state ***/
+ unsigned char Pattern; /*** The pattern of TMS ***/
+ unsigned char Pulses; /*** The number of steps ***/
+} iStates[25] =
+{
+ { DRPAUSE, SHIFTDR, 0x80, 2 },
+ { IRPAUSE, SHIFTIR, 0x80, 2 },
+ { SHIFTIR, IRPAUSE, 0x80, 2 },
+ { SHIFTDR, DRPAUSE, 0x80, 2 },
+ { DRPAUSE, IDLE, 0xC0, 3 },
+ { IRPAUSE, IDLE, 0xC0, 3 },
+ { RESET, IDLE, 0x00, 1 },
+ { RESET, DRPAUSE, 0x50, 5 },
+ { RESET, IRPAUSE, 0x68, 6 },
+ { IDLE, RESET, 0xE0, 3 },
+ { IDLE, DRPAUSE, 0xA0, 4 },
+ { IDLE, IRPAUSE, 0xD0, 5 },
+ { DRPAUSE, RESET, 0xF8, 5 },
+ { DRPAUSE, IRPAUSE, 0xF4, 7 },
+ { DRPAUSE, DRPAUSE, 0xE8, 6 }, /* 06/14/06 Support POLING STATUS LOOP*/
+ { IRPAUSE, RESET, 0xF8, 5 },
+ { IRPAUSE, DRPAUSE, 0xE8, 6 },
+ { IRPAUSE, SHIFTDR, 0xE0, 5 },
+ { SHIFTIR, IDLE, 0xC0, 3 },
+ { SHIFTDR, IDLE, 0xC0, 3 },
+ { RESET, RESET, 0xFC, 6 },
+ { DRPAUSE, DRCAPTURE, 0xE0, 4 }, /* 11/15/05 Support DRCAPTURE*/
+ { DRCAPTURE, DRPAUSE, 0x80, 2 },
+ { IDLE, DRCAPTURE, 0x80, 2 },
+ { IRPAUSE, DRCAPTURE, 0xE0, 4 }
+};
+/*************************************************************
+* *
+* ISPPROCESSVME *
+* *
+* INPUT: *
+* None. *
+* *
+* RETURN: *
+* The return value indicates whether the vme was *
+* processed successfully or not. A return value equal *
+* to or greater than 0 is passing, and less than 0 is *
+* failing. *
+* *
+* DESCRIPTION: *
+* This function is the core of the embedded processor. *
+* It extracts the VME file for the high - level tokens *
+* such as SIR, SDR, STATE, etc, and calls the *
+* appropriate functions to process them. *
+* *
+*************************************************************/
+
+
+static short int g_lastRetCode;
+
+short int ispProcessVME() reentrant
+{
+ unsigned char ucOpcode = 0;
+ unsigned char ucState = 0;
+ short int siRetCode = 0;
+ static char cProgram = 0;
+ unsigned int uiDataSize = 0;
+ int iLoopCount = 0;
+ unsigned int iMovingAlgoIndex = 0;
+
+ /*************************************************************
+ * *
+ * Begin processing the vme algorithm and data files. *
+ * *
+ *************************************************************/
+
+ if ((ucOpcode = fpgaGetByte()) != 0xFF)
+ {
+ //TRACE_INFO_WP("[%02x]", ucOpcode);
+ /*************************************************************
+ * *
+ * This switch statement is the main switch that represents *
+ * the core of the embedded processor. *
+ * *
+ *************************************************************/
+
+ switch (ucOpcode)
+ {
+ case STATE:
+ /*************************************************************
+ * *
+ * Move the state. *
+ * *
+ *************************************************************/
+ ispVMStateMachine(fpgaGetByte());
+ break;
+ case SIR:
+ case SDR:
+ /*************************************************************
+ * *
+ * Execute SIR/SDR command. *
+ * *
+ *************************************************************/
+ siRetCode = ispVMShift(ucOpcode);
+ break;
+ case TCK:
+ /*************************************************************
+ * *
+ * Pulse TCK signal the specified time. *
+ * *
+ *************************************************************/
+ ispVMClocks(ispVMDataSize());
+ break;
+ case WAIT:
+ /*************************************************************
+ * *
+ * Issue delay in specified time. *
+ * *
+ *************************************************************/
+ ispVMDelay(ispVMDataSize());
+ break;
+ case ENDDR:
+ /*************************************************************
+ * *
+ * Get the ENDDR state and store in global variable. *
+ * *
+ *************************************************************/
+ g_cEndDR = fpgaGetByte();
+ break;
+ case ENDIR:
+ /*************************************************************
+ * *
+ * Get the ENDIR state and store in global variable. *
+ * *
+ *************************************************************/
+ g_cEndIR = fpgaGetByte();
+ break;
+ case HIR:
+ g_siHeadIR = (short int) ispVMDataSize();
+ break;
+ case TIR:
+ g_siTailIR = (short int) ispVMDataSize();
+ break;
+ case HDR:
+ g_siHeadDR = (short int) ispVMDataSize();
+ break;
+ case TDR:
+ g_siTailDR = (short int) ispVMDataSize();
+ break;
+
+ case BEGIN_REPEAT:
+ siRetCode = ERR_ALGO_FILE_ERROR;
+ break;
+ case END_REPEAT:
+ /*************************************************************
+ * *
+ * Exit the current repeat frame. *
+ * *
+ *************************************************************/
+ siRetCode = ERR_ALGO_FILE_ERROR;
+ break;
+
+ case LOOP:
+ /*************************************************************
+ * *
+ * Execute repeat loop. *
+ * *
+ *************************************************************/
+ g_usLCOUNTSize = (short int)ispVMDataSize();
+#ifdef VME_DEBUG
+ fprintf(stderr, "MaxLoopCount %d\n", g_usLCOUNTSize );
+#endif
+ /*************************************************************
+ * *
+ * Set the repeat index to the first byte in the repeat loop. *
+ * *
+ *************************************************************/
+
+ fpgaPushAddr();
+ g_iLoopIndex = 0;
+ m_loopState = 1;
+
+#if 0
+ for ( g_iLoopIndex = 0 ; g_iLoopIndex < g_usLCOUNTSize; g_iLoopIndex++ ) {
+ m_loopState = 1;
+ /*************************************************************
+ * *
+ * Initialize the current algorithm index to the beginning of *
+ * the repeat index before each repeat loop. *
+ * *
+ *************************************************************/
+
+ g_iMovingAlgoIndex = g_iLoopMovingIndex;
+ g_iMovingDataIndex = g_iLoopDataMovingIndex;
+
+
+ /*************************************************************
+ * *
+ * Make recursive call. *
+ * *
+ *************************************************************/
+
+ fprintf(stderr, "I:%d ", g_iLoopIndex);
+ siRetCode = ispProcessVME();
+ if (!siRetCode) {
+ fprintf(stderr, "OK ", siRetCode);
+ /*************************************************************
+ * *
+ * Stop if the complete status matched. *
+ * *
+ *************************************************************/
+
+ break;
+ }
+ }
+ m_loopState = 0;
+
+ if (siRetCode != 0) {
+ /*************************************************************
+ * *
+ * Return if the complete status error. *
+ * *
+ *************************************************************/
+ fprintf(stderr, "ERR2 ");
+ return (siRetCode);
+ }
+#endif
+ break;
+
+ case ENDLOOP:
+ /*************************************************************
+ * *
+ * End the current loop. *
+ * *
+ *************************************************************/
+ if(m_loopState) {
+ if(g_lastRetCode == 0) {
+ m_loopState = 0;
+ break;
+ } else {
+ if(g_iLoopIndex < g_usLCOUNTSize) {
+ g_iLoopIndex++;
+ fpgaPopAddr();
+ } else {
+ return -1;
+ }
+ }
+ }
+ break;
+
+ case ENDVME:
+ /*************************************************************
+ * *
+ * If the ENDVME token is found and g_iMovingAlgoIndex is *
+ * greater than or equal to g_iAlgoSize, then that indicates *
+ * the end of the chain. If g_iMovingAlgoIndex is less than *
+ * g_iAlgoSize, then that indicates that there are still more *
+ * devices to be processed. *
+ * *
+ *************************************************************/
+ TRACE_INFO("DFU: ENDVME\n\r");
+ return siRetCode;
+ break;
+ case LCOUNT:
+ /*************************************************************
+ * *
+ * Get the Maximum LoopCount and store in global variable. *
+ * *
+ *************************************************************/
+ ispVMLCOUNT((unsigned short) ispVMDataSize());
+ break;
+ case LDELAY:
+ /*************************************************************
+ * *
+ * Get the State,TCK number and Delay time for the poling loop*
+ * and store in global variable. *
+ * *
+ *************************************************************/
+ ispVMLDELAY();
+ break;
+ case LSDR:
+ /*************************************************************
+ * *
+ * Execute repeat poling status loop. *
+ * *
+ *************************************************************/
+ iMovingAlgoIndex = g_iMovingAlgoIndex;
+ for (iLoopCount = 0; iLoopCount < g_usLCOUNTSize; iLoopCount++)
+ {
+ siRetCode = ispVMShift(SDR);
+ if (!siRetCode)
+ {
+ break;
+ }
+ /*************************************************************
+ * *
+ * If the status is not done, then move to the setting State *
+ * execute the delay and come back and do the checking again *
+ * *
+ *************************************************************/
+ g_iMovingAlgoIndex = iMovingAlgoIndex;
+ ispVMStateMachine(DRPAUSE);
+ m_loopState = 1;
+ ispVMStateMachine(g_ucLDELAYState);
+ m_loopState = 0;
+ ispVMClocks(g_ucLDELAYTCK);
+ ispVMDelay(g_ucLDELAYDelay);
+ }
+ if (siRetCode != 0)
+ {
+ return (siRetCode);
+ }
+ break;
+ case signalENABLE:
+ /******************************************************************
+ * Toggle ispENABLE signal *
+ * *
+ ******************************************************************/
+ ucState = fpgaGetByte();
+ if (ucState == 0x01)
+ writePort(pinENABLE, 0x01);
+ else
+ writePort(pinENABLE, 0x00);
+ ispVMDelay(1);
+ break;
+ case signalTRST:
+ /******************************************************************
+ * Toggle TRST signal *
+ * *
+ ******************************************************************/
+ ucState = fpgaGetByte();
+ if (ucState == 0x01)
+ writePort(pinTRST, 0x01);
+ else
+ writePort(pinTRST, 0x00);
+ ispVMDelay(1);
+ break;
+ default:
+ /*************************************************************
+ * *
+ * Unrecognized opcode. Return with file error. *
+ * *
+ *************************************************************/
+ return ERR_ALGO_FILE_ERROR;
+ }
+
+ g_lastRetCode = siRetCode;
+
+ if (siRetCode < 0)
+ {
+ if(m_loopState)
+ return 0;
+ else return siRetCode;
+ }
+ }
+
+ return 0;
+}
+
+/*************************************************************
+* *
+* ISPVMDATASIZE *
+* *
+* INPUT: *
+* None. *
+* *
+* RETURN: *
+* This function returns a number indicating the size of *
+* the instruction. *
+* *
+* DESCRIPTION: *
+* This function returns a number. The number is the *
+* value found in SVF commands such as SDR, SIR, HIR, and *
+* etc. For example: *
+* SDR 200 TDI(FFF..F); *
+* The return value would be 200. *
+* *
+*************************************************************/
+
+unsigned int ispVMDataSize()
+{
+ unsigned int uiSize = 0;
+ unsigned char ucCurrentByte = 0;
+ unsigned char ucIndex = 0;
+
+ while ((ucCurrentByte = fpgaGetByte()) & 0x80)
+ {
+ uiSize |=((unsigned int)(ucCurrentByte & 0x7F)) << ucIndex;
+ ucIndex += 7;
+ }
+ uiSize |=((unsigned int)(ucCurrentByte & 0x7F)) << ucIndex;
+ return uiSize;
+}
+
+/*************************************************************
+* *
+* ISPVMSHIFTEXEC *
+* *
+* INPUT: *
+* a_uiDataSize: this holds the size of the command. *
+* *
+* RETURN: *
+* Returns 0 if passing, -1 if failing. *
+* *
+* DESCRIPTION: *
+* This function handles the data in the SIR/SDR commands *
+* by either decompressing the data or setting the *
+* respective indexes to point to the appropriate *
+* location in the algo or data array. Note that data *
+* only comes after TDI, DTDI, TDO, DTDO, and MASK. *
+* *
+*************************************************************/
+
+short int ispVMShiftExec(unsigned int a_uiDataSize)
+{
+ unsigned char ucDataByte = 0;
+
+ /*************************************************************
+ * *
+ * Reset the data type register. *
+ * *
+ *************************************************************/
+
+ g_usDataType &= ~(TDI_DATA + TDO_DATA + MASK_DATA + DTDI_DATA + DTDO_DATA + COMPRESS_FRAME);
+
+ /*************************************************************
+ * *
+ * Convert the size from bits to byte. *
+ * *
+ *************************************************************/
+
+ if (a_uiDataSize % 8)
+ {
+ a_uiDataSize = a_uiDataSize / 8 + 1;
+ }
+ else
+ {
+ a_uiDataSize = a_uiDataSize / 8;
+ }
+
+ /*************************************************************
+ * *
+ * Begin extracting the command. *
+ * *
+ *************************************************************/
+
+ while ((ucDataByte = fpgaGetByte()) != CONTINUE)
+ {
+ switch (ucDataByte)
+ {
+ case TDI:
+ /*************************************************************
+ * *
+ * Set data type register to indicate TDI data and set TDI *
+ * index to the current algorithm location. *
+ * *
+ *************************************************************/
+ g_usDataType |= TDI_DATA;
+ g_iTDIIndex = g_iMovingAlgoIndex;
+ g_iMovingAlgoIndex += a_uiDataSize;
+ break;
+ case DTDI:
+ /*************************************************************
+ * *
+ * Set data type register to indicate DTDI data and check the *
+ * next byte to make sure it's the DATA byte. DTDI indicates *
+ * that the data should be read from the data array, not the *
+ * algo array. *
+ * *
+ *************************************************************/
+ g_usDataType |= DTDI_DATA;
+ if (fpgaGetByte() != DATA)
+ {
+ return ERR_ALGO_FILE_ERROR;
+ }
+
+ /*************************************************************
+ * *
+ * If the COMPRESS flag is set, read the next byte from the *
+ * data file array. If the byte is true, then that indicates *
+ * the frame was compressable. Note that even though the *
+ * overall data file was compressed, certain frames may not *
+ * be compressable that is why this byte must be checked. *
+ * *
+ *************************************************************/
+ if (g_usDataType & COMPRESS)
+ {
+ if (fpgaGetByte())
+ {
+ g_usDataType |= COMPRESS_FRAME;
+ }
+ }
+ break;
+ case TDO:
+ /*************************************************************
+ * *
+ * Set data type register to indicate TDO data and set TDO *
+ * index to the current algorithm location. *
+ * *
+ *************************************************************/
+ g_usDataType |= TDO_DATA;
+ g_iTDOIndex = g_iMovingAlgoIndex;
+ g_iMovingAlgoIndex += a_uiDataSize;
+ break;
+ case DTDO:
+ /*************************************************************
+ * *
+ * Set data type register to indicate DTDO data and check the *
+ * next byte to make sure it's the DATA byte. DTDO indicates *
+ * that the data should be read from the data array, not the *
+ * algo array. *
+ * *
+ *************************************************************/
+ g_usDataType |= DTDO_DATA;
+ if (fpgaGetByte() != DATA)
+ {
+ return ERR_ALGO_FILE_ERROR;
+ }
+
+ /*************************************************************
+ * *
+ * If the COMPRESS flag is set, read the next byte from the *
+ * data file array. If the byte is true, then that indicates *
+ * the frame was compressable. Note that even though the *
+ * overall data file was compressed, certain frames may not *
+ * be compressable that is why this byte must be checked. *
+ * *
+ *************************************************************/
+ if (g_usDataType & COMPRESS)
+ {
+ if (fpgaGetByte())
+ {
+ g_usDataType |= COMPRESS_FRAME;
+ }
+ }
+ break;
+ case MASK:
+ /*************************************************************
+ * *
+ * Set data type register to indicate MASK data. Set MASK *
+ * location index to current algorithm array position. *
+ * *
+ *************************************************************/
+ g_usDataType |= MASK_DATA;
+ g_iMASKIndex = g_iMovingAlgoIndex;
+ g_iMovingAlgoIndex += a_uiDataSize;
+ break;
+ default:
+ /*************************************************************
+ * *
+ * Unrecognized or misplaced opcode. Return error. *
+ * *
+ *************************************************************/
+ return ERR_ALGO_FILE_ERROR;
+ }
+ }
+
+ /*************************************************************
+ * *
+ * Reached the end of the instruction. Return passing. *
+ * *
+ *************************************************************/
+
+ return 0;
+}
+
+/*************************************************************
+* *
+* ISPVMSHIFT *
+* *
+* INPUT: *
+* a_cCommand: this argument specifies either the SIR or *
+* SDR command. *
+* *
+* RETURN: *
+* The return value indicates whether the SIR/SDR was *
+* processed successfully or not. A return value equal *
+* to or greater than 0 is passing, and less than 0 is *
+* failing. *
+* *
+* DESCRIPTION: *
+* This function is the entry point to execute an SIR or *
+* SDR command to the device. *
+* *
+*************************************************************/
+
+short int ispVMShift(char a_cCommand)
+{
+ short int siRetCode = 0;
+ unsigned int uiDataSize = ispVMDataSize();
+
+ /*************************************************************
+ * *
+ * Clear any existing SIR/SDR instructions from the data type *
+ * register. *
+ * *
+ *************************************************************/
+
+ g_usDataType &= ~(SIR_DATA + SDR_DATA);
+
+ /*************************************************************
+ * *
+ * Move state machine to appropriate state depending on the *
+ * command. Issue bypass if needed. *
+ * *
+ *************************************************************/
+
+ switch (a_cCommand)
+ {
+ case SIR:
+ /*************************************************************
+ * *
+ * Set the data type register to indicate that it's executing *
+ * an SIR instruction. Move state machine to IRPAUSE, *
+ * SHIFTIR. If header instruction register exists, then *
+ * issue bypass. *
+ * *
+ *************************************************************/
+ g_usDataType |= SIR_DATA;
+ ispVMStateMachine(IRPAUSE);
+ ispVMStateMachine(SHIFTIR);
+ if (g_siHeadIR > 0)
+ {
+ ispVMBypass(g_siHeadIR);
+ sclock();
+ }
+ break;
+ case SDR:
+ /*************************************************************
+ * *
+ * Set the data type register to indicate that it's executing *
+ * an SDR instruction. Move state machine to DRPAUSE, *
+ * SHIFTDR. If header data register exists, then issue *
+ * bypass. *
+ * *
+ *************************************************************/
+ g_usDataType |= SDR_DATA;
+ ispVMStateMachine(DRPAUSE);
+ ispVMStateMachine(SHIFTDR);
+ if (g_siHeadDR > 0)
+ {
+ ispVMBypass(g_siHeadDR);
+ sclock();
+ }
+ break;
+ }
+
+ /*************************************************************
+ * *
+ * Set the appropriate index locations. If error then return *
+ * error code immediately. *
+ * *
+ *************************************************************/
+
+ siRetCode = ispVMShiftExec(uiDataSize);
+
+ if (siRetCode < 0)
+ {
+ return siRetCode;
+ }
+
+ /*************************************************************
+ * *
+ * Execute the command to the device. If TDO exists, then *
+ * read from the device and verify. Else only TDI exists *
+ * which must send data to the device only. *
+ * *
+ *************************************************************/
+
+ if ((g_usDataType & TDO_DATA) ||(g_usDataType & DTDO_DATA))
+ {
+ siRetCode = ispVMRead(uiDataSize);
+ /*************************************************************
+ * *
+ * A frame of data has just been read and verified. If the *
+ * DTDO_DATA flag is set, then check to make sure the next *
+ * byte in the data array, which is the last byte of the *
+ * frame, is the END_FRAME byte. *
+ * *
+ *************************************************************/
+ if (g_usDataType & DTDO_DATA)
+ {
+ if (fpgaGetByte() != END_FRAME)
+ {
+ siRetCode = ERR_DATA_FILE_ERROR;
+ }
+ }
+ }
+ else
+ {
+ ispVMSend(uiDataSize);
+ /*************************************************************
+ * *
+ * A frame of data has just been sent. If the DTDI_DATA flag *
+ * is set, then check to make sure the next byte in the data *
+ * array, which is the last byte of the frame, is the *
+ * END_FRAME byte. *
+ * *
+ *************************************************************/
+ if (g_usDataType & DTDI_DATA)
+ {
+ if (fpgaGetByte() != END_FRAME)
+ {
+ siRetCode = ERR_DATA_FILE_ERROR;
+ }
+ }
+ }
+
+ /*************************************************************
+ * *
+ * Bypass trailer if it exists. Move state machine to *
+ * ENDIR/ENDDR state. *
+ * *
+ *************************************************************/
+
+ switch (a_cCommand)
+ {
+ case SIR:
+ if (g_siTailIR > 0)
+ {
+ sclock();
+ ispVMBypass(g_siTailIR);
+ }
+ ispVMStateMachine(g_cEndIR);
+ break;
+ case SDR:
+ if (g_siTailDR > 0)
+ {
+ sclock();
+ ispVMBypass(g_siTailDR);
+ }
+ ispVMStateMachine(g_cEndDR);
+ break;
+ }
+
+ return siRetCode;
+}
+
+/*************************************************************
+* *
+* SCLOCK *
+* *
+* INPUT: *
+* None. *
+* *
+* RETURN: *
+* None. *
+* *
+* DESCRIPTION: *
+* This function applies a HLL pulse to TCK. *
+* *
+*************************************************************/
+
+void sclock()
+{
+/*************************************************************
+* *
+* Set TCK to HIGH, LOW, LOW. *
+* *
+*************************************************************/
+
+ writePort(pinTCK, 0x01);
+ writePort(pinTCK, 0x00);
+ writePort(pinTCK, 0x00);
+}
+
+/*************************************************************
+* *
+* ISPVMREAD *
+* *
+* INPUT: *
+* a_uiDataSize: this argument is the size of the *
+* command. *
+* *
+* RETURN: *
+* The return value is 0 if passing, and -1 if failing. *
+* *
+* DESCRIPTION: *
+* This function reads a data stream from the device and *
+* compares it to the expected TDO. *
+* *
+*************************************************************/
+
+short int ispVMRead(unsigned int a_uiDataSize)
+{
+ unsigned int uiIndex = 0;
+ unsigned short usErrorCount = 0;
+ unsigned char ucTDIByte = 0;
+ unsigned char ucTDOByte = 0;
+ unsigned char ucMaskByte = 0;
+ unsigned char ucCurBit = 0;
+
+ for (uiIndex = 0;uiIndex < a_uiDataSize; uiIndex++)
+ {
+ if (uiIndex % 8 == 0)
+ {
+ if ( g_usDataType & TDI_DATA ) {
+ /*************************************************************
+ * *
+ * If the TDI_DATA flag is set, then grab the next byte from *
+ * the algo array and increment the TDI index. *
+ * *
+ *************************************************************/
+ ucTDIByte = fpgaGetByte();
+ }
+ else
+ {
+ ucTDIByte = 0xFF;
+ }
+ if (g_usDataType & TDO_DATA)
+ {
+ /*************************************************************
+ * *
+ * If the TDO_DATA flag is set, then grab the next byte from *
+ * the algo array and increment the TDO index. *
+ * *
+ *************************************************************/
+ ucTDOByte = fpgaGetByte();
+ }
+ else
+ {
+ /*************************************************************
+ * *
+ * If TDO_DATA is not set, then DTDO_DATA must be set. If *
+ * the compression counter exists, then the next TDO byte *
+ * must be 0xFF. If it doesn't exist, then get next byte *
+ * from data file array. *
+ * *
+ *************************************************************/
+ if (g_ucCompressCounter)
+ {
+ g_ucCompressCounter--;
+ ucTDOByte =(unsigned char) 0xFF;
+ }
+ else
+ {
+ ucTDOByte = fpgaGetByte();
+
+ /*************************************************************
+ * *
+ * If the frame is compressed and the byte is 0xFF, then the *
+ * next couple bytes must be read to determine how many *
+ * repetitions of 0xFF are there. That value will be stored *
+ * in the variable g_ucCompressCounter. *
+ * *
+ *************************************************************/
+ if ((g_usDataType & COMPRESS_FRAME) &&(ucTDOByte ==(unsigned char) 0xFF))
+ {
+ g_ucCompressCounter = fpgaGetByte();
+ g_ucCompressCounter--;
+ }
+ }
+ }
+
+ if (g_usDataType & MASK_DATA)
+ {
+ ucMaskByte = fpgaGetByte();
+ }
+ else
+ {
+ ucMaskByte =(unsigned char) 0xFF;
+ }
+ }
+
+ ucCurBit = readPort();
+
+ if ((((ucMaskByte << uiIndex % 8) & 0x80) ? 0x01 : 0x00))
+ {
+ if (ucCurBit != (((ucTDOByte << uiIndex % 8) & 0x80) ? 0x01 : 0x00))
+ {
+ usErrorCount++;
+ }
+ }
+
+ /*************************************************************
+ * *
+ * Always shift 0x01 into TDI pin when reading. *
+ * *
+ *************************************************************/
+
+ writePort(pinTDI, (unsigned char) (((ucTDIByte << uiIndex % 8) & 0x80) ? 0x01 : 0x00));
+
+ if (uiIndex < a_uiDataSize - 1)
+ {
+ sclock();
+ }
+ }
+
+ if (usErrorCount > 0)
+ {
+ return -1;
+ }
+
+ return 0;
+}
+
+/*************************************************************
+* *
+* ISPVMSEND *
+* *
+* INPUT: *
+* a_uiDataSize: this argument is the size of the *
+* command. *
+* *
+* RETURN: *
+* None. *
+* *
+* DESCRIPTION: *
+* This function sends a data stream to the device. *
+* *
+*************************************************************/
+
+void ispVMSend(unsigned int a_uiDataSize)
+{
+ unsigned int iIndex;
+ unsigned char ucCurByte = 0;
+ unsigned char ucBitState = 0;
+
+ /*************************************************************
+ * *
+ * Begin processing the data to the device. *
+ * *
+ *************************************************************/
+
+ for (iIndex = 0;iIndex < a_uiDataSize; iIndex++)
+ {
+ if (iIndex % 8 == 0)
+ {
+ if (g_usDataType & TDI_DATA)
+ {
+ /*************************************************************
+ * *
+ * If the TDI_DATA flag is set, then grab the next byte from *
+ * the algo array and increment the TDI index. *
+ * *
+ *************************************************************/
+ ucCurByte = fpgaGetByte();
+ }
+ else
+ {
+ /*************************************************************
+ * *
+ * If TDI_DATA flag is not set, then DTDI_DATA flag must have *
+ * already been set. If the compression counter exists, then *
+ * the next TDI byte must be 0xFF. If it doesn't exist, then *
+ * get next byte from data file array. *
+ * *
+ *************************************************************/
+ if (g_ucCompressCounter)
+ {
+ g_ucCompressCounter--;
+ ucCurByte =(unsigned char) 0xFF;
+ }
+ else
+ {
+ ucCurByte = fpgaGetByte();
+
+ /*************************************************************
+ * *
+ * If the frame is compressed and the byte is 0xFF, then the *
+ * next couple bytes must be read to determine how many *
+ * repetitions of 0xFF are there. That value will be stored *
+ * in the variable g_ucCompressCounter. *
+ * *
+ *************************************************************/
+
+ if ((g_usDataType & COMPRESS_FRAME) &&(ucCurByte ==(unsigned char) 0xFF))
+ {
+ g_ucCompressCounter = fpgaGetByte();
+ g_ucCompressCounter--;
+ }
+ }
+ }
+ }
+
+ ucBitState =(unsigned char)(((ucCurByte << iIndex % 8) & 0x80) ? 0x01 : 0x00);
+ writePort(pinTDI, ucBitState);
+
+ if (iIndex < a_uiDataSize - 1)
+ {
+ sclock();
+ }
+ }
+}
+
+/*************************************************************
+* *
+* ISPVMSTATEMACHINE *
+* *
+* INPUT: *
+* a_cNextState: this is the opcode of the next JTAG *
+* state. *
+* *
+* RETURN: *
+* This functions returns 0 when passing, and -1 when *
+* failure occurs. *
+* *
+* DESCRIPTION: *
+* This function is called to move the device into *
+* different JTAG states. *
+* *
+*************************************************************/
+
+void ispVMStateMachine(char a_cNextState)
+{
+ int cPathIndex, cStateIndex;
+ if ((g_cCurrentJTAGState == DRPAUSE) &&(a_cNextState== DRPAUSE) && m_loopState)
+ {
+ }
+ else if ((g_cCurrentJTAGState == a_cNextState) &&(g_cCurrentJTAGState != RESET))
+ {
+ return;
+ }
+
+ for (cStateIndex = 0;cStateIndex < 25; cStateIndex++)
+ {
+ if ((g_cCurrentJTAGState == iStates[cStateIndex].CurState) &&(a_cNextState == iStates[cStateIndex].NextState))
+ {
+ break;
+ }
+ }
+ g_cCurrentJTAGState = a_cNextState;
+ for (cPathIndex = 0;cPathIndex < iStates[cStateIndex].Pulses; cPathIndex++)
+ {
+ if ((iStates[cStateIndex].Pattern << cPathIndex) & 0x80)
+ {
+ writePort(pinTMS, (unsigned char) 0x01);
+ }
+ else
+ {
+ writePort(pinTMS, (unsigned char) 0x00);
+ }
+ sclock();
+ }
+
+ writePort(pinTDI, 0x00);
+ writePort(pinTMS, 0x00);
+}
+
+/*************************************************************
+* *
+* ISPVMCLOCKS *
+* *
+* INPUT: *
+* a_usClocks: number of clocks to apply. *
+* *
+* RETURN: *
+* None. *
+* *
+* DESCRIPTION: *
+* This procedure applies the specified number of pulses *
+* to TCK. *
+* *
+*************************************************************/
+
+void ispVMClocks(unsigned int a_uiClocks)
+{
+ for (; a_uiClocks > 0; a_uiClocks--)
+ {
+ sclock();
+ }
+}
+
+/*************************************************************
+* *
+* ISPVMBYPASS *
+* *
+* INPUT: *
+* a_siLength: this argument is the length of the *
+* command. *
+* *
+* RETURN: *
+* None. *
+* *
+* DESCRIPTION: *
+* This function takes care of the HIR, HDR, TIR, and TDR *
+* for the purpose of putting the other devices into *
+* bypass mode. *
+* *
+*************************************************************/
+
+void ispVMBypass(unsigned int a_uiLength)
+{
+/*************************************************************
+* *
+* Issue a_siLength number of 0x01 to the TDI pin to bypass. *
+* *
+*************************************************************/
+
+ for (; a_uiLength > 1; a_uiLength--)
+ {
+ writePort(pinTDI, (char) 0x01);
+ sclock();
+ }
+
+ writePort(pinTDI, (char) 0x01);
+}
+/*************************************************************
+* *
+* ispVMLCOUNT *
+* *
+* INPUT: *
+* a_usCountSize: The maximum number of loop required to *
+* poling the status *
+* *
+* *
+* DESCRIPTION: *
+* This function is set the maximum loop count *
+* *
+*************************************************************/
+
+void ispVMLCOUNT(unsigned short a_usCountSize)
+{
+ g_usLCOUNTSize = a_usCountSize;
+}
+/*************************************************************
+* *
+* ispVMLDELAY *
+* *
+* *
+* DESCRIPTION: *
+* This function is set the delay state, number of TCK and*
+* the delay time for poling the status *
+* *
+*************************************************************/
+void ispVMLDELAY()
+{
+ g_ucLDELAYState = IDLE;
+ g_ucLDELAYDelay = 0;
+ g_ucLDELAYTCK = 0;
+ while (1)
+ {
+ unsigned char bytedata = fpgaGetByte();
+ switch (bytedata)
+ {
+ case STATE: /*step BSCAN state machine to specified state*/
+ g_ucLDELAYState = fpgaGetByte();
+ break;
+ case WAIT: /*opcode to wait for specified time in us or ms*/
+ g_ucLDELAYDelay = (short int) ispVMDataSize();
+ break;
+ case TCK: /*pulse TCK signal the specified time*/
+ g_ucLDELAYTCK = (short int) ispVMDataSize();
+ break;
+ case ENDSTATE:
+ return;
+ break;
+ }
+ }
+}