//***************************************************** // Puts the address on the address bus // And gets the value from the data bus // Then returns this value //***************************************************** u16 readCommand(struct FLContext *handle, u32 address){ u8 buffer[4]; buffer[0] = READ; buffer[1] = address & 0xFF; buffer[2] = (address & 0xFF00) >> 8; buffer[3] = (address & 0xFF0000) >> 16; // Ask the flash to send the data at the specified address flWriteChannel(handle, 1000, 0, 4, buffer, NULL); flReadChannel(handle, 1000, 0, 2, buffer, NULL); u16 ret = buffer[0] | (buffer[1] << 8); return ret; }
//***************************************************** // Puts the address on the address bus to the flash // and puts data on the data bus //***************************************************** void writeCommand(struct FLContext *handle, u32 address, u16 data){ u8 buffer[6]; buffer[0] = WRITE; buffer[1] = address; buffer[2] = (address & 0xFF00) >> 8; buffer[3] = (address & 0xFF0000) >> 16; buffer[4] = data & 0xFF; buffer[5] = (data & 0xFF00) >> 8; //printf("Address %x-%x\n", (u8)buffer[2], (u8)buffer[1]); flWriteChannel(handle, 1000, 0, 6, buffer, NULL); }
// Tell the monitor to continue execution with the (possibly new) register/memory context, until // a breakpoint is hit. If there is no breakpoint in the execution-path, this function will wait // forever. // int umdkContWait( struct FLContext *handle, bool debug, struct Registers *regs, const char **error) { int retVal = 0, status, i; uint8 tmpData[65536]; size_t scrapSize; uint32 vbAddr, actualLength; uint16 oldOp; union RegUnion { struct Registers reg; uint32 longs[18]; uint8 bytes[18*4]; } *const u = (union RegUnion *)regs; const uint8 *recvData; FILE *file = NULL; if ( debug ) { // Read RAM status = umdkReadBytes(handle, 0xFF0000, 65536, tmpData, error); CHECK_STATUS(status, status, cleanup); // Save it file = fopen("ramBefore.bin", "wb"); CHECK_STATUS(!file, 13, cleanup, "umdkContWait(): Unable to open ramBefore.bin for writing!"); fwrite(tmpData, 1, 65536, file); fclose(file); file = NULL; // Open trace log file = fopen("trace.log", "wb"); CHECK_STATUS(!file, 13, cleanup, "umdkContWait(): Unable to open trace.log for writing!"); } // Get address of VDP vertical interrupt routine and its first opcode status = umdkDirectReadLong(handle, VB_VEC, &vbAddr, error); CHECK_STATUS(status, status, cleanup); status = umdkDirectReadWord(handle, vbAddr, &oldOp, error); CHECK_STATUS(status, status, cleanup); // Write monitor address to illegal instruction vector status = umdkDirectWriteLong(handle, IL_VEC, MONITOR, error); CHECK_STATUS(status, status, cleanup); if ( debug ) { // Disable tracing (if any) & clear junk from trace FIFO tmpData[0] = 0x00; status = flWriteChannel(handle, 0x01, 1, tmpData, error); CHECK_STATUS(status, 25, cleanup); status = flReadChannel(handle, 0x03, 1, tmpData, error); CHECK_STATUS(status, 20, cleanup); scrapSize = tmpData[0] << 8; status = flReadChannel(handle, 0x04, 1, tmpData, error); CHECK_STATUS(status, 20, cleanup); scrapSize |= tmpData[0]; while ( scrapSize ) { // Clear junk from FIFO status = flReadChannel(handle, 0x02, scrapSize, tmpData, error); CHECK_STATUS(status, 20, cleanup); // Verify no junk remaining status = flReadChannel(handle, 0x03, 1, tmpData, error); CHECK_STATUS(status, 20, cleanup); scrapSize = tmpData[0] << 8; status = flReadChannel(handle, 0x04, 1, tmpData, error); CHECK_STATUS(status, 20, cleanup); scrapSize |= tmpData[0]; } // Enable tracing tmpData[0] = 0x02; status = flWriteChannelAsync(handle, 0x01, 1, tmpData, error); CHECK_STATUS(status, 25, cleanup); } // Set up the continue command and execute it status = umdkDirectWriteWord(handle, CB_INDEX, CMD_CONT, error); CHECK_STATUS(status, status, cleanup); status = umdkDirectWriteWord(handle, CB_FLAG, CF_CMD, error); CHECK_STATUS(status, status, cleanup); if ( debug ) { // Submit 1st read for some trace data status = flReadChannelAsyncSubmit(handle, 2, 22528, NULL, error); CHECK_STATUS(status, 28, cleanup); } // Submit 1st read for the command status flag status = umdkDirectReadBytesAsync(handle, CB_FLAG, 2, error); CHECK_STATUS(status, status, cleanup); do { // If interrupted (escape or ctrl-c in gdb), induce a suspend at the next vblank if ( isInterrupted() ) { status = umdkDirectWriteWord(handle, vbAddr, ILLEGAL, error); CHECK_STATUS(status, status, cleanup); } if ( debug ) { // Submit a read for some trace data status = flReadChannelAsyncSubmit(handle, 2, 22528, NULL, error); CHECK_STATUS(status, 28, cleanup); } // Submit a read for the command status flag status = umdkDirectReadBytesAsync(handle, CB_FLAG, 2, error); CHECK_STATUS(status, status, cleanup); if ( debug ) { // Await the requested trace data status = flReadChannelAsyncAwait(handle, &recvData, &actualLength, &actualLength, error); CHECK_STATUS(status, status, cleanup); // Write it to the trace-log fwrite(recvData, 1, actualLength, file); } // Await the requested command status flag status = flReadChannelAsyncAwait(handle, &recvData, &actualLength, &actualLength, error); CHECK_STATUS(status, status, cleanup); } while ( recvData[0] != 0x00 || recvData[1] != CF_READY ); if ( debug ) { // Await the final block of trace-data status = flReadChannelAsyncAwait(handle, &recvData, &actualLength, &actualLength, error); CHECK_STATUS(status, status, cleanup); // Write it to the trace-log fwrite(recvData, 1, actualLength, file); fclose(file); file = NULL; } // Await the final command-flag status = flReadChannelAsyncAwait(handle, &recvData, &actualLength, &actualLength, error); CHECK_STATUS(status, status, cleanup); // Restore old opcode to vbAddr status = umdkDirectWriteWord(handle, vbAddr, oldOp, error); CHECK_STATUS(status, status, cleanup); // Read saved registers, if necessary if ( regs ) { status = umdkDirectReadBytes(handle, CB_REGS, 18*4, u->bytes, error); CHECK_STATUS(status, status, cleanup); for ( i = 0; i < 18; i++ ) { u->longs[i] = bigEndian32(u->longs[i]); } } if ( debug ) { // Read RAM status = umdkReadBytes(handle, 0xFF0000, 65536, tmpData, error); CHECK_STATUS(status, status, cleanup); // Save it file = fopen("ramAfter.bin", "wb"); CHECK_STATUS(!file, 13, cleanup, "umdkContWait(): Unable to open ramAfter.bin for writing!"); fwrite(tmpData, 1, 65536, file); fclose(file); file = NULL; } cleanup: if ( file ) { fclose(file); } return retVal; }
int main(int argc, const char *argv[]) { int returnCode; struct FLContext *handle = NULL; FLStatus status; const char *error = NULL; uint8 byte = 0x10; uint8 buf[256]; bool flag; bool isNeroCapable, isCommCapable; uint32 fileLen; uint8 *buffer = NULL; uint32 numDevices, scanChain[16], i; const char *vp = NULL, *ivp = NULL, *queryPort = NULL, *portConfig = NULL, *progConfig = NULL, *dataFile = NULL; const char *const prog = argv[0]; printf("FPGALink \"C\" Example Copyright (C) 2011-2013 Chris McClelland\n\n"); argv++; argc--; while ( argc ) { if ( argv[0][0] != '-' ) { unexpected(prog, *argv); FAIL(1); } switch ( argv[0][1] ) { case 'h': usage(prog); FAIL(0); break; case 'q': GET_ARG("q", queryPort, 2); break; case 'd': GET_ARG("d", portConfig, 3); break; case 'v': GET_ARG("v", vp, 4); break; case 'i': GET_ARG("i", ivp, 5); break; case 'p': GET_ARG("p", progConfig, 6); break; case 'f': GET_ARG("f", dataFile, 7); break; default: invalid(prog, argv[0][1]); FAIL(8); } argv++; argc--; } if ( !vp ) { missing(prog, "v <VID:PID>"); FAIL(9); } status = flInitialise(0, &error); CHECK(10); printf("Attempting to open connection to FPGALink device %s...\n", vp); status = flOpen(vp, &handle, NULL); if ( status ) { if ( ivp ) { int count = 60; printf("Loading firmware into %s...\n", ivp); status = flLoadStandardFirmware(ivp, vp, &error); CHECK(11); printf("Awaiting renumeration"); flSleep(1000); do { printf("."); fflush(stdout); flSleep(100); status = flIsDeviceAvailable(vp, &flag, &error); CHECK(12); count--; } while ( !flag && count ); printf("\n"); if ( !flag ) { fprintf(stderr, "FPGALink device did not renumerate properly as %s\n", vp); FAIL(13); } printf("Attempting to open connection to FPGLink device %s again...\n", vp); status = flOpen(vp, &handle, &error); CHECK(14); } else { fprintf(stderr, "Could not open FPGALink device at %s and no initial VID:PID was supplied\n", vp); FAIL(15); } } if ( portConfig ) { printf("Configuring ports...\n"); status = flPortConfig(handle, portConfig, &error); CHECK(16); flSleep(100); } isNeroCapable = flIsNeroCapable(handle); isCommCapable = flIsCommCapable(handle); if ( queryPort ) { if ( isNeroCapable ) { status = jtagScanChain(handle, queryPort, &numDevices, scanChain, 16, &error); CHECK(17); if ( numDevices ) { printf("The FPGALink device at %s scanned its JTAG chain, yielding:\n", vp); for ( i = 0; i < numDevices; i++ ) { printf(" 0x%08X\n", scanChain[i]); } } else { printf("The FPGALink device at %s scanned its JTAG chain but did not find any attached devices\n", vp); } } else { fprintf(stderr, "JTAG chain scan requested but FPGALink device at %s does not support NeroJTAG\n", vp); FAIL(18); } } if ( progConfig ) { printf("Executing programming configuration \"%s\" on FPGALink device %s...\n", progConfig, vp); if ( isNeroCapable ) { status = flProgram(handle, progConfig, NULL, &error); CHECK(19); } else { fprintf(stderr, "Program operation requested but device at %s does not support NeroProg\n", vp); FAIL(20); } } if ( dataFile ) { if ( isCommCapable ) { printf("Enabling FIFO mode...\n"); status = flFifoMode(handle, true, &error); CHECK(21); printf("Zeroing registers 1 & 2...\n"); byte = 0x00; status = flWriteChannel(handle, 1000, 0x01, 1, &byte, &error); CHECK(22); status = flWriteChannel(handle, 1000, 0x02, 1, &byte, &error); CHECK(23); buffer = flLoadFile(dataFile, &fileLen); if ( buffer ) { uint16 checksum = 0x0000; uint32 i; for ( i = 0; i < fileLen; i++ ) { checksum += buffer[i]; } printf( "Writing %0.2f MiB (checksum 0x%04X) from %s to FPGALink device %s...\n", (double)fileLen/(1024*1024), checksum, dataFile, vp); status = flWriteChannel(handle, 30000, 0x00, fileLen, buffer, &error); CHECK(24); } else { fprintf(stderr, "Unable to load file %s!\n", dataFile); FAIL(25); } printf("Reading channel 0..."); status = flReadChannel(handle, 1000, 0x00, 1, buf, &error); CHECK(26); printf("got 0x%02X\n", buf[0]); printf("Reading channel 1..."); status = flReadChannel(handle, 1000, 0x01, 1, buf, &error); CHECK(27); printf("got 0x%02X\n", buf[0]); printf("Reading channel 2..."); status = flReadChannel(handle, 1000, 0x02, 1, buf, &error); CHECK(28); printf("got 0x%02X\n", buf[0]); } else { fprintf(stderr, "Data file load requested but device at %s does not support CommFPGA\n", vp); FAIL(29); } } returnCode = 0; cleanup: if ( error ) { fprintf(stderr, "%s\n", error); flFreeError(error); } flFreeFile(buffer); flClose(handle); return returnCode; }