DLLEXPORT(FLStatus) flFlashStandardFirmware( struct FLContext *handle, const char *newVidPid, const char *jtagPort, uint32 eepromSize, const char *xsvfFile, const char **error) { FLStatus flStatus, returnCode; struct Buffer i2cBuf = {0,}; BufferStatus bStatus; FX2Status fxStatus; uint32 fwSize, xsvfSize, initSize; uint16 newVid, newPid, newDid; uint8 port, tdoBit, tdiBit, tmsBit, tckBit; if ( !usbValidateVidPid(newVidPid) ) { errRender(error, "flFlashStandardFirmware(): The supplied new VID:PID \"%s\" is invalid; it should look like 04B4:8613", newVidPid); FAIL(FL_USB_ERR); } newVid = (uint16)strtoul(newVidPid, NULL, 16); newPid = (uint16)strtoul(newVidPid+5, NULL, 16); newDid = (strlen(newVidPid) == 14) ? (uint16)strtoul(newVidPid+10, NULL, 16) : 0x0000; if ( strlen(jtagPort) != 5 ) { errRender(error, "flFlashStandardFirmware(): JTAG port specification must be <C|D><tdoBit><tdiBit><tmsBit><tckBit>"); FAIL(FL_FX2_ERR); } if ( (jtagPort[0] & 0xDF) == 'A' ) { port = 0; } else if ( (jtagPort[0] & 0xDF) == 'C' ) { port = 2; } else if ( (jtagPort[0] & 0xDF) == 'D' ) { port = 3; } else { errRender(error, "flFlashStandardFirmware(): JTAG port specification must be <A|C|D><tdoBit><tdiBit><tmsBit><tckBit>"); FAIL(FL_FX2_ERR); } if (jtagPort[1] < '0' || jtagPort[1] > '7' || jtagPort[2] < '0' || jtagPort[2] > '7' || jtagPort[3] < '0' || jtagPort[3] > '7' || jtagPort[4] < '0' || jtagPort[4] > '7' ) { errRender(error, "flFlashStandardFirmware(): JTAG port specification must be <A|C|D><tdoBit><tdiBit><tmsBit><tckBit>"); FAIL(FL_FX2_ERR); } tdoBit = jtagPort[1] - '0'; tdiBit = jtagPort[2] - '0'; tmsBit = jtagPort[3] - '0'; tckBit = jtagPort[4] - '0'; if ( port == 0 && (isInvalidPortABit(tdoBit) || isInvalidPortABit(tdiBit) || isInvalidPortABit(tmsBit) || isInvalidPortABit(tckBit)) ) { errRender(error, "flFlashStandardFirmware(): Only bits 0, 1, 3 & 7 are available for JTAG use on port A"); FAIL(FL_FX2_ERR); } bStatus = bufInitialise(&i2cBuf, 0x4000, 0x00, error); CHECK_STATUS(bStatus, "flFlashStandardFirmware()", FL_ALLOC_ERR); if ( xsvfFile ) { flStatus = copyFirmwareAndRewriteIDs( &eepromWithBootFirmware, newVid, newPid, newDid, port, tdoBit, tdiBit, tmsBit, tckBit, &i2cBuf, error); CHECK_STATUS(flStatus, "flFlashStandardFirmware()", flStatus); fwSize = i2cBuf.length; flStatus = convertJtagFileToCsvf(&i2cBuf, xsvfFile, error); CHECK_STATUS(flStatus, "flFlashStandardFirmware()", flStatus); xsvfSize = i2cBuf.length - fwSize; if ( handle->writeBuffer.length ) { // Write a big-endian uint24 length for the init data, then the data itself const uint32 length = handle->writeBuffer.length; if ( length > 0x20000 ) { errRender( error, "flFlashStandardFirmware(): Cannot cope with %lu bytes of init data", length); FAIL(FL_FX2_ERR); } bStatus = bufAppendByte(&i2cBuf, (uint8)((length>>16) & 0xFF), error); CHECK_STATUS(bStatus, "flFlashStandardFirmware()", FL_ALLOC_ERR); bStatus = bufAppendByte(&i2cBuf, (uint8)((length>>8) & 0xFF), error); CHECK_STATUS(bStatus, "flFlashStandardFirmware()", FL_ALLOC_ERR); bStatus = bufAppendByte(&i2cBuf, (uint8)(length & 0xFF), error); CHECK_STATUS(bStatus, "flFlashStandardFirmware()", FL_ALLOC_ERR); bStatus = bufAppendBlock( &i2cBuf, handle->writeBuffer.data, length, error); CHECK_STATUS(bStatus, "flFlashStandardFirmware()", FL_ALLOC_ERR); initSize = length + 3; } else { // Write a zero uint24 length so the firmware knows there's no init data to follow bStatus = bufAppendByte(&i2cBuf, 0x00, error); CHECK_STATUS(bStatus, "flFlashStandardFirmware()", FL_ALLOC_ERR); bStatus = bufAppendByte(&i2cBuf, 0x00, error); CHECK_STATUS(bStatus, "flFlashStandardFirmware()", FL_ALLOC_ERR); bStatus = bufAppendByte(&i2cBuf, 0x00, error); CHECK_STATUS(bStatus, "flFlashStandardFirmware()", FL_ALLOC_ERR); initSize = 3; } } else {
// Load the standard FPGALink firmware into the FX2 at currentVid/currentPid. DLLEXPORT(FLStatus) flLoadStandardFirmware( const char *curVidPid, const char *newVidPid, const char *jtagPort, const char **error) { FLStatus flStatus, returnCode; struct Buffer ramBuf = {0,}; BufferStatus bStatus; FX2Status fxStatus; struct USBDevice *device = NULL; int uStatus; uint16 newVid, newPid, newDid; uint8 port, tdoBit, tdiBit, tmsBit, tckBit; if ( !usbValidateVidPid(newVidPid) ) { errRender(error, "flLoadStandardFirmware(): The supplied VID:PID:DID \"%s\" is invalid; it should look like 1D50:602B or 1D50:602B:0001", newVidPid); FAIL(FL_USB_ERR); } newVid = (uint16)strtoul(newVidPid, NULL, 16); newPid = (uint16)strtoul(newVidPid+5, NULL, 16); newDid = (strlen(newVidPid) == 14) ? (uint16)strtoul(newVidPid+10, NULL, 16) : 0x0000; if ( strlen(jtagPort) != 5 ) { errRender(error, "flLoadStandardFirmware(): JTAG port specification must be <C|D><tdoBit><tdiBit><tmsBit><tckBit>"); FAIL(FL_FX2_ERR); } if ( (jtagPort[0] & 0xDF) == 'A' ) { port = 0; } else if ( (jtagPort[0] & 0xDF) == 'C' ) { port = 2; } else if ( (jtagPort[0] & 0xDF) == 'D' ) { port = 3; } else { errRender(error, "flLoadStandardFirmware(): JTAG port specification must be <A|C|D><tdoBit><tdiBit><tmsBit><tckBit>"); FAIL(FL_FX2_ERR); } if (jtagPort[1] < '0' || jtagPort[1] > '7' || jtagPort[2] < '0' || jtagPort[2] > '7' || jtagPort[3] < '0' || jtagPort[3] > '7' || jtagPort[4] < '0' || jtagPort[4] > '7' ) { errRender(error, "flLoadStandardFirmware(): JTAG port specification must be <A|C|D><tdoBit><tdiBit><tmsBit><tckBit>"); FAIL(FL_FX2_ERR); } tdoBit = jtagPort[1] - '0'; tdiBit = jtagPort[2] - '0'; tmsBit = jtagPort[3] - '0'; tckBit = jtagPort[4] - '0'; if ( port == 0 && (isInvalidPortABit(tdoBit) || isInvalidPortABit(tdiBit) || isInvalidPortABit(tmsBit) || isInvalidPortABit(tckBit)) ) { errRender(error, "flFlashStandardFirmware(): Only bits 0, 1, 3 & 7 are available for JTAG use on port A"); FAIL(FL_FX2_ERR); } uStatus = usbOpenDevice(curVidPid, 1, 0, 0, &device, error); CHECK_STATUS(uStatus, "flLoadStandardFirmware()", FL_USB_ERR); bStatus = bufInitialise(&ramBuf, 0x4000, 0x00, error); CHECK_STATUS(bStatus, "flLoadStandardFirmware()", FL_ALLOC_ERR); flStatus = copyFirmwareAndRewriteIDs( &ramFirmware, newVid, newPid, newDid, port, tdoBit, tdiBit, tmsBit, tckBit, &ramBuf, error); CHECK_STATUS(flStatus, "flLoadStandardFirmware()", flStatus); fxStatus = fx2WriteRAM(device, ramBuf.data, ramBuf.length, error); CHECK_STATUS(fxStatus, "flLoadStandardFirmware()", FL_FX2_ERR); returnCode = FL_SUCCESS; cleanup: bufDestroy(&ramBuf); if ( device ) { usbCloseDevice(device, 0); } return returnCode; }
// Play the CSVF stream into the JTAG port. // FLStatus csvfPlay(struct FLContext *handle, const uint8 *csvfData, const char **error) { FLStatus returnCode = FL_SUCCESS; FLStatus fStatus; uint8 thisByte, numBits; uint32 numBytes; uint8 *tdoPtr, *tdiPtr; uint8 i; uint32 xsdrSize = 0; uint32 xruntest = 0; uint8 tdoMask[CSVF_BUF_SIZE]; uint8 tdiData[CSVF_BUF_SIZE]; uint8 tdoData[CSVF_BUF_SIZE]; uint8 tdoExpected[CSVF_BUF_SIZE]; char data[CSVF_BUF_SIZE*2+1]; char mask[CSVF_BUF_SIZE*2+1]; char expected[CSVF_BUF_SIZE*2+1]; uint8 *tdiAll; const uint8 *ptr = csvfData; fStatus = jtagClockFSM(handle, 0x0000001F, 6, error); // Reset TAP, goto Run-Test/Idle CHECK_STATUS(fStatus, "csvfPlay()", fStatus); thisByte = *ptr++; while ( thisByte != XCOMPLETE ) { switch ( thisByte ) { case XTDOMASK: #ifdef DEBUG printf("XTDOMASK("); #endif numBytes = bitsToBytes(xsdrSize); tdoPtr = tdoMask; while ( numBytes-- ) { thisByte = *ptr++; #ifdef DEBUG printf("%02X", thisByte); #endif *tdoPtr++ = thisByte; } #ifdef DEBUG printf(")\n"); #endif break; case XRUNTEST: xruntest = *ptr++; xruntest <<= 8; xruntest |= *ptr++; xruntest <<= 8; xruntest |= *ptr++; xruntest <<= 8; xruntest |= *ptr++; #ifdef DEBUG printf("XRUNTEST(%08X)\n", xruntest); #endif break; case XSIR: fStatus = jtagClockFSM(handle, 0x00000003, 4, error); // -> Shift-IR CHECK_STATUS(fStatus, "csvfPlay()", fStatus); numBits = *ptr++; #ifdef DEBUG printf("XSIR(%02X, ", numBits); #endif numBytes = bitsToBytes(numBits); tdiPtr = tdiData; while ( numBytes-- ) { thisByte = *ptr++; #ifdef DEBUG printf("%02X", thisByte); #endif *tdiPtr++ = thisByte; } #ifdef DEBUG printf(")\n"); #endif fStatus = jtagShift(handle, numBits, tdiData, NULL, true, error); // -> Exit1-DR CHECK_STATUS(fStatus, "csvfPlay()", fStatus); fStatus = jtagClockFSM(handle, 0x00000001, 2, error); // -> Run-Test/Idle CHECK_STATUS(fStatus, "csvfPlay()", fStatus); if ( xruntest ) { fStatus = jtagClocks(handle, xruntest, error); CHECK_STATUS(fStatus, "csvfPlay()", fStatus); } break; case XSDRSIZE: xsdrSize = *ptr++; xsdrSize <<= 8; xsdrSize |= *ptr++; xsdrSize <<= 8; xsdrSize |= *ptr++; xsdrSize <<= 8; xsdrSize |= *ptr++; #ifdef DEBUG printf("XSDRSIZE(%08X)\n", xsdrSize); #endif break; case XSDRTDO: numBytes = bitsToBytes(xsdrSize); tdiPtr = tdiData; tdoPtr = tdoExpected; while ( numBytes-- ) { *tdiPtr++ = *ptr++; *tdoPtr++ = *ptr++; } numBytes = bitsToBytes(xsdrSize); i = 0; do { fStatus = jtagClockFSM(handle, 0x00000001, 3, error); // -> Shift-DR CHECK_STATUS(fStatus, "csvfPlay()", fStatus); fStatus = jtagShift(handle, xsdrSize, tdiData, tdoData, true, error); // -> Exit1-DR CHECK_STATUS(fStatus, "csvfPlay()", fStatus); fStatus = jtagClockFSM(handle, 0x0000001A, 6, error); // -> Run-Test/Idle CHECK_STATUS(fStatus, "csvfPlay()", fStatus); if ( xruntest ) { fStatus = jtagClocks(handle, xruntest, error); CHECK_STATUS(fStatus, "csvfPlay()", fStatus); } i++; #ifdef DEBUG dumpSimple(tdoData, numBytes, data); dumpSimple(tdoMask, numBytes, mask); dumpSimple(tdoExpected, numBytes, expected); printf("XSDRTDO(attempt: %d; mask: %s; expecting: %s; got: %s)\n", i, mask, expected, data); #endif } while ( tdoMatchFailed(tdoData, tdoMask, tdoExpected, numBytes) && i < 32 ); if ( i == 32 ) { dumpSimple(tdoData, numBytes, data); dumpSimple(tdoMask, numBytes, mask); dumpSimple(tdoExpected, numBytes, expected); errRender( error, "csvfPlay(): XSDRTDO failed:\n Got: %s\n Mask: %s\n Expecting: %s", data, mask, expected); FAIL(FL_PROG_SVF_COMPARE); } break; case XSDR: #ifdef DEBUG // TODO: Need to print actual TDO data too printf("XSDR(%08X)\n", xsdrSize); #endif fStatus = jtagClockFSM(handle, 0x00000001, 3, error); // -> Shift-DR CHECK_STATUS(fStatus, "csvfPlay()", fStatus); numBytes = bitsToBytes(xsdrSize); tdiAll = malloc(numBytes); tdiPtr = tdiAll; while ( numBytes-- ) { *tdiPtr++ = *ptr++; } fStatus = jtagShift(handle, xsdrSize, tdiAll, NULL, true, error); // -> Exit1-DR free(tdiAll); CHECK_STATUS(fStatus, "csvfPlay()", fStatus); fStatus = jtagClockFSM(handle, 0x00000001, 2, error); // -> Run-Test/Idle CHECK_STATUS(fStatus, "csvfPlay()", fStatus); if ( xruntest ) { fStatus = jtagClocks(handle, xruntest, error); CHECK_STATUS(fStatus, "csvfPlay()", fStatus); } break; default: errRender(error, "csvfPlay(): Unsupported command 0x%02X", thisByte); FAIL(FL_PROG_SVF_UNKNOWN_CMD); } thisByte = *ptr++; } cleanup: return returnCode; }