/**************************************************************************//** * @brief Setup clocks necessary to drive RTC/RTCC for EXTCOM GPIO pin. * * @return N/A *****************************************************************************/ static void palClockSetup(CMU_Clock_TypeDef clock) { /* Enable LE domain registers */ CMU_ClockEnable(cmuClock_CORELE, true); #if ( defined(PAL_CLOCK_RTC) && defined(PAL_RTC_CLOCK_LFXO) ) \ || ( defined(PAL_CLOCK_RTCC) && defined(PAL_RTCC_CLOCK_LFXO) ) /* LFA with LFXO setup is relatively time consuming. Therefore, check if it already enabled before calling. */ if ( !(CMU->STATUS & CMU_STATUS_LFXOENS) ) { CMU_OscillatorEnable(cmuOsc_LFXO, true, true); } if ( cmuSelect_LFXO != CMU_ClockSelectGet(clock) ) { CMU_ClockSelectSet(clock, cmuSelect_LFXO); } #elif ( defined(PAL_CLOCK_RTC) && defined(PAL_RTC_CLOCK_LFRCO) ) \ || ( defined(PAL_CLOCK_RTCC) && defined(PAL_RTCC_CLOCK_LFRCO) ) /* Enable LF(A|E)CLK in CMU (will also enable LFRCO oscillator if not enabled) */ CMU_ClockSelectSet(clock, cmuSelect_LFRCO); #elif ( defined(PAL_CLOCK_RTC) && defined(PAL_RTC_CLOCK_ULFRCO) ) \ || ( defined(PAL_CLOCK_RTCC) && defined(PAL_RTCC_CLOCK_ULFRCO) ) /* Enable LF(A|E)CLK in CMU (will also enable ULFRCO oscillator if not enabled) */ CMU_ClockSelectSet(clock, cmuSelect_ULFRCO); #else #error No clock source for RTC defined. #endif }
/**************************************************************************//** * @brief Enables LFACLK and selects LFXO as clock source for RTC * Sets up the RTC to generate an interrupt every second. *****************************************************************************/ static void rtcSetup(unsigned int frequency) { RTC_Init_TypeDef rtcInit = RTC_INIT_DEFAULT; /* Enable LE domain registers */ if ( !( CMU->HFCORECLKEN0 & CMU_HFCORECLKEN0_LE) ) { CMU_ClockEnable(cmuClock_CORELE, true); } #ifdef PAL_RTC_CLOCK_LFXO /* LFA with LFXO setup is relatively time consuming. Therefore, check if it already enabled before calling. */ if ( !(CMU->STATUS & CMU_STATUS_LFXOENS) ) { CMU_OscillatorEnable(cmuOsc_LFXO, true, true); } if ( cmuSelect_LFXO != CMU_ClockSelectGet(cmuClock_LFA) ) { CMU_ClockSelectSet(cmuClock_LFA, cmuSelect_LFXO); } #elif defined PAL_RTC_CLOCK_LFRCO /* Enable LFACLK in CMU (will also enable LFRCO oscillator if not enabled) */ CMU_ClockSelectSet(cmuClock_LFA, cmuSelect_LFRCO); #elif defined PAL_RTC_CLOCK_ULFRCO /* Enable LFACLK in CMU (will also enable ULFRCO oscillator if not enabled) */ CMU_ClockSelectSet(cmuClock_LFA, cmuSelect_ULFRCO); #else #error No clock source for RTC defined. #endif /* Set the prescaler. */ CMU_ClockDivSet( cmuClock_RTC, cmuClkDiv_1 ); /* Enable RTC clock */ CMU_ClockEnable(cmuClock_RTC, true); /* Initialize RTC */ rtcInit.enable = false; /* Do not start RTC after initialization is complete. */ rtcInit.debugRun = false; /* Halt RTC when debugging. */ rtcInit.comp0Top = true; /* Wrap around on COMP0 match. */ RTC_Init(&rtcInit); /* Interrupt at given frequency. */ RTC_CompareSet(0, (CMU_ClockFreqGet(cmuClock_RTC) / frequency) - 1 ); /* Enable interrupt */ NVIC_EnableIRQ(RTC_IRQn); RTC_IntEnable(RTC_IEN_COMP0); /* Start Counter */ RTC_Enable(true); }
/***************************************************************************//** * @brief * Initializes USB device hardware and internal protocol stack data structures, * then connects the data-line (D+ or D-) pullup resistor to signal host that * enumeration can begin. * * @note * You may later use @ref USBD_Disconnect() and @ref USBD_Connect() to force * reenumeration. * * @param[in] p * Pointer to device initialization struct. See @ref USBD_Init_TypeDef. * * @return * @ref USB_STATUS_OK on success, else an appropriate error code. ******************************************************************************/ int USBD_Init( const USBD_Init_TypeDef *p ) { USBD_Ep_TypeDef *ep; CORE_DECLARE_IRQ_STATE; #if !defined( USB_CORECLK_HFRCO ) || !defined( CMU_OSCENCMD_USHFRCOEN ) /* Devices supporting crystal-less USB can use HFRCO or HFXO as core clock. */ /* All other devices must use HFXO as core clock. */ if ( CMU_ClockSelectGet( cmuClock_HF ) != cmuSelect_HFXO ) { CMU_ClockSelectSet( cmuClock_HF, cmuSelect_HFXO ); } #endif #if !defined( CMU_OSCENCMD_USHFRCOEN ) #if ( USB_USBC_32kHz_CLK == USB_USBC_32kHz_CLK_LFXO ) CMU_OscillatorEnable(cmuOsc_LFXO, true, false); #else CMU_OscillatorEnable(cmuOsc_LFRCO, true, false); #endif #else CMU_ClockEnable(cmuClock_CORELE, true); /* LFC clock is needed to detect USB suspend when LEMIDLE is activated. */ #if ( USB_USBC_32kHz_CLK == USB_USBC_32kHz_CLK_LFXO ) CMU_ClockSelectSet(cmuClock_LFC, cmuSelect_LFXO); #else CMU_ClockSelectSet(cmuClock_LFC, cmuSelect_LFRCO); #endif CMU_ClockEnable(cmuClock_USBLE, true); #endif USBTIMER_Init(); memset( dev, 0, sizeof( USBD_Device_TypeDef ) ); dev->setup = dev->setupPkt; dev->state = USBD_STATE_LASTMARKER; dev->savedState = USBD_STATE_NONE; dev->lastState = USBD_STATE_NONE; dev->callbacks = p->callbacks; dev->remoteWakeupEnabled = false; /* Initialize EP0 */ ep = &dev->ep[ 0 ]; ep->in = false; ep->buf = NULL; ep->num = 0; ep->mask = 1; ep->addr = 0; ep->type = USB_EPTYPE_CTRL; ep->txFifoNum = 0; /* FIXME! */ ep->packetSize = 64; dev->ep0MpsCode = _USB_DOEP0CTL_MPS_64B; ep->remaining = 0; ep->xferred = 0; ep->state = D_EP_IDLE; ep->xferCompleteCb = NULL; ep->fifoSize = ep->packetSize / 4; totalTxFifoSize = ep->fifoSize * p->bufferingMultiplier[ 0 ]; totalRxFifoSize = (ep->fifoSize + 1) * p->bufferingMultiplier[ 0 ]; /* Rx-FIFO size: SETUP packets : 4*n + 6 n=#CTRL EP's * GOTNAK : 1 * Status info : 2*n n=#OUT EP's (EP0 included) in HW */ totalRxFifoSize += 10 + 1 + ( 2 * (MAX_NUM_OUT_EPS + 1) ); CORE_ENTER_CRITICAL(); /* Enable USB clock */ CMU->HFCORECLKEN0 |= CMU_HFCORECLKEN0_USB | CMU_HFCORECLKEN0_USBC; #if defined( CMU_OSCENCMD_USHFRCOEN ) CMU->USHFRCOCONF = CMU_USHFRCOCONF_BAND_48MHZ; CMU_ClockSelectSet( cmuClock_USBC, cmuSelect_USHFRCO ); /* Enable USHFRCO Clock Recovery mode. */ CMU->USBCRCTRL |= CMU_USBCRCTRL_EN; /* Turn on Low Energy Mode (LEM) features. */ USB->CTRL = USB_CTRL_LEMOSCCTRL_GATE | USB_CTRL_LEMIDLEEN | USB_CTRL_LEMPHYCTRL; #else CMU_ClockSelectSet( cmuClock_USBC, cmuSelect_HFCLK ); #endif USBHAL_DisableGlobalInt(); if ( USBDHAL_CoreInit( totalRxFifoSize, totalTxFifoSize ) == USB_STATUS_OK ) { USBDHAL_EnableUsbResetAndSuspendInt(); USBHAL_EnableGlobalInt(); NVIC_ClearPendingIRQ( USB_IRQn ); NVIC_EnableIRQ( USB_IRQn ); } else { CORE_EXIT_CRITICAL(); DEBUG_USB_API_PUTS( "\nUSBD_Init(), FIFO setup error" ); EFM_ASSERT( false ); return USB_STATUS_ILLEGAL; } #if ( USB_PWRSAVE_MODE & USB_PWRSAVE_MODE_ONVBUSOFF ) if ( USBHAL_VbusIsOn() ) { USBD_SetUsbState( USBD_STATE_POWERED ); } else #endif { USBD_SetUsbState( USBD_STATE_NONE ); } CORE_EXIT_CRITICAL(); return USB_STATUS_OK; }
void main () { uint32_t lfa_Hz; uint16_t reset_cause; int sleep_mode = 0; uint32_t burtc_ctrl; CHIP_Init(); reset_cause = RMU->RSTCAUSE; RMU_ResetCauseClear(); #if ! defined(_EFM32_ZERO_FAMILY) BSPACM_CORE_BITBAND_PERIPH(RMU->CTRL, _RMU_CTRL_BURSTEN_SHIFT) = 0; #endif SystemCoreClockUpdate(); vBSPACMledConfigure(); setvbuf(stdout, NULL, _IONBF, 0); BSPACM_CORE_ENABLE_INTERRUPT(); printf("\n" __DATE__ " " __TIME__ "\n"); printf("System clock %lu Hz\n", SystemCoreClock); { int i = sizeof(xResetCause)/sizeof(*xResetCause); printf("Reset cause [%04x]:", reset_cause); while (0 <= --i) { const sResetCause * const rcp = xResetCause + i; if (rcp->value == (reset_cause & rcp->mask)) { printf(" %s", rcp->name); } } printf("\nRMU CTRL %lx\n", RMU->CTRL); } /* Enable low-energy support. */ CMU_ClockEnable(cmuClock_CORELE, true); BURTC_Enable(true); if (MAGIC != retained_state->magic) { memset(retained_state, 0, sizeof(*retained_state)); retained_state->magic = MAGIC; printf("Resetting retained state\n"); } ++retained_state->boots; printf("Boot count %lu\n", retained_state->boots); printf("BURTC clock source: "); #if (WITH_ULFRCO - 0) /* Use ULFRCO, which enables EM4 wakeup but is pretty inaccurate. */ printf("ULFRCO\n"); /* NB: DIV2 means 1 kHz instead of 2 kHz */ burtc_ctrl = BURTC_CTRL_CLKSEL_ULFRCO | BURTC_CTRL_PRESC_DIV2; CMU_ClockSelectSet(cmuClock_LFA, cmuSelect_ULFRCO); lfa_Hz = CMU_ClockFreqGet(cmuClock_LFA); { EMU_EM4Init_TypeDef cfg = { .lockConfig = 1, .osc = EMU_EM4CONF_OSC_ULFRCO, .buRtcWakeup = 1, .vreg = 1, }; EMU_EM4Init(&cfg); } #elif (WITH_LFRCO - 0) printf("LFRCO/32\n"); CMU_ClockSelectSet(cmuClock_LFA, cmuSelect_LFRCO); burtc_ctrl = BURTC_CTRL_CLKSEL_LFRCO | BURTC_CTRL_PRESC_DIV32; lfa_Hz = CMU_ClockFreqGet(cmuClock_LFA) / 32; #else printf("LFXO/32\n"); CMU_ClockSelectSet(cmuClock_LFA, cmuSelect_LFXO); burtc_ctrl = BURTC_CTRL_CLKSEL_LFXO | BURTC_CTRL_PRESC_DIV32; lfa_Hz = CMU_ClockFreqGet(cmuClock_LFA) / 32; #endif /* LFA source */ printf("LFA clock at %lu Hz ; wake every %u seconds\n", lfa_Hz, WAKE_INTERVAL_S); /* Initialize BURTC. */ if (! (RMU_RSTCAUSE_EM4WURST & reset_cause)) { printf("Initializing BURTC\n"); BURTC->FREEZE = BURTC_FREEZE_REGFREEZE; BURTC->LPMODE = BURTC_LPMODE_LPMODE_DISABLE; BURTC->CTRL = burtc_ctrl /* CLKSEL + PRESC */ | BURTC_CTRL_RSTEN | BURTC_CTRL_MODE_EM4EN ; BURTC->COMP0 = WAKE_INTERVAL_S * lfa_Hz; BURTC->IEN = BURTC_IF_COMP0; BURTC->CTRL &= ~BURTC_CTRL_RSTEN; BURTC->FREEZE = 0; } else { while (BURTC_SYNCBUSY_COMP0 & BURTC->SYNCBUSY) { } BURTC->COMP0 += WAKE_INTERVAL_S * lfa_Hz; } BURTC->IFC = BURTC_IFC_COMP0; NVIC_EnableIRQ(BURTC_IRQn); printf("BURTC CTRL %lx IEN %lx\n", BURTC->CTRL, BURTC->IEN); (void)iBSPACMperiphUARTflush(hBSPACMdefaultUART, eBSPACMperiphUARTfifoState_TX); while (1) { static const sBSPACMperiphUARTconfiguration cfg = { .speed_baud = 0 }; printf("Sleeping in mode %u, %lu to %lu rtc_if %x or %lx\n", sleep_mode, BURTC->CNT, BURTC->COMP0, burtc_if, BURTC->IF); BSPACM_CORE_DISABLE_INTERRUPT(); do { (void)iBSPACMperiphUARTflush(hBSPACMdefaultUART, eBSPACMperiphUARTfifoState_TX); hBSPACMperiphUARTconfigure(hBSPACMdefaultUART, 0); switch (sleep_mode) { case 0: while (! (BURTC_IF_COMP0 & BURTC->IF)) { } ++sleep_mode; break; case 1: EMU_EnterEM1(); ++sleep_mode; break; case 2: EMU_EnterEM2(true); SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk; if (cmuSelect_ULFRCO == CMU_ClockSelectGet(cmuClock_LFA)) { ++sleep_mode; } else { sleep_mode = 0; } break; case 3: EMU_EnterEM3(true); SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk; if (cmuSelect_ULFRCO == CMU_ClockSelectGet(cmuClock_LFA)) { ++sleep_mode; } else { sleep_mode = 0; } break; case 4: EMU_EnterEM4(); sleep_mode = 0; break; } } while (0); BSPACM_CORE_ENABLE_INTERRUPT(); hBSPACMperiphUARTconfigure(hBSPACMdefaultUART, &cfg); while (BURTC_SYNCBUSY_COMP0 & BURTC->SYNCBUSY) { } BURTC->COMP0 += WAKE_INTERVAL_S * lfa_Hz; /* Giant Gecko * Source EM0 EM1 EM2 EM3 EM4 * ULFRCO 2.5m 1.1m 622n 622n 450n */ } }
/***************************************************************************//** * @brief * Initializes USB device hardware and internal protocol stack data structures, * then connects the data-line (D+ or D-) pullup resistor to signal host that * enumeration can begin. * * @note * You may later use @ref USBD_Disconnect() and @ref USBD_Connect() to force * reenumeration. * * @param[in] p * Pointer to device initialization struct. See @ref USBD_Init_TypeDef. * * @return * @ref USB_STATUS_OK on success, else an appropriate error code. ******************************************************************************/ int USBD_Init( const USBD_Init_TypeDef *p ) { int numEps; USBD_Ep_TypeDef *ep; uint8_t txFifoNum; uint8_t *conf, *confEnd; USB_EndpointDescriptor_TypeDef *epd; USB_InterfaceDescriptor_TypeDef *id; uint32_t totalRxFifoSize, totalTxFifoSize, numInEps, numOutEps; #if !defined( USB_CORECLK_HFRCO ) || !defined( CMU_OSCENCMD_USHFRCOEN ) /* Devices supporting crystal-less USB can use HFRCO or HFXO as core clock. */ /* All other devices must use HFXO as core clock. */ if ( CMU_ClockSelectGet( cmuClock_HF ) != cmuSelect_HFXO ) { CMU_ClockSelectSet( cmuClock_HF, cmuSelect_HFXO ); } #endif #if !defined( CMU_OSCENCMD_USHFRCOEN ) #if ( USB_USBC_32kHz_CLK == USB_USBC_32kHz_CLK_LFXO ) CMU_OscillatorEnable(cmuOsc_LFXO, true, false); #else CMU_OscillatorEnable(cmuOsc_LFRCO, true, false); #endif #else CMU_ClockEnable(cmuClock_CORELE, true); /* LFC clock is needed to detect USB suspend when LEMIDLE is activated. */ #if ( USB_USBC_32kHz_CLK == USB_USBC_32kHz_CLK_LFXO ) CMU_ClockSelectSet(cmuClock_LFC, cmuSelect_LFXO); #else CMU_ClockSelectSet(cmuClock_LFC, cmuSelect_LFRCO); #endif CMU_ClockEnable(cmuClock_USBLE, true); #endif USBTIMER_Init(); memset( dev, 0, sizeof( USBD_Device_TypeDef ) ); dev->setup = dev->setupPkt; dev->deviceDescriptor = p->deviceDescriptor; dev->configDescriptor = (USB_ConfigurationDescriptor_TypeDef*) p->configDescriptor; dev->stringDescriptors = p->stringDescriptors; dev->numberOfStrings = p->numberOfStrings; dev->state = USBD_STATE_LASTMARKER; dev->savedState = USBD_STATE_NONE; dev->lastState = USBD_STATE_NONE; dev->callbacks = p->callbacks; dev->remoteWakeupEnabled = false; /* Initialize EP0 */ ep = &dev->ep[ 0 ]; ep->in = false; ep->buf = NULL; ep->num = 0; ep->mask = 1; ep->addr = 0; ep->type = USB_EPTYPE_CTRL; ep->txFifoNum = 0; ep->packetSize = p->deviceDescriptor->bMaxPacketSize0; if ( ep->packetSize == 32 ) { dev->ep0MpsCode = _USB_DOEP0CTL_MPS_32B; } else if ( ep->packetSize == 64 ) { dev->ep0MpsCode = _USB_DOEP0CTL_MPS_64B; } else { return USB_STATUS_ILLEGAL; } ep->remaining = 0; ep->xferred = 0; ep->state = D_EP_IDLE; ep->xferCompleteCb = NULL; ep->fifoSize = ep->packetSize / 4; totalTxFifoSize = ep->fifoSize * p->bufferingMultiplier[ 0 ]; totalRxFifoSize = (ep->fifoSize + 1) * p->bufferingMultiplier[ 0 ]; #if defined( DEBUG_USB_API ) /* Do a sanity check on the configuration descriptor */ { int i; /* Check if bLength's adds up exactly to wTotalLength */ i = 0; conf = (uint8_t*)dev->configDescriptor; confEnd = conf + dev->configDescriptor->wTotalLength; while ( conf < confEnd ) { if ( *conf == 0 ) break; i += *conf; conf += *conf; } if ( ( conf != confEnd ) || ( i != dev->configDescriptor->wTotalLength ) ) { DEBUG_USB_API_PUTS( "\nUSBD_Init(), Illegal configuration descriptor" ); EFM_ASSERT( false ); return USB_STATUS_ILLEGAL; } } #endif /* defined( DEBUG_USB_API ) */ /* Parse configuration decriptor */ numEps = 0; numInEps = 0; numOutEps = 0; conf = (uint8_t*)dev->configDescriptor; confEnd = conf + dev->configDescriptor->wTotalLength; txFifoNum = 1; while ( conf < confEnd ) { if ( *conf == 0 ) { DEBUG_USB_API_PUTS( "\nUSBD_Init(), Illegal configuration descriptor" ); EFM_ASSERT( false ); return USB_STATUS_ILLEGAL; } if ( *(conf + 1) == USB_ENDPOINT_DESCRIPTOR ) { numEps++; epd = (USB_EndpointDescriptor_TypeDef*)conf; #if defined( __GNUC__ ) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Warray-bounds" #endif ep = &dev->ep[ numEps ]; #if defined( __GNUC__ ) #pragma GCC diagnostic pop #endif ep->in = ( epd->bEndpointAddress & USB_SETUP_DIR_MASK ) != 0; ep->buf = NULL; ep->addr = epd->bEndpointAddress; ep->num = ep->addr & USB_EPNUM_MASK; ep->mask = 1 << ep->num; ep->type = epd->bmAttributes & CONFIG_DESC_BM_TRANSFERTYPE; ep->packetSize = epd->wMaxPacketSize; ep->remaining = 0; ep->xferred = 0; ep->state = D_EP_IDLE; ep->xferCompleteCb = NULL; if ( p->bufferingMultiplier[ numEps ] == 0 ) { DEBUG_USB_API_PUTS( "\nUSBD_Init(), Illegal EP fifo buffer configuration" ); EFM_ASSERT( false ); return USB_STATUS_ILLEGAL; } if ( ep->in ) { numInEps++; ep->txFifoNum = txFifoNum++; ep->fifoSize = ( ( ep->packetSize + 3 ) / 4 ) * p->bufferingMultiplier[ numEps ]; dev->inEpAddr2EpIndex[ ep->num ] = numEps; totalTxFifoSize += ep->fifoSize; if ( ep->num > MAX_NUM_IN_EPS ) { DEBUG_USB_API_PUTS( "\nUSBD_Init(), Illegal IN EP address" ); EFM_ASSERT( false ); return USB_STATUS_ILLEGAL; } } else { numOutEps++; ep->fifoSize = ( ( ( ep->packetSize + 3 ) / 4 ) + 1 ) * p->bufferingMultiplier[ numEps ]; dev->outEpAddr2EpIndex[ ep->num ] = numEps; totalRxFifoSize += ep->fifoSize; if ( ep->num > MAX_NUM_OUT_EPS ) { DEBUG_USB_API_PUTS( "\nUSBD_Init(), Illegal OUT EP address" ); EFM_ASSERT( false ); return USB_STATUS_ILLEGAL; } } } else if ( *(conf + 1) == USB_INTERFACE_DESCRIPTOR ) { id = (USB_InterfaceDescriptor_TypeDef*)conf; if ( id->bAlternateSetting == 0 ) // Only check default interfaces { if ( dev->numberOfInterfaces != id->bInterfaceNumber ) { DEBUG_USB_API_PUTS( "\nUSBD_Init(), Illegal interface number" ); EFM_ASSERT( false ); return USB_STATUS_ILLEGAL; } dev->numberOfInterfaces++; } } conf += *conf; } /* Rx-FIFO size: SETUP packets : 4*n + 6 n=#CTRL EP's * GOTNAK : 1 * Status info : 2*n n=#OUT EP's (EP0 included) in HW */ totalRxFifoSize += 10 + 1 + ( 2 * (MAX_NUM_OUT_EPS + 1) ); if ( dev->configDescriptor->bNumInterfaces != dev->numberOfInterfaces ) { DEBUG_USB_API_PUTS( "\nUSBD_Init(), Illegal interface count" ); EFM_ASSERT( false ); return USB_STATUS_ILLEGAL; } if ( numEps != NUM_EP_USED ) { DEBUG_USB_API_PUTS( "\nUSBD_Init(), Illegal EP count" ); EFM_ASSERT( false ); return USB_STATUS_ILLEGAL; } if ( numInEps > MAX_NUM_IN_EPS ) { DEBUG_USB_API_PUTS( "\nUSBD_Init(), Illegal IN EP count" ); EFM_ASSERT( false ); return USB_STATUS_ILLEGAL; } if ( numOutEps > MAX_NUM_OUT_EPS ) { DEBUG_USB_API_PUTS( "\nUSBD_Init(), Illegal OUT EP count" ); EFM_ASSERT( false ); return USB_STATUS_ILLEGAL; } INT_Disable(); /* Enable USB clock */ CMU->HFCORECLKEN0 |= CMU_HFCORECLKEN0_USB | CMU_HFCORECLKEN0_USBC; #if defined( CMU_OSCENCMD_USHFRCOEN ) CMU->USHFRCOCONF = CMU_USHFRCOCONF_BAND_48MHZ; CMU_ClockSelectSet( cmuClock_USBC, cmuSelect_USHFRCO ); /* Enable USHFRCO Clock Recovery mode. */ CMU->USBCRCTRL |= CMU_USBCRCTRL_EN; /* Turn on Low Energy Mode (LEM) features. */ USB->CTRL = USB_CTRL_LEMOSCCTRL_GATE | USB_CTRL_LEMIDLEEN | USB_CTRL_LEMPHYCTRL; #else CMU_ClockSelectSet( cmuClock_USBC, cmuSelect_HFCLK ); #endif USBHAL_DisableGlobalInt(); if ( USBDHAL_CoreInit( totalRxFifoSize, totalTxFifoSize ) == USB_STATUS_OK ) { USBDHAL_EnableUsbResetAndSuspendInt(); USBHAL_EnableGlobalInt(); NVIC_ClearPendingIRQ( USB_IRQn ); NVIC_EnableIRQ( USB_IRQn ); } else { INT_Enable(); DEBUG_USB_API_PUTS( "\nUSBD_Init(), FIFO setup error" ); EFM_ASSERT( false ); return USB_STATUS_ILLEGAL; } #if ( USB_PWRSAVE_MODE & USB_PWRSAVE_MODE_ONVBUSOFF ) if ( USBHAL_VbusIsOn() ) { USBD_SetUsbState( USBD_STATE_POWERED ); } else #endif { USBD_SetUsbState( USBD_STATE_NONE ); } INT_Enable(); return USB_STATUS_OK; }