cancel
Showing results for 
Search instead for 
Did you mean: 

Known bugs in the OTG / USB library v2.1.0

ivous2
Associate
Posted on January 21, 2014 at 14:04

Here is the list of known bugs in the USB / OTG library v2.1.0:

files - usbd_cdc_core.c / usbd_conf.h

ep descriptors should not use 

#ifdef USE_USB_OTG_HS

but use instead

#ifndef USE_EMBEDDED_PHY 

file - usb_bsp.c

function USB_OTG_BSP_Init 

For OTH-HS using Internal Phy

RCC_AHB1PeriphClockLPModeCmd( RCC_AHB1Periph_OTG_HS_ULPI, DISABLE);  

This problem was discovered some time ago, when OTG-HS is in use and device is put in sleep mode, the ULPI clocks must be switched off, otherwise the OTG functionality is broken.

Whenever GPIO_InitStructure is used, it must be properly initialized first (otherwise it is causing strange side effects):

GPIO_StructInit(&GPIO_InitStructure);

file - usb_dcd_int.c

Search for ''emptyintr'' occurence, where the source code is trying to clear this flag. There are two occurrences:

CLEAR_IN_EP_INTR(1, emptyintr);

CLEAR_IN_EP_INTR( epnum , emptyintr);

It is read only flag, which cannot be cleared, so this interrupt must be masked instead:

fifoemptymsk = 0x1 << epnum;

USB_OTG_MODIFY_REG32(&pdev->regs.DREGS->DIEPEMPMSK, fifoemptymsk, 0)

This problem is causing high CPU load, but the USB is working.

file - usbd_core.c

USBD_Init function

correct order:  

/* Force Device Mode*/

USB_OTG_SetCurrentMode(pdev, DEVICE_MODE);

/* Enable Interrupts */

USB_OTG_BSP_EnableInterrupt(pdev);

On some hosts this is blocking proper enumeration of our device.

file usbh_core.c

missing proper error handling 

USBH_HandleControl function

case CTRL_STATUS_IN_WAIT:

   

    URB_Status = HCD_GetURB_State(pdev , phost->Control.hc_num_in);

    

    if  ( URB_Status == URB_DONE)

    { /* Control transfers completed, Exit the State Machine */

      phost->gState =   phost->gStateBkp;

      phost->Control.state = CTRL_COMPLETE;

    }

   

    else if (URB_Status == URB_ERROR)

    {

      phost->Control.state = CTRL_ERROR; 

    }

    

    else if((HCD_GetCurrentFrame(pdev)\

      - phost->Control.timer) > timeout)

    {

      phost->Control.state = CTRL_ERROR;

    }

     else if(URB_Status == URB_STALL)

    {

      /* Control transfers completed, Exit the State Machine */

      phost->gState =   phost->gStateBkp;

      phost->Control.state = CTRL_STALL; //added

 

      status = USBH_NOT_SUPPORTED; //added

    }

    break;

13 REPLIES 13
Posted on January 22, 2014 at 08:59

Thanks.

Couldn't you get this post get sticky (to appear always at the top of the list)?

JW

garberman
Associate
Posted on April 02, 2014 at 12:56

Hi,

Can I receive USB OTG FS WakeUp interrupt under Standby Mode for the processor STM32F437?

According to the datasheet the answer is ''Yes'' but I could not practical!

Can you help me by practical advice?

tsuneo
Senior
Posted on April 02, 2014 at 19:25

> garberman.sergey:

> Can I receive USB OTG FS WakeUp interrupt under Standby Mode for the processor STM32F437? USB Wakeup event is passed to NVIC over EXTI 2.5 External interrupt/event line mapping (p380, DM00031pdf) EXTI line 18 is connected to the USB OTG FS Wakeup event - NVIC position:42 OTG_FS_WKUP EXTI line 20 is connected to the USB OTG HS (configured in FS) Wakeup event - NVIC position:76 OTG_HS_WKUP STM32_USB-Host-Device_Lib_V2.1.0 has already implemented these events. a) initialization

