cancel
Showing results for 
Search instead for 
Did you mean: 

How to reduce overhead/messages to RTOS with USB iso IN

dirk.frerichs
Associate II

Hi

I implemented a UVC Class with isocronous transfer.

I'm using a STM32F745 mcu with RTOS ( 1000Hz Tickrate )

The USB Host lib is slightly modified to get correct URB messages after iso RX complete transfer.

I receive Images in VGA/QVGA resolution and creates a MJPEG Video Stream with lwIP.

This part works very well.

BUT:

The MCU is constantly used by USBH Task about 85%.

I think the reason is the usage of osMessagePut in the Backgroundfunction

"USBH_VIDEO_Process"

USBH_Process function :

 case HOST_CLASS:  

   /* process class state machine */

   if(phost->pActiveClass != NULL)

   {

           phost->pActiveClass->BgndProcess(phost);

     }

   break;      

my Class works only if i use the

"osMessagePut " in the backgroundprocess

static USBH_StatusTypeDef USBH_VIDEO_Process(USBH_HandleTypeDef *phost) {

   USBH_StatusTypeDef status = USBH_BUSY;

   VIDEO_HandleTypeDef *pVideo;

   pVideo = (VIDEO_HandleTypeDef *)phost->pActiveClass->pData;

   switch (pVideo->StreamState)

   {      

      case VIDEO_STREAM_START:

         USBH_IsocReceiveData( phost ,DMA_USBH_Buffer ,pVideo->EpVideoStream.wMaxPacketSize ,pVideo->EpVideoStream.bPipe );

         pVideo->StreamState      = VIDEO_STREAM_PLAY;

         break;

      case VIDEO_STREAM_PLAY:

         if((phost->Timer-pVideo->EpVideoStream.wTimer) >= pVideo->EpVideoStream.bInterval)

         {

            pVideo->EpVideoStream.wTimer = phost->Timer;

            if( USBH_LL_GetURBState(phost , pVideo->EpVideoStream.bPipe) == USBH_URB_DONE )

            {

               HandleReceivedFrame(   pVideo ,

                                 DMA_USBH_Buffer,

                                 USBH_LL_GetLastXferSize(phost, pVideo->EpVideoStream.bPipe ));

               USBH_IsocReceiveData( phost ,

                  DMA_USBH_Buffer,

                  pVideo->EpVideoStream.wMaxPacketSize,

                  pVideo->EpVideoStream.bPipe );

            }

         }

         osMessagePut ( phost->os_event, USBH_URB_EVENT, pVideo->EpVideoStream.bInterval);

         break;

   }

   return status;

}

if i remove the line:

osMessagePut ( phost->os_event, USBH_URB_EVENT, pVideo->EpVideoStream.bInterval);

then the receiving of frames is stopped after one or two frames.

normaly the USB Interrupt creates a iso IN URB_DONE message -> "ISO IN complete Interrupt"

 else if(hc->ep_type == EP_TYPE_ISOC)

   {

     hc->urb_state = URB_DONE;

     HAL_HCD_HC_NotifyURBChange_Callback(hhcd, chnum, URB_DONE );

   }

This message should wake up the USBH Task and get the Data from buffer and start receiving the next Frame.

The main disadvantage of using :

osMessagePut ( phost->os_event, USBH_URB_EVENT, pVideo->EpVideoStream.bInterval);

is that the interval is 1ms !

The backgroundprocess is woken up every 1ms.

This is like cyclic polling to catch the URB_DONE event.

How can i change this to an interrupt driven taskmanagement ?

1. Start new Transfer

2. ISR creates an RX complete interrupt

3. background process wakes up , get frame and start new transfer

If i try to do this way...

The isr catches at first an Channel Halt interrupt in HCD_HC_IN_IRQHandler

if (((usb->HCINT) & USB_OTG_HCINT_TXERR)==USB_OTG_HCINT_TXERR)

The next interrupt catches an

 if (((usb->HCINT) & USB_OTG_HCINT_CHH)==USB_OTG_HCINT_CHH)

someone an idea ?

best regards

1 REPLY 1
dirk.frerichs
Associate II

no answer? no one have an idea?

At the moment im solving this problem with an other MCU ( RT10xx )