dektronics / printalyzer-densitometer

Reflection and Transmission Densitometer for Photographic Darkroom Use
19 stars 4 forks source link

Implement support for USB suspend/resume #31

Closed dkonigsberg closed 2 years ago

dkonigsberg commented 2 years ago

Overview

USB devices are supposed to support a "suspend" mode, where their power consumption drops to under 2.5mA.

Preliminary testing, as described in #29, showed that normal power consumption is around 20-120mA. However, shutting off all the peripherals and suspending the CPU will drop this to almost 0.5mA which is well within the suspend mode power budget.

Ideally, a device acting as a USB peripheral should be able to handle suspend, resume, and optionally remote wakeup of the host. Since being connected to a laptop that may suspend itself is an expected (albeit secondary) use case, suspend and resume should be correctly supported. Remote wakeup could also be implemented, but is less necessary or expected.

While the STM32L0 hardware does have the necessary support for implementing this, the TinyUSB device stack does not have a functional implementation in the STM32 port.

There is some brief documentation in Section 31.5.5 of RM0376 about how USB suspend mode is handled from the perspective of the USB peripheral.

Also, the HID_Standalone_LPM example looks like it could be a useful reference for handling this case.

Development/Test Rig

In order to test these modes directly, the most practical approach is a rig consisting of the following components:

  1. Laptop with USB 2.0 (EHCI ports, running the USB-IF Compliance Tools, which provide a direct way to stimulate various port behaviors. This is best kept as a dedicated machine, which does not depend on the USB controller used for its ports to run its local keyboard and mouse.
  2. USB 2.0 hub connected to the laptop, to ensure that the laptop using an EHCI driver for its USB port regardless of how our device would otherwise show up. ("USB 2.0 Full-Speed" is kinda a marketing rename of USB 1.1, and such will bind to a UHCI device without this trick.)
  3. USB power and/or protocol analyzer, to make it easy to see when USB traffic should indicate a state change and to directly monitor device current consumption in response to it. (This could be anything from a USB current monitor to a full-blown special-purpose test device.)
  4. The actual device-under-test, a Printalyzer Densitometer prototype, connected to the development workstation via a debug probe.

Implementation Notes

Since TinyUSB does not depend on HAL components for controlling the USB peripheral, some investigation will be needed to ensure that the code enables whatever device features get turned out when the following boxes are checked in CubeMX:

Some tracing through normal behaviors with HAL, the ST USB device stack, and the above-mentioned example, will be necessary to determine what changes must be made to the application code and/or TinyUSB's STM32 port to make all of this work.

Since suspend could be requested at any moment, there needs to be a way to trigger a "stop and drop everything" behavior for the application's main state machine so that all peripheral hardware can be turned off prior to suspending the CPU. Resume will be coming from a more known state, but could easily have its own share of issues.

One important gotcha is that we still need to deal with the watchdog timer (IWDG) when in suspend mode. For development, it probably makes sense to simply turn this off inside the bootloader. However, once working like this, we need to come up with a way of managing it without being disabled.