// Dump the selected range of the HexReader buffers as I2C records to the supplied buffer. This will // split up large chunks into chunks 1023 bytes or smaller so chunk lengths fit in ten bits. // (see TRM 3.4.3) // static I2CStatus dumpChunk( struct Buffer *destination, const struct Buffer *sourceData, const struct Buffer *sourceMask, uint16 address, uint16 length, const char **error) { I2CStatus retVal = I2C_SUCCESS; BufferStatus bStatus; size_t i, startBlock; if ( length == 0 ) { return I2C_SUCCESS; } while ( length > 1023 ) { retVal = dumpChunk(destination, sourceData, sourceMask, address, 1023, error); CHECK_STATUS(retVal, retVal, cleanup, "dumpChunk()"); address = (uint16)(address + 1023); length = (uint16)(length - 1023); } bStatus = bufAppendWordBE(destination, length, error); CHECK_STATUS(bStatus, I2C_BUFFER_ERROR, cleanup, "dumpChunk()"); bStatus = bufAppendWordBE(destination, address, error); CHECK_STATUS(bStatus, I2C_BUFFER_ERROR, cleanup, "dumpChunk()"); startBlock = destination->length; bStatus = bufAppendBlock(destination, sourceData->data + address, length, error); CHECK_STATUS(bStatus, I2C_BUFFER_ERROR, cleanup, "dumpChunk()"); for ( i = 0; i < length; i++ ) { if ( sourceMask->data[address + i] == 0x00 ) { destination->data[startBlock + i] = 0x00; } } cleanup: return retVal; }
// Append a write command to the end of the write buffer. // DLLEXPORT(FLStatus) flAppendWriteChannelCommand( struct FLContext *handle, uint8 chan, uint32 count, const uint8 *data, const char **error) { FLStatus retVal = FL_SUCCESS; BufferStatus bStatus; uint8 command[5]; if ( !handle->writeBuffer.data ) { // write buffer is lazily initialised bStatus = bufInitialise(&handle->writeBuffer, 1024, 0x00, error); CHECK_STATUS(bStatus, FL_ALLOC_ERR, cleanup, "flAppendWriteChannelCommand()"); } command[0] = chan & 0x7F; flWriteLong(count, command+1); bStatus = bufAppendBlock(&handle->writeBuffer, command, 5, error); CHECK_STATUS(bStatus, FL_ALLOC_ERR, cleanup, "flAppendWriteChannelCommand()"); bStatus = bufAppendBlock(&handle->writeBuffer, data, count, error); CHECK_STATUS(bStatus, FL_ALLOC_ERR, cleanup, "flAppendWriteChannelCommand()"); cleanup: return retVal; }
// Finalise the I2C buffers. This involves writing the final record which resets the chip. // DLLEXPORT(I2CStatus) i2cFinalise(struct Buffer *buf, const char **error) { I2CStatus retVal = I2C_SUCCESS; BufferStatus bStatus; const uint8 lastRecord[] = {0x80, 0x01, 0xe6, 0x00, 0x00}; CHECK_STATUS( buf->length < 8 || buf->data[0] != 0xC2, I2C_NOT_INITIALISED, cleanup, "i2cFinalise(): the buffer was not initialised"); bStatus = bufAppendBlock(buf, lastRecord, 5, error); CHECK_STATUS(bStatus, I2C_BUFFER_ERROR, cleanup, "i2cFinalise()"); cleanup: return retVal; }
FLStatus copyFirmwareAndRewriteIDs( const struct FirmwareInfo *fwInfo, uint16 vid, uint16 pid, uint16 did, struct Buffer *dest, const char **error) { FLStatus retVal = FL_SUCCESS; // Can return FL_ALLOC_ERR, FL_FX2_ERR and FL_INTERNAL_ERR BufferStatus bStatus; bStatus = bufAppendBlock(dest, fwInfo->data, fwInfo->length, error); CHECK_STATUS(bStatus, FL_ALLOC_ERR, cleanup, "copyFirmwareAndRewriteIDs()"); dest->data[fwInfo->vp] = (uint8)(vid & 0xFF); dest->data[fwInfo->vp + 1] = (uint8)(vid >> 8); dest->data[fwInfo->vp + 2] = (uint8)(pid & 0xFF); dest->data[fwInfo->vp + 3] = (uint8)(pid >> 8); dest->data[fwInfo->vp + 4] = (uint8)(did & 0xFF); dest->data[fwInfo->vp + 5] = (uint8)(did >> 8); cleanup: return retVal; }
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 {