Description

TE_USB_FX2_GetData() reads data from the USB FX2 microcontroller endpoint EP6 (0x86) and transfers this data to the host computer. This data is generated by the FPGA.

This function takes an already initialized CCyBulkEndPoint double pointer. The device has been previously selected by TE_USB_FX2_Open().

EP6's buffer is an HW buffer inside USB FX2 microcontroller, not the SW driver's buffer (on host computer) whose size is given by BufferSize parameter.

It is necessary that a FW/HW routine reads USB FX2 microcontroller's EP8 buffer.

If the EP6's buffer is not is not properly written by the FPGA(reference design)/other(custom design) the EP6's buffer will become empty and the host computer will be no longer able to receive further packets. In this case the TE_USB_FX2_GetData() function could experience strange behaviors. For example, a very low throughput (9-10 Mbyte/s even if a 31-38 Mbyte/s are expected) could be measured or the function TE_USB_FX2_GetData() fails returning false.

During USB read transmission test (RX: host computer perspective) the EP6's buffer writing is carried out by MicroBlaze (inside the FPGA); this behavior is setted by MicroBlaze API command FX22MB_REG0_START_TX (TX: USB FX2 microcontroller perspective)

SendFPGAcommand(ref TE_USB_FX2_USBDevice,MB_Commands.FX22MB_REG0_TX, TIMEOUT_MS)

Expected Data Throughput 

The maximum data throughput expected (with a DataReadLength= 120*10^6) is 38 Mbyte/s (PacketSize = BufferSize = 102400), but in fact this value is variable between 31-38 Mbyte/s (the mean value seems 33.5 Mbyte/s); so if you measure this range of values, the data reception can be considered as normal.

The data throughput is variable in two ways:

  • depends on the used host computer;
  • varies with every function call (computer loading dependent).

DataRead Size Shall Not Be Too Large

TE_USB_FX2_GetData() seems unable to use too large arrays or, more precisely, this fact seems variable by changing host computer. To be safe, do not try to transfer in a single packet very large data (e.g. 120 millions of byte); transfer the same data with many packets instead (1,200 packets * 100,000 byte) and copy the data in a single large data array if necessary (with Buffer.BlockCopy()).

The use of Buffer.BlockCopy() function seems not to hinder throughput too much (in some case 2 Mbyte/s of difference with C++).

DataRead Size Shall Not Be Too Small

There are two reasons why DataRead size shall not be too small.

The first reason is that PacketSize has a strong influence on DataThroughput. If PacketSize is too small (e.g. 512 byte), you can have very low DataThroughput (2.2 Mbyte/s) even if you use a large driver buffer (driver buffer size = 131,072 bytes). See section 6 TE_USB_FX2_CyAPI.dll: Data Transfer Throughput Optimization.

The second reason is that probably the FPGA imposes your minimum packet size. In a properly used read test mode (using FX22MB_REG0_START_TX and therefore attaching the FPGA), TE_USB_FX2_GetData() is unable to read less than 1024 byte. In a improperly used read test mode (not using FX22MB_REG0_START_TX and therefore detaching the FPGA), TE_USB_FX2_GetData() is able to read a packet size down to 64 byte. The same CyAPI method XferData() used (under the hood) in TE_USB_FX2_SendCommand() is able to read a packet size of 64 byte. These facts prove that the minimum packet size is imposed by FPGA. To be safe, we recommend to use this function with a size multiple of 1 kbyte.

Use of the code

Declaration

public static bool TE_USB_FX2_GetData(ref CyUSBDevice TE_USB_FX2_USBDevice, ref byte[] DataRead, ref int DataReadLength, int PipeNo, uint Timeout, int BufferSize);

Function Call

Your application program shall call this function like this:

TE_USB_FX2.TE_USB_FX2.TE_USB_FX2_GetData(ref TE_USB_FX2_USBDevice, ref DataRead, ref DataReadLength, PI_EP6, Timeout, BufferSize);

Parameters

ref CyUSBDevice TE_USB-FX2_USBDevice

