Skip to main content
brians
Associate II
March 13, 2017
Question

USB initialisation and deinitialisation

  • March 13, 2017
  • 22 replies
  • 7686 views
Posted on March 13, 2017 at 17:13

I am using USB CDC both for bootloader and in the loaded application with the IAR toolset and the CubeMX Middleware/HALlibrary.  Turning off the USB & Timer interrupts before the jump it jumps cleanly and runs the application, except that the USB will not restart (USBD_Start). I am using the normal start USBD start sequence.  If I load the application and run it at the same address all is fine and USB initialises runs as expected.  Is there a prescribed way to turn off USB in the boot loader and re-start it in an application?

    This topic has been closed for replies.

    22 replies

    zdravko
    Associate III
    July 25, 2017
    Posted on July 25, 2017 at 10:07

    I have absolutely the same problem. I have a bootloader and I'm using the usb to update the firmware, once it's ready it should restart and switch all interrupts to the new location where the application resides. However the usb is no longer working, and the communication failes. The user need to hard reset the whole device, after which the usb is reinitialized and the communication is reestablished. This is not very nice and professional so I'm really looking for a solution to the problem or at leas some kind of understanding what is going on and what causes the problem. Please contribute!

    Vangelis Fortounas
    Associate II
    July 25, 2017
    Posted on July 25, 2017 at 19:03

    Hello!!

    You wrote 'Turning off the USB'  How you turn off the USB?

    Do you disconnect it from PC( by MCU soft) before you turn it off?

    howard n2wx
    Associate III
    July 25, 2017
    Posted on July 25, 2017 at 21:23

    Is there a hardwired pullup on the USB D+ line?  If manually removing and reinstalling it after the app restart fixes things then you'll need to switch the pullup in and out of the link with a GPIO pin

    Vangelis Fortounas
    Associate II
    July 25, 2017
    Posted on July 25, 2017 at 22:23

    This is the point!!

    You can use Soft disconnect feature

    This can be done by HAL_PCD_DevConnect(..); or HAL_PCD_DevDisconnect(..)!

    when not use HW pullup.!

    zdravko
    Associate III
    July 26, 2017
    Posted on July 26, 2017 at 16:18

    Thank you very much for your contribution!

    first there is no hardware pullup i.e. the stm32f gpio pull-up is used. Second I added DCD_DevDisconnect(&USB_OTG_dev);

    DCD_DevConnect(&USB_OTG_dev);

    after the USBD_Init function (I'm not using Cube). That however didn't solve the problem. Interestingly the device manager is able to find the device, but somehow I can't open a socket and connect to it as a serial port. I still need to plug it in and out manually.

    Another intersting point to mention is that I can open a socket and communicate with the device after a reset from the RESET button of the stm32f0 disco, which I'm using as a debugger through the SWD.

    I mean that the device manager is finding the device and mapping it to COM30, though the Hyper Terminal is not finding it in the COM port list even after a thousand time refreshment (See the attachment).

    ________________

    Attachments :

    2017-07-26 16_48_17-D__Old_Desktop_hterm.png : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006HyTd&d=%2Fa%2F0X0000000b9U%2Fh81g6iwJE.qRXcip7kl9QUaeihyCDyHurEZY.ryKwKI&asPdf=false
    Vangelis Fortounas
    Associate II
    July 26, 2017
    Posted on July 26, 2017 at 18:34

    Hello!!

    For the second matter

    go to hardware managment ,

    right click to usbcom device

    properties

    goto the port properties or adjust tab (i have Greek windows)

    click advanced button

    change your port name from 30 to under  8   to be compatible with hyperterminal (try the realterm or terraterm)

    I m in a hurry now ..

    I will respond to the first part of issue  later.

    regards

    Vangelis Fortounas
    Associate II
    July 26, 2017
    Posted on July 26, 2017 at 21:46

    Hello again.

    a typical procedure is

    0690X00000603ycQAA.jpg

    in case you don't disconnect (by software) the port before do some change, the pc suposes that usb is connected and with no activity.

    After a reset , give some time (few millisecs .. try 10,20....) to MCU before make the USB initialisation .(preferably initialise it after all other peripherals.)

    when the device is powered from bus introduce also some delay before try to initialise.

    I use all theese methods  with no any kind of problem at all, I can press the reset like machinegun!!  with no any issue.

    Some terminals have another issue.

    When disconnect and reconnect USB device, stops working!!! (teraterm not!!) 

    zdravko
    Associate III
    July 27, 2017
    Posted on July 27, 2017 at 10:24

    Vangelis,

    thank you very much for your contribution. There are two things which I think are misunderstood. The first thing is that I can press the RESET like machingegun too, because the COM port is not available before the pressing of RESET, after that it's working. The next thing is that I'm switching from application to bootloader via a hyperterm software, where the hyperterm is sending a command to the stm32f105 and then smt32f105 is calling NVIC_SystemReset() to switch to the bootloader and that's it! No deinitializations, no disconect nothing. In the bootloader everything is again initialized and USB is DCD_DevConnect(...)-ed. The device manager blinks and refinds the device, though the hyperterm is not able to find the COM part, no matter if it's 1, 10, 20, 30, any number. After RESET it's working! It's working too if I plug out and then in the usb cable.

    MDS
    Associate III
    July 27, 2017
    Posted on July 27, 2017 at 13:59

    I have been writing USB device driver stacks for over 10 years. Assuming you have a Windows host, this sounds like the Windows bug that I found back at Windows XP and it still exists with Window 10.

    If a USB device disconnects while the Windows application has the socket or COM port open, upon reconnection, the USB device will enumerate, but Windows cannot open the socket or COM port. Here is the procedure our installer app uses to revive the connection after it has gone away.

    1. Windows must close the connection, e.g. exit the application.

    2. Then, either Windows can cycle power on the USB port, or issue a USB Bus Reset, or the user can unplug and re-plug the USB device.

    After the Windows app has closed the connection and the USB device has re-enumerated, communications is restored.

    It would be nice if Windows would fix this issue. There appears to be a communications issue between the Windows USB driver and the upper COM/Socket layer. Windows USB driver sees the re-enumeration and Device Manager sees the USB device, but the upper layer is not informed of the re-enumeration so it can close the COM/socket layer. Windows USB sees the USB disconnect, but the upper layer does not see it, or just does not close the upper layer connection. When the USB reconnects, Windows has not closed the upper layer, so it cannot open another connection to the same COM/socket.

    BTW: I ported my USB stack over the HAL low-level USB physical layer. My USB stack supports composite devices which allows simultaneous multiple COM ports or RNDIS with COM ports, and it is dynamically reconfigurable. Porting looked easier than trying to extend the HAL.

    zdravko
    Associate III
    July 31, 2017
    Posted on July 31, 2017 at 13:19

    Hi,

    thank you Merle and Vangelis for your contribution. I've tried with PuTTY and after the device switches from application to bootloader comes an error ''Unable to open connection to COM2. Unable to open serial port''. In addition the teraterm is not finding COM2, though the device manager is. Interestingly this error is different from the case when the COM is occupied. The other thing is that the connection is closed i.e. the application which was talking with the stm32f105 prior the bootloader switch is closed. Even if I reopen and reclose the application the COM2 is still not visible from any other application. Only the device manager sees it. Unplug and re-plug is a solution, but it's not very convienient as there should be someone to do the manuel work. Therefore the question is how to make the windows cycle power the USB or issue USB bus reset, and can this be done from the stm32f105 side?0690X00000607i5QAA.png

    zdravko
    Associate III
    July 31, 2017
    Posted on July 31, 2017 at 13:33

    For example by using somehow the VBUS, which I'm not using right now.

    j2399
    Associate
    August 1, 2017
    Posted on August 01, 2017 at 13:21

    A manual RESET cures the problem, right?

    So you could do the RESET in software at the end of the bootloader.

    This works for me.

    In order not to get into an endless loop, at the beginning of the bootloader there is a switch, which evaluates a flag and goes either right into the application or the main bootloader. There are several predefined flags, but you could also use your own.

    See

    https://github.com/rogerclarkmelbourne/STM32duino-bootloader

     (for F103)

    https://github.com/trueserve/stm32f103-bootloader

     (for F103)

    https://github.com/j1rie/F105-bootloader/blob/master/usbdfu.c#L296

    (uses libopencm3)

    @Vangelis Fortounas: Would you show a little bit of code (especially the 'Unconfigure USB, uninitialize HW' part)?

    MDS
    Associate III
    August 1, 2017
    Posted on August 01, 2017 at 13:31

    The key to recovering the USB interface is to first close the host controller connection on the host computer. Then force the USB device to re-enumerate, by cycling power, a host issued USB bus reset, or the device toggling the D+ pull-up. If you toggle the pull-up, be sure to allow sufficient time for the host controller to see the disconnect. Windows is suppose to have some filter to prevent glitches from causing a disconnect.

    zdravko
    Associate III
    August 3, 2017
    Posted on August 03, 2017 at 11:38

    Skelton.Merle

    ‌ I just figured out that I'm not exactly sure how the OTG is controlling the pull-up resistor, and if it's configured at all. I'm just using the function USB_OTG_BSP_Init from the usb_bsp.c file and USBD_Init from the usbd_core.c all from the usb_otg library. The A11 and A12 which I'm using are configured to be GPIO_Mode_AF_PP and then remaped. After then USBD_Init I'm just saying

    DCD_DevDisconnect(&USB_OTG_dev);

    delay(100);

    DCD_DevConnect(&USB_OTG_dev);

    which is not helping. How to check and make sure that the pull-up resistor is on or off?