9 Replies Latest reply on Sep 27, 2020 8:58 PM by RashiV_61

    DMA callback - CX3 - don't understand produce vs consume

    EtWh_2921621

      I have an image sensor chip sending me buffers. I'm using 4 mipi lanes, and the bandwidth is high. I'm using a multi-channel DMA configuration, per normal. I'm trying to figure out why, in my DMA callback, when I get a MultiChannelCommitBuffer failure of 0x47, my counter for "outstanding DMA buffers committed, but not consumed yet" is 8 or 9. From my limited understanding, the sensor chip is producing buffers, and the USB pipe is consuming buffers. How many buffers can be produced, but not consumed, without some kind of overflow? How many DMA buffers can the sensor produce, if I don't consume them via sending them to the DMA via CyU3PDmaMultiChannelCommitBuffer? Likewise, what's surprising is that when I get a failure 0x47, I start throwing out *everything* in the DMA callback until the DMA is reset on the main thread (in UvcAppStop). I'm shocked to see 8 callbacks for "consumer events". What is it being consumed BY? Is it being consumed by the USB send pipe, or some other consumption object? Because I'm pretty sure I only allocated 4 DMA buffers to be sent to the PC. How could there be 8 outstanding consumptions that come back in the callback as I am shutting the pipe down? That is 4 too many.

       

       

      DMA Reset Event due to DMA callback failure

      #### CyCx3UvcAppDmaCallback:CyU3PDmaMultiChannelCommitBuffer FAILURE 0x47 at frame 50098, outstanding = 8

      DmaCallback GOTDMAERROR, CB_CONS_EVENT

      DmaCallback GOTDMAERROR, CB_CONS_EVENT

      DmaCallback GOTDMAERROR, CB_CONS_EVENT

      DmaCallback GOTDMAERROR, CB_CONS_EVENT

      DmaCallback GOTDMAERROR, CB_PROD_EVENT

          Dma buffer = 400650ec, status = 8

      DmaCallback GOTDMAERROR, CB_PROD_EVENT

          Dma buffer = 4005f0cc, status = 8

      DmaCallback GOTDMAERROR, CB_CONS_EVENT

      DmaCallback GOTDMAERROR, CB_CONS_EVENT

      DmaCallback GOTDMAERROR, CB_CONS_EVENT

      DmaCallback GOTDMAERROR, CB_PROD_EVENT

          Dma buffer = 4004102c, status = 8

      DmaCallback GOTDMAERROR, CB_PROD_EVENT

          Dma buffer = 4006b10c, status = 8

      DmaCallback GOTDMAERROR, CB_CONS_EVENT

      DmaCallback GOTDMAERROR, CB_PROD_EVENT

          Dma buffer = 4004d06c, status = 8

      DmaCallback GOTDMAERROR, CB_PROD_EVENT

          Dma buffer = 4004704c, status = 8

      DmaCallback GOTDMAERROR, CB_PROD_EVENT

          Dma buffer = 4005308c, status = 8

      DmaCallback GOTDMAERROR, CB_PROD_EVENT

          Dma buffer = 400590ac, status = 8

      ****CyCx3UvcAppStop****

       

       

      it's lengthy, and messy, but here is the DMA callback code. I frankly don't know what I'm doing inside this code...

       

      void CyCx3UvcAppDmaCallback (

      CyU3PDmaMultiChannel   *chHandle,

      CyU3PDmaCbType_t  type,

      CyU3PDmaCBInput_t *input )

      {

          CyU3PDmaBuffer_t dmaBuffer;

          CyU3PReturnStatus_t status = CY_U3P_SUCCESS;

          CyU3PReturnStatus_t status2;

       

       

          if( bGotDmaError )

          {

              switch( type )

              {

              case CY_U3P_DMA_CB_XFER_CPLT:

              QueueDiagnosticsMessageP( 4, "DmaCallback GOTDMAERROR, DMA_CB_XFER_CPLT\r\n" );

              break;

              case CY_U3P_DMA_CB_SEND_CPLT:

              QueueDiagnosticsMessageP( 4, "DmaCallback GOTDMAERROR, CB_SEND_CPLT\r\n" );

              break;

              case CY_U3P_DMA_CB_RECV_CPLT:

              QueueDiagnosticsMessageP( 4, "DmaCallback GOTDMAERROR, CB_RECV_CPLT\r\n" );

              break;

              case CY_U3P_DMA_CB_PROD_EVENT:

              QueueDiagnosticsMessageP( 4, "DmaCallback GOTDMAERROR, CB_PROD_EVENT\r\n" );

              break;

              case CY_U3P_DMA_CB_CONS_EVENT:

              QueueDiagnosticsMessageP( 4, "DmaCallback GOTDMAERROR, CB_CONS_EVENT\r\n" );

              break;

              case CY_U3P_DMA_CB_ABORTED:

              QueueDiagnosticsMessageP( 4, "DmaCallback GOTDMAERROR, CB_ABORTED\r\n" );

              break;

              case CY_U3P_DMA_CB_ERROR:

              QueueDiagnosticsMessageP( 4, "DmaCallback GOTDMAERROR, CB_ERROR\r\n" );

              break;

              case CY_U3P_DMA_CB_PROD_SUSP:

              QueueDiagnosticsMessageP( 4, "DmaCallback GOTDMAERROR, PROD_SUSP\r\n" );

          CyU3PDmaMultiChannelResume( chHandle, CyFalse, CyTrue );

              break;

              case CY_U3P_DMA_CB_CONS_SUSP:

              QueueDiagnosticsMessageP( 4, "DmaCallback GOTDMAERROR, CONS_SUSP\r\n" );

              break;

              }

       

       

              if( input != NULL )

              {

              QueueDiagnosticsMessageP( 4, "    Dma buffer = %x, status = %x\r\n", input->buffer_p.buffer, input->buffer_p.status );

              }

              return;

          }

       

       

          if( !glIsApplnActive )

          {

              switch( type )

              {

              case CY_U3P_DMA_CB_XFER_CPLT:

              QueueDiagnosticsMessageP( 4, "DmaCallback STOPPING, DMA_CB_XFER_CPLT\r\n" );

              break;

              case CY_U3P_DMA_CB_SEND_CPLT:

              QueueDiagnosticsMessageP( 4, "DmaCallback STOPPING, CB_SEND_CPLT\r\n" );

              break;

              case CY_U3P_DMA_CB_RECV_CPLT:

              QueueDiagnosticsMessageP( 4, "DmaCallback STOPPING, CB_RECV_CPLT\r\n" );

              break;

              case CY_U3P_DMA_CB_PROD_EVENT:

              QueueDiagnosticsMessageP( 4, "DmaCallback STOPPING, CB_PROD_EVENT\r\n" );

              break;

              case CY_U3P_DMA_CB_CONS_EVENT:

              QueueDiagnosticsMessageP( 4, "DmaCallback STOPPING, CB_CONS_EVENT\r\n" );

              break;

              case CY_U3P_DMA_CB_ABORTED:

              QueueDiagnosticsMessageP( 4, "DmaCallback STOPPING, CB_ABORTED\r\n" );

              break;

              case CY_U3P_DMA_CB_ERROR:

              QueueDiagnosticsMessageP( 4, "DmaCallback STOPPING, CB_ERROR\r\n" );

              break;

              case CY_U3P_DMA_CB_PROD_SUSP:

              QueueDiagnosticsMessageP( 4, "DmaCallback STOPPING, PROD_SUSP\r\n" );

          CyU3PDmaMultiChannelResume( chHandle, CyFalse, CyTrue );

              break;

              case CY_U3P_DMA_CB_CONS_SUSP:

              QueueDiagnosticsMessageP( 4, "DmaCallback STOPPING, CONS_SUSP\r\n" );

              break;

              }

       

              return;

          }

       

       

          if (type == CY_U3P_DMA_CB_PROD_EVENT)

          {

              /* This is a produce event notification to the CPU. This notification is

               * received upon reception of every VIDEO buffer produced by the OV chip. The buffer will not be sent

               * out unless it is explicitly committed. The call shall fail if there

               * is a bus reset / usb disconnect or if there is any application error. */

       

              int WhileLoopIndex = 0;

       

              // loop until we can't get any more dma buffers

              //

              while( 1 )

              {

                  WhileLoopIndex++;

                  if( WhileLoopIndex > 10 )

                  {

      // this happens. frequently. WHY?

                  QueueDiagnosticsMessageP( 4, "    CyCx3UvcAppDmaCallback: InWhileLoop too long\r\n" );

       

                      if( !bGotDmaError )

                      {

                           // start killing the dma...

                           bGotDmaError = CyTrue;

                          CyU3PEventSet(&glCx3Event, CX3_DMA_RESET_EVENT_CB,CYU3P_EVENT_OR);

                      }

       

                      return;

                  }

       

                  status = CyU3PDmaMultiChannelGetBuffer(chHandle, &dmaBuffer, CYU3P_NO_WAIT);

                  if( status != CY_U3P_SUCCESS )

                  {

                       // couldn't get a ready buffer, this is normal

                      break;

                  }

       

                  if(dmaBuffer.count < MSRVIDEOAR_UVC_DATA_BUFFER_SIZE)

                  {

                      //QueueDiagnosticsMessage("DMA EOF Buffer %d\r\n", dmaBuffer.count);

                      CyCx3UvcAppAddHeader ((dmaBuffer.buffer - MSRVIDEOAR_UVC_DATA_BUFFER_HEADER_SIZE), CX3_UVC_HEADER_EOF);

                      glHitFV = CyTrue;     

       

                      gFpsFrameCounter++;

                      gSequentialVideoFrameID++;

                      glVideoFramesCaptured++;

       

      #ifdef RESET_TIMER_ENABLE

              CyU3PTimerStart( &UvcTimer );

      #endif

       

                      // Reset for the next first buffer of the next frame

                      gFirstDmaBufferOfVideofFrame = CyTrue; // start of the video frame, not the very first frame we deliver

                  }

                  else

                  {

                      CyCx3UvcAppAddHeader ((dmaBuffer.buffer - MSRVIDEOAR_UVC_DATA_BUFFER_HEADER_SIZE), CX3_UVC_HEADER_FRAME);

       

                      if (gFirstDmaBufferOfVideofFrame)

                      {

                          MSRVIDEOAR_EMBEDDED_FRAME_METADATA * pMetaData = (MSRVIDEOAR_EMBEDDED_FRAME_METADATA *) dmaBuffer.buffer;

                         

                          gFirstDmaBufferOfVideofFrame = CyFalse;

                          pMetaData->stateFlags = 0;

                          if (gThroughputErrors > 0)

                          {

                              pMetaData->stateFlags |= METASTATEFLAG_THROUGHPUTERROR;

                              gThroughputErrors = 0;

                          }

       

                          uint64_t llSystemTime = VideoARTicksToHundredNanosecs( s_sofSystemTicks );

       

                          // keep track of how many frames per second we produce

                          //

                          uint64_t llDelta = llSystemTime - s_llLastSystemTimeFpsCalculatedAt;

                          if( s_llLastSystemTimeFpsCalculatedAt == 0 || ( llDelta > 10000000 ) )

                          {

                              s_llLastSystemTimeFpsCalculatedAt = llSystemTime;

                              gMeasuredFPS = gFpsFrameCounter;

                              gFpsFrameCounter = 0;

                          }

       

                          pMetaData->ullTickCount = s_sofSystemTicks;

                          pMetaData->TickFreq = gsysClockFreq;

                          pMetaData->sequentialFrameID = gSequentialVideoFrameID;

                          pMetaData->nMeasuredCaptureFPS = gMeasuredFPS;

                          pMetaData->nHowManyTimesCaptureStarted = gTimesCaptureStarted;

                      }

                  }

                 

                  /* Commit Buffer to USB*/

                  // this queues it to be sent over USB.

                  status = CyU3PDmaMultiChannelCommitBuffer (chHandle, (dmaBuffer.count + MSRVIDEOAR_UVC_DATA_BUFFER_HEADER_SIZE), 0);

                  if (status != CY_U3P_SUCCESS)

                  {                   

                      gThroughputErrors++;

                      QueueDiagnosticsMessageP(4,"#### CyCx3UvcAppDmaCallback:CyU3PDmaMultiChannelCommitBuffer FAILURE 0x%x at frame %d, outstanding = %d\r\n", status, gSequentialVideoFrameID, glVideoDmaBuffersCommittedAndNeedingToBeConsumed );

       

                      if( !bGotDmaError )

                      {

                           // start killing the dma...

                           bGotDmaError = CyTrue;

                          CyU3PEventSet(&glCx3Event, CX3_DMA_RESET_EVENT_CB,CYU3P_EVENT_OR);

                      }

       

                      // no matter what, if we got an error, exit. don't flip sockets.

                      return;

                  }

                  else

                  {

                      glVideoDmaBuffersCommittedAndNeedingToBeConsumed++;

                  }

       

                  glActiveSocket ^= 1; /* Toggle the Active Socket */

       

              } // loop until we can't get any more DMA buffers

          }

          else if(type == CY_U3P_DMA_CB_CONS_EVENT)

          {

               glVideoDmaBuffersCommittedAndNeedingToBeConsumed--;

       

              if( glHitFV == CyTrue )

              {

                   if(glVideoDmaBuffersCommittedAndNeedingToBeConsumed == 0)

                   {

                      glHitFV = CyFalse;

                      gConsumedFrames++;

       

                      CyU3PGpioSetValue(VIDEOAR_GPIO_FV, CyFalse);

       

          #ifdef RESET_TIMER_ENABLE

                      CyU3PTimerStop (&UvcTimer);

          #endif

       

                      // immediately switch state to SCK0 or SCK1

                      //

                      if (glActiveSocket)

                          CyU3PGpifSMSwitch(

                              CX3_INVALID_GPIF_STATE,     // from

                              CX3_START_SCK1,             // to

                              CX3_INVALID_GPIF_STATE,     // end state

                              ALPHA_CX3_START_SCK1,       // initial alpha

                              CX3_GPIF_SWITCH_TIMEOUT);   // switch timeout

                      else

                          CyU3PGpifSMSwitch(

                              CX3_INVALID_GPIF_STATE,

                              CX3_START_SCK0,

                              CX3_INVALID_GPIF_STATE,

                              ALPHA_CX3_START_SCK0,

                              CX3_GPIF_SWITCH_TIMEOUT);

       

       

          #ifdef RESET_TIMER_ENABLE

                      CyU3PTimerModify (&UvcTimer, TIMER_PERIOD, 0);

          #endif

                  }

              else

              {

                      // QueueDiagnosticsMessage("#### CyCx3UvcAppDmaCallback CONSUMED, but glVideoDmaBuffersCommittedAndNeedingToBeConsumed = %d\r\n", glVideoDmaBuffersCommittedAndNeedingToBeConsumed );

              }

              }

          }

          else

          {

          if( type == CY_U3P_DMA_CB_ERROR )

          {

              QueueDiagnosticsMessageP( 4, "DmaCallback, detected ERROR\r\n" );

          }

          else if( type == CY_U3P_DMA_CB_ABORTED )

          {

              QueueDiagnosticsMessageP( 4, "DmaCallback, ABORTED\r\n" );

          }

          else if( type == CY_U3P_DMA_CB_PROD_SUSP )

          {

              QueueDiagnosticsMessageP( 4, "DmaCallback, consumer suspend, resumed\r\n" );

          CyU3PDmaMultiChannelResume( chHandle, CyFalse, CyTrue );

          }

          else

          {

      #if false

              CY_U3P_DMA_CB_PROD_SUSP  = (1 << 7), /**< This event is generated when the producer socket is suspended. */

              CY_U3P_DMA_CB_CONS_SUSP  = (1 << 8)  /**< This event is generated when the consumer socket is suspended. */

      #endif

              QueueDiagnosticsMessageP( 4, "DmaCallback, type = %d\r\n", type );

          }

          }

      }

        • 1. Re: DMA callback - CX3 - don't understand produce vs consume
          RashiV_61

          Hello,

           

          From my limited understanding, the sensor chip is producing buffers, and the USB pipe is consuming buffers.

          >> Yes, your understanding is correct. The multi-channel commit buffer failures (0x47) generally happen when the host is slow (consuming data)  as compared to the sensor (producing data)

           

          How many buffers can be produced, but not consumed, without some kind of overflow?

          >> This will depend on the DMA buffers that are allotted to the DMA channel. In the DMA channel configuration, if the DMA buffer count is 4 and the DMA channel is Many to One type 4 buffers will associated with each of the two producer socket (PIB socket in your case). So if 8 of the buffers are filled and not consumed by USB socket, the producer socket will again try to fill the first buffer and that won't be free at that point the commit buffer failure will be seen.

           

          I start throwing out *everything* in the DMA callback until the DMA is reset on the main thread (in UvcAppStop). I'm shocked to see 8 callbacks for "consumer events"

          >> I think this is because the newly produced data is being discarded but the 8 buffers which are already filled are not dumped. So later when USB requests are sent by the host the data in the DMA buffers are consumed by the USB socket. The DMA buffers can be dumped by resetting the DMA channel.

           

           

          To reduce the commit buffer failures please let me know the DMA buffer size that is being used in your application. Please try increasing the DMA buffer size to 32 KB and DMA buffer count to 3. As the DMA buffer size is increased the producer will take some time to fill up the DMA buffer which will reduce the difference in speed of sensor producing data and USB socket consuming data.

           

          Also, we recommend not to use too many Debug Prints in the DMA callbacks. You can use the global variables in the DMA callback to track the DMA events and later get it printed in the for{}. Please refer to the SDK example firmware OV5640 which doesn't print the events in the DMA callback and uses variables to track the DMA events.

           

          Please let me know if any queries on this

           

          Regards,

          Rashi

          • 2. Re: DMA callback - CX3 - don't understand produce vs consume
            EtWh_2921621

            I would say the 0x47 error happens about every minute, once. Sometimes it really blows up, sometimes it's just a little blip. When it really blows up, and the CX3 takes "too long" to recover, the PC gives up the transfer and silently quits the streaming. it's a frustrating bug.

             

            When I get a 0x47 error in the DMA callback, I set an event which signals the main thread to start resetting the DMA (as you say), and the actual way the dma channel is or should be reset, is somewhat of a mystery. I don't know about all the sleep calls in the stop code, or if they should be there, and I don't know about the sleep calls in the start. As I said before, too much sleeping, and the PC gives up. Maybe it's a bug in the PC's USB kernel, I dunno and I can't find out. But I am pretty sure taking too long on the CX3 during a DMA reset causes the PC to quit streaming.

             

            So, I set an event in the DMA, but it's still getting flooded with produced buffers. Look above, and you can see my code that attempts to deal with this. Until the flag is reset by the ApplnStop( ) code, all the successive incoming samples, produced or consumed, are ignored. Eventually (and hopefully soon), the DMA channel will get reset. is my approach correct?

             

            The DMA buffer size is 0x6000 - 24,576 bytes. Large enough, I suppose, for most purposes. the DMA buffer count is 4. (is that ok?)

            I just tried changing the buffer size to 32K, with 4 buffers, and that didn't work, so I set the buffer count to 3, and now it's streaming... but I'm getting frmErrors from the mipi get errors routine, and I didn't get those before. Guess 32K isn't appreciated much. Plus, I'm still getting the 0x47 error, so that wasn't cleared up either with 32K buffers.

             

            I WISH I knew why the PC is occasionally clogging up and causing the 0x47 error. The format is 1704 x 1440 @ 90HZ, with RAW8 being transmitted. That's really not THAT fast...

             

            any ideas? Ever try a project where video of this high bandwidth is being transmitted to the PC?

            • 3. Re: DMA callback - CX3 - don't understand produce vs consume
              RashiV_61

              Hello,

               

              Please share the MIPI structure (CyU3PMipicsiCfg_t) that is generated by the tool this is to check if the pixels are padded with nonimage data (i.e. zeros) or packed

              As mentioned in your previous thread (response 3) CX3 vs Image Sensor PLL's - what's up? is the GPIF bus width (output video format ) 24 bits.

              If MIPI settings are such that the pixels are padded (zeros will be padded) 16 bits will be padded to the image data which in turn will increase the frame size.

              Please share the MIPI receiver configuration settings snippets

               

              The frmError is incremented when an unexpected Frame start (FS) or Frame end (FE) short packet is received. This can be due to some interfacing problem between the CX3's MIPI receiver and the sensor.

               

              "Also, we recommend not to use too many Debug Prints in the DMA callbacks. You can use the global variables in the DMA callback to track the DMA events and later get it printed in the for{}. Please refer to the SDK example firmware OV5640 which doesn't print the events in the DMA callback and uses variables to track the DMA events".

              >> Please let me know if the firmware is modified based on the above suggestion. Please share the complete debug prints (.txt) just after programming the CX3 with the firmware and opening the host application to stream.

               

              - Please confirm if the build variable in the project settings in 1_3_4 (as shown in attachment)

               

              Ever try a project where a video of this high bandwidth is being transmitted to the PC?

              >> Yes we have seen customer streaming at high bandwidth. The maximum bandwidth that the GPIF interface supports when GPIF bus width is 24 bits and PCLK is 100MHz is 2.4Gbps. So we need to confirm if the pixels are packed or padded. If the pixels are padded then the frame size * frame rate will exceed the maximum supported data throughput.

               

              I set an event in the DMA, but it's still getting flooded with produced buffers. Look above, and you can see my code that attempts to deal with this. Until the flag is reset by the ApplnStop( ) code, all the successive incoming samples, produced or consumed, are ignored. Eventually (and hopefully soon), the DMA channel will get reset. is my approach correct?

              >> Please do not modify the recovery on getting the 0x47 error. Please keep it the same as in the default firmware. We can first debug the actual problem and can then later modify it if needed.

               

               

              Regards,

              Rashi

                       

              .

              • 4. Re: DMA callback - CX3 - don't understand produce vs consume
                EtWh_2921621

                CyU3PMipicsiCfg_t OV4688_1704x1400x8bitx90FPSxRAW8_Resolution =

                {

                CY_U3P_CSI_DF_RGB888,  /* CyU3PMipicsiDataFormat_t dataFormat */

                4,                          /* uint8_t numDataLanes */

                2, /* uint8_t pllPrd */

                115, /* uint16_t pllFbd 0x65 -> 0x77*/

                CY_U3P_CSI_PLL_FRS_250_500M, /* CyU3PMipicsiPllClkFrs_t pllFrs CY_U3P_CSI_PLL_FRS_250_500M*/

                CY_U3P_CSI_PLL_CLK_DIV_4, /* CyU3PMipicsiPllClkDiv_t csiRxClkDiv */

                CY_U3P_CSI_PLL_CLK_DIV_4, /* CyU3PMipicsiPllClkDiv_t parClkDiv */

                0,                 /* uint16_t mClkCtl */

                CY_U3P_CSI_PLL_CLK_DIV_2, /* CyU3PMipicsiPllClkDiv_t mClkRefDiv */

                1704,         /* uint16_t hResolution */

                50                         /* uint16_t fifoDelay */

                };

                 

                I assume the pixels aren't padded, just packed. The GPIF bus is set to 24 bit width.

                 

                I got rid of all the debug print messages (I wasn't calling CyU3PDebugPrint, I was calling QueueDiagnosticsMessage, which puts it in a queue to be printed on the application thread). But anyhow, I got rid of them. Now, it still gets the 0x47 error (frequently), but so far it hangs less.

                 

                Yikes. I was not building with 1_3_4. I never thought about that, or knew it was a thing. I inherited this project from somebody else. I switched it to 1_3_4, and now the firmware builds, but it locks up when I run it. Whoops.

                • 5. Re: DMA callback - CX3 - don't understand produce vs consume
                  EtWh_2921621

                  I can't get it to work now. The DMA channel we set up to accept commands from the PC, it won't receive any DMA callbacks when I build with 1.3.4. Is there some kind of "moving from 1.3.3 to 1.3.4 doc with common "gotchas" (problems)?

                  • 6. Re: DMA callback - CX3 - don't understand produce vs consume
                    EtWh_2921621

                    that's odd. I got it to work by switching to debug build instead of release.

                    still seeing error 0x47. I'm going to let it run for a while and see if it hangs.

                    suggestions for why it doesn't work in release but it does in debug?

                    what is the actual difference between debug and release builds when it's firmware instead of PC code?

                    • 7. Re: DMA callback - CX3 - don't understand produce vs consume
                      EtWh_2921621

                      that's odd - i worked on some issues while in debug mode, nothing important. After a while, went back and did a release-mode build, and tried it. this time it worked. Don't know what's going on here. It has been running for half the day and hasn't hung yet. Guess the hang was inside the 1.3.3 firmware. sheesh.

                      • 8. Re: DMA callback - CX3 - don't understand produce vs consume
                        EtWh_2921621

                        well, it's not done yet. Rashi, I'm hoping you can help me on this one.... this broke when I moved from 1_3_3 to 1_3_4.

                        We set up a 2nd set of endpoints... I'm not a CX3 programmer, I inherited this stuff, so I'm not sure how to phrase this... We have a 2nd pipeline that can accept special commands to the firmware. It's not IAMCameraControl compliant or anything, it's just a pipe. Now, when the PC sends it a command, the firmware doesn't get a callback. i'm trying to figure out why. I don't know if something is wrong in the descriptors, or in the setup of the dma channel in the firmware. I'm going to post the firmware code, see if you can see something wrong?

                         

                        void WinUSBDMAInitialize()

                        {

                        CyU3PReturnStatus_t status = CY_U3P_SUCCESS;

                        CyU3PEpConfig_t endpointConfig;

                        CyU3PDmaChannelConfig_t dmaChannelConfig;

                         

                         

                        //

                        // WinUSB socket config.

                        //

                        CyU3PMemSet((uint8_t*)&endpointConfig, 0, sizeof(endpointConfig));

                        endpointConfig.enable = CyTrue;

                        endpointConfig.epType = CY_U3P_USB_EP_BULK;

                        endpointConfig.burstLen = 1; // temporary, see below

                        endpointConfig.streams = 0;

                        endpointConfig.isoPkts = 1;

                         

                         

                        /* Based on the Bus Speed configure the endpoint packet size */

                        switch (CyU3PUsbGetSpeed())

                        {

                        case  CY_U3P_SUPER_SPEED:

                        endpointConfig.pcktSize = 1024;

                        endpointConfig.burstLen = CX3_EP_BULK_SUPER_SPEED_BURST_LEN;

                        break;

                         

                         

                        default:

                        QueueDiagnosticsMessageP(4, "Error! Invalid USB speed.\r\n");

                        break;

                        }

                         

                         

                        status = CyU3PSetEpConfig(VIDEOAR_EP_CAMERACONTROL_OUT, &endpointConfig);

                        if (status != CY_U3P_SUCCESS)

                        {

                        QueueDiagnosticsMessageP(4, "WinUSBDMAInitialize::CyU3PSetEpConfig failed, Err = %d\r\n", status);

                        }

                        status = CyU3PSetEpConfig(VIDEOAR_EP_CAMERACONTROL_IN, &endpointConfig);

                        if (status != CY_U3P_SUCCESS)

                        {

                        QueueDiagnosticsMessageP(4, "WinUSBDMAInitialize::CyU3PSetEpConfig failed, Err = %d\r\n", status);

                        }

                         

                         

                        /* Flush the endpoint memory */

                        CyU3PUsbFlushEp(VIDEOAR_EP_CAMERACONTROL_OUT);

                        CyU3PUsbFlushEp(VIDEOAR_EP_CAMERACONTROL_IN);

                         

                        // Everything below here is setting up the sideband DMA channel

                         

                         

                        // create a manual_in channel so the PC can send us sideband (command) data

                        //

                        CyU3PMemSet((uint8_t*)&dmaChannelConfig, 0, sizeof(dmaChannelConfig));

                        dmaChannelConfig.size = WINUSB_ENDPOINT_CHANNEL_SIZE; // make sure multiple of 16. burst size * max packet size

                        dmaChannelConfig.count = VIDEOAR_WINUSB_BUF_COUNT; // How many can be outstanding at one time...? (efrazer)

                        dmaChannelConfig.prodSckId = CY_U3P_UIB_SOCKET_PROD_6;

                        dmaChannelConfig.consSckId = CY_U3P_CPU_SOCKET_CONS;

                        dmaChannelConfig.dmaMode = CY_U3P_DMA_MODE_BYTE;

                        dmaChannelConfig.notification = CY_U3P_DMA_CB_PROD_EVENT;

                        dmaChannelConfig.cb = OnWinUSBDMACompletionCallback_Recv; // command-receiving routine

                        dmaChannelConfig.prodHeader = 0;

                        dmaChannelConfig.prodFooter = 0;

                        dmaChannelConfig.consHeader = 0;

                        dmaChannelConfig.prodAvailCount = 0;

                         

                         

                        status = CyU3PDmaChannelCreate(

                                &glChHandleWinUSBRecvStream,

                                CY_U3P_DMA_TYPE_MANUAL_IN,

                                &dmaChannelConfig);

                        if (status != CY_U3P_SUCCESS)

                        {

                        QueueDiagnosticsMessageP(4, "WinUSBDMAInitialize::CyU3PDmaChannelCreate failed, Err = %d\r\n", status);

                        }

                         

                         

                            /* Set DMA Channel transfer size */

                            status = CyU3PDmaChannelSetXfer(&glChHandleWinUSBRecvStream, VIDEOAR_DMA_TX_SIZE);

                            if (status != CY_U3P_SUCCESS)

                            {

                                QueueDiagnosticsMessageP(4, "WinUSBDMAInitialize::CyU3PDmaChannelSetXfer failed, Err = %d\r\n", status);

                            }

                         

                         

                           

                           

                            /* Create a DMA MANUAL_OUT channel for the consumer socket. */

                            // we use this to send stuff to the PC

                            dmaChannelConfig.cb = OnWinUSBDMACompletionCallback_Send; // command reply stream

                        dmaChannelConfig.notification = CY_U3P_DMA_CB_XFER_CPLT;

                        dmaChannelConfig.prodSckId = CY_U3P_CPU_SOCKET_PROD;    // CPU = FX3 CPU. IE, we are producing the data

                        dmaChannelConfig.consSckId = CY_U3P_UIB_SOCKET_CONS_6; // this is the socket we send it to

                         

                         

                        status = CyU3PDmaChannelCreate(

                                &glChHandleWinUSBSendStream,

                                CY_U3P_DMA_TYPE_MANUAL_OUT,

                                &dmaChannelConfig);

                        if (status != CY_U3P_SUCCESS)

                        {

                        QueueDiagnosticsMessageP(4, "CyU3PDmaChannelCreate failed, Err = %d\r\n", status);

                        }

                         

                         

                        status = CyU3PDmaChannelSetXfer((CyU3PDmaChannel*) &glChHandleWinUSBSendStream, VIDEOAR_DMA_TX_SIZE);

                        if (status != CY_U3P_SUCCESS)

                        {

                        QueueDiagnosticsMessageP(4, "CyU3PDmaChannelSetXfer failed, Err = %d\r\n", status);

                        }

                         

                         

                        QueueDiagnosticsMessageP(4, "**** WinUSBDMAInitialize EXIT ****\r\n");

                        }

                         

                        keep in mind: this worked in 1_3_3. Broken in 1_3_4... :-(

                        • 9. Re: DMA callback - CX3 - don't understand produce vs consume
                          RashiV_61

                          Hello,

                           

                          The difference between debug build and release build is mentioned in section 5.2 of Getting Started with FX3 SDK

                          The debug (fx3_debug) build of the OS library provides OS services with additional error checks built-in. These checks result in greater memory footprint and slower execution and are disabled in the release ( fx3_release) build

                          In the release build, the firmware will be optimized the most. On changing the optimization level, there is a possibility that the functionality of the firmware changes.

                           

                          Regards,

                          Rashi