diff options
author | Christian Daniel <cd@maintech.de> | 2012-05-17 22:47:51 +0200 |
---|---|---|
committer | Christian Daniel <cd@maintech.de> | 2012-05-17 22:47:51 +0200 |
commit | 5dcfd6a1568a40a5331c0cc8963c0f920858b27c (patch) | |
tree | ae2a8dfa646d2b04abefdfd14d46a4a6fea07421 /firmware/usb-dfu-project | |
parent | c46bad77e52425448b0c67d915b31b6bd1ee8024 (diff) |
added DFU functionality for the FPGA - crudely removed stuff from the loader to make it fit into the 16k
Diffstat (limited to 'firmware/usb-dfu-project')
-rw-r--r-- | firmware/usb-dfu-project/hardware.c | 226 | ||||
-rw-r--r-- | firmware/usb-dfu-project/hardware.h | 11 | ||||
-rw-r--r-- | firmware/usb-dfu-project/main.c | 136 | ||||
-rw-r--r-- | firmware/usb-dfu-project/opcode.h | 135 | ||||
-rw-r--r-- | firmware/usb-dfu-project/slimpro.c | 1255 |
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; + } + } +} |