Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

EZ-USB/CyAPI Speed Problem

Status
Not open for further replies.

Nephazz

Junior Member level 1
Joined
Apr 7, 2010
Messages
15
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Activity points
1,396
Hi,

my current project is to establish an USB connection between a WinXP PC and an FPGA. I don't get my hands dirty on the FPGA though, my boss does this stuff. He needs me to provide datarate of at least 15 MB/s. I've got a board which has "Cypress semiconductor CY3684 / 3674 EZ-USB Advanced development board" printed on and a "CY7C68013A-128AXC 0731 B 04 645490" chip mounted. I use this to develop my WinXP software (MS Visual C++) but the final version will use an FPGA Board from AVnet. The current firmware for the CY7 USB-Controller is the bulkloop.hex deliverd in c:/cypress/usb/examples.

Right now I use the CyAPI and I'am able to establish a connection to the board, get some informations like "number of endpoints" and bulk transfer in and out. To meassure the tranferspeed I use . (source file is attached) Unfortunatly I only get about 1 MB/s. ( I've tried using https://www.cypress.com/?docID=4383 to meassure speed but I can't get it running. It's probably because I use "USB Console" instead of "EZ-USB Control Panel" which I can't find anywhere. )

So ... where is my bottleneck? Is CyAPI in general unable to attain high bandwidth? Do I use it wrong or is it just the expample firmware that doesn't deliver? Do you have any app notes or other must-reads?

have a nice day,
Jan


PS: this is crossposted in https://www.cypress.com/forums/forum/messageview.cfm?catid=8&threadid=10046&enterthread=y


Code:
//***********************************************************
//***********************************************************
//
//	File:		Test_CyAPI.cpp
//	Date:		7.4.10
//	Author:		Kießling, Jan P.
//	Purpose:	getting used to CyAPI and writing basic 
//				functions
//***********************************************************
//***********************************************************



//***********************************************************
//							Includes
//***********************************************************
#include <windows.h>
#include <stdio.h>
//#include <iostream.h>
#include <time.h>
#include <conio.h>
#include <math.h>
#include <CyAPI.h>
#include <string>
#include <iostream>

//***********************************************************
//					Macros and Global Variables
//***********************************************************
using namespace std;
extern HANDLE Handle;
using std::string;
//***********************************************************
//						Declarations
//***********************************************************
bool USBSend512(unsigned char *out, CCyUSBDevice *USBDevice);
bool USBGet512(unsigned char *in, CCyUSBDevice *USBDevice);
void wait_seconds(int seconds);
//***********************************************************
//							main
//***********************************************************
void main (void)
{
	// [USB Init]
	CCyUSBDevice *USBDevice = new CCyUSBDevice(NULL);
	// Attempt to open device #0
	if (USBDevice->DeviceCount() && !USBDevice->Open(0)) // check if there is a device available and if device0 is NOT already open
	{
		cout << "Resetting and opening Device 0" << endl;
		USBDevice->Reset();
		USBDevice->Open(0);
	}
	if (! USBDevice->IsOpen()) 
	{	
		printf("\n Device NOT open\n\n");	
	}
	else
	{
		printf("\n Device open\n\n");	
	}

	// [get information]
	int devices = USBDevice->DeviceCount();
	int altInt = USBDevice->AltIntfcCount();
	int curInt = USBDevice->AltIntfc();
	int eptCount = USBDevice->EndPointCount();
	int maxPaketSize = USBDevice->BulkOutEndPt->MaxPktSize;

	// [print information]
	cout << "FriendlyName: " << USBDevice->FriendlyName << endl;
	//cout << "Number of Cypress Devices: " << devices << endl;
	cout << "Number of alternate interfaces: " << altInt << endl;
	cout << "Using Interface: " << curInt << endl;
	cout << "Number of Endpoints: " << eptCount << endl;
	cout << "Max Paket Size of Bulk Out 1: " << maxPaketSize << endl;
	cout << "Xfer Size = " << USBDevice->BulkOutEndPt->GetXferSize() << endl;

	// [report all Endpoints with type and direction]
	string direction, type;
	for(int c = 0; c < eptCount; c++)
	{
		if(USBDevice->EndPoints[c]->bIn)
		{
			direction = "Input";
		}
		else
		{
			direction = "Output";
		}
		switch(USBDevice->EndPoints[c]->Attributes)
		{
			case 0: 
					type = "Control";
					break;
			case 1: 
					type = "Isochronous";
					break;
			case 2:
					type = "Bulk";
					break;
			case 3:
					type = "Interrupt";
					break;
		}
		cout << "Endpoint " << c << " is " << type << " " << direction << endl; 
	}

	//[Speed Test]
	unsigned char out[512];
	unsigned char in[512];
	time_t t_start, t_end;
	double t_elapsed;
	//init arrays             
	for (c = 0; c < 513; c++)
	{
		out[c] = 0x00+c;
		in[c] = 0x01;
	}
	//start test
	time(&t_start);	//get current time
	for(double ac=0; ac < 65535; ac++)
		{
			USBSend512(out, USBDevice);
			USBGet512(in, USBDevice);
		}				
	time(&t_end);
	t_elapsed = difftime(t_end,t_start);
	cout << " " << t_elapsed << endl;
	//[are the last two arrays equal?]
	bool ka = TRUE;
	for(c = 0; c < 512; c++)
	{
		if(in[c] != out[c])
		{
			ka = FALSE;
		}
	}
	if(ka) 
	{
		cout << "In equals Out" << endl;
	}
	else
	{
		cout << "In doesn't equal Out" << endl;
	}
	//[End of Main]
	USBDevice->Close();
	return;
}

