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