Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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 }
Generated on Tue Jul 12 2022 15:37:27 by
1.7.2