//***********************************************************
//						functions
//***********************************************************

bool USBSend512(unsigned char *out, CCyUSBDevice *USBDevice)
{	
	//this function sends 512 Bytes via USB to an open Endpoint
	//returns TRUE if OK, false if no EP exists
	bool OK = FALSE;
	LONG length = 512;

	if (USBDevice->BulkOutEndPt) //check if EP exists
	{
		OK = (USBDevice->BulkOutEndPt->XferData(out, length)); //sending array
	}
	else
	{
		OK = FALSE;
	}
	return OK;
}
//***********************************************************
bool USBGet512(unsigned char *in, CCyUSBDevice *USBDevice)
{	
	//this function gets 512 Bytes via USB from an open Endpoint
	//returns TRUE if OK, false if no EP exists
	bool OK = FALSE;
	LONG length = 512;

	if (USBDevice->BulkInEndPt) //check if EP exists
	{
		OK = USBDevice->BulkInEndPt->XferData(in, length);
	}
	else
	{
		OK = FALSE;
	}
	return OK;
}
//***********************************************************
void wait_seconds(int seconds)
{
  clock_t endwait;
  endwait = clock () + seconds * CLOCKS_PER_SEC ;
  while (clock() < endwait) 
  {
  
  }
}
 

I'm confident that I solved the problem. Seems a little to good to be true though.

I've changed the firmware to bulksrc.hex which delivers/consumes infinite amount of data. I assume that this happens by setting/clearing some kind of ready flag. Thus the 8051 doesn't take time to read or load the endpoints. This change alone gave me a lot of speed.

The other point is that I used SetXferSize( ) to set it from 0x200 to FFFF. I'm not sure what it exactly does but an appnote recommends it.

Third point is the usage of XferData(). I used to transfer 512 Byte big arrays ... which is only one measly USB packet. Now with each call of this method I hand it a pointer to a FFFF big char array (representing 128 packets). Reading 10000 of these takes me 16 seconds and that'd be around 41 MB/s.

Reading 100000 takes 162 seconds.
 

In case of bulkloop, only/all the data is writtent to USB Out endpoints is returned by IN endpoints. There is no sourcing of data within ezUSB. This moving of data from OUT to IN has to be done by poor 8051 microcontroller. So you can't get enough speed.

In case of bulksrc, while one of the IN endpoints (EP8) sends the data back recived at one of the OUT endpoints (EP4), the others are independent. EP6 actually source a fixed 512 byte packed.

It is not clear what EP's are you using in your application. If you don't send to Ep4, then no data in EP4 and no copy operation by 8051 so its involvement is minimum.
Ep2 will keep getting data without any control/interference from microcontroller and similarly EP6 will keep returning the data without any requirement from microcontroller. This will result in high bandwidth output. That's the essence of ezUSb design.

SetXferSize() adjusts the driver's buffer and hence more data from USB can be buffered internally before returning it to you (Application), which results in lesser overhead. This does help in bandwidth gain to a certain limit but not from 1MBps to 41MBps.

Moreover your attached sampel code shows that you are using USBDevice->BulkInEndPt USBDevice->BulkOutEndPt, which by default point to the first available IN and OUT endpoints respectively (Ep6 and EP2). So no 8051 intervention in USb data path results in higher bandwidth.
 

No offense, I only want to make sure I understand you right: You state that all my coclusions from above are rigth, aren't you?
 

I state that you don't seem to be aware of why you got the high data rate :)

Specifically:
SetXferSize() won't make much difference. Just use the bulkIO and check for yourself.
using bulksrc won't make much difference if you use EP4 and EP8 for sending and receiving the data.

The thing making the difference is "NO Microcontroller INTERVENTION in USB data path"

Keep this in mind while designing your final device.
 

Ok, thanks for the clarification :)
 

SetXferSize() sets the buffer size on the host controller driver... by default cyapi will set it to endpoint size * 8.... changing this using SetXferSize() is capable of making a difference... :D
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top