Arrow / Mbed OS DAPLink Reset
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers usbd_kinetis.c Source File

usbd_kinetis.c

Go to the documentation of this file.
00001 /**
00002  * @file    usbd_kinetis.c
00003  * @brief   
00004  *
00005  * DAPLink Interface Firmware
00006  * Copyright (c) 2009-2016, ARM Limited, All Rights Reserved
00007  * SPDX-License-Identifier: Apache-2.0
00008  *
00009  * Licensed under the Apache License, Version 2.0 (the "License"); you may
00010  * not use this file except in compliance with the License.
00011  * You may obtain a copy of the License at
00012  *
00013  * http://www.apache.org/licenses/LICENSE-2.0
00014  *
00015  * Unless required by applicable law or agreed to in writing, software
00016  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
00017  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00018  * See the License for the specific language governing permissions and
00019  * limitations under the License.
00020  */
00021 
00022 #include "rl_usb.h"
00023 #include "fsl_device_registers.h"
00024 #include "cortex_m.h"
00025 #include "util.h"
00026 #include "string.h"
00027 
00028 #define __NO_USB_LIB_C
00029 #include "usb_config.c"
00030 
00031 typedef struct __BUF_DESC {
00032     uint8_t    stat;
00033     uint8_t    reserved;
00034     uint16_t   bc;
00035     uint32_t   buf_addr;
00036 } BUF_DESC;
00037 
00038 BUF_DESC __align(512) BD[(USBD_EP_NUM + 1) * 2 * 2];
00039 uint8_t EPBuf[(USBD_EP_NUM + 1) * 2 * 2][64];
00040 uint8_t OutEpSize[USBD_EP_NUM + 1];
00041 uint8_t StatQueue[(USBD_EP_NUM + 1) * 2 * 2 + 1];
00042 uint32_t StatQueueHead = 0;
00043 uint32_t StatQueueTail = 0;
00044 uint32_t LastIstat = 0;
00045 uint8_t UsbSuspended = 0;
00046 uint8_t Ep0ZlpOut = 0; 
00047 
00048 uint32_t Data1  = 0x55555555;
00049 
00050 #define BD_OWN_MASK        0x80
00051 #define BD_DATA01_MASK     0x40
00052 #define BD_KEEP_MASK       0x20
00053 #define BD_NINC_MASK       0x10
00054 #define BD_DTS_MASK        0x08
00055 #define BD_STALL_MASK      0x04
00056 
00057 #define TX    1
00058 #define RX    0
00059 #define ODD   0
00060 #define EVEN  1
00061 #define IDX(Ep, dir, Ev_Odd) ((((Ep & 0x0F) * 4) + (2 * dir) + (1 *  Ev_Odd)))
00062 
00063 #define SETUP_TOKEN    0x0D
00064 #define IN_TOKEN       0x09
00065 #define OUT_TOKEN      0x01
00066 #define TOK_PID(idx)   ((BD[idx].stat >> 2) & 0x0F)
00067 
00068 inline static void protected_and(uint32_t *addr, uint32_t val)
00069 {
00070     cortex_int_state_t state;
00071     state = cortex_int_get_and_disable();
00072     *addr = *addr & val;
00073     cortex_int_restore(state);
00074 }
00075 inline static void protected_or(uint32_t *addr, uint32_t val)
00076 {
00077     cortex_int_state_t state;
00078     state = cortex_int_get_and_disable();
00079     *addr = *addr | val;
00080     cortex_int_restore(state);
00081 }
00082 inline static void protected_xor(uint32_t *addr, uint32_t val)
00083 {
00084     cortex_int_state_t state;
00085     state = cortex_int_get_and_disable();
00086     *addr = *addr ^ val;
00087     cortex_int_restore(state);
00088 }
00089 
00090 inline static void stat_enque(uint32_t stat)
00091 {
00092     cortex_int_state_t state;
00093     state = cortex_int_get_and_disable();
00094     StatQueue[StatQueueTail] = stat;
00095     StatQueueTail = (StatQueueTail + 1) % sizeof(StatQueue);
00096     cortex_int_restore(state);
00097 }
00098 
00099 inline static uint32_t stat_deque()
00100 {
00101     cortex_int_state_t state;
00102     uint32_t stat;
00103     state = cortex_int_get_and_disable();
00104     stat = StatQueue[StatQueueHead];
00105     StatQueueHead = (StatQueueHead + 1) % sizeof(StatQueue);
00106     cortex_int_restore(state);
00107 
00108     return stat;
00109 }
00110 
00111 inline static uint32_t stat_is_empty()
00112 {
00113     cortex_int_state_t state;
00114     uint32_t empty;
00115     state = cortex_int_get_and_disable();
00116     empty = StatQueueHead == StatQueueTail;
00117     cortex_int_restore(state);
00118     return empty;
00119 }
00120 
00121 /*
00122  *  USB Device Interrupt enable
00123  *   Called by USBD_Init to enable the USB Interrupt
00124  *    Return Value:    None
00125  */
00126 
00127 void USBD_IntrEna(void)
00128 {
00129     NVIC_EnableIRQ(USB0_IRQn);            /* Enable OTG interrupt               */
00130 }
00131 
00132 
00133 /*
00134  *  USB Device Initialize Function
00135  *   Called by the User to initialize USB
00136  *   Return Value:    None
00137  */
00138 
00139 void USBD_Init(void)
00140 {
00141     OutEpSize[0] = USBD_MAX_PACKET0;
00142     /* Enable all clocks needed for USB to function                             */
00143     /* Set USB clock to 48 MHz                                                  */
00144     SIM->SOPT2   |=   SIM_SOPT2_USBSRC_MASK     | /* MCGPLLCLK used as src      */
00145                       SIM_SOPT2_PLLFLLSEL_MASK  ; /* Select MCGPLLCLK as clock  */
00146 #if defined(TARGET_MK20D5)
00147     SIM->CLKDIV2 &= ~(SIM_CLKDIV2_USBFRAC_MASK  | /* Clear CLKDIV2 FS values    */
00148                       SIM_CLKDIV2_USBDIV_MASK);
00149     SIM->CLKDIV2  =   SIM_CLKDIV2_USBDIV(0)     ; /* USB clk = (PLL*1/2)        */
00150     /*         = ( 48*1/1)=48     */
00151 #endif // TARGET_MK20D5
00152     SIM->SCGC4   |=   SIM_SCGC4_USBOTG_MASK;      /* Enable USBOTG clock        */
00153     USBD_IntrEna();
00154     USB0->USBTRC0 |= USB_USBTRC0_USBRESET_MASK;
00155 
00156     while (USB0->USBTRC0 & USB_USBTRC0_USBRESET_MASK);
00157 
00158     USB0->BDTPAGE1 = (uint8_t)((uint32_t) BD >> 8);
00159     USB0->BDTPAGE2 = (uint8_t)((uint32_t) BD >> 16);
00160     USB0->BDTPAGE3 = (uint8_t)((uint32_t) BD >> 24);
00161     USB0->ISTAT   = 0xFF;                 /* clear interrupt flags              */
00162     /* enable interrupts                                                        */
00163     USB0->INTEN =                            USB_INTEN_USBRSTEN_MASK |
00164             USB_INTEN_TOKDNEEN_MASK |
00165             USB_INTEN_SLEEPEN_MASK  |
00166 #ifdef __RTX
00167             ((USBD_RTX_DevTask   != 0) ? USB_INTEN_SOFTOKEN_MASK : 0) |
00168             ((USBD_RTX_DevTask   != 0) ? USB_INTEN_ERROREN_MASK  : 0) ;
00169 #else
00170             ((USBD_P_SOF_Event   != 0) ? USB_INTEN_SOFTOKEN_MASK : 0) |
00171             ((USBD_P_Error_Event != 0) ? USB_INTEN_ERROREN_MASK  : 0) ;
00172 #endif
00173     USB0->USBCTRL  = USB_USBCTRL_PDE_MASK;/* pull dawn on D+ and D-             */
00174     USB0->USBTRC0 |= (1 << 6);            /* bit 6 must be set to 1             */
00175 }
00176 
00177 
00178 /*
00179  *  USB Device Connect Function
00180  *   Called by the User to Connect/Disconnect USB Device
00181  *    Parameters:      con:   Connect/Disconnect
00182  *    Return Value:    None
00183  */
00184 
00185 void USBD_Connect(uint32_t con)
00186 {
00187     if (con) {
00188         USB0->CTL  |= USB_CTL_USBENSOFEN_MASK;            /* enable USB           */
00189         USB0->CONTROL = USB_CONTROL_DPPULLUPNONOTG_MASK;  /* pull up on D+        */
00190     } else {
00191         USB0->CTL  &= ~USB_CTL_USBENSOFEN_MASK;           /* disable USB          */
00192         USB0->CONTROL &= ~USB_CONTROL_DPPULLUPNONOTG_MASK;/* pull down on D+      */
00193     }
00194 }
00195 
00196 
00197 /*
00198  *  USB Device Reset Function
00199  *   Called automatically on USB Device Reset
00200  *    Return Value:    None
00201  */
00202 
00203 void USBD_Reset(void)
00204 {
00205     uint32_t i;
00206 
00207     NVIC_DisableIRQ(USB0_IRQn);
00208 
00209     for (i = 1; i < 16; i++) {
00210         USB0->ENDPOINT[i].ENDPT = 0x00;
00211     }
00212 
00213     memset(StatQueue, 0, sizeof(StatQueue));
00214     StatQueueHead = 0;
00215     StatQueueTail = 0;
00216     LastIstat = 0;
00217     UsbSuspended = 0;
00218     Ep0ZlpOut = 0;
00219 
00220     /* EP0 control endpoint                                                     */
00221     BD[IDX(0, RX, ODD)].bc       = USBD_MAX_PACKET0;
00222     BD[IDX(0, RX, ODD)].buf_addr = (uint32_t) & (EPBuf[IDX(0, RX, ODD)][0]);
00223     BD[IDX(0, RX, ODD)].stat     = BD_OWN_MASK | BD_DTS_MASK | BD_DATA01_MASK;
00224     BD[IDX(0, RX, EVEN)].stat     = 0;
00225     BD[IDX(0, TX, ODD)].buf_addr = (uint32_t) & (EPBuf[IDX(0, TX, ODD)][0]);
00226     BD[IDX(0, TX, EVEN)].buf_addr = 0;
00227     USB0->ENDPOINT[0].ENDPT = USB_ENDPT_EPHSHK_MASK | /* enable ep handshaking  */
00228                               USB_ENDPT_EPTXEN_MASK | /* enable TX (IN) tran.   */
00229                               USB_ENDPT_EPRXEN_MASK;  /* enable RX (OUT) tran.  */
00230     Data1 = 0x55555555;
00231     USB0->CTL    |=  USB_CTL_ODDRST_MASK;
00232     USB0->ISTAT   =  0xFF;                /* clear all interrupt status flags   */
00233     USB0->ERRSTAT =  0xFF;                /* clear all error flags              */
00234     USB0->ERREN   =  0xFF;                /* enable error interrupt sources     */
00235     USB0->ADDR    =  0x00;                /* set default address                */
00236 
00237     NVIC_EnableIRQ(USB0_IRQn);
00238 }
00239 
00240 
00241 /*
00242  *  USB Device Suspend Function
00243  *   Called automatically on USB Device Suspend
00244  *    Return Value:    None
00245  */
00246 
00247 void USBD_Suspend(void)
00248 {
00249     USB0->INTEN |= USB_INTEN_RESUMEEN_MASK;
00250 }
00251 
00252 
00253 /*
00254  *  USB Device Resume Function
00255  *   Called automatically on USB Device Resume
00256  *    Return Value:    None
00257  */
00258 
00259 void USBD_Resume(void)
00260 {
00261     USB0->INTEN &= ~USB_INTEN_RESUMEEN_MASK;
00262 }
00263 
00264 
00265 /*
00266  *  USB Device Remote Wakeup Function
00267  *   Called automatically on USB Device Remote Wakeup
00268  *    Return Value:    None
00269  */
00270 
00271 void USBD_WakeUp(void)
00272 {
00273     uint32_t i = 50000;
00274 
00275     if (USBD_DeviceStatus & USB_GETSTATUS_REMOTE_WAKEUP) {
00276         USB0->CTL |=  USB_CTL_RESUME_MASK;
00277 
00278         while (i--) {
00279             __nop();
00280         }
00281 
00282         USB0->CTL &= ~USB_CTL_RESUME_MASK;
00283     }
00284 }
00285 
00286 
00287 /*
00288  *  USB Device Remote Wakeup Configuration Function
00289  *    Parameters:      cfg:   Device Enable/Disable
00290  *    Return Value:    None
00291  */
00292 
00293 void USBD_WakeUpCfg(uint32_t cfg)
00294 {
00295     /* Not needed                                                               */
00296 }
00297 
00298 
00299 /*
00300  *  USB Device Set Address Function
00301  *    Parameters:      adr:   USB Device Address
00302  *    Return Value:    None
00303  */
00304 
00305 void USBD_SetAddress(uint32_t  adr, uint32_t setup)
00306 {
00307     if (!setup) {
00308         USB0->ADDR    = adr & 0x7F;
00309     }
00310 }
00311 
00312 
00313 /*
00314  *  USB Device Configure Function
00315  *    Parameters:      cfg:   Device Configure/Deconfigure
00316  *    Return Value:    None
00317  */
00318 
00319 void USBD_Configure(uint32_t cfg)
00320 {
00321 }
00322 
00323 
00324 /*
00325  *  Configure USB Device Endpoint according to Descriptor
00326  *    Parameters:      pEPD:  Pointer to Device Endpoint Descriptor
00327  *    Return Value:    None
00328  */
00329 
00330 void USBD_ConfigEP(USB_ENDPOINT_DESCRIPTOR *pEPD)
00331 {
00332     uint32_t num, val;
00333     num  = pEPD->bEndpointAddress;
00334     val  = pEPD->wMaxPacketSize;
00335 
00336     if (!(pEPD->bEndpointAddress & 0x80)) {
00337         OutEpSize[num] = val;
00338     }
00339 
00340     USBD_ResetEP(num);
00341 }
00342 
00343 
00344 /*
00345  *  Set Direction for USB Device Control Endpoint
00346  *    Parameters:      dir:   Out (dir == 0), In (dir <> 0)
00347  *    Return Value:    None
00348  */
00349 
00350 void USBD_DirCtrlEP(uint32_t dir)
00351 {
00352     /* Not needed                                                               */
00353 }
00354 
00355 
00356 /*
00357  *  Enable USB Device Endpoint
00358  *    Parameters:      EPNum: Device Endpoint Number
00359  *                       EPNum.0..3: Address
00360  *                       EPNum.7:    Dir
00361  *    Return Value:    None
00362  */
00363 
00364 void USBD_EnableEP(uint32_t EPNum)
00365 {
00366     if (EPNum & 0x80) {
00367         EPNum &= 0x0F;
00368         USB0->ENDPOINT[EPNum].ENDPT |= USB_ENDPT_EPHSHK_MASK | /*en ep handshaking*/
00369                                        USB_ENDPT_EPTXEN_MASK;  /*en TX (IN) tran  */
00370     } else {
00371         USB0->ENDPOINT[EPNum].ENDPT |= USB_ENDPT_EPHSHK_MASK | /*en ep handshaking*/
00372                                        USB_ENDPT_EPRXEN_MASK;  /*en RX (OUT) tran.*/
00373     }
00374 }
00375 
00376 
00377 /*
00378  *  Disable USB Endpoint
00379  *    Parameters:      EPNum: Endpoint Number
00380  *                       EPNum.0..3: Address
00381  *                       EPNum.7:    Dir
00382  *    Return Value:    None
00383  */
00384 
00385 void USBD_DisableEP(uint32_t EPNum)
00386 {
00387     if (EPNum & 0x80) {
00388         EPNum &= 0x0F;
00389         USB0->ENDPOINT[EPNum].ENDPT &= ~(USB_ENDPT_EPHSHK_MASK |/*dis handshaking */
00390                                          USB_ENDPT_EPTXEN_MASK);/*dis TX(IN) tran */
00391     } else {
00392         USB0->ENDPOINT[EPNum].ENDPT &= ~(USB_ENDPT_EPHSHK_MASK |/*dis handshaking */
00393                                          USB_ENDPT_EPRXEN_MASK);/*dis RX(OUT) tran*/
00394     }
00395 }
00396 
00397 
00398 /*
00399  *  Reset USB Device Endpoint
00400  *    Parameters:      EPNum: Device Endpoint Number
00401  *                       EPNum.0..3: Address
00402  *                       EPNum.7:    Dir
00403  *    Return Value:    None
00404  */
00405 
00406 void USBD_ResetEP(uint32_t EPNum)
00407 {
00408     if (EPNum & 0x80) {
00409         EPNum &= 0x0F;
00410         protected_or(&Data1, (1 << ((EPNum * 2) + 1)));
00411         BD[IDX(EPNum, TX, ODD)].buf_addr = (uint32_t) & (EPBuf[IDX(EPNum, TX, ODD)][0]);
00412         BD[IDX(EPNum, TX, EVEN)].buf_addr = 0;
00413     } else {
00414         protected_and(&Data1, ~(1 << (EPNum * 2)));
00415         BD[IDX(EPNum, RX, ODD)].bc       = OutEpSize[EPNum];
00416         BD[IDX(EPNum, RX, ODD)].buf_addr = (uint32_t) & (EPBuf[IDX(EPNum, RX, ODD)][0]);
00417         BD[IDX(EPNum, RX, ODD)].stat     = BD_OWN_MASK | BD_DTS_MASK;
00418         BD[IDX(EPNum, RX, EVEN)].stat     = 0;
00419     }
00420 }
00421 
00422 /*
00423  *  Set Stall for USB Device Endpoint
00424  *    Parameters:      EPNum: Device Endpoint Number
00425  *                       EPNum.0..3: Address
00426  *                       EPNum.7:    Dir
00427  *    Return Value:    None
00428  */
00429 
00430 void USBD_SetStallEP(uint32_t EPNum)
00431 {
00432     EPNum &= 0x0F;
00433     USB0->ENDPOINT[EPNum].ENDPT |= USB_ENDPT_EPSTALL_MASK;
00434 }
00435 
00436 
00437 /*
00438  *  Clear Stall for USB Device Endpoint
00439  *    Parameters:      EPNum: Device Endpoint Number
00440  *                       EPNum.0..3: Address
00441  *                       EPNum.7:    Dir
00442  *    Return Value:    None
00443  */
00444 
00445 void USBD_ClrStallEP(uint32_t EPNum)
00446 {
00447     USB0->ENDPOINT[EPNum & 0x0F].ENDPT &= ~USB_ENDPT_EPSTALL_MASK;
00448     USBD_ResetEP(EPNum);
00449 }
00450 
00451 
00452 /*
00453  *  Clear USB Device Endpoint Buffer
00454  *    Parameters:      EPNum: Device Endpoint Number
00455  *                       EPNum.0..3: Address
00456  *                       EPNum.7:    Dir
00457  *    Return Value:    None
00458  */
00459 
00460 void USBD_ClearEPBuf(uint32_t EPNum)
00461 {
00462 }
00463 
00464 
00465 /*
00466  *  Read USB Device Endpoint Data
00467  *    Parameters:      EPNum: Device Endpoint Number
00468  *                       EPNum.0..3: Address
00469  *                       EPNum.7:    Dir
00470  *                     pData: Pointer to Data Buffer
00471  *    Return Value:    Number of bytes read
00472  */
00473 
00474 uint32_t USBD_ReadEP(uint32_t EPNum, uint8_t *pData, uint32_t size)
00475 {
00476     uint32_t n, sz, idx, setup = 0;
00477     idx = IDX(EPNum, RX, 0);
00478     sz  = BD[idx].bc;
00479 
00480     if ((EPNum == 0) && Ep0ZlpOut) {
00481         // This packet was a zero length data out packet. It has already
00482         // been processed by USB0_IRQHandler. Only toggle the DATAx bit
00483         // and return a size of 0.
00484         protected_xor(&Data1, (1 << (idx / 2)));
00485         return 0;
00486     }
00487 
00488     if ((EPNum == 0) && (TOK_PID(idx) == SETUP_TOKEN)) {
00489         setup = 1;
00490     }
00491 
00492     if (size < sz) {
00493         util_assert(0);
00494         sz = size;
00495     }
00496 
00497     for (n = 0; n < sz; n++) {
00498         pData[n] = EPBuf[idx][n];
00499     }
00500 
00501     BD[idx].bc = OutEpSize[EPNum];
00502 
00503     if ((Data1 >> (idx / 2) & 1) == ((BD[idx].stat >> 6) & 1)) {
00504         uint32_t xfer_size = (pData[7] << 8) | (pData[6] << 0);
00505         if (setup && (0 == xfer_size)) {     /* if no setup data stage,            */
00506             protected_and(&Data1, ~1);           /* set DATA0                          */
00507         } else {
00508             protected_xor(&Data1, (1 << (idx / 2)));
00509         }
00510     }
00511 
00512     if ((Data1 >> (idx / 2)) & 1) {
00513         BD[idx].stat  = BD_DTS_MASK | BD_DATA01_MASK;
00514         BD[idx].stat |= BD_OWN_MASK;
00515     } else {
00516         BD[idx].stat  = BD_DTS_MASK;
00517         BD[idx].stat |= BD_OWN_MASK;
00518     }
00519 
00520     return (sz);
00521 }
00522 
00523 
00524 /*
00525  *  Write USB Device Endpoint Data
00526  *    Parameters:      EPNum: Device Endpoint Number
00527  *                       EPNum.0..3: Address
00528  *                       EPNum.7:    Dir
00529  *                     pData: Pointer to Data Buffer
00530  *                     cnt:   Number of bytes to write
00531  *    Return Value:    Number of bytes written
00532  */
00533 
00534 uint32_t USBD_WriteEP(uint32_t EPNum, uint8_t *pData, uint32_t cnt)
00535 {
00536     uint32_t idx, n;
00537     EPNum &= 0x0F;
00538     idx = IDX(EPNum, TX, 0);
00539     BD[idx].bc = cnt;
00540 
00541     for (n = 0; n < cnt; n++) {
00542         EPBuf[idx][n] = pData[n];
00543     }
00544 
00545     if ((Data1 >> (idx / 2)) & 1) {
00546         BD[idx].stat = BD_OWN_MASK | BD_DTS_MASK;
00547     } else {
00548         BD[idx].stat = BD_OWN_MASK | BD_DTS_MASK | BD_DATA01_MASK;
00549     }
00550 
00551     protected_xor(&Data1, (1 << (idx / 2)));
00552     return (cnt);
00553 }
00554 
00555 /*
00556  *  Get USB Device Last Frame Number
00557  *    Parameters:      None
00558  *    Return Value:    Frame Number
00559  */
00560 
00561 uint32_t USBD_GetFrame(void)
00562 {
00563     return ((USB0->FRMNUML | (USB0->FRMNUMH << 8) & 0x07FF));
00564 }
00565 
00566 #ifdef __RTX
00567 U32 LastError;                          /* Last Error                         */
00568 
00569 /*
00570  *  Get USB Device Last Error Code
00571  *    Parameters:      None
00572  *    Return Value:    Error Code
00573  */
00574 
00575 U32 USBD_GetError(void)
00576 {
00577     return (LastError);
00578 }
00579 #endif
00580 
00581 
00582 /*
00583  *  USB Device Interrupt Service Routine
00584  */
00585 void USB0_IRQHandler(void)
00586 {
00587     uint32_t istat, num, dir, ev_odd;
00588     uint32_t new_istat;
00589     uint8_t suspended = 0;
00590 
00591     new_istat = istat = USB0->ISTAT;
00592 
00593     // Read all tokens
00594     if (istat & USB_ISTAT_TOKDNE_MASK) {
00595         while (istat & USB_ISTAT_TOKDNE_MASK) {
00596             uint8_t stat = USB0->STAT;
00597             num    = (stat >> 4) & 0x0F;
00598             dir    = (stat >> 3) & 0x01;
00599             ev_odd = (stat >> 2) & 0x01;
00600 
00601             // Consume all zero length OUT packets on endpoint 0 to prevent
00602             // a subsequent SETUP packet from being dropped
00603             if ((0 == num) && (RX == dir)) {
00604                 uint32_t idx;
00605                 idx = IDX(num, dir, ev_odd);
00606                 if ((TOK_PID(idx) == OUT_TOKEN) && (BD[idx].bc == 0)) {
00607                     BD[idx].bc = OutEpSize[num];
00608                     if (BD[idx].stat & BD_DATA01_MASK) {
00609                         BD[idx].stat = BD_OWN_MASK | BD_DTS_MASK;
00610                     } else {
00611                         BD[idx].stat = BD_OWN_MASK | BD_DTS_MASK | BD_DATA01_MASK;
00612                     }
00613                     stat |= 1 << 0;
00614                 }
00615             }
00616 
00617             stat_enque(stat);
00618             USB0->ISTAT = USB_ISTAT_TOKDNE_MASK;
00619 
00620             // Check if USB is suspending before checking istat
00621             suspended = suspended || USB0->CTL & USB_CTL_TXSUSPENDTOKENBUSY_MASK;
00622             istat = USB0->ISTAT;
00623         }
00624     }
00625 
00626     // Set global istat and suspended flags
00627     new_istat |= istat;
00628     protected_or(&LastIstat, new_istat);
00629     UsbSuspended |= suspended ? 1 : 0;
00630     USB0->ISTAT = istat;
00631 
00632     USBD_SignalHandler();
00633 }
00634 
00635 /*
00636  *  USB Device Service Routine
00637  */
00638 
00639 void USBD_Handler(void)
00640 {
00641     uint32_t istr, num, dir, ev_odd;
00642     cortex_int_state_t state;
00643     uint8_t suspended = 0;
00644 
00645     // Get ISTAT
00646     state = cortex_int_get_and_disable();
00647     istr = LastIstat;
00648     LastIstat = 0;
00649     suspended = UsbSuspended;
00650     UsbSuspended = 0;
00651     cortex_int_restore(state);
00652 
00653 
00654     /* reset interrupt                                                            */
00655     if (istr & USB_ISTAT_USBRST_MASK) {
00656         USBD_Reset();
00657         usbd_reset_core();
00658 #ifdef __RTX
00659 
00660         if (USBD_RTX_DevTask) {
00661             isr_evt_set(USBD_EVT_RESET, USBD_RTX_DevTask);
00662         }
00663 
00664 #else
00665 
00666         if (USBD_P_Reset_Event) {
00667             USBD_P_Reset_Event();
00668         }
00669 
00670 #endif
00671     }
00672 
00673     /* suspend interrupt                                                          */
00674     if (istr & USB_ISTAT_SLEEP_MASK) {
00675         USBD_Suspend();
00676 #ifdef __RTX
00677 
00678         if (USBD_RTX_DevTask) {
00679             isr_evt_set(USBD_EVT_SUSPEND, USBD_RTX_DevTask);
00680         }
00681 
00682 #else
00683 
00684         if (USBD_P_Suspend_Event) {
00685             USBD_P_Suspend_Event();
00686         }
00687 
00688 #endif
00689     }
00690 
00691     /* resume interrupt                                                           */
00692     if (istr & USB_ISTAT_RESUME_MASK) {
00693         USBD_Resume();
00694 #ifdef __RTX
00695 
00696         if (USBD_RTX_DevTask) {
00697             isr_evt_set(USBD_EVT_RESUME, USBD_RTX_DevTask);
00698         }
00699 
00700 #else
00701 
00702         if (USBD_P_Resume_Event) {
00703             USBD_P_Resume_Event();
00704         }
00705 
00706 #endif
00707     }
00708 
00709     /* Start Of Frame                                                             */
00710     if (istr & USB_ISTAT_SOFTOK_MASK) {
00711 #ifdef __RTX
00712 
00713         if (USBD_RTX_DevTask) {
00714             isr_evt_set(USBD_EVT_SOF, USBD_RTX_DevTask);
00715         }
00716 
00717 #else
00718 
00719         if (USBD_P_SOF_Event) {
00720             USBD_P_SOF_Event();
00721         }
00722 
00723 #endif
00724     }
00725 
00726     /* Error interrupt                                                            */
00727     if (istr == USB_ISTAT_ERROR_MASK) {
00728 #ifdef __RTX
00729         LastError = USB0->ERRSTAT;
00730 
00731         if (USBD_RTX_DevTask) {
00732             isr_evt_set(USBD_EVT_ERROR, USBD_RTX_DevTask);
00733         }
00734 
00735 #else
00736 
00737         if (USBD_P_Error_Event) {
00738             USBD_P_Error_Event(USB0->ERRSTAT);
00739         }
00740 
00741 #endif
00742         USB0->ERRSTAT = 0xFF;
00743     }
00744 
00745     /* token interrupt                                                            */
00746     if (istr & USB_ISTAT_TOKDNE_MASK) {
00747         while (!stat_is_empty()) {
00748             uint32_t stat;
00749 
00750             stat = stat_deque();
00751             num    = (stat >> 4) & 0x0F;
00752             dir    = (stat >> 3) & 0x01;
00753             ev_odd = (stat >> 2) & 0x01;
00754 
00755             /* setup packet                                                               */
00756             if ((num == 0) && (TOK_PID((IDX(num, dir, ev_odd))) == SETUP_TOKEN)) {
00757                 Data1 &= ~0x02;
00758                 BD[IDX(0, TX, EVEN)].stat &= ~BD_OWN_MASK;
00759                 BD[IDX(0, TX, ODD)].stat  &= ~BD_OWN_MASK;
00760                 Ep0ZlpOut = 0;
00761 #ifdef __RTX
00762 
00763                 if (USBD_RTX_EPTask[num]) {
00764                     isr_evt_set(USBD_EVT_SETUP, USBD_RTX_EPTask[num]);
00765                 }
00766 
00767 #else
00768 
00769                 if (USBD_P_EP[num]) {
00770                     USBD_P_EP[num](USBD_EVT_SETUP);
00771                 }
00772 
00773 #endif
00774 
00775             } else {
00776                 /* OUT packet                                                                 */
00777                 if (TOK_PID((IDX(num, dir, ev_odd))) == OUT_TOKEN) {
00778                     if (0 == num) {
00779                         Ep0ZlpOut = stat & (1 << 0);
00780                     }
00781 #ifdef __RTX
00782 
00783                     if (USBD_RTX_EPTask[num]) {
00784                         isr_evt_set(USBD_EVT_OUT, USBD_RTX_EPTask[num]);
00785                     }
00786 
00787 #else
00788 
00789                     if (USBD_P_EP[num]) {
00790                         USBD_P_EP[num](USBD_EVT_OUT);
00791                     }
00792 
00793 #endif
00794                 }
00795 
00796                 /* IN packet                                                                  */
00797                 if (TOK_PID((IDX(num, dir, ev_odd))) == IN_TOKEN) {
00798 #ifdef __RTX
00799 
00800                     if (USBD_RTX_EPTask[num]) {
00801                         isr_evt_set(USBD_EVT_IN,  USBD_RTX_EPTask[num]);
00802                     }
00803 
00804 #else
00805 
00806                     if (USBD_P_EP[num]) {
00807                         USBD_P_EP[num](USBD_EVT_IN);
00808                     }
00809 
00810 #endif
00811                 }
00812             }
00813         }
00814     }
00815 
00816     if (suspended) {
00817         USB0->CTL &= ~USB_CTL_TXSUSPENDTOKENBUSY_MASK;
00818     }
00819 }