cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F4 & STM32F7 USB Host Core (Interrupt flood)

Tim Michals
Associate II
Posted on May 19, 2017 at 01:02

Issue:

USB Core issing interrupt at a rate of 8.65us causing high CPU loading.

Software/Chip:

Using USB Host/CDC from STM32Cube V1.15 on a STM32F429 board. 

  USB interrupt sources:

- SOF Interrupts (It is not needed for CDC type transfers) turned this interrupt off and still getting high interrupt rate.

   This is configured in

HAL_StatusTypeDef USB_HostInit (USB_OTG_GlobalTypeDef *USBx, USB_OTG_CfgTypeDef cfg)

.....

  /* Enable interrupts matching to the Host mode ONLY */

  USBx->GINTMSK |= (USB_OTG_GINTMSK_PRTIM            | USB_OTG_GINTMSK_HCIM |\

                 

   USB_OTG_GINTMSK_SOFM

|USB_OTG_GINTSTS_DISCINT|\

                    USB_OTG_GINTMSK_PXFRM_IISOOXFRM  | USB_OTG_GINTMSK_WUIM);

 

  return HAL_OK;

}

- NAK interrupts from bulk in endpoint.  The issue is when the OTG USB gets enough NAKs from the bulk endpoint and issues an interrupt at a rate of 8.625us. 

Solutions

?

Is there a work around that does not degrade USB performance?  The STM32FH7 also has has the same code to re-enable the bulk in endpoint. 

static void HCD_HC_IN_IRQHandler   (HCD_HandleTypeDef *hhcd, uint8_t chnum)

  }

  else if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_NAK)

  {   

    if(hhcd->hc[chnum].ep_type == EP_TYPE_INTR)

    {

      __HAL_HCD_UNMASK_HALT_HC_INT(chnum);  

      USB_HC_Halt(hhcd->Instance, chnum);   

    }

    else if  ((hhcd->hc[chnum].ep_type == EP_TYPE_CTRL)||

         (hhcd->hc[chnum].ep_type == EP_TYPE_BULK))

    {

      /* re-activate the channel  */

      tmpreg = USBx_HC(chnum)->HCCHAR;

      tmpreg &= ~USB_OTG_HCCHAR_CHDIS;

      tmpreg |= USB_OTG_HCCHAR_CHENA;

      USBx_HC(chnum)->HCCHAR = tmpreg;

    }

    hhcd->hc[chnum].state = HC_NAK;

    __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK);

  }

}

There are several postings about this issue (The first posting is the best description of the issue)

https://community.st.com/0D50X00009XkYz2SAF

 

https://community.st.com/0D50X00009XkYSSSA3

 

https://community.st.com/0D50X00009Xked0SAB

 

null
37 REPLIES 37
Posted on February 27, 2018 at 16:23

Imen,

When will the STM32F4 fix be ready?

Tim

Posted on February 27, 2018 at 16:47

Hello

Michals.Tim

,

It is planned to integrate the enhancementin the next release for STM32F4, but, unfortunately, I can't give you any target date for the moment.

Best Regards,

Imen

When your question is answered, please close this topic by clicking "Accept as Solution".
Thanks
Imen
Posted on February 27, 2018 at 22:43

Thanks Imen for the update. However, the 'rework' of the HAL driver pertains only for the DMA case? The standard case without DMA (e.g. for the FS Host where DMA is not available) is not affected by this rework? Unfortunately in our design we use the FS core as CDC Host. The HS core is used as CDC device.

Anyway, I am eager to see the reworked HAL driver.

Best regards,

Lix

Posted on February 28, 2018 at 10:35

Hello

Paulian.Lix_N

,

For the IP OTG in mode FS,there will be no fix as it is IP limitation.

However, our developer team are working on thistopic on thesoftware side to bypass this problem.

Best Regards,

Imen

When your question is answered, please close this topic by clicking "Accept as Solution".
Thanks
Imen
Posted on February 28, 2018 at 23:08

hm... that's quite bad.

eye
Associate
Posted on May 08, 2018 at 05:03

Waiting for a solution for this issue too.

eye
Associate
Posted on May 08, 2018 at 09:59

I walkarounded this issue by handling the NAK interrupt async.

Jim Kaz
Associate II

Posted on May 25, 2018 at 18:17

 

 

 

I ran into the same issue with an L4 processor and I found a way to work around it that seems to work.  I've never looked at any of the F series software frameworks, but I suspect something similar to what I did will work.  I made the following 2 changes.

Inside of the interrupt, where you handle the NAK interrupt, I disable it.  Below is what it looks like on the L4 framework (line I added is in bold):

else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_NAK)
{
    if(hhcd->hc[chnum].ep_type == EP_TYPE_INTR)
   {
      __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
      USB_HC_Halt(hhcd->Instance, chnum);
   }
   /* Clear the NAK flag before re-enabling the channel for new IN request */
   hhcd->hc[chnum].state = HC_NAK;
   __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK);
   // Hack to disable the NAK interrupt completely (it'll be re-enabled in SOF)
   USBx_HC(chnum)->HCINTMSK &= ~USB_OTG_HCINT_NAK;
   if ((hhcd->hc[chnum].ep_type == EP_TYPE_CTRL)||
   (hhcd->hc[chnum].ep_type == EP_TYPE_BULK))
   {
      /* re-activate the channel */
      USBx_HC(chnum)->HCCHAR &= ~USB_OTG_HCCHAR_CHDIS;
      USBx_HC(chnum)->HCCHAR |= USB_OTG_HCCHAR_CHENA;
   }
}

This change by itself will break USB as the NAK interrupt does appear to be important for general functionality.  You have to periodically re-enable the NAK interrupt, and I used the SoF interrupt to do that.

/* Handle Host SOF Interrupts */
if(__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_SOF))
{
   HAL_HCD_SOF_Callback(hhcd);
   __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_SOF);
   // Added hack to re-enable the NAK interrupt because leaving it off is bad
   for (i = 0; i < hhcd->Init.Host_channels; i++)
   {
      USBx_HC(i)->HCINTMSK |= USB_OTG_HCINT_NAK;
   }
}

Re-enabling it for every channel is probably unnecessary, but since this is running in interrupt space I opted for speed rather than checking each channel and seeing if it needed to be re-enabled.

I was getting interrupts every 20 microseconds  This change made it so I'd get the SOF interrupt once a ms, then 20 us later get a NAK and then no spurious interrupts until the next SOF.

I have to thank you immensely for this post. It saved my bacon! Once I started looking at the USB Host code I was pretty lost. I hesitated but eventually implemented your 2 changes and BOOM! The rest of the threads in my app woke up and were no longer starved! Fat and happy!

One post here implied that DMA should be on but, I had to turn off DCache for devices to enumerate. Maybe because MPU & SDRAM use? In the end, the DMA had no effect. So I don't know whether I gain more by having DMA on and Dcache off? My app uses HS Host, FS Device, Timers interrupt, STemWin and DMA LCD.

While solving this bug I found out that :

  1. DMA only for HS on STM32F7
  2. DCache has to be off when using DMA
  3. DMA doesn't affect this problem.

It seemed like ST was going to address this issue . I believe I have the latest HAL but , it seems nothing was done?

Thanks again for posting this. I owe you one!

AEila
Associate

ST team, this issue is pending for a VERY LONG time - not reasonable!!

Any update regarding this topic for F4?