circuitpython: NRF: USB Disconnect / Reconnect / Enumeration fails during sleep

With the most recent patches, issuing time.sleep(x) issues a wfi instruction. This aggressively puts the CPU to sleep. However, this appears to cause USB to no longer enumerate. While this is not an issue with a device that’s powered off of USB, if a device has its own battery, then this will prevent the device from enumerating during sleep.

Steps to reproduce

The following code.py should trigger this bug:

from time import sleep
sleep(60)

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 16 (4 by maintainers)

Commits related to this issue

Most upvoted comments

WFI does work fine if interrupts are enabled, but without disabling interrupts you can never be sure that there isn’t pending data before issuing WFI For example:

sleep_until_time:
       ; ... do some prep involving the RTC
       bl         usb_background
       wfi

usb_background:
       ; ... service USB buffers
       bx lr

Even though usb_background() drains the buffer, you still could have an interrupt arrive between the bx lr and the wfi instruction. If interrupts are enabled, then that will get serviced and there will be data waiting in the queue. If that is a packet from the host, then you will go to sleep without responding to that packet and the host will time out the device.

The solution is to disable interrupts, flush buffers, and issue wfi. If there’s a pending interrupt it will return immediately, allowing you to re-enable interrupts and have it serviced.