This parameter points to the module selected by TE_USB_FX2_Open(). This parameter is passed by reference (ref). See pages 70-93 of CyUSB.NET.pdf (Cypress CyUSB .NET DLL Programmer's Reference)

ref byte[] DataRead

This parameter is passed by reference (ref). C# applications use directly TE_USB_FX2_CyUSB.dll based on CyUSB.dll. To avoid copying back and forth large amount of data between these two DLLs, data is passed by reference rather than by value. This parameter points to the byte array that, after the function returns, will contain the data read from the buffer EP6 of the USB FX2 microcontroller. The data contained in EP6 generated by the FPGA. If no data is contained in EP6, the byte array is left unchanged.

ref int DataReadLength

This parameter is the length (in bytes) of the previous byte array; it is the length of the packet read from the USB FX2 microcontroller endpoint EP6 (0x86). It is typically PacketLength. This parameter is passed by reference (ref).

int PipeNumber

This parameter is the value that identifies the endpoint used for data transfer. It is called PipeNumber because it identifies the buffer (pipe) used by the USB FX2 microcontroller.

uint Timeout

It is the integer time value in milliseconds assigned to the synchronous method XferData() of data transfer used by CyUSB.dll. Timeout is the time that is allowed to the function for sending/receiving the data packet passed to the function; this timeout shall be large enough to allow data/command transmission/reception.. Otherwise the transmission/reception will fail. See 1.1.2 Timeout Setting.

int BufferSize

It is the dimension (in bytes) of the driver buffer (SW) used in data reception of a single endpoint (EP6 0x86 in this case)single endpoint (EP6 0x86 in this case); the total buffer size is the sum of BufferSize of every endpoint used. BufferSize has a strong influence on DataThroughput. If the BufferSize is too small, DataThroughput can be 1/3-1/2 of the maximum value (from a maximum value of 36 Mbyte/s for read transactions to an actual value of 18 Mbyte/s). If BufferSize has a large value (a roomy buffer), the program shall be able to cope with the non-deterministic behavior of C# without losing packets.

Return Value

bool : logical type

This function returns true if it is able to receive the data from buffer EP6 within Timeout milliseconds. This function returns false otherwise.

Simplified Code 1

PACKETLENGTH=100000;
packets=1200;
byte[] data = new byte[packetlen*packets];
byte[] buffer = new byte[packetlen];
for (int i = 0; i < packets; i++)
{
	TE_USB_FX2_GetData(ref TE_USB_FX2_USBDevice, ref buffer, ref packetlen, PI_EP6, TIMEOUT_MS,BUFFER_SIZE)
	Buffer.BlockCopy(buffer, 0, data, total_cnt, packetlen);
	total_cnt += packetlen;
}

Actual code example 1

PACKETLENGTH=100000;
packets=1200;
byte[] data = new byte[packetlen*packets];
byte[] buffer = new byte[packetlen];
//starts test: the FPGA start to write data in the buffer EP6 of FX2 chip
SendFPGAcommand(ref TE_USB_FX2_USBDevice, MB_Commands.FX22MB_REG0_START_TX, TIMEOUT_MS);
test_cnt = 0;
total_cnt = 0;
for (int i = 0; i < packets; i++)
{
	//buffer = &data[total_cnt];
	packetlen = PACKETLENGTH;
	//fixed (byte* buffer = &data[total_cnt])
	bResultXfer = TE_USB_FX2.TE_USB_FX2.TE_USB_FX2_GetData(ref TE_USB_FX2_USBDevice, ref buffer, ref packetlen, PI_EP6, TIMEOUT_MS,BUFFER_SIZE);
	Buffer.BlockCopy(buffer, 0, data, total_cnt, packetlen);
	if (bResultXfer == false)
	{
		//cout << "ERROR" << endl;
		Console.WriteLine("Error Get Data");
		SendFPGAcommand(ref TE_USB_FX2_USBDevice, MB_Commands.FX22MB_REG0_STOP, TIMEOUT_MS);
		return;
	}
	total_cnt += packetlen;
}
//stop test: the FPGA start to write data in the buffer EP6 of FX2 chip
SendFPGAcommand(ref TE_USB_FX2_USBDevice,
MB_Commands.FX22MB_REG0_STOP, TIMEOUT_MS)
  • No labels