andysworkshop / stm32plus

The C++ library for the STM32 F0, F100, F103, F107 and F4 microcontrollers
http://www.andybrown.me.uk
Other
745 stars 224 forks source link

USB and low power modes in stm32f042 #172

Open iromero91 opened 8 years ago

iromero91 commented 8 years ago

Hi! I've been trying out this library and it's been a lot less painful than dealing with STM32Cube. Right now i'm trying to figure out how to use the UsbCustomHid class and sleep mode at the same time. I have one GPIO line sensing the VBUS voltage and i wrote code that calls UsbCustomHid::stop() when VBUS is lost, and ::start() when it comes back, but i found out that once i call stop, start stops working and i can't get the device to enumerate again. This is a device that runs on a coin cell battery and i really need to lower power consumption when USB is not being used. I thought about slowing the clock too when USB is disconnected, but i haven't figured out what's involved with that yet.

iromero91 commented 8 years ago

After much poking around i found out the USB custom hid example also has trouble with reenumeration, first time it connects fine to USB, but if i unplug and try again it fails to enumerate.

andysworkshop commented 8 years ago

Do you have a way that I can reproduce this without a self-powered device? When I modify the sample program to do this then it works as expected:

usb.start();
MillisecondTimer::delay(3000);
usb.stop();
MillisecondTimer::delay(3000);
usb.start();

There must be something else that you're doing that's resetting another part of the system. I suspect a clock somewhere, or maybe even PA11/12 losing their alternate function setting.

iromero91 commented 8 years ago

I tried toggling start and stop a few times and i couldn't observe the problem, there shouldn't be a problem with alternate functions as I'm using the qfp48 package. I tried doing a soft reconnect on the usb port (put the port in suspend mode and back) on linux i did this: (my device was identified as 6-1)

# echo 0 > /sys/bus/usb/devices/6-1/power/autosuspend_delay_ms
# echo auto > /sys/bus/usb/devices/6-1/power/control
# echo on > /sys/bus/usb/devices/6-1/power/control

The device disappeared from lsusb and the journal showed enumeration errors:

-- Logs begin at Thu 2016-05-05 00:43:49 CDT. --
May 17 15:36:25 cpz kernel: usb 6-1: USB disconnect, device number 15
May 17 15:36:26 cpz kernel: usb 6-1: new full-speed USB device number 16 using uhci_hcd
May 17 15:36:26 cpz kernel: usb 6-1: device not accepting address 16, error -32
May 17 15:36:26 cpz kernel: usb 6-1: new full-speed USB device number 17 using uhci_hcd
May 17 15:36:27 cpz kernel: usb 6-1: device not accepting address 17, error -32
May 17 15:36:27 cpz kernel: usb 6-1: new full-speed USB device number 18 using uhci_hcd
May 17 15:36:27 cpz kernel: usb 6-1: device not accepting address 18, error -32
May 17 15:36:27 cpz kernel: usb 6-1: new full-speed USB device number 19 using uhci_hcd
May 17 15:36:28 cpz kernel: usb 6-1: device not accepting address 19, error -32
May 17 15:36:28 cpz kernel: usb usb6-port1: unable to enumerate USB device

I don't know how to perform that on windows, but if you're in a PC or laptop that suspends it's ports on sleep mode you can try by putting it in sleep mode and waking the computer back up, the error will show up. I'm starting to think the library is failing to detect usb disconnect (suspend mode) after missing 3 SOF packets.

iromero91 commented 8 years ago

I've looked into it more and put some code to output the value of the USB device status, when i disconnect it i get UNEXPECTED_START_OF_FRAME, but for some reason it never reaches the STATE_SUSPENDED state, i can't figure it out, programming the same hardware with the STM32Cube HAL seems to work fine after suspension.

iromero91 commented 8 years ago

I've temporarily worked around the issue by using a sense line on vbus, which turns the USB peripheral off when the USB is unplugged. The device still fails to reenumerate after suspend but at least now i can fix it by unplugging it and plugging it back in without a reset or power cycle.

andysworkshop commented 8 years ago

I am still attempting to reproduce this on Windows without any success. So far I haven't been able to cause Windows to suspend a device using any of the SDK tools.

iromero91 commented 8 years ago

Have you tried suspending the machine and waking up? i managed to reproduce it using a windows 10 laptop.