2 Replies Latest reply on Jan 13, 2012 11:32 PM by anand.srinivasan.asokan

    EZ-USB/CyAPI Speed Problem

    jan.philipp.kieling

      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 http://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      http://www.edaboard.com/thread188074.html (code is way better to read there, due to working [code]     
           
      PPS: lol, no *.cpp or *.txt attach allowed?     
           
      //***********************************************************     
      //***********************************************************     
      //     
      // File: Test_CyAPI.cpp     
      // Date: 7.4.10     
      // Author: Kießling, Jan P.     
      // Purpose: getting used to CyAPI and writing basic     
      // functions     
      //***********************************************************     
      //***********************************************************     
           
           
           
      //***********************************************************     
      // Includes     
      //***********************************************************     
      #include            
      #include              
      //#include                
      #include                  
      #include                    
      #include                      
      #include                        
      #include                          
      #include                            
                    
      //***********************************************************              
      // 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);              
      [code]              
      //***********************************************************              
      // 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)              
      {              
                    
      }              
      }              
      [/code]             
                  
                 
                
               
              
             
            
           
          

        • 1. Re: EZ-USB/CyAPI Speed Problem
          jan.philipp.kieling

          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.   
          • 2. Re: EZ-USB/CyAPI Speed Problem
            anand.srinivasan.asokan

            Just wanted to give you explanation for each of your change

               

            1. Bulkloop uses the 8051 to transfer data from endpoint to another (comparing with USB2.0 speed 8051 is very slow, putting it in the datapath will slow down traffic)

               

            2. SetXferSize() is used to set the amount of buffer allocated in host controller driver for the device (For example: If I allocate a 1k buffer, for a 4k transfer the host controller buffer will fill up 4 times and 3 times the host controller would have waited for the OS to read and then clear the buffer. Instead say I use a 4k buffer there is no waiting i.e. more speed). This has its own restriction based on Windows http://msdn.microsoft.com/en-us/library/ff538112.aspx.

               

            3. Similar to above between each Xferdata() time is needed since the OS has to queue and schedule the next Xferdata(). If you use the Asynchronous approach (Beginxferdata/waitforxfer/Finishxferdata) the transfers are queued so the next transfer is queued before the first transfer completes. You should be able to get a slightly higher speed with it. You can use Streamer/screamer example that comes as part of SuiteUSB as reference to implement this.

               

            Regards,

               

            Anand