\STM32_USB-Host-Device_Lib_V2.1.0\Project\USB_Device_Examples\HID\inc\usb_conf.h
/****************** USB OTG FS CONFIGURATION **********************************/
#ifdef USB_OTG_FS_CORE
...
#define USB_OTG_FS_LOW_PWR_MGMT_SUPPORT
/****************** USB OTG HS CONFIGURATION **********************************/
#ifdef USB_OTG_HS_CORE
...
#define USB_OTG_HS_LOW_PWR_MGMT_SUPPORT
#endif

\STM32_USB-Host-Device_Lib_V2.1.0\Project\USB_Device_Examples\HID\src\usb_bsp.c
void USB_OTG_BSP_Init(USB_OTG_CORE_HANDLE *pdev)
{
...
#ifdef USB_OTG_FS_LOW_PWR_MGMT_SUPPORT
EXTI_ClearITPendingBit(EXTI_Line18);
EXTI_InitStructure.EXTI_Line = EXTI_Line18; 
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
EXTI_ClearITPendingBit(EXTI_Line18); 
NVIC_InitStructure.NVIC_IRQChannel = OTG_FS_WKUP_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 5;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
EXTI_ClearITPendingBit(EXTI_Line18); 
#endif 
#ifdef USB_OTG_HS_LOW_PWR_MGMT_SUPPORT
EXTI_ClearITPendingBit(EXTI_Line20);
EXTI_InitStructure.EXTI_Line = EXTI_Line20; 
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
EXTI_ClearITPendingBit(EXTI_Line20); 
NVIC_InitStructure.NVIC_IRQChannel = OTG_HS_WKUP_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 5;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
EXTI_ClearITPendingBit(EXTI_Line20); 
#endif 

b) ISRs

\STM32_USB-Host-Device_Lib_V2.1.0\Project\USB_Device_Examples\HID\src\stm32fxxx_it.c
#ifdef USE_USB_OTG_FS 
void OTG_FS_WKUP_IRQHandler(void)
{
...
}
#ifdef USE_USB_OTG_HS 
void OTG_HS_WKUP_IRQHandler(void)
{
...
]

Tsuneo
garberman
Associate
Posted on April 03, 2014 at 09:53

Many thanks, Tsuneo!

But I had been tried this sample and didn't get results!

Of course, I implemented it into my project... which not trivial.

May be, you know (link) a simple project for example?

chmorgan
Associate II
Posted on April 30, 2014 at 12:45

