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 delaymaster
parent
85079d6a2e
commit
9a4618b05b
|
@ -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)
|
* sets the maximum power (in mA) over USB for the device (default: 500)
|
||||||
* `#define USB_POLLING_INTERVAL_MS 10`
|
* `#define USB_POLLING_INTERVAL_MS 10`
|
||||||
* sets the USB polling rate in milliseconds for the keyboard, mouse, and shared (NKRO/media keys) interfaces
|
* 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`
|
* `#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`.
|
* 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`.
|
||||||
|
|
||||||
|
|
|
@ -102,7 +102,6 @@ static void power_down(uint8_t wdto) {
|
||||||
# if defined(RGBLIGHT_SLEEP) && defined(RGBLIGHT_ENABLE)
|
# if defined(RGBLIGHT_SLEEP) && defined(RGBLIGHT_ENABLE)
|
||||||
rgblight_suspend();
|
rgblight_suspend();
|
||||||
# endif
|
# endif
|
||||||
suspend_power_down_kb();
|
|
||||||
|
|
||||||
// TODO: more power saving
|
// TODO: more power saving
|
||||||
// See PicoPower application note
|
// See PicoPower application note
|
||||||
|
|
|
@ -12,3 +12,7 @@ void suspend_wakeup_init_user(void);
|
||||||
void suspend_wakeup_init_kb(void);
|
void suspend_wakeup_init_kb(void);
|
||||||
void suspend_power_down_user(void);
|
void suspend_power_down_user(void);
|
||||||
void suspend_power_down_kb(void);
|
void suspend_power_down_kb(void);
|
||||||
|
|
||||||
|
#ifndef USB_SUSPEND_WAKEUP_DELAY
|
||||||
|
# define USB_SUSPEND_WAKEUP_DELAY 200
|
||||||
|
#endif
|
||||||
|
|
|
@ -708,6 +708,17 @@ void init_usb_driver(USBDriver *usbp) {
|
||||||
void restart_usb_driver(USBDriver *usbp) {
|
void restart_usb_driver(USBDriver *usbp) {
|
||||||
usbStop(usbp);
|
usbStop(usbp);
|
||||||
usbDisconnectBus(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);
|
usbStart(usbp, &usbcfg);
|
||||||
usbConnectBus(usbp);
|
usbConnectBus(usbp);
|
||||||
}
|
}
|
||||||
|
|
|
@ -435,7 +435,9 @@ void EVENT_USB_Device_Suspend() {
|
||||||
*/
|
*/
|
||||||
void EVENT_USB_Device_WakeUp() {
|
void EVENT_USB_Device_WakeUp() {
|
||||||
print("[W]");
|
print("[W]");
|
||||||
|
#if defined(NO_USB_STARTUP_CHECK)
|
||||||
suspend_wakeup_init();
|
suspend_wakeup_init();
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef SLEEP_LED_ENABLE
|
#ifdef SLEEP_LED_ENABLE
|
||||||
sleep_led_disable();
|
sleep_led_disable();
|
||||||
|
@ -1073,12 +1075,26 @@ int main(void) {
|
||||||
print("Keyboard start.\n");
|
print("Keyboard start.\n");
|
||||||
while (1) {
|
while (1) {
|
||||||
#if !defined(NO_USB_STARTUP_CHECK)
|
#if !defined(NO_USB_STARTUP_CHECK)
|
||||||
while (USB_DeviceState == DEVICE_STATE_Suspended) {
|
if (USB_DeviceState == DEVICE_STATE_Suspended) {
|
||||||
print("[s]");
|
print("[s]");
|
||||||
suspend_power_down();
|
while (USB_DeviceState == DEVICE_STATE_Suspended) {
|
||||||
if (USB_Device_RemoteWakeupEnabled && suspend_wakeup_condition()) {
|
suspend_power_down();
|
||||||
USB_Device_SendRemoteWakeup();
|
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
|
#endif
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue