Browse Source

Address wake from sleep instability (#11450)

* resolve race condition between suspend and wake in LUFA

* avoid multiple calls to suspend_power_down() / suspend_wakeup_init()

* Remove duplicate suspend_power_down_kb() call

* pause on wakeup to wait for USB state to settle

* need the repeated suspend_power_down() (that's where the sleep is)

* more efficient implementation

* fine tune the pause after sending wakeup

* speculative chibios version of pause-after-wake

* make wakeup delay configurable, and adjust value

* better location for wakeup delay
pull/11793/head
Joshua Diamond 3 years ago
committed by GitHub
parent
commit
9a4618b05b
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 37 additions and 5 deletions
  1. +2
    -0
      docs/config_options.md
  2. +0
    -1
      tmk_core/common/avr/suspend.c
  3. +4
    -0
      tmk_core/common/suspend.h
  4. +11
    -0
      tmk_core/protocol/chibios/usb_main.c
  5. +20
    -4
      tmk_core/protocol/lufa/lufa.c

+ 2
- 0
docs/config_options.md View File

@ -97,6 +97,8 @@ This is a C header file that is one of the first things included, and will persi
* sets the maximum power (in mA) over USB for the device (default: 500)
* `#define USB_POLLING_INTERVAL_MS 10`
* sets the USB polling rate in milliseconds for the keyboard, mouse, and shared (NKRO/media keys) interfaces
* `#define USB_SUSPEND_WAKEUP_DELAY 200`
* set the number of milliseconde to pause after sending a wakeup packet
* `#define F_SCL 100000L`
* sets the I2C clock rate speed for keyboards using I2C. The default is `400000L`, except for keyboards using `split_common`, where the default is `100000L`.


+ 0
- 1
tmk_core/common/avr/suspend.c View File

@ -102,7 +102,6 @@ static void power_down(uint8_t wdto) {
# if defined(RGBLIGHT_SLEEP) && defined(RGBLIGHT_ENABLE)
rgblight_suspend();
# endif
suspend_power_down_kb();
// TODO: more power saving
// See PicoPower application note


+ 4
- 0
tmk_core/common/suspend.h View File

@ -12,3 +12,7 @@ void suspend_wakeup_init_user(void);
void suspend_wakeup_init_kb(void);
void suspend_power_down_user(void);
void suspend_power_down_kb(void);
#ifndef USB_SUSPEND_WAKEUP_DELAY
# define USB_SUSPEND_WAKEUP_DELAY 200
#endif

+ 11
- 0
tmk_core/protocol/chibios/usb_main.c View File

@ -708,6 +708,17 @@ void init_usb_driver(USBDriver *usbp) {
void restart_usb_driver(USBDriver *usbp) {
usbStop(usbp);
usbDisconnectBus(usbp);
#if USB_SUSPEND_WAKEUP_DELAY > 0
// Some hubs, kvm switches, and monitors do
// weird things, with USB device state bouncing
// around wildly on wakeup, yielding race
// conditions that can corrupt the keyboard state.
//
// Pause for a while to let things settle...
wait_ms(USB_SUSPEND_WAKEUP_DELAY);
#endif
usbStart(usbp, &usbcfg);
usbConnectBus(usbp);
}


+ 20
- 4
tmk_core/protocol/lufa/lufa.c View File

@ -435,7 +435,9 @@ void EVENT_USB_Device_Suspend() {
*/
void EVENT_USB_Device_WakeUp() {
print("[W]");
#if defined(NO_USB_STARTUP_CHECK)
suspend_wakeup_init();
#endif
#ifdef SLEEP_LED_ENABLE
sleep_led_disable();
@ -1073,12 +1075,26 @@ int main(void) {
print("Keyboard start.\n");
while (1) {
#if !defined(NO_USB_STARTUP_CHECK)
while (USB_DeviceState == DEVICE_STATE_Suspended) {
if (USB_DeviceState == DEVICE_STATE_Suspended) {
print("[s]");
suspend_power_down();
if (USB_Device_RemoteWakeupEnabled && suspend_wakeup_condition()) {
USB_Device_SendRemoteWakeup();
while (USB_DeviceState == DEVICE_STATE_Suspended) {
suspend_power_down();
if (USB_Device_RemoteWakeupEnabled && suspend_wakeup_condition()) {
USB_Device_SendRemoteWakeup();
clear_keyboard();
# if USB_SUSPEND_WAKEUP_DELAY > 0
// Some hubs, kvm switches, and monitors do
// weird things, with USB device state bouncing
// around wildly on wakeup, yielding race
// conditions that can corrupt the keyboard state.
//
// Pause for a while to let things settle...
wait_ms(USB_SUSPEND_WAKEUP_DELAY);
# endif
}
}
suspend_wakeup_init();
}
#endif


Loading…
Cancel
Save