max4146x_comp

Dependencies:   MAX14690

Committer:
sdivarci
Date:
Sun Oct 25 20:10:02 2020 +0000
Revision:
0:0061165683ee
sdivarci

Who changed what in which revision?

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