EFM32 Giant Gecko Software Documentation  efm32gg-doc-4.2.1
em_usbdint.c
Go to the documentation of this file.
1 /**************************************************************************/
16 #include "em_device.h"
17 #if defined( USB_PRESENT ) && ( USB_COUNT == 1 )
18 #include "em_usb.h"
19 #if defined( USB_DEVICE )
20 
21 #include "em_cmu.h"
22 #include "em_usbtypes.h"
23 #include "em_usbhal.h"
24 #include "em_usbd.h"
25 
28 #define HANDLE_INT( x ) if ( status & x ) { Handle_##x(); status &= ~x; }
29 
30 static void Handle_USB_GINTSTS_ENUMDONE ( void );
31 static void Handle_USB_GINTSTS_IEPINT ( void );
32 static void Handle_USB_GINTSTS_OEPINT ( void );
33 static void Handle_USB_GINTSTS_RESETDET ( void );
34 static void Handle_USB_GINTSTS_SOF ( void );
35 static void Handle_USB_GINTSTS_USBRST ( void );
36 static void Handle_USB_GINTSTS_USBSUSP ( void );
37 static void Handle_USB_GINTSTS_WKUPINT ( void );
38 #if defined( USB_DOEP0INT_STUPPKTRCVD )
39 static void HandleOutEpIntr( uint32_t status, USBD_Ep_TypeDef *ep );
40 #else
41 static void ProcessSetup ( void );
42 static void ProcessOepData ( USBD_Ep_TypeDef *ep );
43 #endif
44 
45 #if ( USB_PWRSAVE_MODE )
46 /* Variables and prototypes for USB powerdown (suspend) functionality. */
47 static bool UsbPowerDown( void );
48 static bool UsbPowerUp( void );
49 
50 volatile bool USBD_poweredDown = false;
51 
52 /* Storage for backing up USB core registers. */
53 static uint32_t x_USB_GINTMSK;
54 #if defined(_USB_GOTGCTL_MASK)
55 static uint32_t x_USB_GOTGCTL;
56 #endif
57 static uint32_t x_USB_GAHBCFG;
58 static uint32_t x_USB_GUSBCFG;
59 static uint32_t x_USB_GRXFSIZ;
60 static uint32_t x_USB_GNPTXFSIZ;
61 static uint32_t x_USB_DCFG;
62 static uint32_t x_USB_DCTL;
63 static uint32_t x_USB_DAINTMSK;
64 static uint32_t x_USB_DIEPMSK;
65 static uint32_t x_USB_DOEPMSK;
66 static uint32_t x_USB_PCGCCTL;
67 
68 #if ( NUM_EP_USED > 0 )
69 static uint32_t x_USB_EP_CTL[ NUM_EP_USED ];
70 static uint32_t x_USB_EP_TSIZ[ NUM_EP_USED ];
71 static uint32_t x_USB_EP_DMAADDR[ NUM_EP_USED ];
72 #endif
73 
74 #if ( NUM_EP_USED > MAX_NUM_TX_FIFOS )
75 #define FIFO_CNT MAX_NUM_TX_FIFOS
76 #else
77 #define FIFO_CNT NUM_EP_USED
78 #endif
79 
80 #if ( FIFO_CNT > 0 )
81 static uint32_t x_USB_DIEPTXFS[ FIFO_CNT ];
82 #endif
83 
84 #if ( USB_PWRSAVE_MODE )
85 static uint32_t cmuStatus = 0;
86 #endif
87 
88 #endif /* if ( USB_PWRSAVE_MODE ) */
89 
90 /*
91  * USB_IRQHandler() is the first level handler for the USB peripheral interrupt.
92  */
93 void USB_IRQHandler( void )
94 {
95  uint32_t status;
96  bool servedVbusInterrupt = false;
97 
98  INT_Disable();
99 
100 #if ( USB_PWRSAVE_MODE )
101  if ( USBD_poweredDown )
102  {
103  /* Switch USBC clock from 32kHz to a 48MHz clock to be able to */
104  /* read USB peripheral registers. */
105  /* If we woke up from EM2, HFCLK is now HFRCO. */
106 
107  /* Restore clock oscillators.*/
108 #if defined( CMU_OSCENCMD_USHFRCOEN )
109  if ( ( CMU->STATUS & CMU_STATUS_USHFRCOENS ) == 0 )/*Wakeup from EM2 ?*/
110  {
111  CMU->OSCENCMD = ( cmuStatus
113  | CMU_OSCENCMD_USHFRCOEN;
114  }
115 #else
116  if ( ( CMU->STATUS & CMU_STATUS_HFXOENS ) == 0 ) /* Wakeup from EM2 ? */
117  {
118  CMU->OSCENCMD = cmuStatus
120  }
121 #endif
122 
123  /* Select correct USBC clock.*/
124 #if defined( CMU_OSCENCMD_USHFRCOEN )
125  CMU->CMD = CMU_CMD_USBCCLKSEL_USHFRCO;
126  while ( ( CMU->STATUS & CMU_STATUS_USBCUSHFRCOSEL ) == 0 ){}
127 #else
129  while ( ( CMU->STATUS & CMU_STATUS_USBCHFCLKSEL ) == 0 ){}
130 #endif
131  }
132 #endif /* if ( USB_PWRSAVE_MODE ) */
133 
134  if ( USB->IF && ( USB->CTRL & USB_CTRL_VREGOSEN ) )
135  {
136  if ( USB->IF & USB_IF_VREGOSH )
137  {
138  USB->IFC = USB_IFC_VREGOSH;
139 
140  if ( USB->STATUS & USB_STATUS_VREGOS )
141  {
142  servedVbusInterrupt = true;
143  DEBUG_USB_INT_LO_PUTS( "\nVboN" );
144 
145 #if ( USB_PWRSAVE_MODE )
146  if ( UsbPowerUp() )
147  {
148  USBDHAL_EnableUsbResetAndSuspendInt();
149  }
150  USBD_SetUsbState( USBD_STATE_POWERED );
151 #endif
152  }
153  }
154 
155  if ( USB->IF & USB_IF_VREGOSL )
156  {
157  USB->IFC = USB_IFC_VREGOSL;
158 
159  if ( ( USB->STATUS & USB_STATUS_VREGOS ) == 0 )
160  {
161  servedVbusInterrupt = true;
162  DEBUG_USB_INT_LO_PUTS( "\nVboF" );
163 
164 #if ( USB_PWRSAVE_MODE )
165 #if ( USB_PWRSAVE_MODE & USB_PWRSAVE_MODE_ONVBUSOFF )
166  if ( !USBD_poweredDown )
167  {
168  USB->GINTMSK = 0;
169  USB->GINTSTS = 0xFFFFFFFF;
170  }
171 
172  UsbPowerDown();
173 #endif
174  USBD_SetUsbState( USBD_STATE_NONE );
175 #endif
176  }
177  }
178  }
179 
180  status = USBHAL_GetCoreInts();
181  if ( status == 0 )
182  {
183  INT_Enable();
184  if ( !servedVbusInterrupt )
185  {
186  DEBUG_USB_INT_LO_PUTS( "\nSinT" );
187  }
188  return;
189  }
190 
191  HANDLE_INT( USB_GINTSTS_RESETDET )
192  HANDLE_INT( USB_GINTSTS_WKUPINT )
193  HANDLE_INT( USB_GINTSTS_USBSUSP )
194  HANDLE_INT( USB_GINTSTS_SOF )
195  HANDLE_INT( USB_GINTSTS_ENUMDONE )
196  HANDLE_INT( USB_GINTSTS_USBRST )
197  HANDLE_INT( USB_GINTSTS_IEPINT )
198  HANDLE_INT( USB_GINTSTS_OEPINT )
199 
200  INT_Enable();
201 
202  if ( status != 0 )
203  {
204  DEBUG_USB_INT_LO_PUTS( "\nUinT" );
205  }
206 }
207 
208 /*
209  * Handle port enumeration interrupt. This has nothing to do with normal
210  * device enumeration.
211  */
212 static void Handle_USB_GINTSTS_ENUMDONE( void )
213 {
214 #if ( USB_PWRSAVE_MODE )
215  UsbPowerUp();
216 #endif
217 
218  USBDHAL_Ep0Activate( dev->ep0MpsCode );
219  dev->ep[ 0 ].state = D_EP_IDLE;
220  USBDHAL_EnableInts( dev );
221  DEBUG_USB_INT_LO_PUTS( "EnumD" );
222 }
223 
224 /*
225  * Handle IN endpoint transfer interrupt.
226  */
227 static void Handle_USB_GINTSTS_IEPINT( void )
228 {
229  int epnum;
230  uint16_t epint;
231  uint16_t epmask;
232  uint32_t status;
233  USBD_Ep_TypeDef *ep;
234 
235  DEBUG_USB_INT_HI_PUTCHAR( 'i' );
236 
237  epint = USBDHAL_GetAllInEpInts();
238  for ( epnum = 0, epmask = 1;
239  epnum <= MAX_NUM_IN_EPS;
240  epnum++, epmask <<= 1 )
241  {
242  if ( epint & epmask )
243  {
244  ep = USBD_GetEpFromAddr( USB_SETUP_DIR_MASK | epnum );
245  status = USBDHAL_GetInEpInts( ep );
246 
247  if ( status & USB_DIEP_INT_XFERCOMPL )
248  {
249  USB_DINEPS[ epnum ].INT = USB_DIEP_INT_XFERCOMPL;
250 
251  DEBUG_USB_INT_HI_PUTCHAR( 'c' );
252 
253  if ( epnum == 0 )
254  {
255  if ( ep->remaining > ep->packetSize )
256  {
257  ep->remaining -= ep->packetSize;
258  ep->xferred += ep->packetSize;
259  }
260  else
261  {
262  ep->xferred += ep->remaining;
263  ep->remaining = 0;
264  }
265  USBDEP_Ep0Handler( dev );
266  }
267  else
268  {
269  ep->xferred = ep->remaining -
270  ( ( USB_DINEPS[ epnum ].TSIZ &
273  ep->remaining -= ep->xferred;
274 
275  USBDEP_EpHandler( ep->addr );
276 #if defined( USB_DOEP0INT_STUPPKTRCVD )
277  if ( USB_DINEPS[ ep->num ].INT & USB_DIEP_INT_NAKINTRPT )
278  {
279  USB_DINEPS[ ep->num ].INT = USB_DIEP_INT_NAKINTRPT;
280  }
281 #endif
282  }
283  }
284  }
285  }
286 }
287 
288 /*
289  * Handle OUT endpoint transfer interrupt.
290  */
291 static void Handle_USB_GINTSTS_OEPINT( void )
292 {
293  int epnum;
294  uint16_t epint;
295  uint16_t epmask;
296  uint32_t status;
297  USBD_Ep_TypeDef *ep;
298 
299  DEBUG_USB_INT_HI_PUTCHAR( 'o' );
300 
301  epint = USBDHAL_GetAllOutEpInts();
302  for ( epnum = 0, epmask = 1;
303  epnum <= MAX_NUM_OUT_EPS;
304  epnum++, epmask <<= 1 )
305  {
306  if ( epint & epmask )
307  {
308  ep = USBD_GetEpFromAddr( epnum );
309  status = USBDHAL_GetOutEpInts( ep );
310 
311 #if defined( USB_DOEP0INT_STUPPKTRCVD )
312  HandleOutEpIntr( status, ep );
313 #else
314  if ( status & USB_DOEP_INT_XFERCOMPL )
315  {
316  USB_DOUTEPS[ epnum ].INT = USB_DOEP_INT_XFERCOMPL;
317  DEBUG_USB_INT_HI_PUTCHAR( 'c' );
318  ProcessOepData( ep );
319  }
320 
321  /* Setup Phase Done */
322  if ( status & USB_DOEP0INT_SETUP )
323  {
324  ProcessSetup();
325  }
326 #endif
327  }
328  }
329 }
330 
331 #if !defined( USB_DOEP0INT_STUPPKTRCVD )
332 static void ProcessOepData( USBD_Ep_TypeDef *ep )
333 {
334  if ( ep->num == 0 )
335  {
336  if ( ep->remaining > ep->packetSize )
337  {
338  ep->remaining -= ep->packetSize;
339  ep->xferred += ep->packetSize;
340  }
341  else
342  {
343  ep->xferred += ep->remaining;
344  ep->remaining = 0;
345  }
346  USBDEP_Ep0Handler( dev );
347  }
348  else
349  {
350  ep->xferred = ep->hwXferSize -
351  ( ( USB_DOUTEPS[ ep->num ].TSIZ & _USB_DOEP_TSIZ_XFERSIZE_MASK )>>
353  ep->remaining -= ep->xferred;
354  USBDEP_EpHandler( ep->addr );
355  }
356 }
357 #endif
358 
359 #if !defined( USB_DOEP0INT_STUPPKTRCVD )
360 static void ProcessSetup( void )
361 {
362  DEBUG_USB_INT_LO_PUTS( "\nS" );
363 
364  if ( USB->DOEP0INT & USB_DOEP0INT_BACK2BACKSETUP )
365  { /* Back to back setup packets received */
366  USB->DOEP0INT = USB_DOEP0INT_BACK2BACKSETUP;
367  DEBUG_USB_INT_LO_PUTS( "B2B" );
368 
369  dev->setup = (USB_Setup_TypeDef*)( USB->DOEP0DMAADDR - USB_SETUP_PKT_SIZE );
370  }
371  else
372  {
373  /* Read SETUP packet counter from hw. */
374  int supCnt = ( USB->DOEP0TSIZ & _USB_DOEP0TSIZ_SUPCNT_MASK )
376 
377  if ( supCnt == 3 )
378  supCnt = 2;
379 
380  dev->setup = &dev->setupPkt[ 2 - supCnt ];
381  }
382  USB->DOEP0TSIZ |= 3 << _USB_DOEP0TSIZ_SUPCNT_SHIFT;
383  USB->DOEP0DMAADDR = (uint32_t)dev->setupPkt;
384  USB->DOEP0INT = USB_DOEP0INT_SETUP;
385 
386  USBDEP_Ep0Handler( dev ); /* Call the SETUP handler for EP0 */
387 }
388 #endif
389 
390 /*
391  * Handle USB reset detected interrupt in suspend mode.
392  */
393 static void Handle_USB_GINTSTS_RESETDET ( void )
394 {
395 #if ( USB_PWRSAVE_MODE )
396  if ( ! USBD_poweredDown )
397  {
398  USB->GINTSTS = USB_GINTSTS_RESETDET;
399  }
400 
401  if ( UsbPowerUp() )
402  {
403  USB->GINTSTS = USB_GINTSTS_RESETDET;
404  }
405 
406 #if ( USB_PWRSAVE_MODE & USB_PWRSAVE_MODE_ONVBUSOFF )
407  /* Power down immediately if VBUS is off. */
408  if ( ! ( USB->STATUS & USB_STATUS_VREGOS ) )
409  {
410  UsbPowerDown();
411  }
412 #endif
413 
414 #else
415  USB->GINTSTS = USB_GINTSTS_RESETDET;
416 #endif /* if ( USB_PWRSAVE_MODE ) */
417 
418  if ( USB->STATUS & USB_STATUS_VREGOS )
419  {
420  USBD_SetUsbState( USBD_STATE_DEFAULT );
421  }
422  else
423  {
424  USBD_SetUsbState( USBD_STATE_NONE );
425  }
426  DEBUG_USB_INT_LO_PUTS( "RsuP\n" );
427 }
428 
429 /*
430  * Handle Start Of Frame (SOF) interrupt.
431  */
432 static void Handle_USB_GINTSTS_SOF( void )
433 {
434  USB->GINTSTS = USB_GINTSTS_SOF;
435 
436  if ( dev->callbacks->sofInt )
437  {
438  dev->callbacks->sofInt(
440  }
441 }
442 
443 /*
444  * Handle USB port reset interrupt.
445  */
446 static void Handle_USB_GINTSTS_USBRST( void )
447 {
448  int i;
449 
450  DEBUG_USB_INT_LO_PUTS( "ReseT" );
451 
452  /* Clear Remote Wakeup Signalling */
453  USB->DCTL &= ~( DCTL_WO_BITMASK | USB_DCTL_RMTWKUPSIG );
454  USBHAL_FlushTxFifo( 0 );
455 
456  /* Clear pending interrupts */
457  for ( i = 0; i <= MAX_NUM_IN_EPS; i++ )
458  {
459  USB_DINEPS[ i ].INT = 0xFFFFFFFF;
460  }
461 
462  for ( i = 0; i <= MAX_NUM_OUT_EPS; i++ )
463  {
464  USB_DOUTEPS[ i ].INT = 0xFFFFFFFF;
465  }
466 
468 #if defined( USB_DOEPMSK_STSPHSERCVDMSK )
470  | USB_DOEPMSK_STSPHSERCVDMSK;
471 #else
473 #endif
474  USB->DIEPMSK = USB_DIEPMSK_XFERCOMPLMSK;
475 
476  /* Reset Device Address */
477  USB->DCFG &= ~_USB_DCFG_DEVADDR_MASK;
478 
479  /* Setup EP0 to receive SETUP packets */
480  USBDHAL_StartEp0Setup( dev );
481  USBDHAL_EnableInts( dev );
482 
483  if ( dev->callbacks->usbReset )
484  {
485  dev->callbacks->usbReset();
486  }
487 
488  USBD_SetUsbState( USBD_STATE_DEFAULT );
489  USBDHAL_AbortAllTransfers( USB_STATUS_DEVICE_RESET );
490 }
491 
492 /*
493  * Handle USB port suspend interrupt.
494  */
495 static void Handle_USB_GINTSTS_USBSUSP( void )
496 {
497  USBD_State_TypeDef state;
498 
499  USB->GINTSTS = USB_GINTSTS_USBSUSP;
500  USBDHAL_AbortAllTransfers( USB_STATUS_DEVICE_SUSPENDED );
501  DEBUG_USB_INT_LO_PUTS( "\nSusP" );
502 
504  {
505  USBD_SetUsbState( USBD_STATE_POWERED );
506  }
507 
508  state = USBD_GetUsbState();
509  if ( ( state == USBD_STATE_POWERED ) ||
510  ( state == USBD_STATE_DEFAULT ) ||
511  ( state == USBD_STATE_ADDRESSED ) ||
512  ( state == USBD_STATE_CONFIGURED ) )
513  {
514 #if ( USB_PWRSAVE_MODE )
515  UsbPowerDown();
516 #endif
517  USBD_SetUsbState( USBD_STATE_SUSPENDED );
518  }
519 }
520 
521 /*
522  * Handle USB port wakeup interrupt.
523  */
524 static void Handle_USB_GINTSTS_WKUPINT( void )
525 {
526 #if ( USB_PWRSAVE_MODE )
527  if ( ! USBD_poweredDown )
528  {
529  USB->GINTSTS = USB_GINTSTS_WKUPINT;
530  }
531 
532  if ( UsbPowerUp() )
533  {
534  USB->GINTSTS = USB_GINTSTS_WKUPINT;
535  USBDHAL_StartEp0Setup( dev );
536  USBDHAL_Ep0Activate( dev->ep0MpsCode );
537  }
538 #else
539  USB->GINTSTS = USB_GINTSTS_WKUPINT;
540 #endif
541 
542  USBD_SetUsbState( dev->savedState );
543  DEBUG_USB_INT_LO_PUTS( "WkuP\n" );
544 }
545 
546 #if ( USB_PWRSAVE_MODE )
547 /*
548  * Backup essential USB core registers, and set the core in partial powerdown
549  * mode. Optionally prepare entry into EM2.
550  */
551 static bool UsbPowerDown( void )
552 {
553 #if ( NUM_EP_USED > 0 ) || ( FIFO_CNT > 0 )
554  int i;
555 #endif
556 #if ( NUM_EP_USED > 0 )
557  int epNum;
558  USBD_Ep_TypeDef *ep;
559 #endif
560 
561  if ( !USBD_poweredDown )
562  {
563  USBD_poweredDown = true;
564  DEBUG_USB_INT_LO_PUTCHAR( '\\' );
565 
566  /* Backup USB core registers. */
567  x_USB_GINTMSK = USB->GINTMSK;
568 #if defined(_USB_GOTGCTL_MASK)
569  x_USB_GOTGCTL = USB->GOTGCTL;
570 #endif
571  x_USB_GAHBCFG = USB->GAHBCFG;
572  x_USB_GUSBCFG = USB->GUSBCFG;
573  x_USB_GRXFSIZ = USB->GRXFSIZ;
574  x_USB_GNPTXFSIZ = USB->GNPTXFSIZ;
575  x_USB_DCFG = USB->DCFG;
576  x_USB_DCTL = USB->DCTL;
577  x_USB_DAINTMSK = USB->DAINTMSK;
578  x_USB_DIEPMSK = USB->DIEPMSK;
579  x_USB_DOEPMSK = USB->DOEPMSK;
580  x_USB_PCGCCTL = USB->PCGCCTL;
581 
582 #if ( NUM_EP_USED > 0 )
583  for ( i = 0; i < NUM_EP_USED; i++ )
584  {
585  ep = &dev->ep[ i+1 ];
586  epNum = ep->num;
587  if ( ep->in )
588  {
589  x_USB_EP_CTL[ i ] = USB_DINEPS[ epNum ].CTL;
590  x_USB_EP_TSIZ[ i ] = USB_DINEPS[ epNum ].TSIZ;
591  x_USB_EP_DMAADDR[ i ] = USB_DINEPS[ epNum ].DMAADDR;
592  }
593  else
594  {
595  x_USB_EP_CTL[ i ] = USB_DOUTEPS[ epNum ].CTL;
596  x_USB_EP_TSIZ[ i ] = USB_DOUTEPS[ epNum ].TSIZ;
597  x_USB_EP_DMAADDR[ i ] = USB_DOUTEPS[ epNum ].DMAADDR;
598  }
599  }
600 #endif
601 
602 #if ( FIFO_CNT > 0 )
603  for ( i = 0; i < FIFO_CNT; i++ )
604  {
605  x_USB_DIEPTXFS[ i ] = USB_DIEPTXFS[ i ];
606  }
607 #endif
608 
609  /* Prepare for wakeup on resume and reset. */
610  USB->DCFG = (USB->DCFG & ~_USB_DCFG_RESVALID_MASK) |
612  USB->DCFG |= USB_DCFG_ENA32KHZSUSP;
614 
615  /* Enter partial powerdown mode. */
616  USB->PCGCCTL |= USB_PCGCCTL_PWRCLMP;
617  USB->PCGCCTL |= USB_PCGCCTL_RSTPDWNMODULE;
618  USB->PCGCCTL |= USB_PCGCCTL_STOPPCLK;
619 
620  /* Record current clock settings. */
621  cmuStatus = CMU->STATUS;
622 
623 #if ( USB_PWRSAVE_MODE & USB_PWRSAVE_MODE_ENTEREM2 )
624  /* Enter EM2 on interrupt exit. */
625  SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk | SCB_SCR_SLEEPONEXIT_Msk;
626 #endif
627 
628  /* Switch USBC clock to 32 kHz. */
629 #if ( USB_USBC_32kHz_CLK == USB_USBC_32kHz_CLK_LFXO )
631  while ( ( CMU->STATUS & CMU_STATUS_USBCLFXOSEL ) == 0 ){}
632 #else
634  while ( ( CMU->STATUS & CMU_STATUS_USBCLFRCOSEL ) == 0 ){}
635 #endif
636 
637  return true;
638  }
639  return false;
640 }
641 #endif /* if ( USB_PWRSAVE_MODE ) */
642 
643 #if ( USB_PWRSAVE_MODE )
644 /*
645  * Exit USB core partial powerdown mode, restore essential USB core registers.
646  * Will prevent re-entry back to EM2.
647  * Returns true if a powerup sequence was performed.
648  */
649 static bool UsbPowerUp( void )
650 {
651 #if ( NUM_EP_USED > 0 ) || ( FIFO_CNT > 0 )
652  int i;
653 #endif
654 #if ( NUM_EP_USED > 0 )
655  int epNum;
656  uint32_t tmp;
657  USBD_Ep_TypeDef *ep;
658 #endif
659 
660  if ( USBD_poweredDown )
661  {
662  USBD_poweredDown = false;
663  DEBUG_USB_INT_LO_PUTCHAR( '/' );
664 
665 #if !defined( USB_CORECLK_HFRCO ) || !defined( CMU_OSCENCMD_USHFRCOEN )
666  /* Switch HFCLK from HFRCO to HFXO. */
668 #endif
669 
670  /* Turn off HFRCO when not needed. */
671  if ( ( cmuStatus & CMU_STATUS_HFRCOENS ) == 0 )
672  {
673  CMU->OSCENCMD = CMU_OSCENCMD_HFRCODIS;
674  }
675 
676  /* Exit partial powerdown mode. */
677  USB->PCGCCTL &= ~USB_PCGCCTL_STOPPCLK;
679 
680  if (( USB->GINTSTS & ( USB_GINTSTS_WKUPINT | USB_GINTSTS_RESETDET ) ) == 0)
681  {
682  USB->DCTL = x_USB_DCTL | USB_DCTL_RMTWKUPSIG;
683  USB->DCTL = x_USB_DCTL;
684  }
685 
686  /* Restore USB core registers. */
687  USB->GUSBCFG = x_USB_GUSBCFG;
688  USB->DCFG = x_USB_DCFG;
689 
690 #if ( FIFO_CNT > 0 )
691  for ( i = 0; i < FIFO_CNT; i++ )
692  {
693  USB_DIEPTXFS[ i ] = x_USB_DIEPTXFS[ i ];
694  }
695 #endif
696 
697 #if ( NUM_EP_USED > 0 )
698  for ( i = 0; i < NUM_EP_USED; i++ )
699  {
700  ep = &dev->ep[ i+1 ];
701  epNum = ep->num;
702 
703  tmp = x_USB_EP_CTL[ i ] &
706 
707  if ( x_USB_EP_CTL[ i ] & USB_DIEP_CTL_DPIDEOF )
709  else
711 
712  if ( x_USB_EP_CTL[ i ] & USB_DIEP_CTL_NAKSTS )
713  tmp |= USB_DIEP_CTL_SNAK;
714  else
715  tmp |= USB_DIEP_CTL_CNAK;
716 
717  if ( ep->in )
718  {
719  USB_DINEPS[ epNum ].CTL = tmp;
720  USB_DINEPS[ epNum ].TSIZ = x_USB_EP_TSIZ[ i ];
721  USB_DINEPS[ epNum ].DMAADDR = x_USB_EP_DMAADDR[ i ];
722  }
723  else
724  {
725  USB_DOUTEPS[ epNum ].CTL = tmp;
726  USB_DOUTEPS[ epNum ].TSIZ = x_USB_EP_TSIZ[ i ];
727  USB_DOUTEPS[ epNum ].DMAADDR = x_USB_EP_DMAADDR[ i ];
728  }
729  }
730 #endif
731 
732  USB->PCGCCTL = x_USB_PCGCCTL;
733  USB->DOEPMSK = x_USB_DOEPMSK;
734  USB->DIEPMSK = x_USB_DIEPMSK;
735  USB->DAINTMSK = x_USB_DAINTMSK;
736  USB->DCTL = x_USB_DCTL;
737  USB->GNPTXFSIZ = x_USB_GNPTXFSIZ;
738  USB->GRXFSIZ = x_USB_GRXFSIZ;
739  USB->GAHBCFG = x_USB_GAHBCFG;
740 #if defined(_USB_GOTGCTL_MASK)
741  USB->GOTGCTL = x_USB_GOTGCTL;
742 #endif
743  USB->GINTMSK = x_USB_GINTMSK;
744 
745  USB->DCTL |= USB_DCTL_PWRONPRGDONE;
746 
747 #if ( USB_PWRSAVE_MODE & USB_PWRSAVE_MODE_ENTEREM2 )
748  /* Do not reenter EM2 on interrupt exit. */
749  SCB->SCR &= ~(SCB_SCR_SLEEPDEEP_Msk | SCB_SCR_SLEEPONEXIT_Msk);
750 #endif
751 
752  return true;
753  }
754  return false;
755 }
756 #endif /* if ( USB_PWRSAVE_MODE ) */
757 
758 #if defined( USB_DOEP0INT_STUPPKTRCVD )
759 static void HandleOutEpIntr( uint32_t status, USBD_Ep_TypeDef *ep )
760 {
761  uint32_t doeptsiz;
762 
763  if ( ep->num == 0 )
764  {
765  if ( status & USB_DOEP0INT_XFERCOMPL )
766  {
767  USB->DOEP0INT = USB_DOEP0INT_XFERCOMPL;
768  doeptsiz = USB->DOEP0TSIZ;
769 
770  if ( ep->state == D_EP_IDLE )
771  {
772  if ( status & USB_DOEP0INT_STUPPKTRCVD )
773  {
774  USB->DOEP0INT = USB_DOEP0INT_STUPPKTRCVD;
775  }
776  status = USBDHAL_GetOutEpInts( ep );
777  doeptsiz = USB->DOEP0TSIZ;
778 
779  if ( status & USB_DOEP0INT_SETUP )
780  {
781 retry:
782  /* Already started data stage, clear setup */
783  USB->DOEP0INT = USB_DOEP0INT_SETUP;
784  status &= ~USB_DOEP0INT_SETUP;
785  {
786  int supCnt = ( doeptsiz & _USB_DOEP0TSIZ_SUPCNT_MASK )
788 
789  if ( supCnt == 3 )
790  supCnt = 2;
791 
792  dev->setup = &dev->setupPkt[ 2 - supCnt ];
793  }
794  DEBUG_USB_INT_LO_PUTS( "\nS" );
795  USBDEP_Ep0Handler( dev );
796 
797  /* Prepare for more setup packets */
798  if ( ep->state == D_EP0_IN_STATUS || ep->state == D_EP_TRANSMITTING )
799  {
800  USBDHAL_StartEp0Setup( dev );
801  }
802  }
803  else /* xfercompl && idle && !setup */
804  {
805  status = USBDHAL_GetOutEpInts( ep );
806  if ( status & USB_DOEP0INT_SETUP )
807  goto retry;
808  USBDHAL_StartEp0Setup( dev );
809  }
810  }
811  else /* ep0state != EP0_IDLE */
812  {
813  if ( ep->state == D_EP_RECEIVING )
814  {
815  if ( ep->remaining > ep->packetSize )
816  {
817  ep->remaining -= ep->packetSize;
818  ep->xferred += ep->packetSize;
819  }
820  else
821  {
822  ep->xferred += ep->remaining;
823  ep->remaining = 0;
824  }
825  USBDEP_Ep0Handler( dev );
826  }
827  else if ( ep->state == D_EP0_OUT_STATUS )
828  {
829  USBDEP_Ep0Handler( dev );
830  }
831  }
832  } /* if ( status & USB_DOEP0INT_XFERCOMPL ) */
833 
834  if ( status & USB_DOEP0INT_STSPHSERCVD )
835  {
836  USB->DOEP0INT = USB_DOEP0INT_STSPHSERCVD;
837  }
838 
839  if ( status & USB_DOEP0INT_SETUP )
840  {
841  USB->DOEP0INT = USB_DOEP0INT_SETUP;
842  {
843  int supCnt = ( USB->DOEP0TSIZ & _USB_DOEP0TSIZ_SUPCNT_MASK )
845 
846  if ( supCnt == 3 )
847  supCnt = 2;
848 
849  dev->setup = &dev->setupPkt[ 2 - supCnt ];
850  }
851  DEBUG_USB_INT_LO_PUTS( "\nS" );
852  USBDEP_Ep0Handler( dev );
853  }
854  }
855  else /* epnum != 0 */
856  {
857  if ( status & USB_DOEP_INT_XFERCOMPL )
858  {
859  USB_DOUTEPS[ ep->num ].INT = USB_DOEP_INT_XFERCOMPL;
860 
861  ep->xferred = ep->hwXferSize -
862  ( ( USB_DOUTEPS[ ep->num ].TSIZ & _USB_DOEP_TSIZ_XFERSIZE_MASK )>>
864  ep->remaining -= ep->xferred;
865 
866  USBDEP_EpHandler( ep->addr );
867  }
868  }
869 }
870 #endif
871 
874 #endif /* defined( USB_DEVICE ) */
875 #endif /* defined( USB_PRESENT ) && ( USB_COUNT == 1 ) */
USB protocol stack library API for EFM32/EZR32.
Clock management unit (CMU) API.
void CMU_ClockSelectSet(CMU_Clock_TypeDef clock, CMU_Select_TypeDef ref)
Select reference clock/oscillator used for a clock branch.
Definition: em_cmu.c:2406
#define USB_GINTSTS_USBRST
Definition: efm32gg_usb.h:665
#define USB_PCGCCTL_STOPPCLK
Definition: efm32gg_usb.h:2504
#define USB_PCGCCTL_RSTPDWNMODULE
Definition: efm32gg_usb.h:2519
#define USB_GINTSTS_USBSUSP
Definition: efm32gg_usb.h:660
#define _USB_DCFG_RESVALID_MASK
Definition: efm32gg_usb.h:1532
#define USB_DCFG_ENA32KHZSUSP
Definition: efm32gg_usb.h:1510
#define CMU_STATUS_AUXHFRCOENS
Definition: efm32gg_cmu.h:565
#define USB_GINTSTS_ENUMDONE
Definition: efm32gg_usb.h:670
#define USB_DOEPMSK_XFERCOMPLMSK
Definition: efm32gg_usb.h:1684
#define CMU_OSCENCMD_HFRCODIS
Definition: efm32gg_cmu.h:414
#define _USB_DSTS_SOFFN_MASK
Definition: efm32gg_usb.h:1633
#define CMU_STATUS_HFXOENS
Definition: efm32gg_cmu.h:555
__STATIC_INLINE uint32_t INT_Enable(void)
Enable interrupts.
Definition: em_int.h:94
CMSIS Cortex-M Peripheral Access Layer for Silicon Laboratories microcontroller devices.
#define CMU_STATUS_USBCHFCLKSEL
Definition: efm32gg_cmu.h:620
#define _USB_DSTS_SOFFN_SHIFT
Definition: efm32gg_usb.h:1632
#define USB_SETUP_DIR_MASK
Definition: em_usb.h:60
#define USB_DIEP_CTL_CNAK
Definition: efm32gg_usb.h:2090
#define USB_GINTSTS_SOF
Definition: efm32gg_usb.h:630
#define CMU_CMD_USBCCLKSEL_LFRCO
Definition: efm32gg_cmu.h:494
#define USB_DAINTMSK_INEPMSK0
Definition: efm32gg_usb.h:1807
#define CMU_STATUS_USBCLFXOSEL
Definition: efm32gg_cmu.h:625
#define CMU_STATUS_HFRCOENS
Definition: efm32gg_cmu.h:545
#define _USB_DOEP_TSIZ_XFERSIZE_SHIFT
Definition: efm32gg_usb.h:2472
#define USB_GINTMSK_WKUPINTMSK
Definition: efm32gg_usb.h:879
#define USB_IF_VREGOSL
Definition: efm32gg_usb.h:240
#define USB_IFC_VREGOSH
Definition: efm32gg_usb.h:263
#define _USB_DOEP0TSIZ_SUPCNT_MASK
Definition: efm32gg_usb.h:2329
#define USB_DIEPMSK_XFERCOMPLMSK
Definition: efm32gg_usb.h:1640
USB Setup request package.
Definition: em_usb.h:375
USBD_State_TypeDef
USB device state enumerator.
Definition: em_usb.h:356
#define USB_PCGCCTL_PWRCLMP
Definition: efm32gg_usb.h:2514
#define USB_DCTL_RMTWKUPSIG
Definition: efm32gg_usb.h:1539
#define _USB_DIEP_TSIZ_XFERSIZE_SHIFT
Definition: efm32gg_usb.h:2178
#define _USB_DOEP_TSIZ_XFERSIZE_MASK
Definition: efm32gg_usb.h:2473
#define USB
#define USB_DOEP0INT_BACK2BACKSETUP
Definition: efm32gg_usb.h:2295
#define USB_DIEP_CTL_DPIDEOF
Definition: efm32gg_usb.h:2055
#define CMU_CMD_USBCCLKSEL_HFCLKNODIV
Definition: efm32gg_cmu.h:492
#define USB_IFC_VREGOSL
Definition: efm32gg_usb.h:268
#define CMU_CMD_USBCCLKSEL_LFXO
Definition: efm32gg_cmu.h:493
#define USB_GINTSTS_IEPINT
Definition: efm32gg_usb.h:685
#define USB_IF_VREGOSH
Definition: efm32gg_usb.h:235
USB protocol stack library API for EFM32/EZR32.
#define USB_DAINTMSK_OUTEPMSK0
Definition: efm32gg_usb.h:1842
#define _USB_DCFG_RESVALID_SHIFT
Definition: efm32gg_usb.h:1531
#define _USB_DCFG_DEVADDR_MASK
Definition: efm32gg_usb.h:1516
#define USB_DOEP0INT_XFERCOMPL
Definition: efm32gg_usb.h:2270
USBD_State_TypeDef USBD_GetUsbState(void)
Get current USB device state.
Definition: em_usbd.c:179
#define CMU
#define USB_GINTSTS_OEPINT
Definition: efm32gg_usb.h:690
#define _USB_DIEP_TSIZ_XFERSIZE_MASK
Definition: efm32gg_usb.h:2179
#define USB_DCTL_PWRONPRGDONE
Definition: efm32gg_usb.h:1595
#define USB_DIEP_CTL_SNAK
Definition: efm32gg_usb.h:2095
#define USB_GINTMSK_RESETDETMSK
Definition: efm32gg_usb.h:844
#define USB_DOEP_INT_XFERCOMPL
Definition: efm32gg_usb.h:2423
USB protocol stack library, low level USB peripheral access.
#define USB_DIEP_CTL_SETD1PIDOF
Definition: efm32gg_usb.h:2105
#define USB_GINTSTS_WKUPINT
Definition: efm32gg_usb.h:745
#define USB_DIEP_INT_NAKINTRPT
Definition: efm32gg_usb.h:2169
#define USB_CTRL_VREGOSEN
Definition: efm32gg_usb.h:209
__STATIC_INLINE uint32_t INT_Disable(void)
Disable interrupts.
Definition: em_int.h:71
#define USB_SETUP_PKT_SIZE
Definition: em_usb.h:178
USB protocol stack library, internal type definitions.
#define USB_STATUS_VREGOS
Definition: efm32gg_usb.h:226
#define USB_DIEP_CTL_NAKSTS
Definition: efm32gg_usb.h:2064
#define USB_DIEP_CTL_SETD0PIDEF
Definition: efm32gg_usb.h:2100
#define USB_DIEP_INT_XFERCOMPL
Definition: efm32gg_usb.h:2124
#define USB_DOEP0INT_SETUP
Definition: efm32gg_usb.h:2285
#define _USB_DOEP0TSIZ_SUPCNT_SHIFT
Definition: efm32gg_usb.h:2328
#define USB_DOEPMSK_SETUPMSK
Definition: efm32gg_usb.h:1699
#define CMU_STATUS_USBCLFRCOSEL
Definition: efm32gg_cmu.h:630
#define USB_GINTSTS_RESETDET
Definition: efm32gg_usb.h:710