USB device stack

Dependents:   USBMSD_step1 USBMSD_step1_5 picossd_step1_2cs

Revision:
71:53949e6131f6
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/targets/TARGET_Silicon_Labs/inc/em_usbhal.h	Thu Jul 27 12:14:04 2017 +0100
@@ -0,0 +1,757 @@
+/***************************************************************************//**
+ * @file em_usbhal.h
+ * @brief USB protocol stack library, low level USB peripheral access.
+ * @version 3.20.14
+ *******************************************************************************
+ * @section License
+ * <b>(C) Copyright 2014 Silicon Labs, http://www.silabs.com</b>
+ *******************************************************************************
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#ifndef __EM_USBHAL_H
+#define __EM_USBHAL_H
+
+#include "em_device.h"
+#if defined( USB_PRESENT ) && ( USB_COUNT == 1 )
+#include "em_usb.h"
+#if defined( USB_DEVICE ) || defined( USB_HOST )
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
+
+#define USB_PID_DATA0         0
+#define USB_PID_DATA2         1
+#define USB_PID_DATA1         2
+#define USB_PID_SETUP         3
+
+#define HPRT_F_SPEED          ( 1 << _USB_HPRT_PRTSPD_SHIFT )
+#define HPRT_L_SPEED          ( 2 << _USB_HPRT_PRTSPD_SHIFT )
+#define HCFG_PHYCLK_48MHZ     1
+#define HCFG_PHYCLK_6MHZ      2
+
+#define DOEP0_XFERSIZE_PKTCNT_MASK ( _USB_DOEP0TSIZ_XFERSIZE_MASK | \
+                                     _USB_DOEP0TSIZ_PKTCNT_MASK   )
+#define DOEP_XFERSIZE_PKTCNT_MASK  ( _USB_DOEP_TSIZ_XFERSIZE_MASK | \
+                                     _USB_DOEP_TSIZ_PKTCNT_MASK   )
+
+#define DIEP0_XFERSIZE_PKTCNT_MASK ( _USB_DIEP0TSIZ_XFERSIZE_MASK | \
+                                     _USB_DIEP0TSIZ_PKTCNT_MASK   )
+#define DIEP_XFERSIZE_PKTCNT_MASK  ( _USB_DIEP_TSIZ_XFERSIZE_MASK | \
+                                     _USB_DIEP_TSIZ_PKTCNT_MASK   | \
+                                     _USB_DIEP_TSIZ_MC_MASK       )
+
+#define DIEPCTL_EPTYPE_CONTROL (0 << _USB_DIEP_CTL_EPTYPE_SHIFT )
+#define DIEPCTL_EPTYPE_ISOC    (1 << _USB_DIEP_CTL_EPTYPE_SHIFT )
+#define DIEPCTL_EPTYPE_BULK    (2 << _USB_DIEP_CTL_EPTYPE_SHIFT )
+#define DIEPCTL_EPTYPE_INTR    (3 << _USB_DIEP_CTL_EPTYPE_SHIFT )
+
+#define DOEPCTL_EPTYPE_CONTROL (0 << _USB_DOEP_CTL_EPTYPE_SHIFT )
+#define DOEPCTL_EPTYPE_ISOC    (1 << _USB_DOEP_CTL_EPTYPE_SHIFT )
+#define DOEPCTL_EPTYPE_BULK    (2 << _USB_DOEP_CTL_EPTYPE_SHIFT )
+#define DOEPCTL_EPTYPE_INTR    (3 << _USB_DOEP_CTL_EPTYPE_SHIFT )
+
+#define HCCHAR_EPTYPE_CTRL     (0 << _USB_HC_CHAR_EPTYPE_SHIFT )
+#define HCCHAR_EPTYPE_ISOC     (1 << _USB_HC_CHAR_EPTYPE_SHIFT )
+#define HCCHAR_EPTYPE_BULK     (2 << _USB_HC_CHAR_EPTYPE_SHIFT )
+#define HCCHAR_EPTYPE_INTR     (3 << _USB_HC_CHAR_EPTYPE_SHIFT )
+
+#define GRXSTSP_PKTSTS_DEVICE_GOTNAK          ( 1 << _USB_GRXSTSP_PKTSTS_SHIFT )
+#define GRXSTSP_PKTSTS_DEVICE_DATAOUTRECEIVED ( 2 << _USB_GRXSTSP_PKTSTS_SHIFT )
+#define GRXSTSP_PKTSTS_DEVICE_DATAOUTCOMPLETE ( 3 << _USB_GRXSTSP_PKTSTS_SHIFT )
+#define GRXSTSP_PKTSTS_DEVICE_SETUPCOMPLETE   ( 4 << _USB_GRXSTSP_PKTSTS_SHIFT )
+#define GRXSTSP_PKTSTS_DEVICE_SETUPRECEIVED   ( 6 << _USB_GRXSTSP_PKTSTS_SHIFT )
+
+#define GRXSTSP_PKTSTS_HOST_DATAINRECEIVED  ( 2 << _USB_GRXSTSP_PKTSTS_SHIFT )
+#define GRXSTSP_PKTSTS_HOST_DATAINCOMPLETE  ( 3 << _USB_GRXSTSP_PKTSTS_SHIFT )
+#define GRXSTSP_PKTSTS_HOST_DATATOGGLEERROR ( 5 << _USB_GRXSTSP_PKTSTS_SHIFT )
+#define GRXSTSP_PKTSTS_HOST_CHANNELHALTED   ( 7 << _USB_GRXSTSP_PKTSTS_SHIFT )
+
+#define DCTL_WO_BITMASK \
+          ( _USB_DCTL_CGOUTNAK_MASK  | _USB_DCTL_SGOUTNAK_MASK   | \
+            _USB_DCTL_CGNPINNAK_MASK | _USB_DCTL_SGNPINNAK_MASK  )
+#define GUSBCFG_WO_BITMASK ( USB_GUSBCFG_CORRUPTTXPKT )
+#define DEPCTL_WO_BITMASK \
+          ( USB_DIEP_CTL_CNAK       | USB_DIEP_CTL_SNAK        | \
+            USB_DIEP_CTL_SETD0PIDEF | USB_DIEP_CTL_SETD1PIDOF  )
+
+#define HPRT_WC_MASK ( USB_HPRT_PRTCONNDET | USB_HPRT_PRTENA | \
+                       USB_HPRT_PRTENCHNG  | USB_HPRT_PRTOVRCURRCHNG )
+
+typedef __IO uint32_t USB_FIFO_TypeDef[ 0x1000 / sizeof( uint32_t ) ];
+typedef __IO uint32_t USB_DIEPTXF_TypeDef;
+
+#define USB_DINEPS       ((USB_DIEP_TypeDef    *) &USB->DIEP0CTL )
+#define USB_DOUTEPS      ((USB_DOEP_TypeDef    *) &USB->DOEP0CTL )
+#define USB_FIFOS        ((USB_FIFO_TypeDef    *) &USB->FIFO0D   )
+#define USB_DIEPTXFS     ((USB_DIEPTXF_TypeDef *) &USB->DIEPTXF1 )
+
+void USBHAL_CoreReset( void );
+
+#if defined( USB_DEVICE )
+void USBDHAL_AbortAllTransfers( USB_Status_TypeDef reason );
+USB_Status_TypeDef USBDHAL_CoreInit( const uint32_t totalRxFifoSize,
+                                     const uint32_t totalTxFifoSize );
+void USBDHAL_Connect( void );
+void USBDHAL_Disconnect( void );
+void USBDHAL_AbortAllEps( void );
+void USBDHAL_AbortEpIn( USBD_Ep_TypeDef *ep );
+void USBDHAL_AbortEpOut( USBD_Ep_TypeDef *ep );
+
+__STATIC_INLINE USB_Status_TypeDef USBDHAL_GetStallStatusEp(
+                                   USBD_Ep_TypeDef *ep, uint16_t *halt );
+__STATIC_INLINE uint32_t USBDHAL_GetInEpInts( USBD_Ep_TypeDef *ep );
+__STATIC_INLINE uint32_t USBDHAL_GetOutEpInts( USBD_Ep_TypeDef *ep );
+__STATIC_INLINE void USBDHAL_SetEPDISNAK( USBD_Ep_TypeDef *ep );
+#endif /* defined( USB_DEVICE ) */
+
+#if defined( USB_HOST )
+USB_Status_TypeDef USBHHAL_CoreInit( const uint32_t rxFifoSize,
+                                     const uint32_t nptxFifoSize,
+                                     const uint32_t ptxFifoSize );
+void USBHHAL_HCHalt(  int hcnum, uint32_t hcchar );
+void USBHHAL_HCInit(  int hcnum );
+void USBHHAL_HCStart( int hcnum );
+#endif /* defined( USB_HOST ) */
+
+__STATIC_INLINE void USBHAL_DisableGlobalInt( void )
+{
+  USB->GAHBCFG &= ~USB_GAHBCFG_GLBLINTRMSK;
+}
+
+__STATIC_INLINE void USBHAL_DisablePhyPins( void )
+{
+  USB->ROUTE = _USB_ROUTE_RESETVALUE;
+}
+
+__STATIC_INLINE void USBHAL_DisableUsbInt( void )
+{
+  USB->IEN = _USB_IEN_RESETVALUE;
+}
+
+__STATIC_INLINE void USBHAL_EnableGlobalInt( void )
+{
+  USB->GAHBCFG |= USB_GAHBCFG_GLBLINTRMSK;
+}
+
+__STATIC_INLINE void USBHAL_FlushRxFifo( void )
+{
+  USB->GRSTCTL = USB_GRSTCTL_RXFFLSH;
+  while ( USB->GRSTCTL & USB_GRSTCTL_RXFFLSH ) {}
+}
+
+__STATIC_INLINE void USBHAL_FlushTxFifo( uint8_t fifoNum )
+{
+  USB->GRSTCTL = USB_GRSTCTL_TXFFLSH | ( fifoNum << _USB_GRSTCTL_TXFNUM_SHIFT );
+  while ( USB->GRSTCTL & USB_GRSTCTL_TXFFLSH ) {}
+}
+
+__STATIC_INLINE uint32_t USBHAL_GetCoreInts( void )
+{
+  uint32_t retVal;
+
+  retVal  = USB->GINTSTS;
+  retVal &= USB->GINTMSK;
+
+  return retVal;
+}
+
+__STATIC_INLINE bool USBHAL_VbusIsOn( void )
+{
+  return ( USB->STATUS & USB_STATUS_VREGOS ) != 0;
+}
+
+#if defined( USB_DEVICE )
+__STATIC_INLINE void USBDHAL_ActivateEp( USBD_Ep_TypeDef *ep, bool forceIdle )
+{
+#define DIEP_MPS_EPTYPE_TXFNUM_MASK ( _USB_DIEP_CTL_MPS_MASK    | \
+                                      _USB_DIEP_CTL_EPTYPE_MASK | \
+                                      _USB_DIEP_CTL_TXFNUM_MASK )
+#define DOEP_MPS_EPTYPE_MASK        ( _USB_DOEP_CTL_MPS_MASK    | \
+                                      _USB_DOEP_CTL_EPTYPE_MASK )
+  uint32_t daintmask, depctl;
+
+  if ( forceIdle )
+    ep->state = D_EP_IDLE;
+
+  if ( ep->in )
+  {
+    daintmask = ep->mask;
+    depctl = USB_DINEPS[ ep->num ].CTL & ~DEPCTL_WO_BITMASK;
+
+    if ( !( depctl & USB_DIEP_CTL_USBACTEP ) )
+    {
+      depctl = ( depctl                                     &
+                 ~( DIEP_MPS_EPTYPE_TXFNUM_MASK          |
+                    USB_DIEP_CTL_STALL                     )  ) |
+               ( ep->packetSize << _USB_DIEP_CTL_MPS_SHIFT    ) |
+               ( ep->type       << _USB_DIEP_CTL_EPTYPE_SHIFT ) |
+               ( ep->txFifoNum  << _USB_DIEP_CTL_TXFNUM_SHIFT ) |
+               USB_DIEP_CTL_SETD0PIDEF                          |
+               USB_DIEP_CTL_USBACTEP                            |
+               USB_DIEP_CTL_SNAK;
+    }
+    else
+    {
+      depctl |= USB_DIEP_CTL_SETD0PIDEF;
+    }
+    USB_DINEPS[ ep->num ].CTL = depctl;
+  }
+  else
+  {
+    daintmask = ep->mask << _USB_DAINTMSK_OUTEPMSK0_SHIFT;
+    depctl = USB_DOUTEPS[ ep->num ].CTL & ~DEPCTL_WO_BITMASK;
+
+    if ( !( depctl & USB_DOEP_CTL_USBACTEP ) )
+    {
+      depctl = ( depctl                                     &
+                 ~( DOEP_MPS_EPTYPE_MASK                 |
+                    USB_DOEP_CTL_STALL                     )  ) |
+               ( ep->packetSize << _USB_DOEP_CTL_MPS_SHIFT    ) |
+               ( ep->type       << _USB_DOEP_CTL_EPTYPE_SHIFT ) |
+               USB_DOEP_CTL_SETD0PIDEF                          |
+               USB_DOEP_CTL_USBACTEP                            |
+               USB_DOEP_CTL_SNAK;
+    }
+    else
+    {
+      depctl |= USB_DOEP_CTL_SETD0PIDEF;
+    }
+    USB_DOUTEPS[ ep->num ].CTL = depctl;
+  }
+
+  /* Enable interrupt for this EP */
+  USB->DAINTMSK |= daintmask;
+
+#undef DIEP_MPS_EPTYPE_TXFNUM_MASK
+#undef DOEP_MPS_EPTYPE_MASK
+}
+
+__STATIC_INLINE void USBDHAL_ClearRemoteWakeup( void )
+{
+  USB->DCTL &= ~( DCTL_WO_BITMASK | USB_DCTL_RMTWKUPSIG );
+}
+
+__STATIC_INLINE void USBDHAL_DeactivateEp( USBD_Ep_TypeDef *ep )
+{
+  uint32_t daintmask;
+
+  if ( ep->in )
+  {
+    USB_DINEPS[ ep->num ].CTL = 0;
+    daintmask = ep->mask;
+  }
+  else
+  {
+    USB_DOUTEPS[ ep->num ].CTL = 0;
+    daintmask = ep->mask << _USB_DAINTMSK_OUTEPMSK0_SHIFT;
+  }
+
+  /* Disable interrupt for this EP */
+  USB->DAINTMSK &= ~daintmask;
+}
+
+__STATIC_INLINE void USBDHAL_EnableInts( USBD_Device_TypeDef *dev )
+{
+  uint32_t mask;
+
+  /* Disable all interrupts. */
+  USB->GINTMSK = 0;
+
+  /* Clear pending interrupts */
+  USB->GINTSTS = 0xFFFFFFFF;
+
+  mask = USB_GINTMSK_USBSUSPMSK     |
+         USB_GINTMSK_USBRSTMSK      |
+         USB_GINTMSK_ENUMDONEMSK    |
+         USB_GINTMSK_IEPINTMSK      |
+         USB_GINTMSK_OEPINTMSK      |
+         USB_GINTMSK_WKUPINTMSK;
+
+  if ( dev->callbacks->sofInt )
+  {
+    mask |= USB_GINTMSK_SOFMSK;
+  }
+
+  USB->GINTMSK = mask;
+}
+
+__STATIC_INLINE void USBDHAL_EnableUsbResetAndSuspendInt( void )
+{
+  /* Disable all interrupts. */
+  USB->GINTMSK = 0;
+
+  USB->GINTMSK = USB_GINTMSK_USBRSTMSK | USB_GINTMSK_USBSUSPMSK;
+}
+
+__STATIC_INLINE void USBDHAL_Ep0Activate( uint32_t ep0mps )
+{
+  USB->DCTL = ( USB->DCTL & ~DCTL_WO_BITMASK ) | USB_DCTL_CGNPINNAK;
+
+  USB->DOEP0CTL = ( USB->DOEP0CTL & ~DEPCTL_WO_BITMASK )
+                  | USB_DOEP0CTL_CNAK | USB_DOEP0CTL_EPENA
+                  | ep0mps;
+}
+
+__STATIC_INLINE bool USBDHAL_EpIsStalled( USBD_Ep_TypeDef *ep )
+{
+  bool retVal = false;
+  uint16_t stallStatus;
+
+  if ( USBDHAL_GetStallStatusEp( ep, &stallStatus ) == USB_STATUS_OK )
+  {
+    retVal = stallStatus & 1 ? true : false;
+  }
+  return retVal;
+}
+
+__STATIC_INLINE uint32_t USBDHAL_GetAllInEpInts( void )
+{
+  uint32_t retVal;
+
+  retVal  = USB->DAINT;
+  retVal &= USB->DAINTMSK;
+  return retVal & 0xFFFF;
+}
+
+__STATIC_INLINE uint32_t USBDHAL_GetAllOutEpInts( void )
+{
+  uint32_t retVal;
+
+  retVal  = USB->DAINT;
+  retVal &= USB->DAINTMSK;
+  return retVal >> 16;
+}
+
+__STATIC_INLINE uint32_t USBDHAL_GetInEpInts( USBD_Ep_TypeDef *ep )
+{
+  uint32_t retVal, msk;
+
+  msk    = USB->DIEPMSK;
+  retVal = USB_DINEPS[ ep->num ].INT;
+
+  return retVal & msk;
+}
+
+__STATIC_INLINE uint32_t USBDHAL_GetOutEpInts( USBD_Ep_TypeDef *ep )
+{
+  uint32_t retVal;
+
+  retVal  = USB_DOUTEPS[ ep->num ].INT;
+#if defined( USB_DOEP0INT_STUPPKTRCVD )
+  retVal &= USB->DOEPMSK | USB_DOEP0INT_STUPPKTRCVD;
+#else
+  retVal &= USB->DOEPMSK;
+#endif
+
+  return retVal;
+}
+
+__STATIC_INLINE USB_Status_TypeDef USBDHAL_GetStallStatusEp(
+                                   USBD_Ep_TypeDef *ep, uint16_t *halt )
+{
+  uint32_t depctl, eptype;
+  USB_Status_TypeDef retVal = USB_STATUS_REQ_ERR;
+
+  if ( ep->in == true )
+  {
+    depctl = USB_DINEPS[ ep->num ].CTL;
+    eptype = depctl & _USB_DIEP_CTL_EPTYPE_MASK;
+
+    if (( eptype == DIEPCTL_EPTYPE_INTR ) || ( eptype == DIEPCTL_EPTYPE_BULK ))
+    {
+      *halt = depctl & USB_DIEP_CTL_STALL ? 1 : 0;
+      retVal = USB_STATUS_OK;
+    }
+  }
+  else
+  {
+    depctl = USB_DOUTEPS[ ep->num ].CTL;
+    eptype = depctl & _USB_DOEP_CTL_EPTYPE_MASK;
+
+    if (( eptype == DOEPCTL_EPTYPE_INTR ) || ( eptype == DOEPCTL_EPTYPE_BULK ))
+    {
+      *halt = depctl & USB_DOEP_CTL_STALL ? 1 : 0;
+      retVal = USB_STATUS_OK;
+    }
+  }
+
+  return retVal;
+}
+
+__STATIC_INLINE void USBDHAL_ReenableEp0Setup( USBD_Device_TypeDef *dev )
+
+{
+  USB->DOEP0DMAADDR = (uint32_t)dev->setupPkt;
+  USB->DOEP0CTL = ( USB->DOEP0CTL & ~DEPCTL_WO_BITMASK )
+                  | USB_DOEP0CTL_EPENA
+                  | dev->ep0MpsCode;
+}
+
+__STATIC_INLINE void USBDHAL_SetAddr( uint8_t addr )
+{
+  USB->DCFG = ( USB->DCFG                    &
+                ~_USB_DCFG_DEVADDR_MASK        ) |
+              (addr << _USB_DCFG_DEVADDR_SHIFT );
+}
+
+__STATIC_INLINE void USBDHAL_SetEp0InDmaPtr( uint8_t* addr )
+{
+  USB->DIEP0DMAADDR = (uint32_t)addr;
+}
+
+__STATIC_INLINE void USBDHAL_SetEp0OutDmaPtr( uint8_t* addr )
+{
+  USB->DOEP0DMAADDR = (uint32_t)addr;
+}
+
+__STATIC_INLINE void USBDHAL_SetEPDISNAK( USBD_Ep_TypeDef *ep )
+{
+  if ( ep->in )
+  {
+    USB_DINEPS[ ep->num ].CTL = ( USB_DINEPS[ ep->num ].CTL   &
+                                  ~DEPCTL_WO_BITMASK            ) |
+                                USB_DIEP_CTL_SNAK                 |
+                                USB_DIEP_CTL_EPDIS;
+  }
+  else
+  {
+    USB_DOUTEPS[ ep->num ].CTL = ( USB_DOUTEPS[ ep->num ].CTL   &
+                                   ~DEPCTL_WO_BITMASK             ) |
+                                 USB_DOEP_CTL_EPENA;
+
+    USB_DOUTEPS[ ep->num ].CTL = ( USB_DOUTEPS[ ep->num ].CTL   &
+                                   ~DEPCTL_WO_BITMASK             ) |
+                                 USB_DOEP_CTL_SNAK                  |
+                                 USB_DOEP_CTL_EPDIS;
+  }
+}
+
+__STATIC_INLINE void USBDHAL_SetRemoteWakeup( void )
+{
+  USB->DCTL = ( USB->DCTL & ~DCTL_WO_BITMASK ) | USB_DCTL_RMTWKUPSIG;
+}
+
+__STATIC_INLINE USB_Status_TypeDef USBDHAL_StallEp( USBD_Ep_TypeDef *ep )
+{
+  uint32_t depctl, eptype;
+  USB_Status_TypeDef retVal = USB_STATUS_REQ_ERR;
+
+  if ( ep->in == true )
+  {
+    depctl = USB_DINEPS[ ep->num ].CTL & ~DEPCTL_WO_BITMASK;
+    eptype = depctl & _USB_DIEP_CTL_EPTYPE_MASK;
+
+    if ( eptype != DIEPCTL_EPTYPE_ISOC )
+    {
+      if ( depctl & USB_DIEP_CTL_EPENA )
+      {
+        depctl |= USB_DIEP_CTL_EPDIS;
+      }
+      USB_DINEPS[ ep->num ].CTL = depctl | USB_DIEP_CTL_STALL;
+      retVal = USB_STATUS_OK;
+    }
+  }
+  else
+  {
+    depctl = USB_DOUTEPS[ ep->num ].CTL & ~DEPCTL_WO_BITMASK;
+    eptype = depctl & _USB_DOEP_CTL_EPTYPE_MASK;
+
+    if ( eptype != DIEPCTL_EPTYPE_ISOC )
+    {
+      USB_DOUTEPS[ ep->num ].CTL = depctl | USB_DOEP_CTL_STALL;
+      retVal = USB_STATUS_OK;
+    }
+  }
+
+  return retVal;
+}
+
+__STATIC_INLINE void USBDHAL_StartEp0In( uint32_t len, uint32_t ep0mps )
+{
+  USB->DIEP0TSIZ = ( len << _USB_DIEP0TSIZ_XFERSIZE_SHIFT   ) |
+                   ( 1   << _USB_DIEP0TSIZ_PKTCNT_SHIFT     );
+
+  USB->DIEP0CTL = ( USB->DIEP0CTL & ~DEPCTL_WO_BITMASK )
+                  | USB_DIEP0CTL_CNAK | USB_DIEP0CTL_EPENA
+                  | ep0mps;
+}
+
+__STATIC_INLINE void USBDHAL_StartEp0Out( uint32_t len, uint32_t ep0mps )
+{
+  USB->DOEP0TSIZ = ( len << _USB_DOEP0TSIZ_XFERSIZE_SHIFT ) |
+                   ( 1   << _USB_DOEP0TSIZ_PKTCNT_SHIFT   );
+
+  USB->DOEP0CTL = ( USB->DOEP0CTL & ~DEPCTL_WO_BITMASK )
+                  | USB_DOEP0CTL_CNAK | USB_DOEP0CTL_EPENA
+                  | ep0mps;
+}
+
+__STATIC_INLINE void USBDHAL_StartEp0Setup( USBD_Device_TypeDef *dev )
+{
+  dev->ep[ 0 ].in = false;
+
+#if defined( USB_DOEP0INT_STUPPKTRCVD )
+  USB->DOEP0TSIZ = ( 8*3 << _USB_DOEP0TSIZ_XFERSIZE_SHIFT ) |
+                   ( 1   << _USB_DOEP0TSIZ_PKTCNT_SHIFT   ) |
+                   ( 3   << _USB_DOEP0TSIZ_SUPCNT_SHIFT   );
+#else
+  USB->DOEP0TSIZ = 3 << _USB_DOEP0TSIZ_SUPCNT_SHIFT;
+#endif
+
+  dev->setup = dev->setupPkt;
+  USB->DOEP0DMAADDR = (uint32_t)dev->setup;
+
+#if defined( USB_DOEP0INT_STUPPKTRCVD )
+  USB->DOEP0CTL = ( USB->DOEP0CTL & ~DEPCTL_WO_BITMASK )
+                  | USB_DOEP0CTL_EPENA
+                  | dev->ep0MpsCode;
+#else
+  USB->DOEP0CTL = ( USB->DOEP0CTL & ~DEPCTL_WO_BITMASK )
+                  | USB_DOEP0CTL_CNAK | USB_DOEP0CTL_EPENA
+                  | dev->ep0MpsCode;
+#endif
+}
+
+__STATIC_INLINE void USBDHAL_StartEpIn( USBD_Ep_TypeDef *ep )
+{
+  uint32_t pktcnt, xfersize;
+
+  if ( ep->remaining == 0 )     /* ZLP ? */
+  {
+    pktcnt = 1;
+    xfersize = 0;
+  }
+  else
+  {
+    pktcnt = ( ep->remaining - 1 + ep->packetSize ) / ep->packetSize;
+    xfersize = ep->remaining;
+  }
+
+  USB_DINEPS[ ep->num ].TSIZ =
+                ( USB_DINEPS[ ep->num ].TSIZ                &
+                  ~DIEP_XFERSIZE_PKTCNT_MASK                  ) |
+                ( xfersize << _USB_DIEP_TSIZ_XFERSIZE_SHIFT   ) |
+                ( pktcnt   << _USB_DIEP_TSIZ_PKTCNT_SHIFT     );
+
+  USB_DINEPS[ ep->num ].DMAADDR = (uint32_t)ep->buf;
+  USB_DINEPS[ ep->num ].CTL =
+                  ( USB_DINEPS[ ep->num ].CTL & ~DEPCTL_WO_BITMASK ) |
+                  USB_DIEP_CTL_CNAK                                  |
+                  USB_DIEP_CTL_EPENA;
+}
+
+__STATIC_INLINE void USBDHAL_StartEpOut( USBD_Ep_TypeDef *ep )
+{
+  uint32_t pktcnt, xfersize;
+
+  if ( ep->remaining == 0 )     /* ZLP ? */
+  {
+    pktcnt = 1;
+    xfersize = ep->packetSize;
+  }
+  else
+  {
+    pktcnt = ( ep->remaining - 1 + ep->packetSize ) / ep->packetSize;
+    xfersize = pktcnt * ep->packetSize;
+  }
+
+  USB_DOUTEPS[ ep->num ].TSIZ =
+                  ( USB_DOUTEPS[ ep->num ].TSIZ               &
+                    ~DOEP_XFERSIZE_PKTCNT_MASK                  ) |
+                  ( xfersize << _USB_DOEP_TSIZ_XFERSIZE_SHIFT   ) |
+                  ( pktcnt   << _USB_DOEP_TSIZ_PKTCNT_SHIFT     );
+
+  ep->hwXferSize = xfersize;
+  USB_DOUTEPS[ ep->num ].DMAADDR = (uint32_t)ep->buf;
+  USB_DOUTEPS[ ep->num ].CTL =
+                          ( USB_DOUTEPS[ ep->num ].CTL  &
+                            ~DEPCTL_WO_BITMASK             ) |
+                          USB_DOEP_CTL_CNAK                  |
+                          USB_DOEP_CTL_EPENA;
+}
+
+__STATIC_INLINE USB_Status_TypeDef USBDHAL_UnStallEp( USBD_Ep_TypeDef *ep )
+{
+  uint32_t depctl, eptype;
+  USB_Status_TypeDef retVal = USB_STATUS_REQ_ERR;
+
+  if ( ep->in == true )
+  {
+    depctl = USB_DINEPS[ ep->num ].CTL & ~DEPCTL_WO_BITMASK;
+    eptype = depctl & _USB_DIEP_CTL_EPTYPE_MASK;
+
+    if (( eptype == DIEPCTL_EPTYPE_INTR ) || ( eptype == DIEPCTL_EPTYPE_BULK ))
+    {
+      depctl |=  USB_DIEP_CTL_SETD0PIDEF;
+      depctl &= ~USB_DIEP_CTL_STALL;
+      USB_DINEPS[ ep->num ].CTL = depctl;
+      retVal = USB_STATUS_OK;
+    }
+  }
+  else
+  {
+    depctl = USB_DOUTEPS[ ep->num ].CTL & ~DEPCTL_WO_BITMASK;
+    eptype = depctl & _USB_DOEP_CTL_EPTYPE_MASK;
+
+    if (( eptype == DIEPCTL_EPTYPE_INTR ) || ( eptype == DIEPCTL_EPTYPE_BULK ))
+    {
+      depctl |=  USB_DOEP_CTL_SETD0PIDEF;
+      depctl &= ~USB_DOEP_CTL_STALL;
+      USB_DOUTEPS[ ep->num ].CTL = depctl;
+      retVal = USB_STATUS_OK;
+    }
+  }
+
+  return retVal;
+}
+#endif /* defined( USB_DEVICE ) */
+
+#if defined( USB_HOST )
+__STATIC_INLINE void USBHHAL_HCActivate( int hcnum, uint32_t hcchar, bool intep )
+{
+  uint32_t oddframe;
+
+  if ( intep )
+  {
+    oddframe = USB->HFNUM & 1;
+
+    USB->HC[ hcnum ].CHAR =
+                    ( hcchar &
+                      ~( USB_HC_CHAR_CHDIS | _USB_HC_CHAR_ODDFRM_MASK ) ) |
+
+                    /* Schedule INT transfers to start in next frame. */
+                    ( oddframe & 1 ? 0 : USB_HC_CHAR_ODDFRM             ) |
+
+                    USB_HC_CHAR_CHENA;
+  }
+  else
+  {
+    USB->HC[ hcnum ].CHAR = ( hcchar & ~USB_HC_CHAR_CHDIS ) |
+                              USB_HC_CHAR_CHENA;
+  }
+}
+
+__STATIC_INLINE bool USBHHAL_InitializedAndPowered( void )
+{
+  if ( ( USB->ROUTE & USB_ROUTE_PHYPEN ) &&
+       ( USB->HPRT  & USB_HPRT_PRTPWR  )    )
+    return true;
+  return false;
+}
+
+__STATIC_INLINE void USBHHAL_EnableInts( void )
+{
+  /* Disable all interrupts. */
+  USB->GINTMSK = 0;
+
+  /* Clear pending OTG interrupts */
+  USB->GOTGINT = 0xFFFFFFFF;
+
+  /* Clear pending interrupts */
+  USB->GINTSTS = 0xFFFFFFFF;
+
+  USB->GINTMSK = USB_GINTMSK_PRTINTMSK     |
+                 USB_GINTMSK_HCHINTMSK     |
+                 USB_GINTMSK_DISCONNINTMSK;
+}
+
+__STATIC_INLINE uint16_t USBHHAL_GetFrameNum( void )
+{
+  return USB->HFNUM;
+}
+
+__STATIC_INLINE uint32_t USBHHAL_GetHcChar( uint8_t hcnum )
+{
+  return USB->HC[ hcnum ].CHAR;
+}
+
+__STATIC_INLINE uint32_t USBHHAL_GetHcInts( uint8_t hcnum )
+{
+  uint32_t retVal;
+
+  retVal  = USB->HC[ hcnum ].INT;
+  return retVal;
+}
+
+__STATIC_INLINE uint32_t USBHHAL_GetHostChannelInts( void )
+{
+  return USB->HAINT;
+}
+
+__STATIC_INLINE uint8_t USBHHAL_GetPortSpeed( void )
+{
+  return ( USB->HPRT & _USB_HPRT_PRTSPD_MASK ) >> _USB_HPRT_PRTSPD_SHIFT;
+}
+
+__STATIC_INLINE void USBHHAL_PortReset( bool on )
+{
+  if ( on )
+  {
+    DEBUG_USB_INT_LO_PUTCHAR( '+' );
+    USB->HPRT = ( USB->HPRT & ~HPRT_WC_MASK ) | USB_HPRT_PRTRST;
+  }
+  else
+  {
+    DEBUG_USB_INT_LO_PUTCHAR( '-' );
+    USB->HPRT &= ~( HPRT_WC_MASK | USB_HPRT_PRTRST );
+  }
+}
+
+__STATIC_INLINE void USBHHAL_PortResume( bool on )
+{
+  if ( on )
+  {
+    USB->HPRT = ( USB->HPRT & ~( HPRT_WC_MASK | USB_HPRT_PRTSUSP ) ) |
+                USB_HPRT_PRTRES;
+  }
+  else
+  {
+    USB->HPRT &= ~( HPRT_WC_MASK | USB_HPRT_PRTSUSP | USB_HPRT_PRTRES );
+  }
+}
+
+__STATIC_INLINE void USBHHAL_PortSuspend( void )
+{
+  USB->HPRT = ( USB->HPRT & ~HPRT_WC_MASK ) | USB_HPRT_PRTSUSP;
+}
+
+__STATIC_INLINE void USBHHAL_VbusOn( bool on )
+{
+  if ( on )
+  {
+    USB->HPRT = ( USB->HPRT & ~HPRT_WC_MASK ) | USB_HPRT_PRTPWR;
+    DEBUG_USB_INT_LO_PUTCHAR( '/' );
+  }
+  else
+  {
+    USB->HPRT &= ~( HPRT_WC_MASK | USB_HPRT_PRTPWR );
+    DEBUG_USB_INT_LO_PUTCHAR( '\\' );
+  }
+}
+#endif /* defined( USB_HOST ) */
+
+/** @endcond */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* defined( USB_DEVICE ) || defined( USB_HOST ) */
+#endif /* defined( USB_PRESENT ) && ( USB_COUNT == 1 ) */
+#endif /* __EM_USBHAL_H */