2021-03-16 04:32 AM
Hi all, I just thought I'd add to the list of questions about USB! :grinning_face_with_sweat:
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?
Solved! Go to Solution.
2021-03-17 09:52 AM
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 */
2021-03-17 09:36 AM
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.
2021-03-17 09:52 AM
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 */