キーボードの長押しに対応。
Fork of USBDevice by
Diff: USBDevice/TARGET_Silicon_Labs/src/em_usbdint.c
- Revision:
- 71:53949e6131f6
- Parent:
- 70:2c525a50f1b6
--- a/USBDevice/TARGET_Silicon_Labs/src/em_usbdint.c Thu Jul 20 10:14:36 2017 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,946 +0,0 @@ -/**************************************************************************//** - * @file em_usbdint.c - * @brief USB protocol stack library, USB device peripheral interrupt handlers. - * @version 3.20.14 - ****************************************************************************** - * @section License - * <b>(C) Copyright 2014 Silicon Labs, http://www.silabs.com</b> - ******************************************************************************* - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * 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. - * See the License for the specific language governing permissions and - * limitations under the License. - * - ******************************************************************************/ - -#include "em_device.h" -#if defined( USB_PRESENT ) && ( USB_COUNT == 1 ) -#include "em_usb.h" -#if defined( USB_DEVICE ) - -#include "em_cmu.h" -#include "em_usbtypes.h" -#include "em_usbhal.h" -#include "em_usbd.h" - -#ifdef __MBED__ -extern void usbhal_allow_em2(bool em2_allow); -#endif - -/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */ - -#define HANDLE_INT( x ) if ( status & x ) { Handle_##x(); status &= ~x; } - -static void Handle_USB_GINTSTS_ENUMDONE ( void ); -static void Handle_USB_GINTSTS_IEPINT ( void ); -static void Handle_USB_GINTSTS_OEPINT ( void ); -static void Handle_USB_GINTSTS_RESETDET ( void ); -static void Handle_USB_GINTSTS_SOF ( void ); -static void Handle_USB_GINTSTS_USBRST ( void ); -static void Handle_USB_GINTSTS_USBSUSP ( void ); -static void Handle_USB_GINTSTS_WKUPINT ( void ); -#if defined( USB_DOEP0INT_STUPPKTRCVD ) -static void HandleOutEpIntr( uint32_t status, USBD_Ep_TypeDef *ep ); -#else -static void ProcessSetup ( void ); -static void ProcessOepData ( USBD_Ep_TypeDef *ep ); -#endif - -#if ( USB_PWRSAVE_MODE ) -/* Variables and prototypes for USB powerdown (suspend) functionality. */ -static bool UsbPowerDown( void ); -static bool UsbPowerUp( void ); - -volatile bool USBD_poweredDown = false; - -/* Storage for backing up USB core registers. */ -static uint32_t x_USB_GINTMSK; -#if defined(_USB_GOTGCTL_MASK) -static uint32_t x_USB_GOTGCTL; -#endif -static uint32_t x_USB_GAHBCFG; -static uint32_t x_USB_GUSBCFG; -static uint32_t x_USB_GRXFSIZ; -static uint32_t x_USB_GNPTXFSIZ; -static uint32_t x_USB_DCFG; -static uint32_t x_USB_DCTL; -static uint32_t x_USB_DAINTMSK; -static uint32_t x_USB_DIEPMSK; -static uint32_t x_USB_DOEPMSK; -static uint32_t x_USB_PCGCCTL; - -#if ( NUM_EP_USED > 0 ) -static uint32_t x_USB_EP_CTL[ NUM_EP_USED ]; -static uint32_t x_USB_EP_TSIZ[ NUM_EP_USED ]; -static uint32_t x_USB_EP_DMAADDR[ NUM_EP_USED ]; -#endif - -#if ( NUM_EP_USED > MAX_NUM_TX_FIFOS ) -#define FIFO_CNT MAX_NUM_TX_FIFOS -#else -#define FIFO_CNT NUM_EP_USED -#endif - -#if ( FIFO_CNT > 0 ) -static uint32_t x_USB_DIEPTXFS[ FIFO_CNT ]; -#endif - -#if ( USB_PWRSAVE_MODE ) -static uint32_t cmuStatus = 0; -#endif - -#endif /* if ( USB_PWRSAVE_MODE ) */ - -/* - * USB_IRQHandler() is the first level handler for the USB peripheral interrupt. - */ -void USB_IRQHandler( void ) -{ - uint32_t status; - bool servedVbusInterrupt = false; - - INT_Disable(); - -#if ( USB_PWRSAVE_MODE ) - if ( USBD_poweredDown ) - { - /* Switch USBC clock from 32kHz to a 48MHz clock to be able to */ - /* read USB peripheral registers. */ - /* If we woke up from EM2, HFCLK is now HFRCO. */ - - /* Restore clock oscillators.*/ -#if defined( CMU_OSCENCMD_USHFRCOEN ) - if ( ( CMU->STATUS & CMU_STATUS_USHFRCOENS ) == 0 )/*Wakeup from EM2 ?*/ - { - CMU->OSCENCMD = ( cmuStatus - & ( CMU_STATUS_AUXHFRCOENS | CMU_STATUS_HFXOENS ) ) - | CMU_OSCENCMD_USHFRCOEN; - } -#else - if ( ( CMU->STATUS & CMU_STATUS_HFXOENS ) == 0 ) /* Wakeup from EM2 ? */ - { - CMU->OSCENCMD = cmuStatus - & ( CMU_STATUS_AUXHFRCOENS | CMU_STATUS_HFXOENS ); - } -#endif - - /* Select correct USBC clock.*/ -#if defined( CMU_OSCENCMD_USHFRCOEN ) - CMU->CMD = CMU_CMD_USBCCLKSEL_USHFRCO; - while ( ( CMU->STATUS & CMU_STATUS_USBCUSHFRCOSEL ) == 0 ){} -#else - CMU->CMD = CMU_CMD_USBCCLKSEL_HFCLKNODIV; - while ( ( CMU->STATUS & CMU_STATUS_USBCHFCLKSEL ) == 0 ){} -#endif - } -#endif /* if ( USB_PWRSAVE_MODE ) */ - - if ( USB->IF && ( USB->CTRL & USB_CTRL_VREGOSEN ) ) - { - if ( USB->IF & USB_IF_VREGOSH ) - { - USB->IFC = USB_IFC_VREGOSH; - - if ( USB->STATUS & USB_STATUS_VREGOS ) - { - servedVbusInterrupt = true; - DEBUG_USB_INT_LO_PUTS( "\nVboN" ); - -#if ( USB_PWRSAVE_MODE ) - if ( UsbPowerUp() ) - { - USBDHAL_EnableUsbResetAndSuspendInt(); - } - USBD_SetUsbState( USBD_STATE_POWERED ); -#endif - } - } - - if ( USB->IF & USB_IF_VREGOSL ) - { - USB->IFC = USB_IFC_VREGOSL; - - if ( ( USB->STATUS & USB_STATUS_VREGOS ) == 0 ) - { - servedVbusInterrupt = true; - DEBUG_USB_INT_LO_PUTS( "\nVboF" ); - -#if ( USB_PWRSAVE_MODE ) -#if ( USB_PWRSAVE_MODE & USB_PWRSAVE_MODE_ONVBUSOFF ) - if ( !USBD_poweredDown ) - { - USB->GINTMSK = 0; - USB->GINTSTS = 0xFFFFFFFF; - } - - UsbPowerDown(); -#endif - USBD_SetUsbState( USBD_STATE_NONE ); -#endif - } - } - } - - status = USBHAL_GetCoreInts(); - if ( status == 0 ) - { - INT_Enable(); - if ( !servedVbusInterrupt ) - { - DEBUG_USB_INT_LO_PUTS( "\nSinT" ); - } - return; - } - - HANDLE_INT( USB_GINTSTS_RESETDET ) - HANDLE_INT( USB_GINTSTS_WKUPINT ) - HANDLE_INT( USB_GINTSTS_USBSUSP ) - HANDLE_INT( USB_GINTSTS_SOF ) - HANDLE_INT( USB_GINTSTS_ENUMDONE ) - HANDLE_INT( USB_GINTSTS_USBRST ) - HANDLE_INT( USB_GINTSTS_IEPINT ) - HANDLE_INT( USB_GINTSTS_OEPINT ) - - INT_Enable(); - - if ( status != 0 ) - { - DEBUG_USB_INT_LO_PUTS( "\nUinT" ); - } -} - -/* - * Handle port enumeration interrupt. This has nothing to do with normal - * device enumeration. - */ -static void Handle_USB_GINTSTS_ENUMDONE( void ) -{ -#if ( USB_PWRSAVE_MODE ) - UsbPowerUp(); -#endif - - USBDHAL_Ep0Activate( dev->ep0MpsCode ); - dev->ep[ 0 ].state = D_EP_IDLE; - USBDHAL_EnableInts( dev ); - DEBUG_USB_INT_LO_PUTS( "EnumD" ); -} - -/* - * Handle IN endpoint transfer interrupt. - */ -static void Handle_USB_GINTSTS_IEPINT( void ) -{ - int epnum; - uint16_t epint; - uint16_t epmask; - uint32_t status; - USBD_Ep_TypeDef *ep; - - DEBUG_USB_INT_HI_PUTCHAR( 'i' ); - - epint = USBDHAL_GetAllInEpInts(); - for ( epnum = 0, epmask = 1; - epnum <= MAX_NUM_IN_EPS; - epnum++, epmask <<= 1 ) - { - if ( epint & epmask ) - { - ep = USBD_GetEpFromAddr( USB_SETUP_DIR_MASK | epnum ); - status = USBDHAL_GetInEpInts( ep ); - - if ( status & USB_DIEP_INT_XFERCOMPL ) - { - USB_DINEPS[ epnum ].INT = USB_DIEP_INT_XFERCOMPL; - - DEBUG_USB_INT_HI_PUTCHAR( 'c' ); - - if ( epnum == 0 ) - { - if ( ep->remaining > ep->packetSize ) - { - ep->remaining -= ep->packetSize; - ep->xferred += ep->packetSize; - } - else - { - ep->xferred += ep->remaining; - ep->remaining = 0; - } - USBDEP_Ep0Handler( dev ); - } - else - { - ep->xferred = ep->remaining - - ( ( USB_DINEPS[ epnum ].TSIZ & - _USB_DIEP_TSIZ_XFERSIZE_MASK ) >> - _USB_DIEP_TSIZ_XFERSIZE_SHIFT ); - ep->remaining -= ep->xferred; - - USBDEP_EpHandler( ep->addr ); -#if defined( USB_DOEP0INT_STUPPKTRCVD ) - if ( USB_DINEPS[ ep->num ].INT & USB_DIEP_INT_NAKINTRPT ) - { - USB_DINEPS[ ep->num ].INT = USB_DIEP_INT_NAKINTRPT; - } -#endif - } - } - } - } -} - -/* - * Handle OUT endpoint transfer interrupt. - */ -static void Handle_USB_GINTSTS_OEPINT( void ) -{ - int epnum; - uint16_t epint; - uint16_t epmask; - uint32_t status; - USBD_Ep_TypeDef *ep; - - DEBUG_USB_INT_HI_PUTCHAR( 'o' ); - - epint = USBDHAL_GetAllOutEpInts(); - for ( epnum = 0, epmask = 1; - epnum <= MAX_NUM_OUT_EPS; - epnum++, epmask <<= 1 ) - { - if ( epint & epmask ) - { - ep = USBD_GetEpFromAddr( epnum ); - status = USBDHAL_GetOutEpInts( ep ); - -#if defined( USB_DOEP0INT_STUPPKTRCVD ) - HandleOutEpIntr( status, ep ); -#else - if ( status & USB_DOEP_INT_XFERCOMPL ) - { - USB_DOUTEPS[ epnum ].INT = USB_DOEP_INT_XFERCOMPL; - DEBUG_USB_INT_HI_PUTCHAR( 'c' ); - ProcessOepData( ep ); - } - - /* Setup Phase Done */ - if ( status & USB_DOEP0INT_SETUP ) - { - ProcessSetup(); - } -#endif - } - } -} - -#if !defined( USB_DOEP0INT_STUPPKTRCVD ) -static void ProcessOepData( USBD_Ep_TypeDef *ep ) -{ - if ( ep->num == 0 ) - { - -#ifdef __MBED__ - int xfer_size = ep->packetSize - (( USB->DOEP0TSIZ & _USB_DOEP0TSIZ_XFERSIZE_MASK ) - >> _USB_DOEP0TSIZ_XFERSIZE_SHIFT); - int setup_pkt_received = USBDHAL_GetOutEpInts( ep ) & USB_DOEP0INT_SETUP; - - if ( (!setup_pkt_received && xfer_size == 0) || - (setup_pkt_received && xfer_size == 8) ) - { - /* Higher levels need to see the correct transfer amount for ZLPs */ - ep->remaining = 0; - ep->xferred = 0; - } - else - { - /* FIXME - does not work if actual read size > 56 */ - if ( setup_pkt_received ) xfer_size -= 8; - - ep->xferred = xfer_size; - ep->remaining -= xfer_size; - } -#else - if ( ep->remaining > ep->packetSize ) - { - ep->remaining -= ep->packetSize; - ep->xferred += ep->packetSize; - } - else - { - ep->xferred += ep->remaining; - ep->remaining = 0; - } -#endif - - USBDEP_Ep0Handler( dev ); - } - else - { - ep->xferred = ep->hwXferSize - - ( ( USB_DOUTEPS[ ep->num ].TSIZ & _USB_DOEP_TSIZ_XFERSIZE_MASK )>> - _USB_DOEP_TSIZ_XFERSIZE_SHIFT ); - ep->remaining -= ep->xferred; - USBDEP_EpHandler( ep->addr ); - } -} -#endif - -#if !defined( USB_DOEP0INT_STUPPKTRCVD ) -static void ProcessSetup( void ) -{ - DEBUG_USB_INT_LO_PUTS( "\nS" ); - - if ( USB->DOEP0INT & USB_DOEP0INT_BACK2BACKSETUP ) - { /* Back to back setup packets received */ - USB->DOEP0INT = USB_DOEP0INT_BACK2BACKSETUP; - DEBUG_USB_INT_LO_PUTS( "B2B" ); - - dev->setup = (USB_Setup_TypeDef*)( USB->DOEP0DMAADDR - USB_SETUP_PKT_SIZE ); - } - else - { - /* Read SETUP packet counter from hw. */ - int supCnt = ( USB->DOEP0TSIZ & _USB_DOEP0TSIZ_SUPCNT_MASK ) - >> _USB_DOEP0TSIZ_SUPCNT_SHIFT; - - if ( supCnt == 3 ) - supCnt = 2; - - dev->setup = &dev->setupPkt[ 2 - supCnt ]; - } - USB->DOEP0TSIZ |= 3 << _USB_DOEP0TSIZ_SUPCNT_SHIFT; - USB->DOEP0DMAADDR = (uint32_t)dev->setupPkt; - USB->DOEP0INT = USB_DOEP0INT_SETUP; - - USBDEP_Ep0Handler( dev ); /* Call the SETUP handler for EP0 */ -} -#endif - -/* - * Handle USB reset detected interrupt in suspend mode. - */ -static void Handle_USB_GINTSTS_RESETDET ( void ) -{ -#if ( USB_PWRSAVE_MODE ) - if ( ! USBD_poweredDown ) - { - USB->GINTSTS = USB_GINTSTS_RESETDET; - } - - if ( UsbPowerUp() ) - { - USB->GINTSTS = USB_GINTSTS_RESETDET; - } - -#if ( USB_PWRSAVE_MODE & USB_PWRSAVE_MODE_ONVBUSOFF ) - /* Power down immediately if VBUS is off. */ - if ( ! ( USB->STATUS & USB_STATUS_VREGOS ) ) - { - UsbPowerDown(); - } -#endif - -#else - USB->GINTSTS = USB_GINTSTS_RESETDET; -#endif /* if ( USB_PWRSAVE_MODE ) */ - - if ( USB->STATUS & USB_STATUS_VREGOS ) - { - USBD_SetUsbState( USBD_STATE_DEFAULT ); - } - else - { - USBD_SetUsbState( USBD_STATE_NONE ); - } - DEBUG_USB_INT_LO_PUTS( "RsuP\n" ); -} - -/* - * Handle Start Of Frame (SOF) interrupt. - */ -static void Handle_USB_GINTSTS_SOF( void ) -{ - USB->GINTSTS = USB_GINTSTS_SOF; - - if ( dev->callbacks->sofInt ) - { - dev->callbacks->sofInt( - ( USB->DSTS & _USB_DSTS_SOFFN_MASK ) >> _USB_DSTS_SOFFN_SHIFT ); - } -} - -/* - * Handle USB port reset interrupt. - */ -static void Handle_USB_GINTSTS_USBRST( void ) -{ - int i; - - DEBUG_USB_INT_LO_PUTS( "ReseT" ); - - /* Clear Remote Wakeup Signalling */ - USB->DCTL &= ~( DCTL_WO_BITMASK | USB_DCTL_RMTWKUPSIG ); - USBHAL_FlushTxFifo( 0 ); - - /* Clear pending interrupts */ - for ( i = 0; i <= MAX_NUM_IN_EPS; i++ ) - { - USB_DINEPS[ i ].INT = 0xFFFFFFFF; - } - - for ( i = 0; i <= MAX_NUM_OUT_EPS; i++ ) - { - USB_DOUTEPS[ i ].INT = 0xFFFFFFFF; - } - - USB->DAINTMSK = USB_DAINTMSK_INEPMSK0 | USB_DAINTMSK_OUTEPMSK0; -#if defined( USB_DOEPMSK_STSPHSERCVDMSK ) - USB->DOEPMSK = USB_DOEPMSK_SETUPMSK | USB_DOEPMSK_XFERCOMPLMSK - | USB_DOEPMSK_STSPHSERCVDMSK; -#else - USB->DOEPMSK = USB_DOEPMSK_SETUPMSK | USB_DOEPMSK_XFERCOMPLMSK; -#endif - USB->DIEPMSK = USB_DIEPMSK_XFERCOMPLMSK; - - /* Reset Device Address */ - USB->DCFG &= ~_USB_DCFG_DEVADDR_MASK; - - /* Setup EP0 to receive SETUP packets */ - USBDHAL_StartEp0Setup( dev ); - USBDHAL_EnableInts( dev ); - - if ( dev->callbacks->usbReset ) - { - dev->callbacks->usbReset(); - } - - USBD_SetUsbState( USBD_STATE_DEFAULT ); - USBDHAL_AbortAllTransfers( USB_STATUS_DEVICE_RESET ); -} - -/* - * Handle USB port suspend interrupt. - */ -static void Handle_USB_GINTSTS_USBSUSP( void ) -{ - USBD_State_TypeDef state; - - USB->GINTSTS = USB_GINTSTS_USBSUSP; - USBDHAL_AbortAllTransfers( USB_STATUS_DEVICE_SUSPENDED ); - DEBUG_USB_INT_LO_PUTS( "\nSusP" ); - - if ( USBD_GetUsbState() == USBD_STATE_NONE ) - { - USBD_SetUsbState( USBD_STATE_POWERED ); - } - - state = USBD_GetUsbState(); - if ( ( state == USBD_STATE_POWERED ) || - ( state == USBD_STATE_DEFAULT ) || - ( state == USBD_STATE_ADDRESSED ) || - ( state == USBD_STATE_CONFIGURED ) ) - { -#if ( USB_PWRSAVE_MODE ) - UsbPowerDown(); -#endif - USBD_SetUsbState( USBD_STATE_SUSPENDED ); - } -} - -/* - * Handle USB port wakeup interrupt. - */ -static void Handle_USB_GINTSTS_WKUPINT( void ) -{ -#if ( USB_PWRSAVE_MODE ) - if ( ! USBD_poweredDown ) - { - USB->GINTSTS = USB_GINTSTS_WKUPINT; - } - - if ( UsbPowerUp() ) - { - USB->GINTSTS = USB_GINTSTS_WKUPINT; - USBDHAL_StartEp0Setup( dev ); - USBDHAL_Ep0Activate( dev->ep0MpsCode ); - } -#else - USB->GINTSTS = USB_GINTSTS_WKUPINT; -#endif - - USBD_SetUsbState( dev->savedState ); - DEBUG_USB_INT_LO_PUTS( "WkuP\n" ); -} - -#if ( USB_PWRSAVE_MODE ) -/* - * Backup essential USB core registers, and set the core in partial powerdown - * mode. Optionally prepare entry into EM2. - */ -static bool UsbPowerDown( void ) -{ -#if ( NUM_EP_USED > 0 ) || ( FIFO_CNT > 0 ) - int i; -#endif -#if ( NUM_EP_USED > 0 ) - int epNum; - USBD_Ep_TypeDef *ep; -#endif - - if ( !USBD_poweredDown ) - { - USBD_poweredDown = true; - DEBUG_USB_INT_LO_PUTCHAR( '\\' ); - - /* Backup USB core registers. */ - x_USB_GINTMSK = USB->GINTMSK; -#if defined(_USB_GOTGCTL_MASK) - x_USB_GOTGCTL = USB->GOTGCTL; -#endif - x_USB_GAHBCFG = USB->GAHBCFG; - x_USB_GUSBCFG = USB->GUSBCFG; - x_USB_GRXFSIZ = USB->GRXFSIZ; - x_USB_GNPTXFSIZ = USB->GNPTXFSIZ; - x_USB_DCFG = USB->DCFG; - x_USB_DCTL = USB->DCTL; - x_USB_DAINTMSK = USB->DAINTMSK; - x_USB_DIEPMSK = USB->DIEPMSK; - x_USB_DOEPMSK = USB->DOEPMSK; - x_USB_PCGCCTL = USB->PCGCCTL; - -#if ( NUM_EP_USED > 0 ) - for ( i = 0; i < NUM_EP_USED; i++ ) - { - ep = &dev->ep[ i+1 ]; - epNum = ep->num; - if ( ep->in ) - { - x_USB_EP_CTL[ i ] = USB_DINEPS[ epNum ].CTL; - x_USB_EP_TSIZ[ i ] = USB_DINEPS[ epNum ].TSIZ; - x_USB_EP_DMAADDR[ i ] = USB_DINEPS[ epNum ].DMAADDR; - } - else - { - x_USB_EP_CTL[ i ] = USB_DOUTEPS[ epNum ].CTL; - x_USB_EP_TSIZ[ i ] = USB_DOUTEPS[ epNum ].TSIZ; - x_USB_EP_DMAADDR[ i ] = USB_DOUTEPS[ epNum ].DMAADDR; - } - } -#endif - -#if ( FIFO_CNT > 0 ) - for ( i = 0; i < FIFO_CNT; i++ ) - { - x_USB_DIEPTXFS[ i ] = USB_DIEPTXFS[ i ]; - } -#endif - - /* Prepare for wakeup on resume and reset. */ - USB->DCFG = (USB->DCFG & ~_USB_DCFG_RESVALID_MASK) | - (4 << _USB_DCFG_RESVALID_SHIFT); - USB->DCFG |= USB_DCFG_ENA32KHZSUSP; - USB->GINTMSK = USB_GINTMSK_RESETDETMSK | USB_GINTMSK_WKUPINTMSK; - - /* Enter partial powerdown mode. */ - USB->PCGCCTL |= USB_PCGCCTL_PWRCLMP; - USB->PCGCCTL |= USB_PCGCCTL_RSTPDWNMODULE; - USB->PCGCCTL |= USB_PCGCCTL_STOPPCLK; - - /* Record current clock settings. */ - cmuStatus = CMU->STATUS; - -#if ( USB_PWRSAVE_MODE & USB_PWRSAVE_MODE_ENTEREM2 ) -#ifndef __MBED__ - /* Enter EM2 on interrupt exit. */ - SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk | SCB_SCR_SLEEPONEXIT_Msk; -#else - usbhal_allow_em2(true); -#endif -#endif - - /* Switch USBC clock to 32 kHz. */ -#if ( USB_USBC_32kHz_CLK == USB_USBC_32kHz_CLK_LFXO ) - CMU->CMD = CMU_CMD_USBCCLKSEL_LFXO; - while ( ( CMU->STATUS & CMU_STATUS_USBCLFXOSEL ) == 0 ){} -#else - CMU->CMD = CMU_CMD_USBCCLKSEL_LFRCO; - while ( ( CMU->STATUS & CMU_STATUS_USBCLFRCOSEL ) == 0 ){} -#endif - - return true; - } - return false; -} -#endif /* if ( USB_PWRSAVE_MODE ) */ - -#if ( USB_PWRSAVE_MODE ) -/* - * Exit USB core partial powerdown mode, restore essential USB core registers. - * Will prevent re-entry back to EM2. - * Returns true if a powerup sequence was performed. - */ -static bool UsbPowerUp( void ) -{ -#if ( NUM_EP_USED > 0 ) || ( FIFO_CNT > 0 ) - int i; -#endif -#if ( NUM_EP_USED > 0 ) - int epNum; - uint32_t tmp; - USBD_Ep_TypeDef *ep; -#endif - - if ( USBD_poweredDown ) - { - USBD_poweredDown = false; - DEBUG_USB_INT_LO_PUTCHAR( '/' ); - -#if !defined( USB_CORECLK_HFRCO ) || !defined( CMU_OSCENCMD_USHFRCOEN ) - /* Switch HFCLK from HFRCO to HFXO. */ - CMU_ClockSelectSet( cmuClock_HF, cmuSelect_HFXO ); -#endif - - /* Turn off HFRCO when not needed. */ - if ( ( cmuStatus & CMU_STATUS_HFRCOENS ) == 0 ) - { - CMU->OSCENCMD = CMU_OSCENCMD_HFRCODIS; - } - - /* Exit partial powerdown mode. */ - USB->PCGCCTL &= ~USB_PCGCCTL_STOPPCLK; - USB->PCGCCTL &= ~(USB_PCGCCTL_PWRCLMP | USB_PCGCCTL_RSTPDWNMODULE); - - if (( USB->GINTSTS & ( USB_GINTSTS_WKUPINT | USB_GINTSTS_RESETDET ) ) == 0) - { - USB->DCTL = x_USB_DCTL | USB_DCTL_RMTWKUPSIG; - USB->DCTL = x_USB_DCTL; - } - - /* Restore USB core registers. */ - USB->GUSBCFG = x_USB_GUSBCFG; - USB->DCFG = x_USB_DCFG; - -#if ( FIFO_CNT > 0 ) - for ( i = 0; i < FIFO_CNT; i++ ) - { - USB_DIEPTXFS[ i ] = x_USB_DIEPTXFS[ i ]; - } -#endif - -#if ( NUM_EP_USED > 0 ) - for ( i = 0; i < NUM_EP_USED; i++ ) - { - ep = &dev->ep[ i+1 ]; - epNum = ep->num; - - tmp = x_USB_EP_CTL[ i ] & - ~( USB_DIEP_CTL_CNAK | USB_DIEP_CTL_SNAK | - USB_DIEP_CTL_SETD0PIDEF | USB_DIEP_CTL_SETD1PIDOF ); - - if ( x_USB_EP_CTL[ i ] & USB_DIEP_CTL_DPIDEOF ) - tmp |= USB_DIEP_CTL_SETD1PIDOF; - else - tmp |= USB_DIEP_CTL_SETD0PIDEF; - - if ( x_USB_EP_CTL[ i ] & USB_DIEP_CTL_NAKSTS ) - tmp |= USB_DIEP_CTL_SNAK; - else - tmp |= USB_DIEP_CTL_CNAK; - - if ( ep->in ) - { - USB_DINEPS[ epNum ].CTL = tmp; - USB_DINEPS[ epNum ].TSIZ = x_USB_EP_TSIZ[ i ]; - USB_DINEPS[ epNum ].DMAADDR = x_USB_EP_DMAADDR[ i ]; - } - else - { - USB_DOUTEPS[ epNum ].CTL = tmp; - USB_DOUTEPS[ epNum ].TSIZ = x_USB_EP_TSIZ[ i ]; - USB_DOUTEPS[ epNum ].DMAADDR = x_USB_EP_DMAADDR[ i ]; - } - } -#endif - - USB->PCGCCTL = x_USB_PCGCCTL; - USB->DOEPMSK = x_USB_DOEPMSK; - USB->DIEPMSK = x_USB_DIEPMSK; - USB->DAINTMSK = x_USB_DAINTMSK; - USB->DCTL = x_USB_DCTL; - USB->GNPTXFSIZ = x_USB_GNPTXFSIZ; - USB->GRXFSIZ = x_USB_GRXFSIZ; - USB->GAHBCFG = x_USB_GAHBCFG; -#if defined(_USB_GOTGCTL_MASK) - USB->GOTGCTL = x_USB_GOTGCTL; -#endif - USB->GINTMSK = x_USB_GINTMSK; - - USB->DCTL |= USB_DCTL_PWRONPRGDONE; - -#if ( USB_PWRSAVE_MODE & USB_PWRSAVE_MODE_ENTEREM2 ) -#ifndef __MBED__ - /* Do not reenter EM2 on interrupt exit. */ - SCB->SCR &= ~(SCB_SCR_SLEEPDEEP_Msk | SCB_SCR_SLEEPONEXIT_Msk); -#else - usbhal_allow_em2(false); -#endif -#endif - - return true; - } - return false; -} -#endif /* if ( USB_PWRSAVE_MODE ) */ - -#if defined( USB_DOEP0INT_STUPPKTRCVD ) -static void HandleOutEpIntr( uint32_t status, USBD_Ep_TypeDef *ep ) -{ - uint32_t doeptsiz; - - if ( ep->num == 0 ) - { - if ( status & USB_DOEP0INT_XFERCOMPL ) - { - USB->DOEP0INT = USB_DOEP0INT_XFERCOMPL; - doeptsiz = USB->DOEP0TSIZ; - - if ( ep->state == D_EP_IDLE ) - { - if ( status & USB_DOEP0INT_STUPPKTRCVD ) - { - USB->DOEP0INT = USB_DOEP0INT_STUPPKTRCVD; - } - status = USBDHAL_GetOutEpInts( ep ); - doeptsiz = USB->DOEP0TSIZ; - - if ( status & USB_DOEP0INT_SETUP ) - { -retry: - /* Already started data stage, clear setup */ - USB->DOEP0INT = USB_DOEP0INT_SETUP; - status &= ~USB_DOEP0INT_SETUP; - { - int supCnt = ( doeptsiz & _USB_DOEP0TSIZ_SUPCNT_MASK ) - >> _USB_DOEP0TSIZ_SUPCNT_SHIFT; - - if ( supCnt == 3 ) - supCnt = 2; - - dev->setup = &dev->setupPkt[ 2 - supCnt ]; - } - DEBUG_USB_INT_LO_PUTS( "\nS" ); - USBDEP_Ep0Handler( dev ); - - /* Prepare for more setup packets */ - if ( ep->state == D_EP0_IN_STATUS || ep->state == D_EP_TRANSMITTING ) - { - USBDHAL_StartEp0Setup( dev ); - } - } - else /* xfercompl && idle && !setup */ - { - status = USBDHAL_GetOutEpInts( ep ); - if ( status & USB_DOEP0INT_SETUP ) - goto retry; - USBDHAL_StartEp0Setup( dev ); - } - } - else /* ep0state != EP0_IDLE */ - { -#ifdef __MBED__ - if ( ep->state == D_EP_RECEIVING ) - { - int xfer_size = ep->packetSize - (( USB->DOEP0TSIZ & _USB_DOEP0TSIZ_XFERSIZE_MASK ) - >> _USB_DOEP0TSIZ_XFERSIZE_SHIFT); - int setup_pkt_received = status & USB_DOEP0INT_SETUP; - - if ( (!setup_pkt_received && xfer_size == 0) || - (setup_pkt_received && xfer_size == 8) ) - { - /* Higher levels need to see the correct transfer amount for ZLPs */ - ep->remaining = 0; - ep->xferred = 0; - } - else - { - /* FIXME - does not work if actual read size > 56 */ - if ( setup_pkt_received ) xfer_size -= 8; - - ep->xferred = xfer_size; - ep->remaining -= xfer_size; - } - - USBDEP_Ep0Handler( dev ); - } -#else - if ( ep->state == D_EP_RECEIVING ) - { - if ( ep->remaining > ep->packetSize ) - { - ep->remaining -= ep->packetSize; - ep->xferred += ep->packetSize; - } - else - { - ep->xferred += ep->remaining; - ep->remaining = 0; - } - USBDEP_Ep0Handler( dev ); - } - else if ( ep->state == D_EP0_OUT_STATUS ) - { - USBDEP_Ep0Handler( dev ); - } -#endif - } - } /* if ( status & USB_DOEP0INT_XFERCOMPL ) */ - - if ( status & USB_DOEP0INT_STSPHSERCVD ) - { - USB->DOEP0INT = USB_DOEP0INT_STSPHSERCVD; - } - - if ( status & USB_DOEP0INT_SETUP ) - { - USB->DOEP0INT = USB_DOEP0INT_SETUP; - { - int supCnt = ( USB->DOEP0TSIZ & _USB_DOEP0TSIZ_SUPCNT_MASK ) - >> _USB_DOEP0TSIZ_SUPCNT_SHIFT; - - if ( supCnt == 3 ) - supCnt = 2; - - dev->setup = &dev->setupPkt[ 2 - supCnt ]; - } - DEBUG_USB_INT_LO_PUTS( "\nS" ); - USBDEP_Ep0Handler( dev ); - } - } - else /* epnum != 0 */ - { - if ( status & USB_DOEP_INT_XFERCOMPL ) - { - USB_DOUTEPS[ ep->num ].INT = USB_DOEP_INT_XFERCOMPL; - - ep->xferred = ep->hwXferSize - - ( ( USB_DOUTEPS[ ep->num ].TSIZ & _USB_DOEP_TSIZ_XFERSIZE_MASK )>> - _USB_DOEP_TSIZ_XFERSIZE_SHIFT ); - ep->remaining -= ep->xferred; - - USBDEP_EpHandler( ep->addr ); - } - } -} -#endif - -/** @endcond */ - -#endif /* defined( USB_DEVICE ) */ -#endif /* defined( USB_PRESENT ) && ( USB_COUNT == 1 ) */