STM32F070 - firmware-controlled USB connection and HSE activation
How can I make the device appear disconnected on the host while physically connected? (i.e. It should disappear from Windows Device Manager.) Why doesn't calling HAL_PCD_DevDisconnect() cause that to happen?
  


Calling HAL_PCD_DevDisconnect() with the proper parameters does indeed disconnect DPPU, thus making the device disappear from Windows Device Manager. The error in the question is that in MX_USB_DEVICE_DeInit(),

HAL_PCD_DevDisconnect((PCD_HandleTypeDef *)&amp;hUsbDeviceFS.pData);


should be

HAL_PCD_DevDisconnect((PCD_HandleTypeDef *)hUsbDeviceFS.pData);


(without the address operator &amp;).

Here is a revised version of the USB de-init function:

void MX_USB_DEVICE_DeInit(void)
{
   PCD_HandleTypeDef *hpcd = (PCD_HandleTypeDef *)hUsbDeviceFS.pData;

   if (hpcd != NULL)
   {
      HAL_PCD_DevDisconnect(hpcd);
      USBD_DeInit(&amp;hUsbDeviceFS);
   }
}



  
  Is the above the right way to go about this? Are the actions all required? Are they in the right order?
  


Close. There's more to the clock configuration than just turning HSE on or off.

STM32CubeMX generates SystemClock_Config(). You can use it as a model for the "Configure system clocks" steps in the list below.


Event - Detect physical USB connection


Configure system clocks


Enable HSE
Turn on PLL
Set SYSCLKSOURCE to PLLCLK
Set UsbClockSelection to PLL
Configure systick

Initialize USB and connect Data+ pull-up (DPPU) to trigger USB enumeration by host - MX_USB_DEVICE_Init() does all of this

Event - Detect physical USB disconnection


Disconnect DPPU (HAL_PCD_DevDisconnect())
De-initialize USB (USBD_DeInit())
Configure system clocks (note many steps in reverse order from above)


Turn off USB peripheral
Switch sysclk back to HSI
Disable HSE (not sure if driving PF0-OSC_IN low is necessary)
Turn off PLL
Configure systick





  
  Do I need to call any functions besides USBD_DeInit() to de-init USB?
  


No, that does it. Dig into the call stacks and you'll find that USBD_DeInit() calls everything that USBD_Stop() does and more.