// Read bytes asynchronously from the specified channel (1 <= count <= 0x10000). // DLLEXPORT(FLStatus) flReadChannelAsyncSubmit( struct FLContext *handle, uint8 chan, uint32 count, uint8 *buffer, const char **error) { FLStatus retVal = FL_SUCCESS, fStatus; uint8 command[3]; USBStatus uStatus; size_t queueDepth; const uint16 count16 = (count == 0x10000) ? 0x0000 : (uint16)count; CHECK_STATUS( !handle->isCommCapable, FL_PROTOCOL_ERR, cleanup, "flReadChannelAsyncSubmit(): This device does not support CommFPGA"); CHECK_STATUS( count == 0, FL_PROTOCOL_ERR, cleanup, "flReadChannelAsyncSubmit(): Zero-length reads are illegal!"); CHECK_STATUS( count > 0x10000, FL_PROTOCOL_ERR, cleanup, "flReadChannelAsyncSubmit(): Transfer length exceeds 0x10000"); // Write command command[0] = chan | 0x80; flWriteWord(count16, command+1); fStatus = bufferAppend(handle, command, 3, error); CHECK_STATUS(fStatus, fStatus, cleanup, "flReadChannelAsyncSubmit()"); // Flush outstanding async writes fStatus = flFlushAsyncWrites(handle, error); CHECK_STATUS(fStatus, fStatus, cleanup, "flReadChannelAsyncSubmit()"); // Maybe do a few awaits, to keep things balanced queueDepth = usbNumOutstandingRequests(handle->device); while ( queueDepth > 2 && !handle->completionReport.flags.isRead ) { uStatus = usbBulkAwaitCompletion( handle->device, &handle->completionReport, error ); CHECK_STATUS(uStatus, FL_USB_ERR, cleanup, "flReadChannelAsyncSubmit()"); queueDepth--; } // Then request the data uStatus = usbBulkReadAsync( handle->device, handle->commInEP, // endpoint to read buffer, // pointer to buffer, or null count, // number of data bytes 5000, // max timeout: 49 days error ); CHECK_STATUS(uStatus, FL_USB_ERR, cleanup, "flReadChannelAsyncSubmit()"); cleanup: return retVal; }
int bufferRead(void) { int retVal = 0; USBStatus uStatus; struct USBDevice *deviceHandle = NULL; const char *error = NULL; uint8 *ptr; const uint8 *buf; struct CompletionReport completionReport; // Init library uStatus = usbInitialise(0, &error); CHECK_STATUS(uStatus, 1, cleanup); // Open device uStatus = usbOpenDevice("1d50:602b", 1, 0, 0, &deviceHandle, &error); CHECK_STATUS(uStatus, 2, cleanup); // Select CommFPGA conduit (FX2 slave FIFOs = 0x0001) uStatus = usbControlWrite(deviceHandle, 0x80, 0x0000, 0x0001, NULL, 0, 1000, &error); CHECK_STATUS(uStatus, 3, cleanup); // Get the next available 64KiB write buffer uStatus = usbBulkWriteAsyncPrepare(deviceHandle, &ptr, &error); // Write request command CHECK_STATUS(uStatus, 4, cleanup); buf = ptr; // Populate the buffer with a couple of FPGA write commands and one FPGA read command *ptr++ = 0x00; // write ch0 *ptr++ = (uint8)(CHUNK_SIZE >> 24); *ptr++ = (uint8)(CHUNK_SIZE >> 16); *ptr++ = (uint8)(CHUNK_SIZE >> 8); *ptr++ = (uint8)(CHUNK_SIZE & 0xFF); memcpy(ptr, randomData, CHUNK_SIZE); ptr += CHUNK_SIZE; *ptr++ = 0x00; // write ch0 *ptr++ = (uint8)(CHUNK_SIZE >> 24); *ptr++ = (uint8)(CHUNK_SIZE >> 16); *ptr++ = (uint8)(CHUNK_SIZE >> 8); *ptr++ = (uint8)(CHUNK_SIZE & 0xFF); memcpy(ptr, randomData+CHUNK_SIZE, CHUNK_SIZE); ptr += CHUNK_SIZE; *ptr++ = 0x80; // read ch0 *ptr++ = (uint8)(CHUNK_SIZE >> 24); *ptr++ = (uint8)(CHUNK_SIZE >> 16); *ptr++ = (uint8)(CHUNK_SIZE >> 8); *ptr++ = (uint8)(CHUNK_SIZE & 0xFF); // Submit the write uStatus = usbBulkWriteAsyncSubmit(deviceHandle, 2, (uint32)(ptr-buf), 1000, &error); CHECK_STATUS(uStatus, 5, cleanup); // Submit the read uStatus = usbBulkReadAsync(deviceHandle, 6, NULL, CHUNK_SIZE, 9000, &error); // Read response data CHECK_STATUS(uStatus, 6, cleanup); // Wait for them to be serviced uStatus = usbBulkAwaitCompletion(deviceHandle, &completionReport, &error); CHECK_STATUS(uStatus, 7, cleanup); printCompletionReport(&completionReport); uStatus = usbBulkAwaitCompletion(deviceHandle, &completionReport, &error); CHECK_STATUS(uStatus, 8, cleanup); printCompletionReport(&completionReport); cleanup: usbCloseDevice(deviceHandle, 0); if ( error ) { fprintf(stderr, "%s\n", error); usbFreeError(error); } return retVal; }
int multiRead(uint32 reqCount, uint32 reqSize, double *speed) { int retVal = 0; USBStatus uStatus; struct USBDevice *deviceHandle = NULL; const char *error = NULL; uint8 buf[5]; struct CompletionReport completionReport; uint32 numBytes; double totalTime; #ifdef WIN32 LARGE_INTEGER tvStart, tvEnd, freq; DWORD_PTR mask = 1; SetThreadAffinityMask(GetCurrentThread(), mask); QueryPerformanceFrequency(&freq); #else struct timeval tvStart, tvEnd; long long startTime, endTime; #endif // We can make one FPGA request message and re-use it buf[0] = 0x80; // write ch0 buf[1] = (uint8)(reqSize >> 24); buf[2] = (uint8)(reqSize >> 16); buf[3] = (uint8)(reqSize >> 8); buf[4] = (uint8)(reqSize & 0xFF); // Init library uStatus = usbInitialise(0, &error); CHECK_STATUS(uStatus, 1, cleanup); // Open device uStatus = usbOpenDevice("1d50:602b", 1, 0, 0, &deviceHandle, &error); CHECK_STATUS(uStatus, 2, cleanup); // Select CommFPGA conduit (FX2 slave FIFOs = 0x0001) uStatus = usbControlWrite(deviceHandle, 0x80, 0x0000, 0x0001, NULL, 0, 1000, &error); CHECK_STATUS(uStatus, 3, cleanup); // Record start time #ifdef WIN32 QueryPerformanceCounter(&tvStart); #else gettimeofday(&tvStart, NULL); #endif // Send a couple of read commands to the FPGA uStatus = usbBulkWriteAsync(deviceHandle, 2, buf, 5, 9000, &error); // Write request command CHECK_STATUS(uStatus, 4, cleanup); uStatus = usbBulkReadAsync(deviceHandle, 6, NULL, reqSize, 9000, &error); // Read response data CHECK_STATUS(uStatus, 5, cleanup); uStatus = usbBulkWriteAsync(deviceHandle, 2, buf, 5, 9000, &error); // Write request command CHECK_STATUS(uStatus, 6, cleanup); uStatus = usbBulkReadAsync(deviceHandle, 6, NULL, reqSize, 9000, &error); // Read response data CHECK_STATUS(uStatus, 7, cleanup); // On each iteration, await completion and send a new read command numBytes = (reqCount+2)*reqSize; while ( reqCount-- ) { uStatus = usbBulkAwaitCompletion(deviceHandle, &completionReport, &error); CHECK_STATUS(uStatus, 8, cleanup); printCompletionReport(&completionReport); uStatus = usbBulkAwaitCompletion(deviceHandle, &completionReport, &error); CHECK_STATUS(uStatus, 9, cleanup); printCompletionReport(&completionReport); uStatus = usbBulkWriteAsync(deviceHandle, 2, buf, 5, 9000, &error); // Write request command CHECK_STATUS(uStatus, 10, cleanup); uStatus = usbBulkReadAsync(deviceHandle, 6, NULL, reqSize, 9000, &error); // Read response data CHECK_STATUS(uStatus, 11, cleanup); } // Wait for the stragglers... uStatus = usbBulkAwaitCompletion(deviceHandle, &completionReport, &error); CHECK_STATUS(uStatus, 12, cleanup); printCompletionReport(&completionReport); uStatus = usbBulkAwaitCompletion(deviceHandle, &completionReport, &error); CHECK_STATUS(uStatus, 13, cleanup); printCompletionReport(&completionReport); uStatus = usbBulkAwaitCompletion(deviceHandle, &completionReport, &error); CHECK_STATUS(uStatus, 14, cleanup); printCompletionReport(&completionReport); uStatus = usbBulkAwaitCompletion(deviceHandle, &completionReport, &error); CHECK_STATUS(uStatus, 15, cleanup); printCompletionReport(&completionReport); // Record stop time #ifdef WIN32 QueryPerformanceCounter(&tvEnd); totalTime = (double)(tvEnd.QuadPart - tvStart.QuadPart); totalTime /= freq.QuadPart; *speed = (double)numBytes / (1024*1024*totalTime); #else gettimeofday(&tvEnd, NULL); startTime = tvStart.tv_sec; startTime *= 1000000; startTime += tvStart.tv_usec; endTime = tvEnd.tv_sec; endTime *= 1000000; endTime += tvEnd.tv_usec; totalTime = (double)(endTime - startTime); totalTime /= 1000000; // convert from uS to S. *speed = (double)numBytes / (1024*1024*totalTime); #endif cleanup: usbCloseDevice(deviceHandle, 0); if ( error ) { fprintf(stderr, "%s\n", error); usbFreeError(error); } return retVal; }