4

i have programmed my stm32f103 blue-pill board with USB-CDC protocol

I can read and write on this Port

But after performing a hardware reset, the COM port is unavailable I have to unplug the USB connection and re-plug it again then the COM port appears.

Is it possible to avoid this?

-Thanks

nema1
  • 91
  • 1
  • 4
  • Well you are reseting the device with USB side plugged in, I don't think OS usb adapter driver would be ready for that. OS side is thinking that the device is in full initialized state where as you have reseted the device. You can plugin and unplug the usb device of yours which will also lead to the reset but with OS being ready for that type of reset. – Rajnesh Mar 01 '19 at 08:46

4 Answers4

5

If you reset the bluepill you need to pull down the D+ line for several milliseconds to let know the host that it has to start the enumeration process.

0___________
  • 60,014
  • 4
  • 34
  • 74
  • USB devices are usually not equipped with pull-downs on those lines. – David Grayson Mar 01 '19 at 18:50
  • 1
    @DavidGrayson yep difficult to understand. Set gpio to output. Set it low wait some time, set the AF function back. – 0___________ Mar 01 '19 at 18:53
  • No, you definitely don't want to set the line to an output because then you will cause a short circuit if the host is sending packets on the bus at that time. You can just let the line float, and it will get pulled down by the pull-down on the host side. – David Grayson Mar 01 '19 at 18:54
  • You can't I afraid. It has the external pull-up, it also have the serial resistor so you will not fry the pin – 0___________ Mar 01 '19 at 18:56
  • OK, yeah, I can see now that the board was badly designed. It should have made the D+ pull-up be controllable for situations like this (unless you really need every single I/O line). Also, it pulls D+ up to 5 V when you are supposed to only pull it up to 3.3 V. – David Grayson Mar 01 '19 at 19:00
  • Yes this solved the problem, thanks a lot. – A.R.S.D. Apr 24 '21 at 13:53
  • Will you please tell just what code should I put in a specific place? I tried setting/resetting PA12 in various combinations before and after `MX_USB_DEVICE_Init();` and with different delays. None made any difference: I had to replug always. Linux is the host. – Alexey Orlov May 17 '22 at 21:38
  • @AlexeyOrlovyou need to have one transistor circuit to reenumerate. See nucleo board circuit for details – 0___________ May 17 '22 at 22:39
  • @0___________ I need to create some external circuit for my STM32F103C8T6, then? Sorry, I am not an experienced user. Can you find a link to this circuit for me? – Alexey Orlov May 18 '22 at 01:52
2

Use case: STM32F103C8T6, STM32CubeIDE

USB_DEVICE/App/usb_device.c (mostly copy-pasted from MX_GPIO_Init():

...
void MX_USB_DEVICE_Init(void)
{
  /* USER CODE BEGIN USB_DEVICE_Init_PreTreatment */

  /* Rendering hardware reset harmless (no need to replug USB cable): */
  GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOA_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_12, GPIO_PIN_RESET);

  /*Configure GPIO pin : PA12, a.k.a. USB_DP */
  GPIO_InitStruct.Pin = GPIO_PIN_12;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  HAL_Delay(5);
  /* Hardware reset rendered harmless! */

  /* USER CODE END USB_DEVICE_Init_PreTreatment */
  ...
}
...

Inspired by a blog post about the not quite right (10k instead of 1.5k) R10 on certain noname Blue Pills.

Alexey Orlov
  • 2,412
  • 3
  • 27
  • 46
0

But after performing a hardware reset, the COM port is unavailable I have to unplug the USB connection

I see this exact behaviour in Windows 7 - when the COM port is open during reset. Same story when the user disconnects and re-connects the USB device while the COM port is left open in an application.

You have 2 possible workarounds:

  • Close the COM port before the hardware reset
  • Upgrade to Windows 10

Note that you still need to close and re-open the COM port on windows 10 on hardware reset (or USB replugging).

Turbo J
  • 7,563
  • 1
  • 23
  • 43
  • the host will not reenumerate it. it is a wrong answer and any windows upgrades will not help at all – 0___________ Mar 02 '19 at 19:01
  • @P__J__ Incorrect, I observe the exact same behavior when working with USB CDC on STMs. Possibly an issue with the ST driver. Steps to reproduce: Allow host to enumerate the device, open COM port in the host, disconnect the device completely (power down) without closing the COM port in the host, re-connect the device. Even though the host correctly re-enumerates the device, the COM port remains unusable. You need to manually close and reopen it wherever you left it open on the host. – J_S Mar 05 '19 at 08:36
  • @JacekŚlimok this completely wrong. You probably have made many mistakes in your code and this pseudo workaround works only by accident. Stm32 can driver works fine. – 0___________ Mar 05 '19 at 08:42
  • @P__J__ Any example as-is provided by ST on any demoboard proves this and it's consistent even when using their older (SthPeriph) examples. If you go ahead and assume what the quality of my code is without even seeing any, there's no point of continuing this conversation. I do however think it's safe to assume you didn't even bother trying the exact described scenario yourself. – J_S Mar 05 '19 at 09:09
  • @JacekŚlimok is rather hard to understand what you mean. On my devices everything works OK, without any "magic". If your code requires some strange actions - it is the sign of the error there - not in the USB stack. i have designed tens of devices using CDC class on STM32 uCs. ] – 0___________ Mar 05 '19 at 12:40
0

This solution worked on my BluePill with hal USB library. Paste this to USB_DEVICE\App\usb_device.c -> MX_USB_DEVICE_Init() user code brackets:

LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOA);

LL_GPIO_InitTypeDef GPIO_InitStruct = { 0 };
GPIO_InitStruct.Pin = USB_DM_Pin | USB_DP_Pin;
GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;
LL_GPIO_Init(USB_DM_GPIO_Port, &GPIO_InitStruct);

GPIO_InitStruct.Pin = USB_DP_Pin;
GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Pull = LL_GPIO_OUTPUT_PUSHPULL;
LL_GPIO_Init(USB_DP_GPIO_Port, &GPIO_InitStruct);
LL_GPIO_ResetOutputPin(USB_DP_GPIO_Port, USB_DP_Pin);

LL_mDelay(5);

GPIO_InitStruct.Pin = USB_DP_Pin;
GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;
LL_GPIO_Init(USB_DP_GPIO_Port, &GPIO_InitStruct);

Wierd thing is that hal doesn't configure GPIO at all. Debugged through every call from CPU start and didn't find it. But it works out of the box.

viteo
  • 303
  • 3
  • 13