1 Reply Latest reply on Nov 28, 2014 7:27 AM by shashank.rebbapragada

    Periodic data transfer delay during Isochrnonous transfer using Auto mode DMA

    manuj.sharma

       I am transferring data from a WIndows 8 PC to a PSoC 5LP board connected to PC thrugh USB 2.0.

         

      The host application, written in VC++, sends data in a loop to PSoC over an Isochronous OUT EP (EP6) using XferData() API call.

         

      ISOC OUT EP (EP6) is configured with maximum packet size of 1023 bytes. The firmware uses Auto Mode DMA to transfer data from OUT EP SRAM to local buffer (array).

         

      The main loop in host application is:

         

      bufSizeMultiplier = 8;

         

      maxPktSize = IsocOutEpt->MaxPktSize; // Max packet size of the ISOC OUT EP (configured to be 1023 bytes)

         

      bufSize = maxPktSize * bufSizeMultiplier;  // Buffer size (bufSize) is 8 times the Max packet size of the ISOC OUT EP

         

      IsocOutEpt->SetXferSize(bufSize);

         

               XferDataBuffer = new UCHAR[bufSize]; // Allocate the buffer (array) of size bufSize

         

      // Initialize the buffer with some dummy data

         

      for (i = 0; i < bufSize; i++) {

         

      xferDataBuffer[i] = i;

         

              }

         

      while(1){

         

      if ((IsocOutEpt->XferData(xferDataBuffer, bufSize))) // Transfer the buffer data to PSoC

         

      {  

         

      //   printf("Sender: XferData succeeded\n");

         

      }

         

      else

         

      printf("Sender: XferData failed\n");

         

         

       

         

      The firmware code uses USBFS_1_ReadOutEP() call to initialize and configure the DMA whenever  the device configuration changes (in our case, it just changes once in the begining, so this call is executed only once in the begining). In subsequent loops, firmware waits until the OUT buffer is full, and then re-arms the EP6 OUT end point using USBFS_1_EnableOutEP() call.

         

       

         

      In order to see the time taken by the DMA operations, we use two GPIO pins of PSoC. Pin 1 is toggled (between high(1) and low(0)) only when the configuration changes and pin 2 is toggled every time before checking the EP buffer to be full and re-arming the EP6 OUT end point. The value (signals) on these pins are monitored using Oscilloscope. Since in our program runs, the configuration just changed only once in the begining, Pin1 becomes high and stays high forever (see the yellow signal in enclosed images).

         

       

         

      However, we noticed following behavior for Pin 2: Signal on Pin2 toggles bewteen High and Low 4 times (with duration of nearly 1 millisec), and then stays low for nearly 5 to 6 millisec. The signal then again becomes high and toggles between high and low values 4 times, and then remain low for nearly 5-6 millisec. This pattern repeats indefinitely: After every block of 4 transitions (between high and low), the signal remains low for 5-6 millisec. To me, this suggests that the DMA transfer operation is periodically interrupted for 5-6 millisec, which leads to a periodic delay in data transfer. Enclosed image 1 shows the signal pattern when the program starts; image 2 shows it at a later duration.

         

       

         

      Can somebody suggest what could be the problem? Is any spurious interrupt is periodically occuring which is disrupting DMA transfer? If yes then how to check/handle/disable such interrupt? Or, am I doing something wrong in my application and/or firmware code?

         

      The main loop of the firmware is as follows:

         

       

         

              counter = 0;

         

      for (;;) {

         

                  if (USBFS_1_IsConfigurationChanged() != 0)   // Executes only once in the begining in our case

         

                 {

         

                       AltSettingNumber = USBFS_1_GetInterfaceSetting(0);

         

                       if (AltSettingNumber == 1) // Our confguration uses Alternate Interace 1 for OUT EP6

         

                       {

         

                               if (configChangedCounter % 2 == 0)

         

                                      Pin1_DR |= Pin1_MASK;  // Make Pin 1 high   (Shown in yellow color in enclosed images)

         

                               else

         

                                      Pin1_DR &= ~Pin1_MASK; // Make Pin 1 low

         

                   

         

                               configChangedCounter++;

         

         

         

                              Pin2_DR |= Pin2_MASK; // Make Pin 2 high

         

                      

         

                              USBFS_1_ReadOutEP(EP6, &Isochronous_OUT_Buffer1[0], BUFSIZE);      // Configure DMA

         

                              USBFS_1_EnableOutEP(EP6);

         

                      } 

         

              }

         

              

         

               if (AltSettingNumber == 1)

         

               {

         

                  // Alternately make Pin-2  high(1) or low (0) based on even or odd counter value

         

                  if (counter % 2 == 0)

         

                      Pin2_DR &= ~Pin2_MASK; 

         

                  else

         

                      Pin2_DR |= Pin2_MASK;

         

                  

         

                  counter++;

         

                  

         

                  // Wait to OUT buffer to become full

         

                  while (USBFS_1_bGetEPState(EP6) != USBFS_1_OUT_BUFFER_FULL){}

         

                  USBFS_1_EnableOutEP(EP6);   // Rearm EP6 OUT EP

         

               } 

         

          }

         

       

         

      Thanks,

         

       

         

      Manuj Sharma