e8fd5f4928f5afa30f82db3a532fc52e1ccf6674
[rapper.git] / new_cmsis / usb / hw.c
1 /*----------------------------------------------------------------------------
2  *      U S B  -  K e r n e l
3  *----------------------------------------------------------------------------
4  * Name:    usbhw.c
5  * Purpose: USB Hardware Layer Module for NXP's LPC17xx MCU
6  * Version: V1.20
7  *----------------------------------------------------------------------------
8  *      This software is supplied "AS IS" without any warranties, express,
9  *      implied or statutory, including but not limited to the implied
10  *      warranties of fitness for purpose, satisfactory quality and
11  *      noninfringement. Keil extends you a royalty-free right to reproduce
12  *      and distribute executable files created using this software for use
13  *      on NXP Semiconductors LPC family microcontroller devices only. Nothing 
14  *      else gives you the right to use this software.
15  *
16  * Copyright (c) 2009 Keil - An ARM Company. All rights reserved.
17  *----------------------------------------------------------------------------
18  * History:
19  *          V1.20 Added USB_ClearEPBuf
20  *          V1.00 Initial Version
21  *----------------------------------------------------------------------------*/
22 #include <board.h>                        /* LPC17xx definitions */
23 #include "usb.h"
24 #include "cfg.h"
25 #include "reg.h"
26 #include "hw.h"
27 #include "core.h"
28 #include "user.h"
29
30 #if defined (  __CC_ARM__  )
31 #pragma diag_suppress 1441
32 #endif
33
34
35 #define EP_MSK_CTRL 0x0001      /* Control Endpoint Logical Address Mask */
36 #define EP_MSK_BULK 0xC924      /* Bulk Endpoint Logical Address Mask */
37 #define EP_MSK_INT  0x4492      /* Interrupt Endpoint Logical Address Mask */
38 #define EP_MSK_ISO  0x1248      /* Isochronous Endpoint Logical Address Mask */
39
40
41 #if USB_DMA
42
43 #pragma arm section zidata = "USB_RAM"
44 uint32_t UDCA[USB_EP_NUM];                     /* UDCA in USB RAM */
45 uint32_t DD_NISO_Mem[4*DD_NISO_CNT];           /* Non-Iso DMA Descriptor Memory */
46 uint32_t DD_ISO_Mem [5*DD_ISO_CNT];            /* Iso DMA Descriptor Memory */
47 #pragma arm section zidata
48 uint32_t udca[USB_EP_NUM];                     /* UDCA saved values */
49
50 uint32_t DDMemMap[2];                          /* DMA Descriptor Memory Usage */
51
52 #endif
53
54
55 /*
56  *  Get Endpoint Physical Address
57  *    Parameters:      EPNum: Endpoint Number
58  *                       EPNum.0..3: Address
59  *                       EPNum.7:    Dir
60  *    Return Value:    Endpoint Physical Address
61  */
62
63 uint32_t EPAdr (uint32_t EPNum) {
64   uint32_t val;
65
66   val = (EPNum & 0x0F) << 1;
67   if (EPNum & 0x80) {
68     val += 1;
69   }
70   return (val);
71 }
72
73
74 /*
75  *  Write Command
76  *    Parameters:      cmd:   Command
77  *    Return Value:    None
78  */
79
80 void WrCmd (uint32_t cmd) {
81
82   USB->USBDevIntClr = CCEMTY_INT;
83   USB->USBCmdCode = cmd;
84   while ((USB->USBDevIntSt & CCEMTY_INT) == 0);
85 }
86
87
88 /*
89  *  Write Command Data
90  *    Parameters:      cmd:   Command
91  *                     val:   Data
92  *    Return Value:    None
93  */
94
95 void WrCmdDat (uint32_t cmd, uint32_t val) {
96
97   USB->USBDevIntClr = CCEMTY_INT;
98   USB->USBCmdCode = cmd;
99   while ((USB->USBDevIntSt & CCEMTY_INT) == 0);
100   USB->USBDevIntClr = CCEMTY_INT;
101   USB->USBCmdCode = val;
102   while ((USB->USBDevIntSt & CCEMTY_INT) == 0);
103 }
104
105
106 /*
107  *  Write Command to Endpoint
108  *    Parameters:      cmd:   Command
109  *                     val:   Data
110  *    Return Value:    None
111  */
112
113 void WrCmdEP (uint32_t EPNum, uint32_t cmd){
114
115   USB->USBDevIntClr = CCEMTY_INT;
116   USB->USBCmdCode = CMD_SEL_EP(EPAdr(EPNum));
117   while ((USB->USBDevIntSt & CCEMTY_INT) == 0);
118   USB->USBDevIntClr = CCEMTY_INT;
119   USB->USBCmdCode = cmd;
120   while ((USB->USBDevIntSt & CCEMTY_INT) == 0);
121 }
122
123
124 /*
125  *  Read Command Data
126  *    Parameters:      cmd:   Command
127  *    Return Value:    Data Value
128  */
129
130 uint32_t RdCmdDat (uint32_t cmd) {
131
132   USB->USBDevIntClr = CCEMTY_INT | CDFULL_INT;
133   USB->USBCmdCode = cmd;
134   while ((USB->USBDevIntSt & CDFULL_INT) == 0);
135   return (USB->USBCmdData);
136 }
137
138
139 /*
140  *  USB Initialize Function
141  *   Called by the User to initialize USB
142  *    Return Value:    None
143  */
144
145 void USB_Init (void) {
146
147   PINCON->PINSEL1 &= ~((3<<26)|(3<<28));   /* P0.29 D+, P0.30 D- */
148   PINCON->PINSEL1 |=  ((1<<26)|(1<<28));   /* PINSEL1 26.27, 28.29  = 01 */
149
150   PINCON->PINSEL3 &= ~((3<< 4)|(3<<28));   /* P1.18 GoodLink, P1.30 VBUS */
151   PINCON->PINSEL3 |=  ((1<< 4)|(2<<28));   /* PINSEL3 4.5 = 01, 28.29 = 10 */
152
153   PINCON->PINSEL4 &= ~((3<<18)        );   /* P2.9 SoftConnect */
154   PINCON->PINSEL4 |=  ((1<<18)        );   /* PINSEL4 18.19 = 01 */
155
156   SC->PCONP |= (1UL<<31);                /* USB PCLK -> enable USB Per.       */
157
158   USB->USBClkCtrl = 0x1A;                /* Dev, PortSel, AHB clock enable */
159   while ((USB->USBClkSt & 0x1A) != 0x1A); 
160
161   NVIC_EnableIRQ(USB_IRQn);               /* enable USB interrupt */
162
163   USB_Reset();
164   USB_SetAddress(0);
165 }
166
167
168 /*
169  *  USB Connect Function
170  *   Called by the User to Connect/Disconnect USB
171  *    Parameters:      con:   Connect/Disconnect
172  *    Return Value:    None
173  */
174
175 void USB_Connect (uint32_t con) {
176   WrCmdDat(CMD_SET_DEV_STAT, DAT_WR_BYTE(con ? DEV_CON : 0));
177 }
178
179
180 /*
181  *  USB Reset Function
182  *   Called automatically on USB Reset
183  *    Return Value:    None
184  */
185
186 void USB_Reset (void) {
187 #if USB_DMA
188   uint32_t n;
189 #endif
190
191   USB->USBEpInd = 0;
192   USB->USBMaxPSize = USB_MAX_PACKET0;
193   USB->USBEpInd = 1;
194   USB->USBMaxPSize = USB_MAX_PACKET0;
195   while ((USB->USBDevIntSt & EP_RLZED_INT) == 0);
196
197   USB->USBEpIntClr  = 0xFFFFFFFF;
198   USB->USBEpIntEn   = 0xFFFFFFFF ^ USB_DMA_EP;
199   USB->USBDevIntClr = 0xFFFFFFFF;
200   USB->USBDevIntEn  = DEV_STAT_INT    | EP_SLOW_INT    |
201                (USB_SOF_EVENT   ? FRAME_INT : 0) |
202                (USB_ERROR_EVENT ? ERR_INT   : 0);
203
204 #if USB_DMA
205   USB->USBUDCAH   = USB_RAM_ADR;
206   USB->USBDMARClr = 0xFFFFFFFF;
207   USB->USBEpDMADis  = 0xFFFFFFFF;
208   USB->USBEpDMAEn   = USB_DMA_EP;
209   USB->USBEoTIntClr = 0xFFFFFFFF;
210   USB->USBNDDRIntClr = 0xFFFFFFFF;
211   USB->USBSysErrIntClr = 0xFFFFFFFF;
212   USB->USBDMAIntEn  = 0x00000007;
213   DDMemMap[0] = 0x00000000;
214   DDMemMap[1] = 0x00000000;
215   for (n = 0; n < USB_EP_NUM; n++) {
216     udca[n] = 0;
217     UDCA[n] = 0;
218   }
219 #endif
220 }
221
222
223 /*
224  *  USB Suspend Function
225  *   Called automatically on USB Suspend
226  *    Return Value:    None
227  */
228
229 void USB_Suspend (void) {
230   /* Performed by Hardware */
231 }
232
233
234 /*
235  *  USB Resume Function
236  *   Called automatically on USB Resume
237  *    Return Value:    None
238  */
239
240 void USB_Resume (void) {
241   /* Performed by Hardware */
242 }
243
244
245 /*
246  *  USB Remote Wakeup Function
247  *   Called automatically on USB Remote Wakeup
248  *    Return Value:    None
249  */
250
251 void USB_WakeUp (void) {
252
253   if (USB_DeviceStatus & USB_GETSTATUS_REMOTE_WAKEUP) {
254     WrCmdDat(CMD_SET_DEV_STAT, DAT_WR_BYTE(DEV_CON));
255   }
256 }
257
258
259 /*
260  *  USB Remote Wakeup Configuration Function
261  *    Parameters:      cfg:   Enable/Disable
262  *    Return Value:    None
263  */
264
265 void USB_WakeUpCfg (uint32_t cfg) {
266   /* Not needed */
267 }
268
269
270 /*
271  *  USB Set Address Function
272  *    Parameters:      adr:   USB Address
273  *    Return Value:    None
274  */
275
276 void USB_SetAddress (uint32_t adr) {
277   WrCmdDat(CMD_SET_ADDR, DAT_WR_BYTE(DEV_EN | adr)); /* Don't wait for next */
278   WrCmdDat(CMD_SET_ADDR, DAT_WR_BYTE(DEV_EN | adr)); /*  Setup Status Phase */
279 }
280
281
282 /*
283  *  USB Configure Function
284  *    Parameters:      cfg:   Configure/Deconfigure
285  *    Return Value:    None
286  */
287
288 void USB_Configure (uint32_t cfg) {
289
290   WrCmdDat(CMD_CFG_DEV, DAT_WR_BYTE(cfg ? CONF_DVICE : 0));
291
292   USB->USBReEp = 0x00000003;
293   while ((USB->USBDevIntSt & EP_RLZED_INT) == 0);
294   USB->USBDevIntClr = EP_RLZED_INT;
295 }
296
297
298 /*
299  *  Configure USB Endpoint according to Descriptor
300  *    Parameters:      pEPD:  Pointer to Endpoint Descriptor
301  *    Return Value:    None
302  */
303
304 void USB_ConfigEP (USB_ENDPOINT_DESCRIPTOR *pEPD) {
305   uint32_t num;
306
307   num = EPAdr(pEPD->bEndpointAddress);
308   USB->USBReEp |= (1 << num);
309   USB->USBEpInd = num;
310   USB->USBMaxPSize = pEPD->wMaxPacketSize;
311   while ((USB->USBDevIntSt & EP_RLZED_INT) == 0);
312   USB->USBDevIntClr = EP_RLZED_INT;
313 }
314
315
316 /*
317  *  Set Direction for USB Control Endpoint
318  *    Parameters:      dir:   Out (dir == 0), In (dir <> 0)
319  *    Return Value:    None
320  */
321
322 void USB_DirCtrlEP (uint32_t dir) {
323   /* Not needed */
324 }
325
326
327 /*
328  *  Enable USB Endpoint
329  *    Parameters:      EPNum: Endpoint Number
330  *                       EPNum.0..3: Address
331  *                       EPNum.7:    Dir
332  *    Return Value:    None
333  */
334
335 void USB_EnableEP (uint32_t EPNum) {
336   WrCmdDat(CMD_SET_EP_STAT(EPAdr(EPNum)), DAT_WR_BYTE(0));
337 }
338
339
340 /*
341  *  Disable USB Endpoint
342  *    Parameters:      EPNum: Endpoint Number
343  *                       EPNum.0..3: Address
344  *                       EPNum.7:    Dir
345  *    Return Value:    None
346  */
347
348 void USB_DisableEP (uint32_t EPNum) {
349   WrCmdDat(CMD_SET_EP_STAT(EPAdr(EPNum)), DAT_WR_BYTE(EP_STAT_DA));
350 }
351
352
353 /*
354  *  Reset USB Endpoint
355  *    Parameters:      EPNum: Endpoint Number
356  *                       EPNum.0..3: Address
357  *                       EPNum.7:    Dir
358  *    Return Value:    None
359  */
360
361 void USB_ResetEP (uint32_t EPNum) {
362   WrCmdDat(CMD_SET_EP_STAT(EPAdr(EPNum)), DAT_WR_BYTE(0));
363 }
364
365
366 /*
367  *  Set Stall for USB Endpoint
368  *    Parameters:      EPNum: Endpoint Number
369  *                       EPNum.0..3: Address
370  *                       EPNum.7:    Dir
371  *    Return Value:    None
372  */
373
374 void USB_SetStallEP (uint32_t EPNum) {
375   WrCmdDat(CMD_SET_EP_STAT(EPAdr(EPNum)), DAT_WR_BYTE(EP_STAT_ST));
376 }
377
378
379 /*
380  *  Clear Stall for USB Endpoint
381  *    Parameters:      EPNum: Endpoint Number
382  *                       EPNum.0..3: Address
383  *                       EPNum.7:    Dir
384  *    Return Value:    None
385  */
386
387 void USB_ClrStallEP (uint32_t EPNum) {
388   WrCmdDat(CMD_SET_EP_STAT(EPAdr(EPNum)), DAT_WR_BYTE(0));
389 }
390
391
392 /*
393  *  Clear USB Endpoint Buffer
394  *    Parameters:      EPNum: Endpoint Number
395  *                       EPNum.0..3: Address
396  *                       EPNum.7:    Dir
397  *    Return Value:    None
398  */
399
400 void USB_ClearEPBuf (uint32_t EPNum) {
401   WrCmdEP(EPNum, CMD_CLR_BUF);
402 }
403
404
405 /*
406  *  Read USB Endpoint Data
407  *    Parameters:      EPNum: Endpoint Number
408  *                       EPNum.0..3: Address
409  *                       EPNum.7:    Dir
410  *                     pData: Pointer to Data Buffer
411  *    Return Value:    Number of bytes read
412  */
413
414 uint32_t USB_ReadEP (uint32_t EPNum, uint8_t *pData) {
415   uint32_t cnt, n;
416
417   USB->USBCtrl = ((EPNum & 0x0F) << 2) | CTRL_RD_EN;
418
419   do {
420     cnt = USB->USBRxPLen;
421   } while ((cnt & PKT_RDY) == 0);
422   cnt &= PKT_LNGTH_MASK;
423
424   for (n = 0; n < (cnt + 3) / 4; n++) {
425     *((__packed uint32_t *)pData) = USB->USBRxData;
426     pData += 4;
427   }
428   USB->USBCtrl = 0;
429
430   if (((EP_MSK_ISO >> EPNum) & 1) == 0) {   /* Non-Isochronous Endpoint */
431     WrCmdEP(EPNum, CMD_CLR_BUF);
432   }
433
434   return (cnt);
435 }
436
437
438 /*
439  *  Write USB Endpoint Data
440  *    Parameters:      EPNum: Endpoint Number
441  *                       EPNum.0..3: Address
442  *                       EPNum.7:    Dir
443  *                     pData: Pointer to Data Buffer
444  *                     cnt:   Number of bytes to write
445  *    Return Value:    Number of bytes written
446  */
447
448 uint32_t USB_WriteEP (uint32_t EPNum, uint8_t *pData, uint32_t cnt) {
449   uint32_t n;
450
451   USB->USBCtrl = ((EPNum & 0x0F) << 2) | CTRL_WR_EN;
452
453   USB->USBTxPLen = cnt;
454
455   for (n = 0; n < (cnt + 3) / 4; n++) {
456     USB->USBTxData = *((__packed uint32_t *)pData);
457     pData += 4;
458   }
459   USB->USBCtrl = 0;
460   WrCmdEP(EPNum, CMD_VALID_BUF);
461   return (cnt);
462 }
463
464 #if USB_DMA
465
466 /* DMA Descriptor Memory Layout */
467 const uint32_t DDAdr[2] = { DD_NISO_ADR, DD_ISO_ADR };
468 const uint32_t DDSz [2] = { 16,          20         };
469
470
471 /*
472  *  Setup USB DMA Transfer for selected Endpoint
473  *    Parameters:      EPNum: Endpoint Number
474  *                     pDD: Pointer to DMA Descriptor
475  *    Return Value:    TRUE - Success, FALSE - Error
476  */
477
478 uint32_t USB_DMA_Setup(uint32_t EPNum, USB_DMA_DESCRIPTOR *pDD) {
479   uint32_t num, ptr, nxt, iso, n;
480
481   iso = pDD->Cfg.Type.IsoEP;                /* Iso or Non-Iso Descriptor */
482   num = EPAdr(EPNum);                       /* Endpoint's Physical Address */
483
484   ptr = 0;                                  /* Current Descriptor */
485   nxt = udca[num];                          /* Initial Descriptor */
486   while (nxt) {                             /* Go through Descriptor List */
487     ptr = nxt;                              /* Current Descriptor */
488     if (!pDD->Cfg.Type.Link) {              /* Check for Linked Descriptors */
489       n = (ptr - DDAdr[iso]) / DDSz[iso];   /* Descriptor Index */
490       DDMemMap[iso] &= ~(1 << n);           /* Unmark Memory Usage */
491     }
492     nxt = *((uint32_t *)ptr);                  /* Next Descriptor */
493   }
494
495   for (n = 0; n < 32; n++) {                /* Search for available Memory */
496     if ((DDMemMap[iso] & (1 << n)) == 0) {
497       break;                                /* Memory found */
498     }
499   }
500   if (n == 32) return (FALSE);              /* Memory not available */
501
502   DDMemMap[iso] |= 1 << n;                  /* Mark Memory Usage */
503   nxt = DDAdr[iso] + n * DDSz[iso];         /* Next Descriptor */
504
505   if (ptr && pDD->Cfg.Type.Link) {
506     *((uint32_t *)(ptr + 0))  = nxt;           /* Link in new Descriptor */
507     *((uint32_t *)(ptr + 4)) |= 0x00000004;    /* Next DD is Valid */
508   } else {
509     udca[num] = nxt;                        /* Save new Descriptor */
510     UDCA[num] = nxt;                        /* Update UDCA in USB */
511   }
512
513   /* Fill in DMA Descriptor */
514   *(((uint32_t *)nxt)++) =  0;                 /* Next DD Pointer */
515   *(((uint32_t *)nxt)++) =  pDD->Cfg.Type.ATLE |
516                        (pDD->Cfg.Type.IsoEP << 4) |
517                        (pDD->MaxSize <<  5) |
518                        (pDD->BufLen  << 16);
519   *(((uint32_t *)nxt)++) =  pDD->BufAdr;
520   *(((uint32_t *)nxt)++) =  pDD->Cfg.Type.LenPos << 8;
521   if (iso) {
522     *((uint32_t *)nxt) =  pDD->InfoAdr;
523   }
524
525   return (TRUE); /* Success */
526 }
527
528
529 /*
530  *  Enable USB DMA Endpoint
531  *    Parameters:      EPNum: Endpoint Number
532  *                       EPNum.0..3: Address
533  *                       EPNum.7:    Dir
534  *    Return Value:    None
535  */
536
537 void USB_DMA_Enable (uint32_t EPNum) {
538   USB->USBEpDMAEn = 1 << EPAdr(EPNum);
539 }
540
541
542 /*
543  *  Disable USB DMA Endpoint
544  *    Parameters:      EPNum: Endpoint Number
545  *                       EPNum.0..3: Address
546  *                       EPNum.7:    Dir
547  *    Return Value:    None
548  */
549
550 void USB_DMA_Disable (uint32_t EPNum) {
551   USB->USBEpDMADis = 1 << EPAdr(EPNum);
552 }
553
554
555 /*
556  *  Get USB DMA Endpoint Status
557  *    Parameters:      EPNum: Endpoint Number
558  *                       EPNum.0..3: Address
559  *                       EPNum.7:    Dir
560  *    Return Value:    DMA Status
561  */
562
563 uint32_t USB_DMA_Status (uint32_t EPNum) {
564   uint32_t ptr, val;
565           
566   ptr = UDCA[EPAdr(EPNum)];                 /* Current Descriptor */
567   if (ptr == 0) 
568         return (USB_DMA_INVALID);
569
570   val = *((uint32_t *)(ptr + 3*4));            /* Status Information */
571   switch ((val >> 1) & 0x0F) {
572     case 0x00:                              /* Not serviced */
573       return (USB_DMA_IDLE);
574     case 0x01:                              /* Being serviced */
575       return (USB_DMA_BUSY);
576     case 0x02:                              /* Normal Completition */
577       return (USB_DMA_DONE);
578     case 0x03:                              /* Data Under Run */
579       return (USB_DMA_UNDER_RUN);
580     case 0x08:                              /* Data Over Run */
581       return (USB_DMA_OVER_RUN);
582     case 0x09:                              /* System Error */
583       return (USB_DMA_ERROR);
584   }
585
586   return (USB_DMA_UNKNOWN);
587 }
588
589
590 /*
591  *  Get USB DMA Endpoint Current Buffer Address
592  *    Parameters:      EPNum: Endpoint Number
593  *                       EPNum.0..3: Address
594  *                       EPNum.7:    Dir
595  *    Return Value:    DMA Address (or -1 when DMA is Invalid)
596  */
597
598 uint32_t USB_DMA_BufAdr (uint32_t EPNum) {
599   uint32_t ptr, val;
600
601   ptr = UDCA[EPAdr(EPNum)];                 /* Current Descriptor */
602   if (ptr == 0)
603   {
604         return ((uint32_t)(-1));                /* DMA Invalid */
605   }
606
607   val = *((uint32_t *)(ptr + 2*4));         /* Buffer Address */
608   return (val);                             /* Current Address */
609 }
610
611
612 /*
613  *  Get USB DMA Endpoint Current Buffer Count
614  *   Number of transfered Bytes or Iso Packets
615  *    Parameters:      EPNum: Endpoint Number
616  *                       EPNum.0..3: Address
617  *                       EPNum.7:    Dir
618  *    Return Value:    DMA Count (or -1 when DMA is Invalid)
619  */
620
621 uint32_t USB_DMA_BufCnt (uint32_t EPNum) {
622   uint32_t ptr, val;
623
624   ptr = UDCA[EPAdr(EPNum)];                 /* Current Descriptor */
625   if (ptr == 0)
626   { 
627         return ((uint32_t)(-1));                /* DMA Invalid */
628   }
629   val = *((uint32_t *)(ptr + 3*4));         /* Status Information */
630   return (val >> 16);                       /* Current Count */
631 }
632
633
634 #endif /* USB_DMA */
635
636
637 /*
638  *  Get USB Last Frame Number
639  *    Parameters:      None
640  *    Return Value:    Frame Number
641  */
642
643 uint32_t USB_GetFrame (void) {
644   uint32_t val;
645
646   WrCmd(CMD_RD_FRAME);
647   val = RdCmdDat(DAT_RD_FRAME);
648   val = val | (RdCmdDat(DAT_RD_FRAME) << 8);
649
650   return (val);
651 }
652
653
654 /*
655  *  USB Interrupt Service Routine
656  */
657
658 void USB_IRQHandler (void) {
659   uint32_t disr, val, n, m;
660   uint32_t episr, episrCur;
661
662   disr = USB->USBDevIntSt;       /* Device Interrupt Status */
663
664   /* Device Status Interrupt (Reset, Connect change, Suspend/Resume) */
665   if (disr & DEV_STAT_INT) {
666     USB->USBDevIntClr = DEV_STAT_INT;
667     WrCmd(CMD_GET_DEV_STAT);
668     val = RdCmdDat(DAT_GET_DEV_STAT);       /* Device Status */
669     if (val & DEV_RST) {                    /* Reset */
670       USB_Reset();
671 #if   USB_RESET_EVENT
672       USB_Reset_Event();
673 #endif
674     }
675     if (val & DEV_CON_CH) {                 /* Connect change */
676 #if   USB_POWER_EVENT
677       USB_Power_Event(val & DEV_CON);
678 #endif
679     }
680     if (val & DEV_SUS_CH) {                 /* Suspend/Resume */
681       if (val & DEV_SUS) {                  /* Suspend */
682         USB_Suspend();
683 #if     USB_SUSPEND_EVENT
684         USB_Suspend_Event();
685 #endif
686       } else {                              /* Resume */
687         USB_Resume();
688 #if     USB_RESUME_EVENT
689         USB_Resume_Event();
690 #endif
691       }
692     }
693     goto isr_end;
694   }
695
696 #if USB_SOF_EVENT
697   /* Start of Frame Interrupt */
698   if (disr & FRAME_INT) {
699     USB_SOF_Event();
700   }
701 #endif
702
703 #if USB_ERROR_EVENT
704   /* Error Interrupt */
705   if (disr & ERR_INT) {
706     WrCmd(CMD_RD_ERR_STAT);
707     val = RdCmdDat(DAT_RD_ERR_STAT);
708     USB_Error_Event(val);
709   }
710 #endif
711
712   /* Endpoint's Slow Interrupt */
713   if (disr & EP_SLOW_INT) {
714     episrCur = 0;
715     episr    = USB->USBEpIntSt;
716     for (n = 0; n < USB_EP_NUM; n++) {      /* Check All Endpoints */
717       if (episr == episrCur) break;         /* break if all EP interrupts handled */
718       if (episr & (1 << n)) {
719         episrCur |= (1 << n);
720         m = n >> 1;
721   
722         USB->USBEpIntClr = (1 << n);
723         while ((USB->USBDevIntSt & CDFULL_INT) == 0);
724         val = USB->USBCmdData;
725   
726         if ((n & 1) == 0) {                 /* OUT Endpoint */
727           if (n == 0) {                     /* Control OUT Endpoint */
728             if (val & EP_SEL_STP) {         /* Setup Packet */
729               if (USB_P_EP[0]) {
730                 USB_P_EP[0](USB_EVT_SETUP);
731                 continue;
732               }
733             }
734           }
735           if (USB_P_EP[m]) {
736             USB_P_EP[m](USB_EVT_OUT);
737           }
738         } else {                            /* IN Endpoint */
739           if (USB_P_EP[m]) {
740             USB_P_EP[m](USB_EVT_IN);
741           }
742         }
743       }
744     }
745     USB->USBDevIntClr = EP_SLOW_INT;
746   }
747
748 #if USB_DMA
749
750   if (USB->USBDMAIntSt & 0x00000001) {          /* End of Transfer Interrupt */
751     val = USB->USBEoTIntSt;
752     for (n = 2; n < USB_EP_NUM; n++) {      /* Check All Endpoints */
753       if (val & (1 << n)) {
754         m = n >> 1;
755         if ((n & 1) == 0) {                 /* OUT Endpoint */
756           if (USB_P_EP[m]) {
757             USB_P_EP[m](USB_EVT_OUT_DMA_EOT);
758           }
759         } else {                            /* IN Endpoint */
760           if (USB_P_EP[m]) {
761             USB_P_EP[m](USB_EVT_IN_DMA_EOT);
762           }
763         }
764       }
765     }
766     USB->USBEoTIntClr = val;
767   }
768
769   if (USB->USBDMAIntSt & 0x00000002) {          /* New DD Request Interrupt */
770     val = USB->USBNDDRIntSt;
771     for (n = 2; n < USB_EP_NUM; n++) {      /* Check All Endpoints */
772       if (val & (1 << n)) {
773         m = n >> 1;
774         if ((n & 1) == 0) {                 /* OUT Endpoint */
775           if (USB_P_EP[m]) {
776             USB_P_EP[m](USB_EVT_OUT_DMA_NDR);
777           }
778         } else {                            /* IN Endpoint */
779           if (USB_P_EP[m]) {
780             USB_P_EP[m](USB_EVT_IN_DMA_NDR);
781           }
782         }
783       }
784     }
785     USB->USBNDDRIntClr = val;
786   }
787
788   if (USB->USBDMAIntSt & 0x00000004) {          /* System Error Interrupt */
789     val = USB->USBSysErrIntSt;
790     for (n = 2; n < USB_EP_NUM; n++) {      /* Check All Endpoints */
791       if (val & (1 << n)) {
792         m = n >> 1;
793         if ((n & 1) == 0) {                 /* OUT Endpoint */
794           if (USB_P_EP[m]) {
795             USB_P_EP[m](USB_EVT_OUT_DMA_ERR);
796           }
797         } else {                            /* IN Endpoint */
798           if (USB_P_EP[m]) {
799             USB_P_EP[m](USB_EVT_IN_DMA_ERR);
800           }
801         }
802       }
803     }
804     USB->USBSysErrIntClr = val;
805   }
806
807 #endif /* USB_DMA */
808
809 isr_end:
810   return;
811 }