cancel
Showing results for 
Search instead for 
Did you mean: 

Getting sleep to work when USB CDC is enabled?

PMath.4
Senior III

My program has the option of sleeping for a period using the RTC to wake or sleeping until the wakeup pin is set high. Both these functions work perfectly if I talk to the outside world using a uart.

However, I configure CDC as a serial port SLEEP doesn't work - or at least the USB never disconnects.

I'm using USB STOP and USB DEINIT before the sleep command but these don't seem to do anything. Any ideas appreciated

            while(totalseconds>0){
                if(totalseconds>30.0){
                    timetosleep=30*2048;
                    totalseconds-=30.0;
                } else {
                    timetosleep= (int)(totalseconds*2048.0);
                    totalseconds=0.0;
                }
                USBD_Stop(&hUsbDeviceFS);
                USBD_DeInit(&hUsbDeviceFS);
                HAL_NVIC_SetPriority(RTC_WKUP_IRQn, 0x0F, 0);
                HAL_NVIC_EnableIRQ(RTC_WKUP_IRQn);
                HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, timetosleep, RTC_WAKEUPCLOCK_RTCCLK_DIV16);
                HAL_SuspendTick();
                HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFE);
                HAL_RTCEx_DeactivateWakeUpTimer(&hrtc);
                HAL_NVIC_DisableIRQ(RTC_WKUP_IRQn);
            }
             SYSCLKConfig_STOP();
             HAL_ResumeTick();
             MX_USB_DEVICE_Init();

13 REPLIES 13
PMath.4
Senior III

Doesn't enumerate at all without the resistor - this discussion is pointless since you are not helping with the actual issue which is the failure of the routines to disconnect - not connect.

A fixed pullup is there, it is going to stay there, and if sleep won't work then so be it.

> Doesn't enumerate at all without the resistor

Then you have some other hardware error, maybe DP pin has a bad solder joint. Try to set the pin as GPIO (but you MUST have the OTG clock switched off in RCC, as it overrides GPIO settings - this is a known fact undocumented by ST), wiggle it and measure.

The internal DP pullup is switched on/off by (OTG_FS/HS_)DCTL.SDIS, see Soft disconnect section in RM. Some other bits have to be switched off/on, too, I am not going to discuss the details here (part of which would be the explanation why you've seen VBUS being mentioned in that other section - it's written from the sole perspective of the module being utilized in all its capabilities); but once you have a working connection, those bits are all in place. So, what you can easily do is, place a breakpoint at the place where you would want to go to sleep, and there, in the debugger, toggle OTG_xS_DCTL.SDIS - you should see the internal pullup to connect and disconnect, that's measured easily by pulling the pin in question down.

JW

Ons KOOLI
Senior III

Hi PMath.4,

ST provides the USB link power management. Can you please take a look at the HID_LPM_Standalone project ? You can find it, for example, under Projects\STM32446E_EVAL\Applications\USB_Device\HID_LPM_Standalone directory.

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
  if (GPIO_Pin == KEY_BUTTON_PIN)
  {
#if (USBD_LPM_ENABLED == 1)
    if(hpcd.lpm_active)
    {
      if(hpcd.LPM_State == LPM_L1)
      {
        if ((&hpcd)->Init.low_power_enable)
        {
          /* Reset SLEEPDEEP bit of Cortex System Control Register */
          SCB->SCR &= (uint32_t)~((uint32_t)(SCB_SCR_SLEEPDEEP_Msk | SCB_SCR_SLEEPONEXIT_Msk));  
          
          SystemClockConfig_STOP();
        }
        
        /* Ungate PHY clock */
        __HAL_PCD_UNGATE_PHYCLOCK((&hpcd));
        
        /* Activate Remote wakeup */
        HAL_PCD_ActivateRemoteWakeup((&hpcd));
        
        /* Remote wakeup delay */
        HAL_Delay(10);
        
        /* Disable Remote wakeup */
        HAL_PCD_DeActivateRemoteWakeup((&hpcd));
        
        /* change state to configured */
        ((USBD_HandleTypeDef *)hpcd.pData)->dev_state = USBD_STATE_CONFIGURED;
        
        /* clear L1 flag */
        hpcd.LPM_State = LPM_L0;
      }
      else
#endif
        if ((((USBD_HandleTypeDef *)hpcd.pData)->dev_remote_wakeup == 1)&&
            (((USBD_HandleTypeDef *)hpcd.pData)->dev_state == USBD_STATE_SUSPENDED))
        {
          if ((&hpcd)->Init.low_power_enable)
          {
            /* Reset SLEEPDEEP bit of Cortex System Control Register */
            SCB->SCR &= (uint32_t)~((uint32_t)(SCB_SCR_SLEEPDEEP_Msk | SCB_SCR_SLEEPONEXIT_Msk));  
            
            SystemClockConfig_STOP();
          }
          
          /* Ungate PHY clock */
          __HAL_PCD_UNGATE_PHYCLOCK((&hpcd));
          
          /* Activate Remote wakeup */
          HAL_PCD_ActivateRemoteWakeup((&hpcd));
          
          /* Remote wakeup delay */
          HAL_Delay(10);
          
          /* Disable Remote wakeup */
          HAL_PCD_DeActivateRemoteWakeup((&hpcd));
          
          /* change state to configured */
          ((USBD_HandleTypeDef *)hpcd.pData)->dev_state = USBD_STATE_CONFIGURED;
          
          /* Change remote_wakeup feature to 0*/
          ((USBD_HandleTypeDef *)hpcd.pData)->dev_remote_wakeup=0;
        }
    }
  }
}

I really hope this could be helpful. Else, you can share with me your .ioc file, if you are working with STM32CubeMx, to look further for your issue or report it internally if necessary.

Best Regards,

Ons.

Ons KOOLI
Senior III

Hi PMath.4,

Any updates on your issue ?

Best Regards,

Ons.