EFM32 Wonder Gecko Software Documentation  efm32wg-doc-4.2.1
em_usbhal.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 ) || defined( USB_HOST )
20 
21 #include "em_usbtypes.h"
22 #include "em_usbhal.h"
23 #if defined( USB_DEVICE )
24 #include "em_usbd.h"
25 #endif
26 #if defined( USB_HOST )
27 #include "em_usbh.h"
28 #endif
29 #include "em_cmu.h"
30 #include "em_gpio.h"
31 
34 #define EPABORT_BREAK_LOOP_COUNT 15000 /* Approx. 100 ms */
35 
36 /* NOTE: The sequence of error message strings must agree with the */
37 /* definition of USB_Status_TypeDef enum. */
38 static const char * const errMsg[] =
39 {
40  [ USB_STATUS_OK ] = "No errors",
41  [ -USB_STATUS_REQ_ERR ] = "Setup request error",
42  [ -USB_STATUS_EP_BUSY ] = "Endpoint is busy",
43  [ -USB_STATUS_REQ_UNHANDLED ] = "Setup request not handled",
44  [ -USB_STATUS_ILLEGAL ] = "Illegal operation attempted",
45  [ -USB_STATUS_EP_STALLED ] = "Endpoint is stalled",
46  [ -USB_STATUS_EP_ABORTED ] = "Transfer aborted",
47  [ -USB_STATUS_EP_ERROR ] = "Transfer error",
48  [ -USB_STATUS_EP_NAK ] = "Endpoint NAK",
49  [ -USB_STATUS_DEVICE_UNCONFIGURED ] = "Device is not configured",
50  [ -USB_STATUS_DEVICE_SUSPENDED ] = "Device is suspended",
51  [ -USB_STATUS_DEVICE_RESET ] = "Device has been reset",
52  [ -USB_STATUS_TIMEOUT ] = "Transfer timeout",
53  [ -USB_STATUS_DEVICE_REMOVED ] = "Device removed",
54  [ -USB_STATUS_HC_BUSY ] = "Host channel is busy",
55  [ -USB_STATUS_DEVICE_MALFUNCTION ] = "Device malfunction",
56  [ -USB_STATUS_PORT_OVERCURRENT ] = "VBUS overcurrent",
57 };
61 /***************************************************************************/
71 char *USB_GetErrorMsgString( int error )
72 {
73  if ( error >= 0 )
74  return (char*)errMsg[ 0 ];
75 
76  return (char*)errMsg[ -error ];
77 }
78 
79 
80 #if defined( USB_USE_PRINTF )
81 /***************************************************************************/
92 void USB_PrintErrorMsgString( char *pre, int error )
93 {
94  if ( pre )
95  {
96  USB_PRINTF( "%s", pre );
97  }
98 
99  if ( error > USB_STATUS_OK )
100  {
101  USB_PRINTF( "%d", error );
102  }
103  else
104  {
105  USB_PRINTF( "%s", USB_GetErrorMsgString( error ) );
106  }
107 }
108 #endif /* defined( USB_USE_PRINTF ) */
109 
112 #if defined( DEBUG_EFM_USER )
113 static void PrintI( int i )
114 {
115 #if !defined ( USER_PUTCHAR )
116  (void)i;
117 #else
118  if ( i >= 10 )
119  {
120  PrintI( i / 10 );
121  }
122 
123  DEBUG_USB_API_PUTCHAR( ( i % 10 ) + '0' );
124 #endif
125 }
126 
127 void assertEFM( const char *file, int line )
128 {
129 #if !defined ( USER_PUTCHAR )
130  (void)file;
131 #endif
132 
133  DEBUG_USB_API_PUTS( "\nASSERT " );
134  DEBUG_USB_API_PUTS( file );
135  DEBUG_USB_API_PUTCHAR( ' ' );
136  PrintI( line );
137  for(;;){}
138 }
139 #endif /* defined( DEBUG_EFM_USER ) */
140 
141 #if defined ( USER_PUTCHAR )
142 void USB_Puts( const char *p )
143 {
144  while( *p )
145  USB_PUTCHAR( *p++ );
146 }
147 #endif /* defined ( USER_PUTCHAR ) */
148 
149 void USBHAL_CoreReset( void )
150 {
151  USB->PCGCCTL &= ~USB_PCGCCTL_STOPPCLK;
153 
154  /* Core Soft Reset */
155  USB->GRSTCTL |= USB_GRSTCTL_CSFTRST;
156  while ( USB->GRSTCTL & USB_GRSTCTL_CSFTRST ) {}
157 
158  USBTIMER_DelayUs( 1 );
159 
160  /* Wait for AHB master IDLE state. */
161  while ( !( USB->GRSTCTL & USB_GRSTCTL_AHBIDLE ) ) {}
162 }
163 
164 #ifdef USB_DEVICE
165 void USBDHAL_Connect( void )
166 {
167  USB->DCTL &= ~( DCTL_WO_BITMASK | USB_DCTL_SFTDISCON );
168 }
169 
170 USB_Status_TypeDef USBDHAL_CoreInit( uint32_t totalRxFifoSize,
171  uint32_t totalTxFifoSize )
172 {
173  uint8_t i, j;
174  uint16_t start, depth;
175  USBD_Ep_TypeDef *ep;
176 
177 #if !defined( USB_VBUS_SWITCH_NOT_PRESENT )
179  GPIO_PinModeSet( gpioPortF, 5, gpioModePushPull, 0 ); /* Enable VBUSEN pin */
180  USB->ROUTE = USB_ROUTE_PHYPEN | USB_ROUTE_VBUSENPEN; /* Enable PHY pins. */
181 #else
182  USB->ROUTE = USB_ROUTE_PHYPEN; /* Enable PHY pins. */
183 #endif
184 
185  USBHAL_CoreReset(); /* Reset USB core */
186 
187 #if defined( USB_GUSBCFG_FORCEHSTMODE )
188  /* Force Device Mode */
189  USB->GUSBCFG = ( USB->GUSBCFG &
190  ~(GUSBCFG_WO_BITMASK | USB_GUSBCFG_FORCEHSTMODE ) ) |
192 #endif
193 
194  INT_Enable();
195  USBTIMER_DelayMs( 50 );
196  INT_Disable();
197 
198  /* Set device speed */
199  USB->DCFG = ( USB->DCFG & ~_USB_DCFG_DEVSPD_MASK ) | 3; /* Full speed PHY */
200 
201  /* Stall on non-zero len status OUT packets (ctrl transfers). */
202  USB->DCFG |= USB_DCFG_NZSTSOUTHSHK;
203 
204  /* Set periodic frame interval to 80% */
205  USB->DCFG &= ~_USB_DCFG_PERFRINT_MASK;
206 
207  USB->GAHBCFG = ( USB->GAHBCFG & ~_USB_GAHBCFG_HBSTLEN_MASK ) |
209 
210  /* Ignore frame numbers on ISO transfers. */
211  USB->DCTL = ( USB->DCTL & ~DCTL_WO_BITMASK ) | USB_DCTL_IGNRFRMNUM;
212 
213  /* Set Rx FIFO size */
214  start = EFM32_MAX( totalRxFifoSize, MIN_EP_FIFO_SIZE_INWORDS );
215  USB->GRXFSIZ = ( start << _USB_GRXFSIZ_RXFDEP_SHIFT ) &
217 
218  /* Set Tx EP0 FIFO size */
219  depth = EFM32_MAX( dev->ep[ 0 ].fifoSize, MIN_EP_FIFO_SIZE_INWORDS );
220  USB->GNPTXFSIZ = ( ( depth << _USB_GNPTXFSIZ_NPTXFINEPTXF0DEP_SHIFT ) &
222  ( ( start << _USB_GNPTXFSIZ_NPTXFSTADDR_SHIFT ) &
224 
225 
226  /* Set Tx EP FIFO sizes for all IN ep's */
227  for ( j = 1; j <= MAX_NUM_TX_FIFOS; j++ )
228  {
229  for ( i = 1; i <= MAX_NUM_IN_EPS; i++ )
230  {
231  ep = USBD_GetEpFromAddr( USB_SETUP_DIR_MASK | i );
232  if ( ep ) /* Is EP in use ? */
233  {
234  if ( ep->txFifoNum == j ) /* Is it correct FIFO number ? */
235  {
236  start += depth;
237  depth = EFM32_MAX( ep->fifoSize, MIN_EP_FIFO_SIZE_INWORDS );
238  USB_DIEPTXFS[ ep->txFifoNum - 1 ] =
239  ( depth << _USB_DIEPTXF1_INEPNTXFDEP_SHIFT ) |
241  }
242  }
243  }
244  }
245 
246  if ( totalRxFifoSize + totalTxFifoSize > MAX_DEVICE_FIFO_SIZE_INWORDS )
247  return USB_STATUS_ILLEGAL;
248 
249  if ( start > MAX_DEVICE_FIFO_SIZE_INWORDS )
250  return USB_STATUS_ILLEGAL;
251 
252  /* Flush the FIFO's */
253  USBHAL_FlushTxFifo( 0x10 ); /* All Tx FIFO's */
254  USBHAL_FlushRxFifo(); /* The Rx FIFO */
255 
256  /* Disable all device interrupts */
257  USB->DIEPMSK = 0;
258  USB->DOEPMSK = 0;
259  USB->DAINTMSK = 0;
260  USB->DIEPEMPMSK = 0;
261 
262  /* Disable all EP's, clear all EP ints. */
263  for ( i = 0; i <= MAX_NUM_IN_EPS; i++ )
264  {
265  USB_DINEPS[ i ].CTL = 0;
266  USB_DINEPS[ i ].TSIZ = 0;
267  USB_DINEPS[ i ].INT = 0xFFFFFFFF;
268  }
269 
270  for ( i = 0; i <= MAX_NUM_OUT_EPS; i++ )
271  {
272  USB_DOUTEPS[ i ].CTL = 0;
273  USB_DOUTEPS[ i ].TSIZ = 0;
274  USB_DOUTEPS[ i ].INT = 0xFFFFFFFF;
275  }
276 
277 #if ( USB_DCTL_SFTDISCON_DEFAULT != 0 )
278  USBD_Connect();
279 #endif
280 
281  /* Enable VREGO sense. */
282  USB->CTRL |= USB_CTRL_VREGOSEN;
285  /* Force a VREGO interrupt. */
286  if ( USB->STATUS & USB_STATUS_VREGOS)
287  USB->IFS = USB_IFS_VREGOSH;
288  else
289  USB->IFS = USB_IFS_VREGOSL;
290 
291  return USB_STATUS_OK;
292 }
293 
294 void USBDHAL_Disconnect( void )
295 {
296  USB->DCTL = ( USB->DCTL & ~DCTL_WO_BITMASK ) | USB_DCTL_SFTDISCON;
297 }
298 
299 void USBDHAL_AbortEpIn( USBD_Ep_TypeDef *ep )
300 {
301  /* Clear epdis & inepnakeff INT's */
302  USB_DINEPS[ ep->num ].INT |= USB_DIEP_INT_EPDISBLD |
304 
305  /* Enable epdis & inepnakeff INT's */
307  USB_DINEPS[ ep->num ].CTL = ( USB_DINEPS[ ep->num ].CTL &
308  ~DEPCTL_WO_BITMASK ) |
310 
311  /* Wait for inepnakeff INT */
312  while ( !( USBDHAL_GetInEpInts( ep ) & USB_DIEP_INT_INEPNAKEFF ) ) {}
313  USB_DINEPS[ ep->num ].INT = USB_DIEP_INT_INEPNAKEFF;
314  USB->DIEPMSK &= ~USB_DIEPMSK_INEPNAKEFFMSK;
315 
316  DEBUG_USB_INT_LO_PUTCHAR( '.' );
317 
318  USBDHAL_SetEPDISNAK( ep );
319  /* Wait for epdis INT */
320  while ( !( USBDHAL_GetInEpInts( ep ) & USB_DIEP_INT_EPDISBLD ) ) {}
321  USB_DINEPS[ ep->num ].INT = USB_DIEP_INT_EPDISBLD;
322  USB->DIEPMSK &= ~USB_DIEPMSK_EPDISBLDMSK;
323  USBHAL_FlushTxFifo( ep->txFifoNum );
324 
325  /* Clear any interrupts generated by the abort sequence. */
326  NVIC_ClearPendingIRQ( USB_IRQn );
327 
328  DEBUG_USB_INT_LO_PUTCHAR( '.' );
329 }
330 
331 void USBDHAL_AbortEpOut( USBD_Ep_TypeDef *ep )
332 {
333  int cnt;
334 
335  /* Clear epdis INT's */
336  USB_DOUTEPS[ ep->num ].INT |= USB_DOEP_INT_EPDISBLD;
337 
338  /* Clear Global OUT NAK if already set */
339  USB->DCTL = ( USB->DCTL & ~DCTL_WO_BITMASK ) | USB_DCTL_CGOUTNAK;
340  USB->GINTMSK |= USB_GINTMSK_GOUTNAKEFFMSK; /* Enable GOUTNAKEFF int */
341 
342  /* Set Global OUT NAK */
343  USB->DCTL = ( USB->DCTL & ~DCTL_WO_BITMASK ) | USB_DCTL_SGOUTNAK;
344 
345  /* Wait for goutnakeff */
346  cnt = EPABORT_BREAK_LOOP_COUNT;
347  while ( !( USB->GINTSTS & USB_GINTSTS_GOUTNAKEFF ) && cnt )
348  {
349  cnt--;
350  }
351 
352  USB->GINTMSK &= ~USB_GINTMSK_GOUTNAKEFFMSK; /* Disable GOUTNAKEFF int */
353  USB->DOEPMSK |= USB_DOEPMSK_EPDISBLDMSK; /* Enable EPDIS interrupt */
354 
355  DEBUG_USB_INT_LO_PUTCHAR( ',' );
356 
357  USBDHAL_SetEPDISNAK( ep ); /* Disable ep */
358 
359  /* Wait for epdis INT */
360  cnt = EPABORT_BREAK_LOOP_COUNT;
361  while ( !( USBDHAL_GetOutEpInts( ep ) & USB_DOEP_INT_EPDISBLD ) && cnt )
362  {
363  cnt--;
364  }
365 
366  USB_DOUTEPS[ ep->num ].INT = USB_DOEP_INT_EPDISBLD;
367  USB->DOEPMSK &= ~USB_DOEPMSK_EPDISBLDMSK; /* Disable EPDIS interrupt */
368 
369  /* Clear Global OUT NAK */
370  USB->DCTL = ( USB->DCTL & ~DCTL_WO_BITMASK ) | USB_DCTL_CGOUTNAK;
371 
372  /* Clear any interrupts generated by the abort sequence. */
373  NVIC_ClearPendingIRQ( USB_IRQn );
374 
375  DEBUG_USB_INT_LO_PUTCHAR( ',' );
376 }
377 
378 void USBDHAL_AbortAllEps( void )
379 {
380  int i, cnt;
381  USBD_Ep_TypeDef *ep;
382  uint16_t im, om, inmask=0, outmask=0;
383 
384  /* Clear epdis & inepnakeff INT's */
385  for ( i = 1; i <= NUM_EP_USED; i++ )
386  {
387  ep = &dev->ep[i];
388  if ( ep->state != D_EP_IDLE )
389  {
390  if ( ep->in )
391  {
392  inmask |= ep->mask;
393  USB_DINEPS[ ep->num ].INT |= USB_DIEP_INT_EPDISBLD |
395  }
396  else
397  {
398  outmask |= ep->mask;
399  USB_DOUTEPS[ ep->num ].INT |= USB_DOEP_INT_EPDISBLD;
400  }
401  }
402  }
403 
404  if ( inmask )
405  {
406  /* Enable epdis & inepnakeff INT's */
408 
409  /* Set NAK on all IN ep's */
410  im = inmask;
411  for ( i = 1; i <= NUM_EP_USED; i++ )
412  {
413  ep = &dev->ep[i];
414  if ( im & ep->mask )
415  {
416  USB_DINEPS[ ep->num ].CTL = ( USB_DINEPS[ ep->num ].CTL &
417  ~DEPCTL_WO_BITMASK ) |
419  }
420  }
421  }
422 
423  if ( outmask )
424  {
425  /* Clear Global OUT NAK if already set */
426  USB->DCTL = ( USB->DCTL & ~DCTL_WO_BITMASK ) | USB_DCTL_CGOUTNAK;
427 
428  USB->GINTMSK |= USB_GINTMSK_GOUTNAKEFFMSK; /* Enable GOUTNAKEFF int */
429 
430  /* Set Global OUT NAK */
431  USB->DCTL = ( USB->DCTL & ~DCTL_WO_BITMASK ) | USB_DCTL_SGOUTNAK;
432 
433  /* Wait for goutnakeff */
434  cnt = EPABORT_BREAK_LOOP_COUNT;
435  while ( !( USB->GINTSTS & USB_GINTSTS_GOUTNAKEFF ) && cnt )
436  {
437  cnt--;
438  }
439  USB->GINTMSK &= ~USB_GINTMSK_GOUTNAKEFFMSK; /* Disable GOUTNAKEFF int */
440  USB->DOEPMSK |= USB_DOEPMSK_EPDISBLDMSK; /* Enable EPDIS interrupt */
441  }
442 
443  if ( inmask )
444  {
445  /* Wait for inepnakeff INT on all IN ep's */
446  im = inmask;
447  cnt = EPABORT_BREAK_LOOP_COUNT;
448  do
449  {
450  for ( i = 1; i <= NUM_EP_USED; i++ )
451  {
452  ep = &dev->ep[i];
453  if ( im & ep->mask )
454  {
455  if ( USBDHAL_GetInEpInts( ep ) & USB_DIEP_INT_INEPNAKEFF )
456  {
457  USB_DINEPS[ ep->num ].INT = USB_DIEP_INT_INEPNAKEFF;
458  im &= ~ep->mask;
459  }
460  }
461  }
462  cnt--;
463  } while ( im && cnt );
464  USB->DIEPMSK &= ~USB_DIEPMSK_INEPNAKEFFMSK;
465  }
466 
467  DEBUG_USB_INT_LO_PUTCHAR( '\'' );
468 
469  /* Disable ep's */
470  for ( i = 1; i <= NUM_EP_USED; i++ )
471  {
472  ep = &dev->ep[i];
473  if ( ep->state != D_EP_IDLE )
474  {
475  USBDHAL_SetEPDISNAK( ep );
476  }
477  }
478 
479  /* Wait for epdis INT */
480  im = inmask;
481  om = outmask;
482  cnt = EPABORT_BREAK_LOOP_COUNT;
483  do
484  {
485  for ( i = 1; i <= NUM_EP_USED; i++ )
486  {
487  ep = &dev->ep[i];
488  if ( ep->in && ( im & ep->mask ) )
489  {
490  if ( USBDHAL_GetInEpInts( ep ) & USB_DIEP_INT_EPDISBLD )
491  {
492  USB_DINEPS[ ep->num ].INT = USB_DIEP_INT_EPDISBLD;
493  im &= ~ep->mask;
494  }
495  }
496 
497  if ( !ep->in && ( om & ep->mask ) )
498  {
499  if ( USBDHAL_GetOutEpInts( ep ) & USB_DOEP_INT_EPDISBLD )
500  {
501  USB_DOUTEPS[ ep->num ].INT = USB_DOEP_INT_EPDISBLD;
502  om &= ~ep->mask;
503  }
504  }
505  }
506  cnt--;
507  } while ( ( im || om ) && cnt );
508 
509  if ( inmask )
510  {
511  USB->DIEPMSK &= ~USB_DIEPMSK_EPDISBLDMSK; /* Disable EPDIS interrupt */
512  USBHAL_FlushTxFifo( 0x10 ); /* Flush all Tx FIFO's */
513  }
514 
515  if ( outmask )
516  {
517  USB->DOEPMSK &= ~USB_DOEPMSK_EPDISBLDMSK; /* Disable EPDIS interrupt */
518  /* Clear Global OUT NAK */
519  USB->DCTL = ( USB->DCTL & ~DCTL_WO_BITMASK ) | USB_DCTL_CGOUTNAK;
520  }
521 
522  DEBUG_USB_INT_LO_PUTCHAR( '\'' );
523 }
524 
525 void USBDHAL_AbortAllTransfers( USB_Status_TypeDef reason )
526 {
527  int i;
528  USBD_Ep_TypeDef *ep;
530 
531  if ( reason != USB_STATUS_DEVICE_RESET )
532  {
533  USBDHAL_AbortAllEps();
534  }
535 
536  for ( i = 1; i <= NUM_EP_USED; i++ )
537  {
538  ep = &(dev->ep[i]);
539  if ( ep->state != D_EP_IDLE )
540  {
541  ep->state = D_EP_IDLE;
542  if ( ep->xferCompleteCb )
543  {
544  callback = ep->xferCompleteCb;
545  ep->xferCompleteCb = NULL;
546 
547  if ( ( dev->lastState == USBD_STATE_CONFIGURED ) &&
548  ( dev->state == USBD_STATE_ADDRESSED ) )
549  {
550  USBDHAL_DeactivateEp( ep );
551  }
552 
553  DEBUG_TRACE_ABORT( reason );
554  callback( reason, ep->xferred, ep->remaining );
555  }
556  }
557  }
558 
559  /* Clear any interrupts generated by the abort sequence. */
560  NVIC_ClearPendingIRQ( USB_IRQn );
561 }
562 #endif /* defined( USB_DEVICE ) */
563 
564 #if defined( USB_HOST )
565 USB_Status_TypeDef USBHHAL_CoreInit( uint32_t rxFifoSize,
566  uint32_t nptxFifoSize,
567  uint32_t ptxFifoSize )
568 {
569  uint8_t i;
570 
571  rxFifoSize /= 4; /* Convert from byte count to word count. */
572  nptxFifoSize /= 4;
573  ptxFifoSize /= 4;
574 
576  GPIO_PinModeSet( gpioPortF, 5, gpioModePushPull, 0 ); /* Enable VBUSEN pin */
577 
578 #if ( USB_VBUSOVRCUR_PORT != USB_VBUSOVRCUR_PORT_NONE )
579  /* Enable VBUS overcurrent flag pin. */
580  GPIO_PinModeSet( USB_VBUSOVRCUR_PORT, USB_VBUSOVRCUR_PIN, gpioModeInput, 0 );
581 #endif
582 
583  USB->ROUTE = USB_ROUTE_PHYPEN | USB_ROUTE_VBUSENPEN; /* Enable PHY pins. */
584  USBHAL_CoreReset(); /* Reset USB core */
585 
586  /* Force Host Mode */
587  USB->GUSBCFG = ( USB->GUSBCFG &
588  ~(GUSBCFG_WO_BITMASK | USB_GUSBCFG_FORCEDEVMODE ) ) |
590 
591  INT_Enable();
592  USBTIMER_DelayMs( 100 );
593  INT_Disable();
594 
595  /* Set 48 MHz PHY clock, FS/LS mode */
596  USB->HCFG = ( USB->HCFG & ~_USB_HCFG_FSLSPCLKSEL_MASK ) |
597  ( 1 << _USB_HCFG_FSLSPCLKSEL_SHIFT ) |
598  ( USB_HCFG_FSLSSUPP );
599 
600  USB->GAHBCFG = ( USB->GAHBCFG & ~_USB_GAHBCFG_HBSTLEN_MASK ) |
602 
603  /* Set Rx FIFO size */
604  USB->GRXFSIZ = ( rxFifoSize << _USB_GRXFSIZ_RXFDEP_SHIFT ) &
606 
607  /* Set Tx FIFO sizes */
608  USB->GNPTXFSIZ = ( ( nptxFifoSize <<
611  ( ( rxFifoSize <<
613  _USB_GNPTXFSIZ_NPTXFSTADDR_MASK );
614 
615  USB->HPTXFSIZ = ( ( ptxFifoSize << _USB_HPTXFSIZ_PTXFSIZE_SHIFT ) &
617  ( ( ( rxFifoSize + nptxFifoSize )
620 
621  /* Flush Tx and Rx FIFO's */
622  USBHAL_FlushTxFifo( 0x10 );
623  USBHAL_FlushRxFifo();
624 
625  for ( i = 0; i < MAX_NUM_HOSTCHANNELS; i++ )
626  {
627  USB->HC[ i ].CHAR = USB_HC_CHAR_CHDIS; /* Disable channel */
628  USB->HC[ i ].INT = 0xFFFFFFFF; /* Clear pending interrupts */
629  }
630 
631  /* Enable and halt all channels */
632  for ( i = 0; i < MAX_NUM_HOSTCHANNELS; i++ )
633  {
634  USB->HC[ i ].CHAR |= USB_HC_CHAR_CHDIS | USB_HC_CHAR_CHENA;
635  do
636  {
637  __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP();
638  }
639  while ( USB->HC[ i ].CHAR & USB_HC_CHAR_CHENA );
640  }
641 
642  /* Disable all interrupts */
643  for ( i = 0; i < MAX_NUM_HOSTCHANNELS; i++ )
644  {
645  USB->HC[ i ].INTMSK = 0;
646  }
647 
648  USB->HAINTMSK = 0;
649 
650  return USB_STATUS_OK;
651 }
652 
653 void USBHHAL_HCHalt( int hcnum, uint32_t hcchar )
654 {
656  USB->HC[ hcnum ].CHAR = hcchar;
657 }
658 
659 void USBHHAL_HCInit( int hcnum )
660 {
661  USBH_Ep_TypeDef *ep;
662 
663  ep = hcs[ hcnum ].ep;
664  USB->HC[ hcnum ].INT = 0xFFFFFFFF; /* Clear all interrupt flags */
665 
666  switch ( ep->type ) /* Enable host channel int. types */
667  {
668  case USB_EPTYPE_CTRL:
669  case USB_EPTYPE_BULK:
670  case USB_EPTYPE_INTR:
671  USB->HC[ hcnum ].INTMSK = USB_HC_INT_CHHLTD;
672  break;
673  }
674 
675  hcs[ hcnum ].errorCnt = 0;
676 
677  USB->HAINTMSK |= 1 << hcnum; /* Enable host channel interrupt */
678 
679  USB->HC[ hcnum ].CHAR = /* Program HCCHAR register */
681  ( ( ep->addr & USB_EPNUM_MASK ) << _USB_HC_CHAR_EPNUM_SHIFT ) |
682  ( ep->type << _USB_HC_CHAR_EPTYPE_SHIFT ) |
684  ( ep->in ? USB_HC_CHAR_EPDIR : 0 ) |
685  ( ep->parentDevice->speed ==
686  HPRT_L_SPEED >> _USB_HPRT_PRTSPD_SHIFT
687  ? USB_HC_CHAR_LSPDDEV : 0 );
688 }
689 
690 void USBHHAL_HCStart( int hcnum )
691 {
692  USBH_Hc_TypeDef *hc;
693  uint16_t packets, len;
694 
695  hc = &hcs[ hcnum ];
696  hc->status = 0;
697  hc->idle = false;
698 
699  if ( hc->remaining > 0 )
700  {
701  packets = ( hc->remaining + hc->ep->packetSize - 1 ) / hc->ep->packetSize;
702  }
703  else
704  {
705  packets = 1;
706  }
707 
708  if ( hc->ep->in )
709  {
710  len = packets * hc->ep->packetSize;
711  }
712  else
713  {
714  len = hc->remaining;
715  }
716 
717  /* Initialize the HCTSIZn register */
718  hc->hwXferSize = len;
719  USB->HC[ hcnum ].TSIZ =
720  ( ( len << _USB_HC_TSIZ_XFERSIZE_SHIFT ) &
722  ( ( packets << _USB_HC_TSIZ_PKTCNT_SHIFT ) &
724  ( ( hc->ep->toggle << _USB_HC_TSIZ_PID_SHIFT ) &
726 
727  USB->HC[ hcnum ].DMAADDR = (uint32_t)hc->buf;
728 
729  USBHHAL_HCActivate( hcnum,
730  USB->HC[ hcnum ].CHAR,
731  hc->ep->type == USB_EPTYPE_INTR );
732 }
733 #endif /* defined( USB_HOST ) */
734 
737 #endif /* defined( USB_DEVICE ) || defined( USB_HOST ) */
738 #endif /* defined( USB_PRESENT ) && ( USB_COUNT == 1 ) */
#define USB_DIEP_INT_INEPNAKEFF
Definition: efm32wg_usb.h:2149
USB protocol stack library API for EFM32/EZR32.
Clock management unit (CMU) API.
#define USB_ROUTE_PHYPEN
Definition: efm32wg_usb.h:291
#define USB_GRSTCTL_CSFTRST
Definition: efm32wg_usb.h:557
#define USB_HC_INT_CHHLTD
Definition: efm32wg_usb.h:1362
#define USB_GINTSTS_GOUTNAKEFF
Definition: efm32wg_usb.h:650
#define USB_EPNUM_MASK
Definition: em_usb.h:179
#define _USB_HC_TSIZ_XFERSIZE_MASK
Definition: efm32wg_usb.h:1466
#define USB_GRSTCTL_AHBIDLE
Definition: efm32wg_usb.h:602
#define _USB_HC_CHAR_EPNUM_SHIFT
Definition: efm32wg_usb.h:1300
USB protocol stack library API for EFM32/EZR32.
#define EFM32_MAX(a, b)
Definition: em_common.h:81
#define _USB_DCFG_PERFRINT_MASK
Definition: efm32wg_usb.h:1520
#define USB_IFS_VREGOSH
Definition: efm32wg_usb.h:249
#define USB_IFC_VREGOSH
Definition: efm32wg_usb.h:263
int USB_PRINTF(const char *format,...)
Transmit "printf" formated data on the debug serial port.
__STATIC_INLINE uint32_t INT_Enable(void)
Enable interrupts.
Definition: em_int.h:94
#define USB_GINTMSK_GOUTNAKEFFMSK
Definition: efm32wg_usb.h:784
void USB_PrintErrorMsgString(char *pre, int error)
Format and print a text string given an error code, prepends an optional user supplied leader string...
Definition: em_usbhal.c:92
#define _USB_HPTXFSIZ_PTXFSIZE_SHIFT
Definition: efm32wg_usb.h:1032
#define _USB_HCFG_FSLSPCLKSEL_SHIFT
Definition: efm32wg_usb.h:1112
#define _USB_HC_CHAR_DEVADDR_SHIFT
Definition: efm32wg_usb.h:1334
#define USB_STATUS_VREGOS
Definition: efm32wg_usb.h:226
CMSIS Cortex-M Peripheral Access Layer for Silicon Laboratories microcontroller devices.
#define USB_SETUP_DIR_MASK
Definition: em_usb.h:60
#define _USB_GNPTXFSIZ_NPTXFSTADDR_SHIFT
Definition: efm32wg_usb.h:988
#define USB_DCTL_SFTDISCON
Definition: efm32wg_usb.h:1544
#define USB_HC_CHAR_CHDIS
Definition: efm32wg_usb.h:1343
#define _USB_HC_TSIZ_PID_SHIFT
Definition: efm32wg_usb.h:1473
void USBD_Connect(void)
Start USB device operation.
Definition: em_usbd.c:123
#define USB_PCGCCTL_RSTPDWNMODULE
Definition: efm32wg_usb.h:2519
#define _USB_HC_TSIZ_PID_MASK
Definition: efm32wg_usb.h:1474
char * USB_GetErrorMsgString(int error)
Return an error message string for a given error code.
Definition: em_usbhal.c:71
#define USB_DCTL_SGOUTNAK
Definition: efm32wg_usb.h:1585
#define USB_HC_CHAR_EPDIR
Definition: efm32wg_usb.h:1304
#define _USB_HC_TSIZ_XFERSIZE_SHIFT
Definition: efm32wg_usb.h:1465
void USBTIMER_DelayMs(uint32_t msec)
Active wait millisecond delay function. Can also be used inside interrupt handlers.
Definition: em_usbtimer.c:135
#define USB_IFC_VREGOSL
Definition: efm32wg_usb.h:268
#define _USB_GNPTXFSIZ_NPTXFSTADDR_MASK
Definition: efm32wg_usb.h:989
int(* USB_XferCompleteCb_TypeDef)(USB_Status_TypeDef status, uint32_t xferred, uint32_t remaining)
USB transfer callback function.
Definition: em_usb.h:663
#define USB_DCTL_IGNRFRMNUM
Definition: efm32wg_usb.h:1600
uint16_t packetSize
Definition: em_usb.h:869
#define _USB_DIEPTXF1_INEPNTXFSTADDR_MASK
Definition: efm32wg_usb.h:1041
#define USB_GUSBCFG_FORCEDEVMODE
Definition: efm32wg_usb.h:543
#define _USB_DCFG_DEVSPD_MASK
Definition: efm32wg_usb.h:1498
#define _USB_HPTXFSIZ_PTXFSTADDR_MASK
Definition: efm32wg_usb.h:1029
#define _USB_HC_TSIZ_PKTCNT_MASK
Definition: efm32wg_usb.h:1470
USB_Status_TypeDef
USB transfer status enumerator.
Definition: em_usb.h:316
#define USB_DIEP_INT_EPDISBLD
Definition: efm32wg_usb.h:2129
#define USB
void GPIO_PinModeSet(GPIO_Port_TypeDef port, unsigned int pin, GPIO_Mode_TypeDef mode, unsigned int out)
Set the mode for a GPIO pin.
Definition: em_gpio.c:226
#define USB_CTRL_VREGOSEN
Definition: efm32wg_usb.h:209
struct USBH_Device_TypeDef * parentDevice
Definition: em_usb.h:867
#define _USB_HCFG_FSLSPCLKSEL_MASK
Definition: efm32wg_usb.h:1113
General Purpose IO (GPIO) peripheral API.
#define _USB_HC_CHAR_MPS_SHIFT
Definition: efm32wg_usb.h:1296
#define _USB_GAHBCFG_HBSTLEN_MASK
Definition: efm32wg_usb.h:451
#define USB_EPTYPE_CTRL
Definition: em_usb.h:169
#define USB_HCFG_FSLSSUPP
Definition: efm32wg_usb.h:1120
#define USB_PCGCCTL_PWRCLMP
Definition: efm32wg_usb.h:2514
#define USB_DOEPMSK_EPDISBLDMSK
Definition: efm32wg_usb.h:1689
#define _USB_GNPTXFSIZ_NPTXFINEPTXF0DEP_SHIFT
Definition: efm32wg_usb.h:992
USB protocol stack library API for EFM32/EZR32.
#define USB_PCGCCTL_STOPPCLK
Definition: efm32wg_usb.h:2504
#define USB_DIEP_CTL_SNAK
Definition: efm32wg_usb.h:2095
uint8_t addr
Definition: em_usb.h:875
void CMU_ClockEnable(CMU_Clock_TypeDef clock, bool enable)
Enable/disable a clock.
Definition: em_cmu.c:1369
#define USB_ROUTE_VBUSENPEN
Definition: efm32wg_usb.h:296
#define _USB_GRXFSIZ_RXFDEP_SHIFT
Definition: efm32wg_usb.h:980
#define USB_DCFG_NZSTSOUTHSHK
Definition: efm32wg_usb.h:1505
#define _USB_GRXFSIZ_RXFDEP_MASK
Definition: efm32wg_usb.h:981
#define USB_DIEPMSK_EPDISBLDMSK
Definition: efm32wg_usb.h:1645
#define USB_DIEPMSK_INEPNAKEFFMSK
Definition: efm32wg_usb.h:1665
#define _USB_HC_CHAR_EPTYPE_SHIFT
Definition: efm32wg_usb.h:1318
#define USB_EPTYPE_INTR
Definition: em_usb.h:172
uint8_t type
Definition: em_usb.h:868
#define _USB_DIEPTXF1_INEPNTXFDEP_SHIFT
Definition: efm32wg_usb.h:1044
#define _USB_HPTXFSIZ_PTXFSTADDR_SHIFT
Definition: efm32wg_usb.h:1028
#define USB_IFS_VREGOSL
Definition: efm32wg_usb.h:254
#define _USB_HPTXFSIZ_PTXFSIZE_MASK
Definition: efm32wg_usb.h:1033
USB protocol stack library, low level USB peripheral access.
#define _USB_HC_TSIZ_PKTCNT_SHIFT
Definition: efm32wg_usb.h:1469
#define USB_HC_CHAR_LSPDDEV
Definition: efm32wg_usb.h:1313
__STATIC_INLINE uint32_t INT_Disable(void)
Disable interrupts.
Definition: em_int.h:71
#define USB_HC_CHAR_CHENA
Definition: efm32wg_usb.h:1348
USB HOST endpoint status data.
Definition: em_usb.h:862
USB protocol stack library, internal type definitions.
#define USB_GAHBCFG_DMAEN
Definition: efm32wg_usb.h:464
int USB_PUTCHAR(char c)
Transmit a single char on the debug serial port.
#define USB_DOEP_INT_EPDISBLD
Definition: efm32wg_usb.h:2428
#define USB_DCTL_CGOUTNAK
Definition: efm32wg_usb.h:1590
#define _USB_GNPTXFSIZ_NPTXFINEPTXF0DEP_MASK
Definition: efm32wg_usb.h:993
void USBTIMER_DelayUs(uint32_t usec)
Active wait microsecond delay function. Can also be used inside interrupt handlers.
Definition: em_usbtimer.c:156
#define USB_GUSBCFG_FORCEHSTMODE
Definition: efm32wg_usb.h:538
#define _USB_HPRT_PRTSPD_SHIFT
Definition: efm32wg_usb.h:1282
#define USB_GAHBCFG_HBSTLEN_INCR
Definition: efm32wg_usb.h:460
#define USB_EPTYPE_BULK
Definition: em_usb.h:171