Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

rp2: Selectively leave the USB clocks enabled in light sleep.#15111

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Conversation

projectgus
Copy link
Contributor

@projectgusprojectgus commentedMay 24, 2024
edited
Loading

Without this change going to lightsleep stops the USB peripheral clock, and can lead to either the device going into a weird state or the host deciding to issue a bus reset.

This change only keeps the USB peripheral clocks enabled if the USB device is currently active and a host has configured the device. Otherwise USB clocks are disabled same as before.

Increases power consumption in light sleep (measured at the USB port for a PICO board as 1.2-1.3mA without this change, and 3.4-3.5mA with this change). I think can argue that if you have a working active USB host connection, an extra 2mA is unlikely to be significant.

(EDIT: Above measurement was originally off by a factor of 10, corrected in comments.)

As discussed athttps://github.com/orgs/micropython/discussions/14401

Tested with

  • The code supplied in the linked discussion, viampremote run
  • mpremote a1 exec "import machine; machine.lightsleep(5000)" (plus some longer and shorter delays, up to 30 seconds).
  • Same command as above, via REPL (allows interactively sending bytes to the USB device to try and bring it back.)

Details

Logic analyser shows that without this change the USB Host continues sending SoF and other requests to the sleeping device, and it doesn't respond so every transfer is an error. On my system, the host seems to keep trying indefinitely. After waking, TinyUSB ends up in a bad state and doesn't set up any new transfers itself (i.e. the USB-CDC doesn't send any data to the host.) If using a REPL, pressing a key to send some data from the host to the device is enough to make it come back from this weird state and it seems to resume normal operations.

Behaviour seems to vary between host controllers - the discussion includes anexample of the host deciding the device is no longer responding and resetting it. I wasn't able to reproduce this here, can only guess it depends on the host controller (and/or maybe the hub controller, especially for superspeed hubs.)

With this change applied, the USB device continues to respond to host transfers and (presumably) will even complete pending endpoint transfers. All other requests are NAKed while still asleep, but the interaction with the host seems to resume correctly on wake.

Alternatives

One alternative approach would be to disconnect the USB device pins when going into lightsleep. This would cause the host to definitely see the device as disconnected, rather than ending up in the current weird in-between states. Also no increase in power usage. If we do the planned work to support transparent USB serial disconnect/reconnect in mpremote then it will probably be possible for mpremote to cleanly recover the connection on wake, also.

I also did some experiments with getting TinyUSB and the host to recover from the weird in-between state, without the host needing to initiate an OUT transfer. This obviously doesn't help for hosts which trigger a full bus reset, but might help for some hosts. I had a little unreliable success with this, but it seems flaky.

This work was funded through GitHub sponsors.

Josverl and AmirHmZz reacted with eyes emoji
@github-actionsGitHub Actions
Copy link

github-actionsbot commentedMay 24, 2024
edited
Loading

Code size report:

   bare-arm:    +0 +0.000% minimal x86:    +0 +0.000%    unix x64:    +0 +0.000% standard      stm32:    +0 +0.000% PYBV10     mimxrt:    +0 +0.000% TEENSY40        rp2:   +48 +0.014% RPI_PICO       samd:    +0 +0.000% ADAFRUIT_ITSYBITSY_M4_EXPRESS

Without this change going to lightsleep stops the USB peripheral clock, andcan lead to either the device going into a weird state or the host decidingto issue a bus reset.This change only keeps the USB peripheral clocks enabled if the USB deviceis currently active and a host has configured the device.  This means theUSB device continues to respond to host transfers and (presumably) willeven complete pending endpoint transfers.  All other requests are NAKedwhile still asleep, but the interaction with the host seems to resumecorrectly on wakeOtherwise, if USB is not active or configured by a host, USB clocks aredisabled, the same as before.With the change, one can issue a `machine.lightsleep(...)` with USB CDCconnected and the USB CDC remains connected during the sleep and resumeswhen the lightsleep finishes.Tested on a RPi Pico, the power consumption is:- During normal idle at the REPL, about 15.3mA.- During lightsleep, prior to this change, about 1.35mA.- During lightsleep, with this change and USB CDC connected, about 3.7mA.If power consumption should be as low as possible when USB is connected,one can use `machine.USBDevice` to disable the USB before enteringlightsleep.As discussed athttps://github.com/orgs/micropython/discussions/14401This work was funded through GitHub Sponsors.Signed-off-by: Angus Gratton <angus@redyak.com.au>
@dpgeorgedpgeorgeforce-pushed thefeature/rp2_usb_clocked_lightsleep branch fromd6986d6 toa84c7a0CompareJune 3, 2024 06:11
@dpgeorge
Copy link
Member

This is a really great enhancement (and very simple)! It's not very user friendly that USB resumes in a broken state after lightsleep finishes.

Tested it and it works very well.

But I think you're current measurements are a factor of 10 too high. Idle REPL consumption is about 15mA, lightsleep is about 1.35mA without this PR, and about 3.67mA with this PR. IMO that's totally acceptable, a few extra mA to keep the USB alive.

If users really need to get lower power consumption with USB connected they can usemachine.USBDevice to turn off the USB before entering lightsleep.

@dpgeorgedpgeorge merged commita84c7a0 intomicropython:masterJun 3, 2024
8 checks passed
@projectgus
Copy link
ContributorAuthor

projectgus commentedJun 3, 2024
edited
Loading

But I think you're current measurements are a factor of 10 too high. Idle REPL consumption is about 15mA, lightsleep is about 1.35mA without this PR, and about 3.67mA with this PR. IMO that's totally acceptable, a few extra mA to keep the USB alive.

Oh you're right, that does sound more reasonable! Thanks.

EDIT: Yes I quickly checked and I definitely read off the value wrong.

@projectgusprojectgus deleted the feature/rp2_usb_clocked_lightsleep branchJune 3, 2024 23:40
@mungewell
Copy link
Contributor

@projectgus
I submitted a PR which exposes all the 'sleep_en[01]' bits to userland, so that I can tell Pico to keep the PIO clocks running.
#16183

How would you feel if I replaced the 'disable_usb' parameter, and included checking 'sleep_en[]' for the appropriate bits - thus keeping USB clock running.

@projectgus
Copy link
ContributorAuthor

@mungewell Thanks for the heads-up. I will aim to get back to you on your PR soon.

@mungewell
Copy link
Contributor

they can use machine.USBDevice to turn off the USB before entering lightsleep

Can someone please explain what command I can use to turn of the USB. I have enabled (and connected to) the UART REPL, the USB is still showing connected when Ilsub on my Linux box.

Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment
Reviewers
No reviews
Assignees
No one assigned
Labels
Projects
None yet
Milestone
No milestone
Development

Successfully merging this pull request may close these issues.

3 participants
@projectgus@dpgeorge@mungewell

[8]ページ先頭

©2009-2025 Movatter.jp