From e284aabd95ed57307dcf72dc94c163fbe23f4769 Mon Sep 17 00:00:00 2001 From: Stefan Kerkmann Date: Wed, 22 Feb 2023 18:23:52 +0100 Subject: [PATCH] RP2040: fix host remote wakeup Previously a device which attempted to wake a sleeping host would not be notified about the resumed operation and thus stay suspended for ever. This is due to the fact that only a host initiated wakeup would trigger a interrupt. As a workaround we use the SOF interrupt which is enabled for a short amount of time to detect the resume of the bus and wakeup the device. --- os/hal/ports/RP/LLD/USBDv1/hal_usb_lld.c | 19 ++++++++++++++----- os/hal/ports/RP/LLD/USBDv1/hal_usb_lld.h | 12 ++++-------- .../RP2040/RT-RP2040-PICO-ADC/cfg/mcuconf.h | 1 - .../RP2040/RT-RP2040-PICO-HID/cfg/mcuconf.h | 1 - .../RT-RP2040-PICO-I2C-24AA01/cfg/mcuconf.h | 1 - .../RT-RP2040-PICO-SERIAL/cfg/mcuconf.h | 1 - 6 files changed, 18 insertions(+), 17 deletions(-) diff --git a/os/hal/ports/RP/LLD/USBDv1/hal_usb_lld.c b/os/hal/ports/RP/LLD/USBDv1/hal_usb_lld.c index 5512dbbdb8..7a2b8cbaaa 100644 --- a/os/hal/ports/RP/LLD/USBDv1/hal_usb_lld.c +++ b/os/hal/ports/RP/LLD/USBDv1/hal_usb_lld.c @@ -426,15 +426,22 @@ OSAL_IRQ_HANDLER(RP_USBCTRL_IRQ_HANDLER) { _usb_wakeup(usbp); } -#if RP_USB_USE_SOF_INTR == TRUE /* SOF handling.*/ if (ints & USB_INTS_DEV_SOF) { + /* SOF interrupt was used to detect resume of the USB bus after issuing a + * remote wake up of the host, therefore we disable it again. */ + if (usbp->config->sof_cb == NULL) { + USB->INTE &= ~USB_INTE_DEV_SOF; + } + if (usbp->state == USB_SUSPENDED) { + _usb_wakeup(usbp); + } + _usb_isr_invoke_sof_cb(usbp); /* Clear SOF flag by reading SOF_RD */ (void)USB->SOFRD; } -#endif /* RP_USB_USE_SOF_INTR */ /* Endpoint events handling.*/ if (ints & USB_INTS_BUFF_STATUS) { @@ -534,12 +541,14 @@ void usb_lld_start(USBDriver *usbp) { USB_INTE_DEV_SUSPEND | USB_INTE_BUS_RESET | USB_INTE_BUFF_STATUS; + + if (usbp->config->sof_cb != NULL) { + USB->INTE |= USB_INTE_DEV_SOF; + } + #if RP_USB_USE_ERROR_DATA_SEQ_INTR == TRUE USB->INTE |= USB_INTE_ERROR_DATA_SEQ; #endif /* RP_USB_USE_ERROR_DATA_SEQ_INTR */ -#if RP_USB_USE_SOF_INTR == TRUE - USB->INTE |= USB_INTE_DEV_SOF; -#endif /* RP_USB_USE_SOF_INTR */ /* Enable USB interrupt. */ nvicEnableVector(RP_USBCTRL_IRQ_NUMBER, RP_IRQ_USB0_PRIORITY); diff --git a/os/hal/ports/RP/LLD/USBDv1/hal_usb_lld.h b/os/hal/ports/RP/LLD/USBDv1/hal_usb_lld.h index aafe541b56..21d365d19d 100644 --- a/os/hal/ports/RP/LLD/USBDv1/hal_usb_lld.h +++ b/os/hal/ports/RP/LLD/USBDv1/hal_usb_lld.h @@ -6,7 +6,7 @@ You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - + Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -88,13 +88,6 @@ extern bool usb_vbus_detect(void); #endif -/** - * @brief Enables the SOF interrupt. - */ -#if !defined(RP_USB_USE_SOF_INTR) || defined(__DOXYGEN__) -#define RP_USB_USE_SOF_INTR FALSE -#endif - /** * @brief Enables the error data sequence interrupt. * @details This flag is useful if you develop low level driver. @@ -438,6 +431,9 @@ struct USBDriver { */ #define usb_lld_wakeup_host(usbp) \ do { \ + /* remote wakeup doesn't trigger the wakeup interrupt, therefore \ + * we use the SOF interrupt to detect resume of the bus. */ \ + USB->INTE |= USB_INTE_DEV_SOF; \ USB->SET.SIECTRL = USB_SIE_CTRL_RESUME; \ } while (false) diff --git a/testhal/RP/RP2040/RT-RP2040-PICO-ADC/cfg/mcuconf.h b/testhal/RP/RP2040/RT-RP2040-PICO-ADC/cfg/mcuconf.h index 4cfec7ad35..154bd4414f 100644 --- a/testhal/RP/RP2040/RT-RP2040-PICO-ADC/cfg/mcuconf.h +++ b/testhal/RP/RP2040/RT-RP2040-PICO-ADC/cfg/mcuconf.h @@ -90,7 +90,6 @@ #define RP_USB_USE_USBD1 FALSE #define RP_USB_FORCE_VBUS_DETECT TRUE #define RP_USE_EXTERNAL_VBUS_DETECT FALSE -#define RP_USB_USE_SOF_INTR TRUE #define RP_USB_USE_ERROR_DATA_SEQ_INTR TRUE /* diff --git a/testhal/RP/RP2040/RT-RP2040-PICO-HID/cfg/mcuconf.h b/testhal/RP/RP2040/RT-RP2040-PICO-HID/cfg/mcuconf.h index e45ac55914..996b78c17e 100644 --- a/testhal/RP/RP2040/RT-RP2040-PICO-HID/cfg/mcuconf.h +++ b/testhal/RP/RP2040/RT-RP2040-PICO-HID/cfg/mcuconf.h @@ -90,7 +90,6 @@ #define RP_USB_USE_USBD0 TRUE #define RP_USB_FORCE_VBUS_DETECT TRUE #define RP_USE_EXTERNAL_VBUS_DETECT FALSE -#define RP_USB_USE_SOF_INTR FALSE #define RP_USB_USE_ERROR_DATA_SEQ_INTR TRUE #endif /* MCUCONF_H */ diff --git a/testhal/RP/RP2040/RT-RP2040-PICO-I2C-24AA01/cfg/mcuconf.h b/testhal/RP/RP2040/RT-RP2040-PICO-I2C-24AA01/cfg/mcuconf.h index 928ebc8183..18b329f447 100644 --- a/testhal/RP/RP2040/RT-RP2040-PICO-I2C-24AA01/cfg/mcuconf.h +++ b/testhal/RP/RP2040/RT-RP2040-PICO-I2C-24AA01/cfg/mcuconf.h @@ -92,7 +92,6 @@ #define RP_USB_USE_USBD1 FALSE #define RP_USB_FORCE_VBUS_DETECT TRUE #define RP_USE_EXTERNAL_VBUS_DETECT FALSE -#define RP_USB_USE_SOF_INTR TRUE #define RP_USB_USE_ERROR_DATA_SEQ_INTR TRUE /* diff --git a/testhal/RP/RP2040/RT-RP2040-PICO-SERIAL/cfg/mcuconf.h b/testhal/RP/RP2040/RT-RP2040-PICO-SERIAL/cfg/mcuconf.h index 62f546c6b1..996b78c17e 100644 --- a/testhal/RP/RP2040/RT-RP2040-PICO-SERIAL/cfg/mcuconf.h +++ b/testhal/RP/RP2040/RT-RP2040-PICO-SERIAL/cfg/mcuconf.h @@ -90,7 +90,6 @@ #define RP_USB_USE_USBD0 TRUE #define RP_USB_FORCE_VBUS_DETECT TRUE #define RP_USE_EXTERNAL_VBUS_DETECT FALSE -#define RP_USB_USE_SOF_INTR TRUE #define RP_USB_USE_ERROR_DATA_SEQ_INTR TRUE #endif /* MCUCONF_H */