2018-12-06 03:05 AM
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
2019-02-17 11:06 PM
no answer? no one have an idea?
At the moment im solving this problem with an other MCU ( RT10xx )