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