diff --git a/os/hal/ports/SN32/LLD/SN32F2xx/USB/hal_usb_lld.c b/os/hal/ports/SN32/LLD/SN32F2xx/USB/hal_usb_lld.c index d9e2a7d386..cb6f91c7f1 100644 --- a/os/hal/ports/SN32/LLD/SN32F2xx/USB/hal_usb_lld.c +++ b/os/hal/ports/SN32/LLD/SN32F2xx/USB/hal_usb_lld.c @@ -208,10 +208,8 @@ static void sn32_usb_write_fifo(usbep_t ep, const uint8_t *buf, size_t sz, bool static void usb_lld_serve_interrupt(USBDriver *usbp) { uint32_t iwIntFlag; - /* Get Interrupt Status and clear immediately. */ + /* Get Interrupt Status */ iwIntFlag = SN32_USB->INSTS; - /* Keep only PRESETUP & ERR_SETUP flags. */ - SN32_USB->INSTSC = ~(mskEP0_PRESETUP | mskERR_SETUP); if (iwIntFlag == 0) { //@20160902 add for EMC protection @@ -292,7 +290,15 @@ static void usb_lld_serve_interrupt(USBDriver *usbp) { ///////////////////////////////////////////////// /* Device Status Interrupt (SOF) */ ///////////////////////////////////////////////// - if ((iwIntFlag & mskUSB_SOF) && (SN32_USB->INTEN & mskUSB_SOF_IE)) { + if (iwIntFlag & mskUSB_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) { + SN32_USB->INTEN &= ~mskUSB_SOF_IE; + } + if (usbp->state == USB_SUSPENDED) { + _usb_wakeup(usbp); + } /* SOF */ _usb_isr_invoke_sof_cb(usbp); SN32_USB->INSTSC = (mskUSB_SOF); @@ -458,6 +464,16 @@ void usb_lld_start(USBDriver *usbp) { #endif /* SN32_USB_USE_USB1 == TRUE */ /* Reset procedure enforced on driver start.*/ usb_lld_reset(usbp); + + /* Enable other interrupts.*/ + SN32_USB->INTEN |= (mskUSB_IE|mskEPnACK_EN|mskBUSWK_IE); + if (usbp->config->sof_cb != NULL) { + SN32_USB->INTEN |= mskUSB_SOF_IE; + } + //SN32_USB->INTEN |= (mskEP1_NAK_EN|mskEP2_NAK_EN|mskEP3_NAK_EN|mskEP4_NAK_EN); +#if (USB_ENDPOINTS_NUMBER > 4) + //SN32_USB->INTEN |= (mskEP5_NAK_EN|mskEP6_NAK_EN); +#endif /* (USB_ENDPOINTS_NUMBER > 4) */ } } @@ -502,14 +518,6 @@ void usb_lld_reset(USBDriver *usbp) { /* EP0 initialization.*/ usbp->epc[0] = &ep0config; usb_lld_init_endpoint(usbp, 0); - - /* Enable other interrupts.*/ - SN32_USB->INTEN |= (mskUSB_IE|mskEPnACK_EN|mskBUSWK_IE|mskUSB_SOF_IE); - //SN32_USB->INTEN |= (mskEP1_NAK_EN|mskEP2_NAK_EN|mskEP3_NAK_EN|mskEP4_NAK_EN); -#if (USB_ENDPOINTS_NUMBER > 4) - //SN32_USB->INTEN |= (mskEP5_NAK_EN|mskEP6_NAK_EN); -#endif /* (USB_ENDPOINTS_NUMBER > 4) */ - } /** diff --git a/os/hal/ports/SN32/LLD/SN32F2xx/USB/hal_usb_lld.h b/os/hal/ports/SN32/LLD/SN32F2xx/USB/hal_usb_lld.h index a114f1237e..5226c8f923 100644 --- a/os/hal/ports/SN32/LLD/SN32F2xx/USB/hal_usb_lld.h +++ b/os/hal/ports/SN32/LLD/SN32F2xx/USB/hal_usb_lld.h @@ -390,6 +390,9 @@ struct USBDriver { #define usb_lld_wakeup_host(usbp) \ do { \ SN32_USB->SGCTL = (mskBUS_DRVEN|mskBUS_K_STATE); \ + /* remote wakeup doesn't trigger the wakeup interrupt, therefore \ + * we use the SOF interrupt to detect resume of the bus. */ \ + SN32_USB->INTEN |= mskUSB_SOF_IE; \ osalThreadSleepMilliseconds(SN32_USB_HOST_WAKEUP_DURATION); \ SN32_USB->SGCTL &= ~mskBUS_DRVEN; \ } while (false)