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

« Back to documentation index

Show/hide line numbers usbd_max32625.c Source File

usbd_max32625.c

00001 /* CMSIS-DAP Interface Firmware
00002  * Copyright (c) 2009-2013 ARM Limited
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00017 #include <string.h>
00018 #include "rl_usb.h"
00019 #include "util.h"
00020 
00021 #include "max32625.h"
00022 #include "usb_regs.h"
00023 #include "clkman_regs.h"
00024 #include "pwrman_regs.h"
00025 #include "tmr_regs.h"
00026 
00027 #define __NO_USB_LIB_C
00028 #include "usb_config.c"
00029 
00030 #define EPNUM_MASK  (~USB_ENDPOINT_DIRECTION_MASK)
00031 
00032 #define INIT_INTS     (MXC_F_USB_DEV_INTEN_BRST | MXC_F_USB_DEV_INTFL_BRST_DN | MXC_F_USB_DEV_INTEN_VBUS | MXC_F_USB_DEV_INTFL_NO_VBUS)
00033 #define CONNECT_INTS  (MXC_F_USB_DEV_INTEN_SETUP | MXC_F_USB_DEV_INTEN_EP_IN | MXC_F_USB_DEV_INTEN_EP_OUT | MXC_F_USB_DEV_INTEN_DMA_ERR)
00034 
00035 typedef struct {
00036     volatile uint32_t buf0_desc;
00037     volatile uint32_t buf0_address;
00038     volatile uint32_t buf1_desc;
00039     volatile uint32_t buf1_address;
00040 } ep_buffer_t;
00041 
00042 typedef struct {
00043     ep_buffer_t out_buffer;
00044     ep_buffer_t in_buffer;
00045 } ep0_buffer_t;
00046 
00047 typedef struct {
00048     ep0_buffer_t ep0;
00049     ep_buffer_t ep[MXC_USB_NUM_EP - 1];
00050 } ep_buffer_descriptor_t;
00051 
00052 typedef struct {
00053     U8 type;
00054     U16 len;
00055 } ep_info_t;
00056 
00057 /* static storage for endpoint buffer descriptor table, must be 512 byte aligned for DMA */
00058 __attribute__ ((aligned (512)))
00059 ep_buffer_descriptor_t ep_buffer_descriptor;
00060 
00061 static uint32_t ep_buffer[MXC_USB_NUM_EP][MXC_USB_MAX_PACKET / sizeof(uint32_t)];
00062 static ep_info_t ep_info[MXC_USB_NUM_EP];
00063 static volatile int suspended;
00064 static volatile int setup_waiting;
00065 static volatile int ep0_expect_zlp;
00066 
00067 #if CDC_ENDPOINT
00068 /* CDC-ACM class processes FIFOs in the SOF interrupt. The USB Device interface
00069  * of Maxim's microcontrollers does not provide and SOF interrupt. A periodic
00070  * timer interrupt is used instead.
00071  */
00072 /******************************************************************************/
00073 void TMR0_IRQHandler(void)
00074 {
00075     MXC_TMR0->intfl = MXC_TMR0->intfl;
00076 
00077     if (usbd_configured()) {
00078         USBD_CDC_ACM_SOF_Event();
00079     }
00080 }
00081 #endif
00082 
00083 /******************************************************************************/
00084 static ep_buffer_t *get_desc(U32 EPNum)
00085 {
00086     ep_buffer_t *desc;
00087 
00088     if (EPNum == 0x80) {
00089         desc = &ep_buffer_descriptor.ep0.in_buffer;
00090     } else if (EPNum == 0x00) {
00091         desc = &ep_buffer_descriptor.ep0.out_buffer;
00092     } else {
00093         desc = &ep_buffer_descriptor.ep[(EPNum & EPNUM_MASK) - 1];
00094     }
00095 
00096     return desc;
00097 }
00098 
00099 /*
00100  *  USB Device Interrupt enable
00101  *   Called by USBD_Init to enable the USB Interrupt
00102  *    Return Value:    None
00103  */
00104 
00105 void          USBD_IntrEna(void)
00106 {
00107     NVIC_EnableIRQ(USB_IRQn );            /* Enable OTG interrupt */
00108 }
00109 
00110 /******************************************************************************/
00111 /*
00112  *  Usb interrupt enable/disable
00113  *    Parameters:      ena: enable/disable
00114  *                       0: disable interrupt
00115  *                       1: enable interrupt
00116  */
00117 #ifdef __RTX
00118 void __svc(1) USBD_Intr (int ena);
00119 void __SVC_1 (int ena)
00120 {
00121     if (ena) {
00122         NVIC_EnableIRQ(USB_IRQn );           /* Enable USB interrupt               */
00123     } else {
00124         NVIC_DisableIRQ(USB_IRQn );          /* Disable USB interrupt              */
00125     }
00126 }
00127 #endif
00128 
00129 /******************************************************************************/
00130 static void reset_state(void)
00131 {
00132     unsigned int ep;
00133 
00134     suspended = 0;
00135     setup_waiting = 0;
00136     ep0_expect_zlp = 0;
00137     memset(ep_info, 0, sizeof(ep_info));
00138 
00139     MXC_USB->ep[0] |= (MXC_S_USB_EP_DIR_CONTROL | MXC_F_USB_EP_INT_EN | MXC_F_USB_EP_DT);
00140     for (ep = 1; ep < MXC_USB_NUM_EP; ep++) {
00141         MXC_USB->ep[ep] = MXC_F_USB_EP_DT;
00142     }
00143 }
00144 
00145 /*
00146  *  USB Device Initialize Function
00147  *   Called by the User to initialize USB Device
00148  *    Return Value:    None
00149  */
00150 void USBD_Init (void)
00151 {
00152     uint32_t reg;
00153 
00154     /* Enable USB power domain */
00155     MXC_PWRMAN->pwr_rst_ctrl |= MXC_F_PWRMAN_PWR_RST_CTRL_USB_POWERED;
00156     /* Setup the USB clocking, select  */
00157     MXC_CLKMAN->clk_ctrl |= MXC_F_CLKMAN_CLK_CTRL_USB_CLOCK_ENABLE;
00158     /* Force USB clock gater */
00159     reg = MXC_CLKMAN->clk_gate_ctrl0;
00160     reg &= ~MXC_F_CLKMAN_CLK_GATE_CTRL0_USB_CLK_GATER;
00161     reg |= (0x2 << MXC_F_CLKMAN_CLK_GATE_CTRL0_USB_CLK_GATER_POS);
00162     MXC_CLKMAN->clk_gate_ctrl0 = reg;
00163 
00164     MXC_USB->cn = 0;
00165     MXC_USB->cn = MXC_F_USB_CN_USB_EN;
00166     MXC_USB->dev_inten = 0;
00167     MXC_USB->dev_intfl = 0xFFFF;  // clear interrupts
00168     MXC_USB->dev_cn = 0;
00169     MXC_USB->dev_cn |= MXC_F_USB_DEV_CN_URST;
00170     MXC_USB->dev_cn = 0;
00171 
00172     reset_state();
00173 
00174     /* set the descriptor location */
00175     MXC_USB->ep_base = (uint32_t)&ep_buffer_descriptor;
00176 
00177     /* enable some interrupts */
00178     MXC_USB->dev_inten = INIT_INTS;
00179     NVIC_EnableIRQ(USB_IRQn );
00180 }
00181 
00182 /*
00183  *  USB Device Connect Function
00184  *   Called by the User to Connect/Disconnect USB Device
00185  *    Parameters:      con:   Connect/Disconnect
00186  *    Return Value:    None
00187  */
00188 void USBD_Connect (BOOL con)
00189 {
00190     if (con) {
00191         MXC_USB->dev_intfl = 0xFFFF;  // clear interrupts
00192         MXC_USB->dev_inten |= CONNECT_INTS;
00193         MXC_USB->ep[0] |= MXC_F_USB_EP_INT_EN;
00194         MXC_USB->dev_cn |= (MXC_F_USB_DEV_CN_CONNECT | MXC_F_USB_DEV_CN_FIFO_MODE);
00195     } else {
00196         MXC_USB->dev_inten &= ~CONNECT_INTS;
00197         MXC_USB->ep[0] &= ~MXC_F_USB_EP_INT_EN;
00198         MXC_USB->dev_cn &= ~MXC_F_USB_DEV_CN_CONNECT;
00199     }
00200 }
00201 
00202 /*
00203  *  USB Device Remote Wakeup Configuration Function
00204  *    Parameters:      cfg:   Device Enable/Disable
00205  *    Return Value:    None
00206  */
00207 void USBD_WakeUpCfg (BOOL cfg)
00208 {
00209 }
00210 
00211 /*
00212  *  USB Device Set Address Function
00213  *    Parameters:      adr:   USB Device Address
00214  *    Return Value:    None
00215  */
00216 void USBD_SetAddress (U32 adr, U32 setup)
00217 {
00218     /* Performed by Hardware */
00219 }
00220 
00221 /*
00222  *  USB Device Configure Function
00223  *    Parameters:      cfg:   Device Configure/Deconfigure
00224  *    Return Value:    None
00225  */
00226 void USBD_Configure (BOOL cfg)
00227 {
00228 #if CDC_ENDPOINT
00229     /* CDC-ACM class processes FIFOs in the SOF interrupt. The USB Device interface
00230      * of Maxim's microcontrollers does not provide and SOF interrupt. A periodic
00231      * timer interrupt is used instead.
00232      */
00233 
00234     #define SOF_INT_US  1000
00235 
00236     if (cfg) {
00237         // Setup timer interrupt for SOF
00238         MXC_TMR0->ctrl = MXC_S_TMR_CTRL_MODE_CONTINUOUS;
00239         MXC_TMR0->count32 = 0;
00240         MXC_TMR0->term_cnt32 = (SystemCoreClock / 1000000) * SOF_INT_US;
00241 
00242         // Enable the interrupt
00243         MXC_TMR0->intfl = MXC_TMR0->intfl;
00244         NVIC_EnableIRQ(TMR0_0_IRQn);
00245         MXC_TMR0->inten = MXC_F_TMR_INTEN_TIMER0;
00246 
00247         // Start the timer
00248         MXC_TMR0->ctrl |= MXC_F_TMR_CTRL_ENABLE0;
00249 
00250     } else {
00251         // Disable tmr
00252         MXC_TMR0->ctrl &= ~(MXC_F_TMR_CTRL_ENABLE0);
00253     }
00254 #endif
00255 }
00256 
00257 /*
00258  *  Configure USB Device Endpoint according to Descriptor
00259  *    Parameters:      pEPD:  Pointer to Device Endpoint Descriptor
00260  *    Return Value:    None
00261  */
00262 void USBD_ConfigEP (USB_ENDPOINT_DESCRIPTOR *pEPD)
00263 {
00264     U32 EPNum;
00265 
00266     EPNum = pEPD->bEndpointAddress & EPNUM_MASK;
00267 
00268     if (EPNum < MXC_USB_NUM_EP) {
00269 
00270         // Clear existing configurations
00271         MXC_USB->ep[EPNum] = MXC_F_USB_EP_DT;
00272 
00273         if (pEPD->bEndpointAddress & USB_ENDPOINT_DIRECTION_MASK) {
00274             ep_info[EPNum].type = MXC_S_USB_EP_DIR_IN;
00275         } else {
00276             ep_info[EPNum].type = MXC_S_USB_EP_DIR_OUT;
00277         }
00278 
00279         ep_info[EPNum].len = pEPD->wMaxPacketSize;
00280     }
00281 }
00282 
00283 /*
00284  *  Set Direction for USB Device Control Endpoint
00285  *    Parameters:      dir:   Out (dir == 0), In (dir <> 0)
00286  *    Return Value:    None
00287  */
00288 void USBD_DirCtrlEP (U32 dir)
00289 {
00290     /* Not needed */
00291 }
00292 
00293 /*
00294  *  Enable USB Device Endpoint
00295  *    Parameters:      EPNum: Device Endpoint Number
00296  *                       EPNum.0..3: Address
00297  *                       EPNum.7:    Dir
00298  *    Return Value:    None
00299  */
00300 void USBD_EnableEP (U32 EPNum)
00301 {
00302     ep_buffer_t *desc = get_desc(EPNum);
00303 
00304     EPNum &= EPNUM_MASK;
00305     MXC_USB->ep[EPNum] |= (MXC_F_USB_EP_INT_EN | ep_info[EPNum].type | MXC_F_USB_EP_DT);
00306 
00307     if (ep_info[EPNum].type == MXC_S_USB_EP_DIR_OUT) {
00308         // This is an OUT endpoint. Go ahead and register a request.
00309         desc = get_desc(EPNum);
00310         desc->buf0_address = (uint32_t)ep_buffer[EPNum];
00311         desc->buf0_desc = sizeof(ep_buffer[EPNum]);
00312         MXC_USB->out_owner = (1 << EPNum);
00313     }
00314 }
00315 
00316 /*
00317  *  Disable USB Device Endpoint
00318  *    Parameters:      EPNum: Device Endpoint Number
00319  *                       EPNum.0..3: Address
00320  *                       EPNum.7:    Dir
00321  *    Return Value:    None
00322  */
00323 void USBD_DisableEP (U32 EPNum)
00324 {
00325     EPNum &= EPNUM_MASK;
00326     MXC_USB->ep[EPNum] = 0;
00327 }
00328 
00329 /*
00330  *  Reset USB Device Endpoint
00331  *    Parameters:      EPNum: Device Endpoint Number
00332  *                       EPNum.0..3: Address
00333  *                       EPNum.7:    Dir
00334  *    Return Value:    None
00335  */
00336 void USBD_ResetEP (U32 EPNum)
00337 {
00338     ep_buffer_t *desc = get_desc(EPNum);
00339 
00340     EPNum &= EPNUM_MASK;
00341     MXC_USB->ep[EPNum] |= MXC_F_USB_EP_DT;
00342 
00343     if (ep_info[EPNum].type == MXC_S_USB_EP_DIR_OUT) {
00344         // This is an OUT endpoint. Go ahead and register a request.
00345         desc = get_desc(EPNum);
00346         desc->buf0_address = (uint32_t)ep_buffer[EPNum];
00347         desc->buf0_desc = sizeof(ep_buffer[EPNum]);
00348         MXC_USB->out_owner = (1 << EPNum);
00349     }
00350 }
00351 
00352 /*
00353  *  Set Stall for USB Device Endpoint
00354  *    Parameters:      EPNum: Device Endpoint Number
00355  *                       EPNum.0..3: Address
00356  *                       EPNum.7:    Dir
00357  *    Return Value:    None
00358  */
00359 void USBD_SetStallEP (U32 EPNum)
00360 {
00361     EPNum &= EPNUM_MASK;
00362 
00363     if (EPNum == 0) {
00364         MXC_USB->ep[0] |= (MXC_F_USB_EP_ST_STALL | MXC_F_USB_EP_STALL);
00365     } else {
00366         MXC_USB->ep[EPNum] |= MXC_F_USB_EP_STALL;
00367     }
00368 }
00369 
00370 /*
00371  *  Clear Stall for USB Device Endpoint
00372  *    Parameters:      EPNum: Device Endpoint Number
00373  *                       EPNum.0..3: Address
00374  *                       EPNum.7:    Dir
00375  *    Return Value:    None
00376  */
00377 void USBD_ClrStallEP (U32 EPNum)
00378 {
00379     USBD_ResetEP(EPNum);
00380     MXC_USB->ep[EPNum & EPNUM_MASK] &= ~MXC_F_USB_EP_STALL;
00381 }
00382 
00383 /*
00384  *  Read USB Device Endpoint Data
00385  *    Parameters:      EPNum: Device Endpoint Number
00386  *                       EPNum.0..3: Address
00387  *                       EPNum.7:    Dir
00388  *                     pData: Pointer to Data Buffer
00389  *    Return Value:    Number of bytes read
00390  */
00391 U32 USBD_ReadEP (U32 EPNum, U8 *pData, U32 size)
00392 {
00393     U32 cnt;
00394     ep_buffer_t *desc = get_desc(EPNum);
00395     USB_SETUP_PACKET *sup;
00396 
00397     EPNum &= EPNUM_MASK;
00398 
00399     if ((EPNum == 0) && setup_waiting) {
00400         cnt = USBD_MAX_PACKET0;
00401 
00402         if (size < cnt) {
00403             cnt = size;
00404         }
00405         setup_waiting = 0;
00406         memcpy(pData, (void*)&MXC_USB->setup0, cnt);
00407         sup = (USB_SETUP_PACKET*)pData;
00408 
00409         if ( (sup->bmRequestType.Dir == REQUEST_HOST_TO_DEVICE) && (sup->wLength > 0) ) {
00410             // There is an OUT stage for this setup packet. Register a request.
00411             if (!(MXC_USB->out_owner & 1)) {
00412                 desc = &ep_buffer_descriptor.ep0.out_buffer;
00413                 desc->buf0_address = (uint32_t)ep_buffer[0];
00414                 desc->buf0_desc = sup->wLength;
00415                 MXC_USB->out_owner = 1;
00416             }
00417         }
00418     } else {
00419         cnt = desc->buf0_desc;
00420 
00421         if (size < cnt) {
00422             cnt = size;
00423         }
00424         memcpy(pData, ep_buffer[EPNum], cnt);
00425 
00426         // Register the next request.
00427         desc->buf0_address = (uint32_t)ep_buffer[EPNum];
00428         desc->buf0_desc = sizeof(ep_buffer[EPNum]);
00429         MXC_USB->out_owner = (1 << EPNum);
00430     }
00431 
00432     return cnt;
00433 }
00434 
00435 /*
00436  *  Write USB Device Endpoint Data
00437  *    Parameters:      EPNum: Endpoint Number
00438  *                       EPNum.0..3: Address
00439  *                       EPNum.7:    Dir
00440  *                     pData: Pointer to Data Buffer
00441  *                     cnt:   Number of bytes to write
00442  *    Return Value:    Number of bytes written
00443  */
00444 U32 USBD_WriteEP (U32 EPNum, U8 *pData, U32 cnt)
00445 {
00446     ep_buffer_t *desc = get_desc(EPNum);
00447     uint32_t mask;
00448 
00449     EPNum &= EPNUM_MASK;
00450     mask = (1 << EPNum);
00451 
00452     if (MXC_USB->in_owner & mask) {
00453         return 0;
00454     }
00455 
00456     if (EPNum == 0) {
00457         // Prepare to ACK the status stage.
00458         MXC_USB->ep[0] |= MXC_F_USB_EP_ST_ACK;
00459 
00460         if ((cnt == 0) && !ep0_expect_zlp) {
00461             // This is a status stage ACK. Handled in hardware.
00462             return 0;
00463         } else if (cnt == USBD_MAX_PACKET0) {
00464             ep0_expect_zlp = 1;
00465         } else {
00466             ep0_expect_zlp = 0;
00467         }
00468     }
00469 
00470     if (cnt > MXC_USB_MAX_PACKET) {
00471         cnt = MXC_USB_MAX_PACKET;
00472     }
00473 
00474     /* prepare data to be sent */
00475     memcpy(ep_buffer[EPNum], pData, cnt);
00476     desc->buf0_address = (uint32_t)ep_buffer[EPNum];
00477     desc->buf0_desc = cnt;
00478 
00479     /* start the transaction */
00480     MXC_USB->in_owner = mask;
00481 
00482     return cnt;
00483 }
00484 
00485 /*
00486  *  USB Device Interrupt Service Routine
00487  */
00488 void USB_IRQHandler (void)
00489 {
00490     NVIC_DisableIRQ(USB_IRQn );
00491     USBD_SignalHandler();
00492 }
00493 
00494 void USBD_Handler(void)
00495 {
00496     uint32_t irq_flags;
00497     unsigned int ep;
00498     uint32_t ep_int, mask;
00499 
00500     // Read and clear interrupts
00501     irq_flags = MXC_USB->dev_intfl;
00502     MXC_USB->dev_intfl = irq_flags;
00503 
00504     /* reset interrupt */
00505     if (irq_flags & MXC_F_USB_DEV_INTFL_BRST) {
00506         if (suspended) {
00507             suspended = 0;
00508 #ifdef __RTX
00509             if (USBD_RTX_DevTask) {
00510                 isr_evt_set(USBD_EVT_RESUME, USBD_RTX_DevTask);
00511             }
00512 #else
00513             if (USBD_P_Resume_Event) {
00514                 USBD_P_Resume_Event();
00515             }
00516 #endif
00517         }
00518 
00519         reset_state();
00520         usbd_reset_core();
00521 
00522 #ifdef __RTX
00523         if (USBD_RTX_DevTask) {
00524             isr_evt_set(USBD_EVT_RESET, USBD_RTX_DevTask);
00525         }
00526 #else
00527         if (USBD_P_Reset_Event) {
00528             USBD_P_Reset_Event();
00529         }
00530 #endif
00531 
00532     }
00533 
00534     /* reset done interrupt */
00535     if (irq_flags & MXC_F_USB_DEV_INTFL_BRST_DN) {
00536         reset_state();
00537     }
00538 
00539     /* suspend interrupt */
00540     if (irq_flags & MXC_F_USB_DEV_INTFL_SUSP) {
00541         suspended = 1;
00542 #ifdef __RTX
00543         if (USBD_RTX_DevTask) {
00544             isr_evt_set(USBD_EVT_SUSPEND, USBD_RTX_DevTask);
00545         }
00546 #else
00547         if (USBD_P_Suspend_Event) {
00548             USBD_P_Suspend_Event();
00549         }
00550 #endif
00551     }
00552 
00553     if (irq_flags & MXC_F_USB_DEV_INTFL_VBUS) {
00554 #ifdef __RTX
00555         if (USBD_RTX_DevTask) {
00556             isr_evt_set(USBD_EVT_POWER_ON,  USBD_RTX_DevTask);
00557         }
00558 #else
00559         if (USBD_P_Power_Event) {
00560             USBD_P_Power_Event(1);
00561         }
00562 #endif
00563     }
00564 
00565     if (irq_flags & MXC_F_USB_DEV_INTFL_NO_VBUS) {
00566 #ifdef __RTX
00567         if (USBD_RTX_DevTask) {
00568             isr_evt_set(USBD_EVT_POWER_OFF, USBD_RTX_DevTask);
00569         }
00570 #else
00571         if (USBD_P_Power_Event) {
00572             USBD_P_Power_Event(0);
00573         }
00574 #endif
00575     }
00576 
00577     if (irq_flags & MXC_F_USB_DEV_INTFL_SETUP) {
00578         setup_waiting = 1;
00579 #ifdef __RTX
00580         if (USBD_RTX_EPTask[0]) {
00581             isr_evt_set(USBD_EVT_SETUP, USBD_RTX_EPTask[0]);
00582         }
00583 #else
00584         if (USBD_P_EP[0]) {
00585             USBD_P_EP[0](USBD_EVT_SETUP);
00586         }
00587 #endif
00588     }
00589 
00590     if (irq_flags & MXC_F_USB_DEV_INTFL_EP_IN) {
00591 
00592         // Read and clear endpoint interrupts
00593         ep_int = MXC_USB->in_int;
00594         MXC_USB->in_int = ep_int;
00595 
00596         mask = 1;
00597         for (ep = 0; ep < MXC_USB_NUM_EP; ep++) {
00598             if (ep_int & mask) {
00599 #ifdef __RTX
00600                 if (USBD_RTX_EPTask[ep]) {
00601                     isr_evt_set(USBD_EVT_IN,  USBD_RTX_EPTask[ep]);
00602                 }
00603 #else
00604                 if (USBD_P_EP[ep]) {
00605                     USBD_P_EP[ep](USBD_EVT_IN);
00606                 }
00607 #endif
00608             }
00609 
00610             mask <<= 1;
00611         }
00612     }
00613 
00614     if (irq_flags & MXC_F_USB_DEV_INTFL_EP_OUT) {
00615 
00616         // Read and clear endpoint interrupts
00617         ep_int = MXC_USB->out_int;
00618         MXC_USB->out_int = ep_int;
00619 
00620         mask = 1;
00621         for (ep = 0; ep < MXC_USB_NUM_EP; ep++) {
00622             if (ep_int & mask) {
00623 #ifdef __RTX
00624                 if (USBD_RTX_EPTask[ep]) {
00625                     isr_evt_set(USBD_EVT_OUT, USBD_RTX_EPTask[ep]);
00626                 }
00627 #else
00628                 if (USBD_P_EP[ep]) {
00629                     USBD_P_EP[ep](USBD_EVT_OUT);
00630                 }
00631 #endif
00632             }
00633 
00634             mask <<= 1;
00635         }
00636     }
00637 
00638     if (irq_flags & MXC_F_USB_DEV_INTFL_DMA_ERR) {
00639         // Read and clear endpoint interrupts
00640         ep_int = MXC_USB->dma_err_int;
00641         MXC_USB->dma_err_int = ep_int;
00642         while(1); // not recoverable
00643     }
00644 
00645     NVIC_EnableIRQ(USB_IRQn );
00646 
00647 }