cancel
Showing results for 
Search instead for 
Did you mean: 

VBUS sensing doesn't work because internal pull-up is activated during USB init rather than when connected - STM32F072

MattKefford
Associate III

Hi all, I just thought I'd add to the list of questions about USB! 😅

I read AN4879 and it says "when the host presence is detected by the device, the device connects its pull up resistor". This is very clear - first detect the host, second activate the pull-up. What actually happens in the Cube generated code though is that the USB device is initialised at boot and the embedded pull-up is immediately activated, whether a cable is attached or not.

This is triggered by a chain of function calls:

MX_USB_DEVICE_Init() -> USBD_Start() -> USBD_LL_Start() -> HAL_PCD_Start() -> USB_DevConnect() -> USBx->BCDR |= (uint16_t)USB_BCDR_DPPU;

This code is Cube generated so if I remove the call to USB_Start() it will just get added back in next time I make a change.

Should I call USBD_Stop() straight after the USBD_Start() or is there a different way to go about this? Then use my vbus detect pin to call USBD_Start() when the cable is plugged in. 

A second and perhaps bigger issue this is causing is that, because I'm using a TVS device for protection, when the D+ pull-up is active it causes 2.56V to appear on the vbus pin (3.26V from the D+ line then 0.7V dropped across the TVS diode) this goes through a potential divider (R1=62k,R2=100k) and results in 1.57V on my vbus detect pin therefore I can detect the connected event but never detect a disconnect event as once the pull-up is active the vbus pins will never go below 1.57V and VIL is 1.36V.

I could swap the resistors so I get 1V when unplugged and 2V when plugged.

Has anyone else run into these issues? Is there a different way to detect connect/disconnect events? Do you just let the embedded pull-up go high upon USB init or do you override the default behaviour?

1 ACCEPTED SOLUTION

Accepted Solutions
MattKefford
Associate III

I've tested using the LL functions and it works fine so I think I'd recommend those as they don't interfere with the USB class.

In MX_USB_DEVICE_Init() :-

 /* USER CODE BEGIN USB_DEVICE_Init_PostTreatment */

 // Begin in an off state and detect when cable is plugged in

 //USBD_Stop(&hUsbDeviceFS);

 USBD_LL_Stop(&hUsbDeviceFS);

 /* USER CODE END USB_DEVICE_Init_PostTreatment */

View solution in original post

2 REPLIES 2
MattKefford
Associate III

So just to follow up on this, answering my own questions but hopefully helping others out in a similar position...

I now have USB host detection and the embedded pull-up working as it should =)

It seems fine to just stop the USB immediately after starting it. Strange thing to have to do but it works.

I did swap the resistors to give a ratio of 0.4 which results in 2V when the cable is plugged in and 1V when the cable is unplugged. 1V is low enough to be a logic low so then the embedded pull-up can be disabled and the voltage drops to 0V. I'm not using the Vbus as this is a self-powered board so I only need it as a signal.

I could use an interrupt but I just added code to my main loop to check this pin, do some basic de-bouncing and a basic state machine to start/stop the USB only when needed.

static USB_PU_e usbPullupState = USB_PU_OFF;
 
   GPIO_PinState usbDetect = HAL_GPIO_ReadPin(USB_DET_GPIO_Port, USB_DET_Pin);
 
   // If USB is off and needs to be on - turn it on
   if((usbDetect == GPIO_PIN_SET) && (usbPullupState == USB_PU_OFF))
   {
      HAL_Delay(1);   // Basic debounce
 
      if(GPIO_PIN_SET == HAL_GPIO_ReadPin(USB_DET_GPIO_Port, USB_DET_Pin))
      {
         //USBD_Start(&hUsbDeviceFS);
         USBD_LL_Start(&hUsbDeviceFS);
         usbPullupState = USB_PU_ON;
      }
   }
   // If USB is on and needs to be off - turn it off
   else if((usbDetect == GPIO_PIN_RESET) && (usbPullupState == USB_PU_ON))
   {
      HAL_Delay(1);   // Basic debounce
 
      if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(USB_DET_GPIO_Port, USB_DET_Pin))
      {
         //USBD_Stop(&hUsbDeviceFS);    // This will deinit the USB class
         USBD_LL_Stop(&hUsbDeviceFS);
         usbPullupState = USB_PU_OFF;
      }
   }

So far everything seems fine. When the USB is stopped and my code calls CDC_Transmit_FS() it just fails the TxState check and returns early so no messages are getting buffered or left pending.

The thing I'm not sure about now is should I be using USBD_Start() and USBD_Stop() or USBD_LL_Start() and USBD_LL_Stop() ?

USBD_Stop() stops the driver but also de-inits the class and USBD_Start() starts the driver but doesn't init the class so I'm not even sure how it is working currently as the class should become de-initialised.

MattKefford
Associate III

I've tested using the LL functions and it works fine so I think I'd recommend those as they don't interfere with the USB class.

In MX_USB_DEVICE_Init() :-

 /* USER CODE BEGIN USB_DEVICE_Init_PostTreatment */

 // Begin in an off state and detect when cable is plugged in

 //USBD_Stop(&hUsbDeviceFS);

 USBD_LL_Stop(&hUsbDeviceFS);

 /* USER CODE END USB_DEVICE_Init_PostTreatment */