12 Replies Latest reply on Sep 20, 2017 9:07 AM by milkfish1227_2635671

    EP0 Read() takes 5 seconds to complete.

    milkfish1227_2635671

      I had hard time to response to my original post with attachments. So I create this new discussion.

       

      I added the source code and the screen shot. Set the breakpoint on Rea and next statement, you can see from VS IDE how much time it take to execute that statement.

      I am using VS2017 free community version. Thx

       

         bResult = ept->Read(rxBuf, bytesToSend);

         printf("txBuf[0-3] \r\n");

        • 1. Re: EP0 Read() takes 5 seconds to complete.
          milkfish1227_2635671

          Forgot the FX3 firmware code. I am using UsbSpiGpioMode project. It's in CyFxUSBSetupCB() for WRITE case.

           

          The only thing this vendor request doing is loopback the data read from EP1.

           

          CyBool_t

          CyFxUSBSetupCB (

                  uint32_t setupdat0,

                  uint32_t setupdat1)

          {

          ...

                      case CY_FX_RQT_SPI_FLASH_WRITE:

                          status = CyU3PUsbGetEP0Data (wLength, glEp0Buffer, NULL);

          //                if (status == CY_U3P_SUCCESS)

          //                {

          //                    status = CyFxSpiTransfer (wIndex, wLength, glEp0Buffer, CyFalse);

          //                }

           

                          // for testing

                          status = CyU3PUsbSendEP0Data (wLength, glEp0Buffer);

          • 2. Re: EP0 Read() takes 5 seconds to complete.
            Madhu Lakshmipathy

            Hi,

             

            Can you please check in your FX3 firmware, which part of the code execution takes much time? Did you check any other writes on your SPI Flash  in general and how much time it takes? If you comment out the SPI Flash code and just looping back the EP0 data is it taking this much time?

             

            Please let us know your observations.

             

            Regards,

            -Madhu Sudhan

            • 3. Re: EP0 Read() takes 5 seconds to complete.
              milkfish1227_2635671

              The FX3 firmware only get EP0 data, then send EP0 data. The time was take from host VS IDE. I haven't tried on Eclipse to measure the time yet.

               

              In my post, I do have have host side VS solution. Can you give it a try to see if it happened on your side? I have been tried on different PCs.

               

                          case CY_FX_RQT_SPI_FLASH_WRITE:

                              status = CyU3PUsbGetEP0Data (wLength, glEp0Buffer, NULL);

              //                if (status == CY_U3P_SUCCESS)

              //                {

              //                    status = CyFxSpiTransfer (wIndex, wLength, glEp0Buffer, CyFalse);

              //                }

               

               

                              // for testing

                              status = CyU3PUsbSendEP0Data (wLength, glEp0Buffer);

              • 4. Re: EP0 Read() takes 5 seconds to complete.
                milkfish1227_2635671

                Any suggestions? I am stuck. Thx

                • 5. Re: EP0 Read() takes 5 seconds to complete.
                  ntan

                  Following image is the "Figure 8-37. Control Read and Write Sequences" in the "Universal Serial Bus Specification Revision 2.0" document.

                  GS003206.png

                  There are three kinds of sequences WRITE, READ, and NO-DATA.  When the vendor request CY_FX_RQT_SPI_FLASH_WRITE is handled, the WRITE sequence is attempted because there is a CyU3PUsbGetEP0Data() function to get the "Data Stage" packets from the HOST.  After these packets, the HOST expects to receive a "Status Stage" packet from the DEVICE.  Please note that the "Status Stage" cannot have any data in the packet.  "Status Stage" is just used for an acknowledge.

                  In your code snippet, CyU3PUsbSendEP0Data() API function is invoked after the "Data Stage" to generate a "IN" packet with some data.  This packet does not follow the USB specification.

                   

                  If you want to receive some data from the FX3 device with a Control Transfer, the HOST must issue another Control READ Transfer.

                   

                  Regards,

                  Noriaki

                  • 6. Re: EP0 Read() takes 5 seconds to complete.
                    milkfish1227_2635671

                    I did have the Read() function in host app right after the Write(). See below. I did attached the host app solution in my first post.

                     

                    int main()

                    {

                       CCyUSBDevice *USBDevice = new CCyUSBDevice(NULL);

                     

                       //  Attempt to open device #0

                       if (USBDevice->DeviceCount() && !USBDevice->Open(0))

                       {

                          USBDevice->Reset();

                          USBDevice->Open(0);

                       }

                     

                       //  Just for typing efficiency

                       CCyControlEndPoint  *ept = USBDevice->ControlEndPt;

                       ept->Target = TGT_ENDPT;

                       ept->ReqType = REQ_VENDOR;

                       ept->ReqCode = 0xC2;

                       ept->Value = 0;

                       ept->Index = 0;

                     

                       unsigned char  txBuf[256], rxBuf[256];

                       ZeroMemory(txBuf, 256);

                       ZeroMemory(rxBuf, 256);

                       LONG bytesToSend = 4;

                       bool bResult = true;

                         

                       txBuf[0] = 1;

                       txBuf[1] = 2;

                       txBuf[2] = 3;

                       txBuf[3] = 4;

                       bResult = ept->Write(txBuf, bytesToSend);

                     

                       bResult = ept->Read(rxBuf, bytesToSend);

                     

                       printf("txBuf[0-3] \r\n");

                       for (int i = 0; i < bytesToSend; i++)

                          printf("%d ", txBuf[i]);

                     

                       printf("\r\n\r\nrxBuf[0-3] \r\n");

                       for (int i = 0; i < bytesToSend; i++)

                          printf("%d ", rxBuf[i]);

                     

                       return 0;

                    }

                    • 7. Re: EP0 Read() takes 5 seconds to complete.
                      ntan

                      I am saying "the Read() function in host app right after the Write()" is out of the USB specification.  The behavior of the HOST and device driver for that sequence may not be specified.

                       

                      Regards,

                      Noriaki

                      • 8. Re: EP0 Read() takes 5 seconds to complete.
                        milkfish1227_2635671

                        Here is the Write/Read function ins CyAPI. I believe it should be doing the whole sequence of what you mentioned in USB spec.

                         

                        Write( ) sets the CyControlEndPoint Direction member to DIR_TO_DEVICE and then calls CCyUSBEndPoint::XferData( ). The buf parameter points to a memory buffer where the read bytes will be placed. The len parameter tells how many bytes are to be read. Returns true if the write operation was successful. Passes-back the actual number of bytes transferred in the len parameter.

                         

                        Read( ) sets the CyControlEndPoint Direction member to DIR_FROM_DEVICE and then calls CCyUSBEndPoint::XferData( ). The buf parameter points to a memory buffer where the read bytes will be placed. The len parameter tells how many bytes are to be read. Returns true if the read operation was successful. Passes-back the actual number of bytes transferred in the len parameter

                        • 9. Re: EP0 Read() takes 5 seconds to complete.
                          ntan

                          How about the "Status Stage" transaction?

                           

                          At the end of a Control Transfer, the "Status Stage" transaction must be handled.

                          Did you check the return value from the Write() and Read() method?

                           

                          Regards,

                          Noriaki

                          • 10. Re: EP0 Read() takes 5 seconds to complete.
                            milkfish1227_2635671

                            Both return are true. See below example from CyAPI programmer's reference.

                             

                            Are you saying this document is wrong?

                             

                            Example

                            CCyUSBDevice *USBDevice = new CCyUSBDevice(NULL);

                            // Just for typing efficiency

                            CCyControlEndPoint *ept = USBDevice->ControlEndPt;

                            ept->Target = TGT_DEVICE;

                            ept->ReqType = REQ_VENDOR;

                            ept->ReqCode = 0x07;

                            ept->Value = 1;

                            ept->Index = 0;

                            unsigned char buf[512];

                            ZeroMemory(buf,512);

                            LONG bytesToSend = 128;

                            ept->Write(buf, bytesToSend);

                             

                            CCyUSBDevice *USBDevice = new CCyUSBDevice(NULL);

                            // Just for typing efficiency

                            CCyControlEndPoint *ept = USBDevice->ControlEndPt;

                            ept->Target = TGT_DEVICE;

                            ept->ReqType = REQ_VENDOR;

                            ept->ReqCode = 0x07;

                            ept->Value = 1;

                            ept->Index = 0;

                            unsigned char buf[512];

                            LONG bytesToRead = 64;

                            ept->Read(buf, bytesToRead);

                            • 11. Re: EP0 Read() takes 5 seconds to complete.
                              ntan

                              I am saying the firmware does not follow the USB specification.  Please go back to the Control Transfer sequence.

                              GS003206.png

                               

                              Following is the behavior of the PC application and the FX3 firmware assumed by me..

                               

                              (1) PC initiates a Control WRITE Transfer by calling the Write() method.  PC sends a SETUP packet as the Setup Stage.

                              (2) FX3 receives the SETUP packet and call the SetupCB() function.

                              (3) PC sends an OUT packet as the Data Stage.

                              (4) In the callback function FX3 receives the OUT packet by calling the CyU3PUsbGetEP0Data() function.

                              (5) When all data of the OUT packet received, FX3 sends an IN packet as the Status Stage.  The Control WRITE transfer completed.

                              (6) FX3 calls the CyU3PUsbSendEP0Data() function to send a packet.  The data is stored in the EP0 buffer and FX3 exit from the SetupCB() function.

                              (7) PC calls the Read() method to initiate a Control READ Transfer.  PC sends a SETUP packet as the Setup Stage.

                              (8) FX3 receives the SETUP packet and call the SetupCB() function again.

                              (9) PC waits for an IN packet as the Data Stage.  PC may receive a DATA packet set at the step (6)

                              (10) PC returns an OUT packet (with NO DATA) as the Status Stage.

                              (11) In the callback function FX3 receives an OUT packet (with NO DATA) sent at step (10) by calling the CyU3PUsbGetEP0Data() function.

                              (12) After the OUT packet received, FX3 sends an IN packet as the Status Stage.  But PC does not receive the packet because PC does not initiate any packet.

                              (13) After timeout time flies, the connection will be reset.

                              (14) FX3 calls the CyU3PUsbSendEP0Data() function to send a packet but PC does not receive the packet.

                               

                              This issue is caused by the insufficient procedure in the SetupCB() function.

                              As I said in a reply "I recommend to define Control WRITE and READ transfer sequence separately to follow the USB specification."

                               

                              Regards,

                              Noriaki

                              • 12. Re: EP0 Read() takes 5 seconds to complete.
                                milkfish1227_2635671

                                All right. You think the issue is in firmware SetupCB() function.

                                 

                                Here is from Cypress UsbSpiRegMode sample code CyFxUSBSetupCB() function. Do you think Cypress is not doing their sample code correctly?

                                 

                                CyBool_t

                                CyFxUSBSetupCB (

                                        uint32_t setupdat0,

                                        uint32_t setupdat1)

                                {

                                 

                                    /* Handle supported vendor requests. */

                                    if (bType == CY_U3P_USB_VENDOR_RQT)

                                    {

                                 

                                        switch (bRequest)

                                        {

                                 

                                            case CY_FX_RQT_SPI_FLASH_WRITE:

                                                status = CyU3PUsbGetEP0Data (wLength, glEp0Buffer, NULL);

                                                if (status == CY_U3P_SUCCESS)

                                                {

                                                    status = CyFxSpiTransfer (wIndex, wLength,

                                                            glEp0Buffer, CyFalse);

                                                }

                                                break;