--- a/Libraries/STM32_USB_Device_Library/Class/cdc/src/usbd_cdc_core.c
+++ b/Libraries/STM32_USB_Device_Library/Class/cdc/src/usbd_cdc_core.c
@@ -625,7 +625,7 @@ static uint8_t usbd_cdc_Setup (void *pdev,
else /* No Data request */
{
/* Transfer the command to the interface layer */
- APP_FOPS.pIf_Ctrl(req->bRequest, NULL, 0);
+ APP_FOPS.pIf_Ctrl(req->bRequest, (uint8_t*)req, 0);
}

Here is another library fix I picked up from the forums, '' Modify usbd_cdc_Setup() to pass the request buffer into the APP_FOPS.pIf_Ctrl() function pointer callback. Change is per instructions by chinzei.tsuneo on the st forums to enable passing the ''No data request'' setup packets through to the callback function for processing. ''
chmorgan
Associate II
Posted on April 30, 2014 at 12:55

Is it within the license for the library to be able to push it to some place like github? It seems a waste for everyone to be applying the same set of fixes to the library over and over.

chmorgan
Associate II
Posted on April 30, 2014 at 14:45

file - usb_dcd_int.c

Search for ''emptyintr'' occurence, where the source code is trying to clear this flag. There are two occurrences:

CLEAR_IN_EP_INTR(1, emptyintr);

CLEAR_IN_EP_INTR( epnum , emptyintr);

It is read only flag, which cannot be cleared, so this interrupt must be masked instead:

fifoemptymsk = 0x1 << epnum;

USB_OTG_MODIFY_REG32(&pdev->regs.DREGS->DIEPEMPMSK, fifoemptymsk, 0)

This problem is causing high CPU load, but the USB is working.

Re: this fix, I've applied this change to DCD_WriteEmptyTxFifo() that I found from another forum discussion. This function appears to be called at all locations where the CLEAR_*** calls are made so it looked like a better fix:

/**

* @brief DCD_WriteEmptyTxFifo

* check FIFO for the next packet to be loaded

* @param pdev: device instance

* @retval status

*/

static uint32_t DCD_WriteEmptyTxFifo(USB_OTG_CORE_HANDLE *pdev, uint32_t epnum)

{

USB_OTG_DTXFSTSn_TypeDef txstatus;

USB_OTG_EP *ep;

uint32_t len = 0;

uint32_t len32b;

txstatus.d32 = 0;

ep = &pdev->dev.in_ep[epnum]; 

len = ep->xfer_len - ep->xfer_count;

if (len > ep->maxpacket)

{

len = ep->maxpacket;

}

len32b = (len + 3) / 4;

txstatus.d32 = USB_OTG_READ_REG32( &pdev->regs.INEP_REGS[epnum]->DTXFSTS);

while (txstatus.b.txfspcavail > len32b &&

ep->xfer_count < 
ep-
>xfer_len &&

ep->xfer_len != 0)

{

/* Write the FIFO */

len = ep->xfer_len - ep->xfer_count;

if (len > ep->maxpacket)

{

len = ep->maxpacket;

}

len32b = (len + 3) / 4;

USB_OTG_WritePacket (pdev , ep->xfer_buff, epnum, len);

ep->xfer_buff += len;

ep->xfer_count += len;

#if 1

// NOTE: Fix from [DEAD LINK /public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flooded%20empty%20FIFO%20interrupts%20still%20make%20USB%20devices%20crawl&currentviews=413]https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flooded%20empty%20FIFO%20interrupts%20still%20make%20USB%20devices%20crawl¤tviews=413

if( ep->xfer_count >= ep->xfer_len){

uint32_t fifoemptymsk = 1 << 
epnum
;

USB_OTG_MODIFY_REG32(&pdev->regs.DREGS->DIEPEMPMSK, fifoemptymsk, 0);

break;

}

#endif

txstatus.d32 = USB_OTG_READ_REG32(&pdev->regs.INEP_REGS[epnum]->DTXFSTS);

}

return 1;

}

chmorgan
Associate II
Posted on April 30, 2014 at 15:02

file - usbd_core.c

USBD_Init function

correct order:

/* Force Device Mode*/

USB_OTG_SetCurrentMode(pdev, DEVICE_MODE); /* Enable Interrupts */ USB_OTG_BSP_EnableInterrupt(pdev);

On some hosts this is blocking proper enumeration of our device.

I'm not seeing the call to USB_OTG_SetCurrentMode() in my version of USBD_Init():

/**

* @brief USBD_Init

* Initailizes the device stack and load the class driver

* @param pdev: device instance

* @param core_address: USB OTG core ID

* @param class_cb: Class callback structure address

* @param usr_cb: User callback structure address

* @retval None

*/

void USBD_Init(USB_OTG_CORE_HANDLE *pdev,

USB_OTG_CORE_ID_TypeDef coreID,

USBD_DEVICE *pDevice, 

USBD_Class_cb_TypeDef *class_cb, 

USBD_Usr_cb_TypeDef *usr_cb)

{

/* Hardware Init */

USB_OTG_BSP_Init(pdev); 

USBD_DeInit(pdev);

/*Register class and user callbacks */

pdev->dev.class_cb = class_cb;

pdev->dev.usr_cb = usr_cb; 

pdev->dev.usr_device = pDevice; 

/* set USB OTG core params */

DCD_Init(pdev , coreID);

/* Upon Init call usr callback */

pdev->dev.usr_cb->Init();

/* Enable Interrupts */

USB_OTG_BSP_EnableInterrupt(pdev);

}

Is this fix suggesting that a call to USB_OTG_SetCurrentMode() be added prior to enabling interrupts?