AnsweredAssumed Answered

STM32F4, USB HS with ULPI and Suspend/Wakeup

Question asked by kueppers.simon on Apr 29, 2014
Latest reply on Apr 29, 2014 by kueppers.simon
Hi guys,
I am in need of your help, unfortunately STs documentation is lacking some information here.

I am basically trying to implement a USB device (CDC-ACM to be precise) that utilizes suspend/wakeup. I am using the "STM32_USB-Host-Device_Lib_V2.1.0" and looked into the HID example for help. 
Unfortunately there is no example that shows the USB HS with suspend/wakeup using an external ULPI. I am using the SMSC USB3300 ULPI chip with an external 24MHz crystal.

The first thing that baffles me is in dcd_int.c:
Below the function DCD_HandleUSBSuspend_ISR gets called on a suspend interrupt. This interrupt gets called successfully.

uint32_t USBD_OTG_ISR_Handler (USB_OTG_CORE_HANDLE *pdev)
    if (gintr_status.b.usbsuspend)
      retval |= DCD_HandleUSBSuspend_ISR(pdev);

Now, inside this function I see:

if((pdev->cfg.low_power) && (dsts.b.suspsts == 1) &&
  (pdev->dev.connection_status == 1) &&
  (prev_status  == USB_OTG_CONFIGURED))
  /*  switch-off the clocks */

The strange part now is, that I cannot find another reference of dev.connection_status, which gets tested in this if-statement, thus this variable never gets to 1 and I wonder why and what I am missing.
Also prev_status (which gets set by dev.device_status) never equals USB_OTG_CONFIGURED which is defined as 3. It always is equal to 2, which is defined as USB_OTG_ADDRESSED

This lead to the problem that obviously, the ULPI never went into the low power mode. I commented out the two non-reachable if-conditions and now I can see the USB3300 to stop its external 24MHz oscillator. I should note that I commented out the deepsleep part in this function

Now comes the second thing, I can not yet understand. As in the HID example, I activated the EXTI_Line20 and enabled the OTG_HS_WKUP_IRQn in USB_OTG_BSP_Init. Now when I disable my device in the windows device manager, I no longer see the SOF microframes on my oscilloscope. The suspend interrupt gets called and I disable the USB3300 clocks as shown above. 
Unfortunately, the OTG_HS_WKUP_IRQHandler gets called now immediately and with the call to USB_OTG_UngateClock enables the USB3300 clocks again. After some time, the HS core sees the suspend condition on the bus and goes to suspend AGAIN. This keeps repeating on and on.

So I had some long looks into the Ref Man having the tongue at the right angle and read something like:
EXTI line 20 is connected to the USB OTG HS (configured in FS) Wakeup event

So I wondered: since I am using HS usb with external phy and the USB OTH HS core, is this even necessary for waking up? Maybe the strange behaviour is here? 
The sad thing is, that I can't seem to find anything on people trying to use USB suspend with external PHYs.
As far as I understood, the EXTI Line 20 is used to asynchronously detect any changes on the USB lines and feed it into the NVIC, which in turn knows that it has to call the OTG_HS_WKUP_IRQHandler.
Now since I am using the ULPI, I don't think this is valid anymore. However, there seems to be yet another instance of wakeup interrupts buried within the HS core: OTG_HS_GINTSTS contains an interrupt status flag for waking up: WKUINT
And now I am completely confused why there are so many configuraiton possibilites for the wakeup interrupt. 
Again, since the documentation is lacking information on this (or I simply can not find it, though searching for some days now) I can not figure out, how to correctly implement USB HS wake up using the external PHY.

This is why am I am searching for help here in the forum and hope someone can shed some light onto this. I am very much looking forward to any means of helping, thanks!

EDIT at 14:58. Found this in the reference manual of the USB stack:
Even if the #define USB_OTG_HS_LOW_PWR_MGMT_SUPPORT is uncommented, the
USB HID Device enters Low Power mode but cannot wakeup after a new Host
This behavior is normal since the wakeup signal in the USB OTG HS Core is available
only when the USB OTG HS core is working in Full Speed mode.

What exactly does that mean? Do I have to set the core into FS mode after suspend and then wait for wake up? Or should I use FS mode only?