]> git.sur5r.net Git - freertos/blob - FreeRTOS-Plus/Demo/FreeRTOS_Plus_UDP_and_CLI_LPC1830_GCC/ThirdParty/USB_CDC/usbhw.c
01c222d67e668cfe139cdddaa6022768af262791
[freertos] / FreeRTOS-Plus / Demo / FreeRTOS_Plus_UDP_and_CLI_LPC1830_GCC / ThirdParty / USB_CDC / usbhw.c
1 /**********************************************************************
2 * $Id$          usbhw.c                                 2011-06-02
3 *//**
4 * @file         usbhw.c
5 * @brief         USB Hardware Layer Module for NXP's lpc43xx MCU
6 * @version      1.0
7 * @date         02. June. 2011
8 * @author       NXP MCU SW Application Team
9 *
10 * Copyright(C) 2011, NXP Semiconductor
11 * All rights reserved.
12 *
13 ***********************************************************************
14 * Software that is described herein is for illustrative purposes only
15 * which provides customers with programming information regarding the
16 * products. This software is supplied "AS IS" without any warranties.
17 * NXP Semiconductors assumes no responsibility or liability for the
18 * use of the software, conveys no license or title under any patent,
19 * copyright, or mask work right to the product. NXP Semiconductors
20 * reserves the right to make changes in the software without
21 * notification. NXP Semiconductors also make no representation or
22 * warranty that such application will be suitable for the specified
23 * use without further testing or modification.
24 **********************************************************************/
25 #include <string.h>
26 #include "lpc18xx.H"                        /* lpc43xx definitions */
27 #include "lpc_types.h"
28 #include "usb.h"
29 #include "usbhw.h"
30 #include "usbcfg.h"
31 #include "usbcore.h"
32 #include "lpc18xx_scu.h"
33 #include "lpc18xx_cgu.h"
34 #include "FreeRTOS.h"
35 #ifdef __CC_ARM
36 #pragma diag_suppress 1441
37 #endif
38
39 #ifdef __ICCARM__
40 #pragma data_alignment=2048
41 DQH_T ep_QH[EP_NUM_MAX];
42 #pragma data_alignment=32
43 DTD_T ep_TD[EP_NUM_MAX];
44 #pragma data_alignment=4
45 #elif defined   (  __GNUC__  )
46 #define __align(x) __attribute__((aligned(x)))
47 DQH_T ep_QH[EP_NUM_MAX] __attribute__((aligned(2048)));
48 DTD_T ep_TD[EP_NUM_MAX] __attribute__((aligned(32)));
49 #else
50 DQH_T __align(2048) ep_QH[EP_NUM_MAX];
51 DTD_T __align(32) ep_TD[EP_NUM_MAX];
52 #endif
53
54
55 static uint32_t ep_read_len[4];
56 volatile uint32_t DevStatusFS2HS = FALSE;
57 LPC_USBDRV_INIT_T g_drv;
58
59 /*
60  *  Get Endpoint Physical Address
61  *    Parameters:      EPNum: Endpoint Number
62  *                       EPNum.0..3: Address
63  *                       EPNum.7:    Dir
64  *    Return Value:    Endpoint Physical Address
65  */
66
67 uint32_t EPAdr (uint32_t EPNum) {
68   uint32_t val;
69
70   val = (EPNum & 0x0F) << 1;
71   if (EPNum & 0x80) {
72     val += 1;
73   }
74   return (val);
75 }
76
77 /*
78  *  USB Initialize Function
79  *   Called by the User to initialize USB
80  *    Return Value:    None
81  */
82
83 void USB_Init (LPC_USBDRV_INIT_T* cbs)
84 {
85   memcpy(&g_drv, cbs, sizeof(LPC_USBDRV_INIT_T));
86   /*maxp for EP0 should be atleast 8 */
87   if( g_drv.ep0_maxp == 0)
88     g_drv.ep0_maxp = 64;
89
90 #ifdef USE_USB0
91         scu_pinmux(0x8,1,MD_PLN_FAST,FUNC1);    //  0: motocon pcap0_1          1: usb0 usb0_ind1           2:  nc                      3: gpio4 gpio4_1
92         scu_pinmux(0x8,2,MD_PLN_FAST,FUNC1);    //  0: motocon pcap0_0          1: usb0 usb0_ind0           2:  nc                      3: gpio4 gpio4_2
93 #endif
94 #ifdef USE_USB0
95         CGU_SetPLL0();
96         CGU_EnableEntity(CGU_CLKSRC_PLL0, ENABLE);
97         CGU_EntityConnect(CGU_CLKSRC_PLL0, CGU_BASE_USB0);
98 #else
99         CGU_SetPLL1(5);
100         CGU_EnableEntity(CGU_CLKSRC_PLL1, ENABLE);
101         CGU_EntityConnect(CGU_CLKSRC_PLL1, CGU_BASE_USB1);\r
102         /* enable USB phy */
103     LPC_CREG->CREG0 &= ~(1 << 5);
104     /* enable USB1_DP and USB1_DN on chip FS phy */
105     LPC_SCU->SFSUSB = 0x12;
106     /* enable USB1_VBUS */
107     scu_pinmux(0x2, 5, MD_PLN | MD_EZI | MD_ZI, FUNC2);
108
109 #endif
110         /* Turn on the phy */
111 #ifdef USE_USB0
112         LPC_CREG->CREG0 &= ~(1<<5);
113 #endif
114         /* reset the controller */
115         LPC_USB->USBCMD_D = USBCMD_RST;
116         /* wait for reset to complete */
117         while (LPC_USB->USBCMD_D & USBCMD_RST);
118
119         /* Program the controller to be the USB device controller */
120         LPC_USB->USBMODE_D =   USBMODE_CM_DEV
121                           | USBMODE_SDIS
122                           | USBMODE_SLOM ;
123
124         /* set OTG transcever in proper state, device is present
125         on the port(CCS=1), port enable/disable status change(PES=1). */
126 #ifdef USE_USB0 
127         LPC_USB->OTGSC = (1<<3) | (1<<0) /*| (1<<16)| (1<<24)| (1<<25)| (1<<26)| (1<<27)| (1<<28)| (1<<29)| (1<<30)*/;
128 #else
129         /* force full speed */
130         LPC_USB->PORTSC1_D |= (1<<24);
131 #endif
132
133 #ifdef USE_USB0
134         NVIC_EnableIRQ(USB0_IRQn); //  enable USB0 interrrupts
135         NVIC_SetPriority(USB0_IRQn, configMIN_LIBRARY_INTERRUPT_PRIORITY );
136 #else
137         NVIC_EnableIRQ(USB1_IRQn); //  enable USB1 interrrupts
138         NVIC_SetPriority(USB0_IRQn, configMIN_LIBRARY_INTERRUPT_PRIORITY );
139 #endif
140
141         USB_Reset();
142         USB_SetAddress(0);
143         return;
144 }
145
146 /*
147  *  USB Connect Function
148  *   Called by the User to Connect/Disconnect USB
149  *    Parameters:      con:   Connect/Disconnect
150  *    Return Value:    None
151  */
152 void USB_Connect (uint32_t con) {
153   if (con)
154     LPC_USB->USBCMD_D |= USBCMD_RS;
155   else
156     LPC_USB->USBCMD_D &= ~USBCMD_RS;
157 }
158
159
160 /*
161  *  USB Reset Function
162  *   Called automatically on USB Reset
163  *    Return Value:    None
164  */
165
166 void USB_Reset (void)
167 {
168   uint32_t i;
169
170   DevStatusFS2HS = FALSE;
171   /* disable all EPs */
172   LPC_USB->ENDPTCTRL0 &= ~(EPCTRL_RXE | EPCTRL_TXE);
173   LPC_USB->ENDPTCTRL2 &= ~(EPCTRL_RXE | EPCTRL_TXE);
174   LPC_USB->ENDPTCTRL3 &= ~(EPCTRL_RXE | EPCTRL_TXE);
175
176   /* Clear all pending interrupts */
177   LPC_USB->ENDPTNAK   = 0xFFFFFFFF;
178   LPC_USB->ENDPTNAKEN = 0;
179   LPC_USB->USBSTS_D     = 0xFFFFFFFF;
180   LPC_USB->ENDPTSETUPSTAT = LPC_USB->ENDPTSETUPSTAT;
181   LPC_USB->ENDPTCOMPLETE  = LPC_USB->ENDPTCOMPLETE;
182   while (LPC_USB->ENDPTPRIME)                  /* Wait until all bits are 0 */
183   {
184   }
185   LPC_USB->ENDPTFLUSH = 0xFFFFFFFF;
186   while (LPC_USB->ENDPTFLUSH); /* Wait until all bits are 0 */
187
188
189   /* Set the interrupt Threshold control interval to 0 */
190   LPC_USB->USBCMD_D &= ~0x00FF0000;
191
192   /* Zero out the Endpoint queue heads */
193   memset((void*)ep_QH, 0, EP_NUM_MAX * sizeof(DQH_T));
194   /* Zero out the device transfer descriptors */
195   memset((void*)ep_TD, 0, EP_NUM_MAX * sizeof(DTD_T));
196   memset((void*)ep_read_len, 0, sizeof(ep_read_len));
197   /* Configure the Endpoint List Address */
198   /* make sure it in on 64 byte boundary !!! */
199   /* init list address */
200   LPC_USB->ENDPOINTLISTADDR = (uint32_t)ep_QH;
201   /* Initialize device queue heads for non ISO endpoint only */
202   for (i = 0; i < EP_NUM_MAX; i++)
203   {
204     ep_QH[i].next_dTD = (uint32_t)&ep_TD[i];
205   }
206   /* Enable interrupts */
207   LPC_USB->USBINTR_D =  USBSTS_UI
208                      | USBSTS_UEI
209                      | USBSTS_PCI
210                      | USBSTS_URI
211                      | USBSTS_SLI
212                      | USBSTS_NAKI;
213 //  LPC_USB->usbintr |= (0x1<<7);               /* Test SOF */
214   /* enable ep0 IN and ep0 OUT */
215   ep_QH[0].cap  = QH_MAXP(g_drv.ep0_maxp)
216                   | QH_IOS
217                   | QH_ZLT;
218   ep_QH[1].cap  = QH_MAXP(g_drv.ep0_maxp)
219                   | QH_IOS
220                   | QH_ZLT;
221   /* enable EP0 */
222   LPC_USB->ENDPTCTRL0 = EPCTRL_RXE | EPCTRL_RXR | EPCTRL_TXE | EPCTRL_TXR;
223   return;
224
225 }
226
227
228 /*
229  *  USB Suspend Function
230  *   Called automatically on USB Suspend
231  *    Return Value:    None
232  */
233
234 void USB_Suspend (void) {
235   /* Performed by Hardware */
236 }
237
238
239 /*
240  *  USB Resume Function
241  *   Called automatically on USB Resume
242  *    Return Value:    None
243  */
244
245 void USB_Resume (void) {
246   /* Performed by Hardware */
247 }
248
249
250 /*
251  *  USB Remote Wakeup Function
252  *   Called automatically on USB Remote Wakeup
253  *    Return Value:    None
254  */
255
256 void USB_WakeUp (void) {
257
258   //if (USB_DeviceStatus & USB_GETSTATUS_REMOTE_WAKEUP)
259   {
260     /* Set FPR bit in PORTSCX reg p63 */
261     LPC_USB->PORTSC1_D |= USBPRTS_FPR ;
262   }
263 }
264
265
266 /*
267  *  USB Remote Wakeup Configuration Function
268  *    Parameters:      cfg:   Enable/Disable
269  *    Return Value:    None
270  */
271
272 void USB_WakeUpCfg (uint32_t cfg) {
273   ( void ) cfg;
274   /* Not needed */
275 }
276
277
278 /*
279  *  USB Set Address Function
280  *    Parameters:      adr:   USB Address
281  *    Return Value:    None
282  */
283
284 void USB_SetAddress (uint32_t adr) {
285   LPC_USB->DEVICEADDR = USBDEV_ADDR(adr);
286   LPC_USB->DEVICEADDR |= USBDEV_ADDR_AD;
287 }
288
289 /*
290 *  USB set test mode Function
291 *    Parameters:      mode:   test mode
292 *    Return Value:    TRUE if supported else FALSE
293 */
294
295 uint32_t USB_SetTestMode(uint8_t mode)
296 {
297   uint32_t portsc;
298
299   if ((mode > 0) && (mode < 8))
300   {
301     portsc = LPC_USB->PORTSC1_D & ~(0xF << 16);
302
303     LPC_USB->PORTSC1_D = portsc | (mode << 16);
304     return TRUE;
305   }
306   return (FALSE);
307 }
308
309 /*
310  *  USB Configure Function
311  *    Parameters:      cfg:   Configure/Deconfigure
312  *    Return Value:    None
313  */
314
315 void USB_Configure (uint32_t cfg) {
316         ( void ) cfg;
317 }
318
319
320 /*
321  *  Configure USB Endpoint according to Descriptor
322  *    Parameters:      pEPD:  Pointer to Endpoint Descriptor
323  *    Return Value:    None
324  */
325
326 void USB_ConfigEP (USB_ENDPOINT_DESCRIPTOR *pEPD) {
327   uint32_t num, lep;
328   uint32_t ep_cfg;
329   uint8_t  bmAttributes;
330
331   lep = pEPD->bEndpointAddress & 0x7F;
332   num = EPAdr(pEPD->bEndpointAddress);
333
334   ep_cfg = ((uint32_t*)&(LPC_USB->ENDPTCTRL0))[lep];
335   /* mask the attributes we are not-intersetd in */
336   bmAttributes = pEPD->bmAttributes & USB_ENDPOINT_TYPE_MASK;
337   /* set EP type */
338   if (bmAttributes != USB_ENDPOINT_TYPE_ISOCHRONOUS)
339   {
340     /* init EP capabilities */
341     ep_QH[num].cap  = QH_MAXP(pEPD->wMaxPacketSize)
342                       | QH_IOS | QH_ZLT ;
343     /* The next DTD pointer is INVALID */
344     ep_TD[num].next_dTD = 0x01 ;
345   }
346   else
347   {
348     /* init EP capabilities */
349     ep_QH[num].cap  = QH_MAXP(0x400) | QH_ZLT;
350   }
351   /* setup EP control register */
352   if (pEPD->bEndpointAddress & 0x80)
353   {
354     ep_cfg &= ~0xFFFF0000;
355     ep_cfg |= EPCTRL_TX_TYPE(bmAttributes)
356               | EPCTRL_TXR;
357   }
358   else
359   {
360     ep_cfg &= ~0xFFFF;
361     ep_cfg |= EPCTRL_RX_TYPE(bmAttributes)
362               | EPCTRL_RXR;
363   }
364   ((uint32_t*)&(LPC_USB->ENDPTCTRL0))[lep] = ep_cfg;
365   return;
366 }
367
368 /*
369  *  Set Direction for USB Control Endpoint
370  *    Parameters:      dir:   Out (dir == 0), In (dir <> 0)
371  *    Return Value:    None
372  */
373
374 void USB_DirCtrlEP (uint32_t dir) {
375   /* Not needed */
376   ( void ) dir;
377 }
378
379
380 /*
381  *  Enable USB Endpoint
382  *    Parameters:      EPNum: Endpoint Number
383  *                       EPNum.0..3: Address
384  *                       EPNum.7:    Dir
385  *    Return Value:    None
386  */
387
388 void USB_EnableEP (uint32_t EPNum) {
389   uint32_t lep, bitpos;
390
391   lep = EPNum & 0x0F;
392
393   if (EPNum & 0x80)
394   {
395     ((uint32_t*)&(LPC_USB->ENDPTCTRL0))[lep] |= EPCTRL_TXE;
396   }
397   else
398   {
399     ((uint32_t*)&(LPC_USB->ENDPTCTRL0))[lep] |= EPCTRL_RXE;
400     /* enable NAK interrupt */
401     bitpos = USB_EP_BITPOS(EPNum);
402     LPC_USB->ENDPTNAKEN |= (1<<bitpos);
403   }
404 }
405
406 /*
407  *  Disable USB Endpoint
408  *    Parameters:      EPNum: Endpoint Number
409  *                       EPNum.0..3: Address
410  *                       EPNum.7:    Dir
411  *    Return Value:    None
412  */
413
414 void USB_DisableEP (uint32_t EPNum) {
415   uint32_t lep, bitpos;
416
417   lep = EPNum & 0x0F;
418   if (EPNum & 0x80)
419   {
420     ((uint32_t*)&(LPC_USB->ENDPTCTRL0))[lep] &= ~EPCTRL_TXE;
421   }
422   else
423   {
424     /* disable NAK interrupt */
425     bitpos = USB_EP_BITPOS(EPNum);
426     LPC_USB->ENDPTNAKEN &= ~(1<<bitpos);
427     ((uint32_t*)&(LPC_USB->ENDPTCTRL0))[lep] &= ~EPCTRL_RXE;
428   }
429 }
430
431 /*
432  *  Reset USB Endpoint
433  *    Parameters:      EPNum: Endpoint Number
434  *                       EPNum.0..3: Address
435  *                       EPNum.7:    Dir
436  *    Return Value:    None
437  */
438
439 void USB_ResetEP (uint32_t EPNum) {
440   uint32_t bit_pos = USB_EP_BITPOS(EPNum);
441   uint32_t lep = EPNum & 0x0F;
442
443   /* flush EP buffers */
444   LPC_USB->ENDPTFLUSH = (1<<bit_pos);
445   while (LPC_USB->ENDPTFLUSH & (1<<bit_pos));
446   /* reset data toggles */
447   if (EPNum & 0x80)
448   {
449     ((uint32_t*)&(LPC_USB->ENDPTCTRL0))[lep] |= EPCTRL_TXR;
450   }
451   else
452   {
453     ((uint32_t*)&(LPC_USB->ENDPTCTRL0))[lep] |= EPCTRL_RXR;
454   }
455 }
456
457 /*
458  *  Set Stall for USB Endpoint
459  *    Parameters:      EPNum: Endpoint Number
460  *                       EPNum.0..3: Address
461  *                       EPNum.7:    Dir
462  *    Return Value:    None
463  */
464
465 void USB_SetStallEP (uint32_t EPNum) {
466   uint32_t lep;
467
468   lep = EPNum & 0x0F;
469   if (EPNum & 0x80)
470   {
471     ((uint32_t*)&(LPC_USB->ENDPTCTRL0))[lep] |= EPCTRL_TXS;
472   }
473   else
474   {
475     ((uint32_t*)&(LPC_USB->ENDPTCTRL0))[lep] |= EPCTRL_RXS;
476   }
477 }
478
479 /*
480  *  Clear Stall for USB Endpoint
481  *    Parameters:      EPNum: Endpoint Number
482  *                       EPNum.0..3: Address
483  *                       EPNum.7:    Dir
484  *    Return Value:    None
485  */
486
487 void USB_ClrStallEP (uint32_t EPNum) {
488   uint32_t lep;
489
490   lep = EPNum & 0x0F;
491   if (EPNum & 0x80)
492   {
493     ((uint32_t*)&(LPC_USB->ENDPTCTRL0))[lep] &= ~EPCTRL_TXS;
494     /* reset data toggle */
495     ((uint32_t*)&(LPC_USB->ENDPTCTRL0))[lep] |= EPCTRL_TXR;
496   }
497   else
498   {
499     ((uint32_t*)&(LPC_USB->ENDPTCTRL0))[lep] &= ~EPCTRL_RXS;
500     /* reset data toggle */
501     ((uint32_t*)&(LPC_USB->ENDPTCTRL0))[lep] |= EPCTRL_RXR;
502   }
503 }
504
505 /*
506  *  Process DTD
507  *    Parameters:      EPNum: Endpoint Number
508  *                       EPNum.0..3: Address
509  *                       EPNum.7:    Dir
510  *                     Buffer pointer
511  *                     Transfer buffer size
512  *    Return Value:    None
513  */
514 void USB_ProgDTD(uint32_t Edpt, uint32_t ptrBuff, uint32_t TsfSize)
515 {
516   DTD_T*  pDTD;
517
518   pDTD = (DTD_T*)&ep_TD[ Edpt ];
519
520   /* Zero out the device transfer descriptors */
521   memset((void*)pDTD, 0, sizeof(DTD_T));
522   /* The next DTD pointer is INVALID */
523   pDTD->next_dTD = 0x01 ;
524
525   /* Length */
526   pDTD->total_bytes = ((TsfSize & 0x7fff) << 16);
527   pDTD->total_bytes |= TD_IOC ;
528   pDTD->total_bytes |= 0x80 ;
529
530   pDTD->buffer0 = ptrBuff;
531   pDTD->buffer1 = (ptrBuff + 0x1000) & 0xfffff000;
532   pDTD->buffer2 = (ptrBuff + 0x2000) & 0xfffff000;
533   pDTD->buffer3 = (ptrBuff + 0x3000) & 0xfffff000;
534   pDTD->buffer4 = (ptrBuff + 0x4000) & 0xfffff000;
535
536   ep_QH[Edpt].next_dTD = (uint32_t)(&ep_TD[ Edpt ]);
537   ep_QH[Edpt].total_bytes &= (~0xC0) ;
538 }
539
540 /*
541 *  Read USB Endpoint Data
542 *    Parameters:      EPNum: Endpoint Number
543 *                       EPNum.0..3: Address
544 *                       EPNum.7:    Dir
545 *                     pData: Pointer to Data Buffer
546 *    Return Value:    Number of bytes read
547 */
548 uint32_t USB_ReadSetupPkt(uint32_t EPNum, uint32_t *pData)
549 {
550   uint32_t setup_int, cnt = 0;
551   uint32_t num = EPAdr(EPNum);
552
553   setup_int = LPC_USB->ENDPTSETUPSTAT ;
554   /* Clear the setup interrupt */
555   LPC_USB->ENDPTSETUPSTAT = setup_int;
556
557   /* ********************************** */
558   /*  Check if we have received a setup */
559   /* ********************************** */
560   if (setup_int & (1<<0))                    /* Check only for bit 0 */
561     /* No setup are admitted on other endpoints than 0 */
562   {
563     do
564     {
565       /* Setup in a setup - must considere only the second setup */
566       /*- Set the tripwire */
567       LPC_USB->USBCMD_D |= USBCMD_SUTW ;
568
569       /* Transfer Set-up data to the gtmudsCore_Request buffer */
570       pData[0] = ep_QH[num].setup[0];
571       pData[1] = ep_QH[num].setup[1];
572       cnt = 8;
573
574     }
575     while (!(LPC_USB->USBCMD_D & USBCMD_SUTW)) ;
576
577     /* setup in a setup - Clear the tripwire */
578     LPC_USB->USBCMD_D &= (~USBCMD_SUTW);
579   }
580   while ((setup_int = LPC_USB->ENDPTSETUPSTAT) != 0)
581   {
582     /* Clear the setup interrupt */
583     LPC_USB->ENDPTSETUPSTAT = setup_int;
584   }
585   return cnt;
586 }
587
588 /*
589 *  Enque read request
590 *    Parameters:      EPNum: Endpoint Number
591 *                       EPNum.0..3: Address
592 *                       EPNum.7:    Dir
593 *                     pData: Pointer to Data Buffer
594 *    Return Value:    Number of bytes read
595 */
596
597 uint32_t USB_ReadReqEP(uint32_t EPNum, uint8_t *pData, uint32_t len)
598 {
599   uint32_t num = EPAdr(EPNum);
600   uint32_t n = USB_EP_BITPOS(EPNum);
601
602   USB_ProgDTD(num, (uint32_t)pData, len);
603   ep_read_len[EPNum & 0x0F] = len;
604   /* prime the endpoint for read */
605   LPC_USB->ENDPTPRIME |= (1<<n);
606   return len;
607 }
608 /*
609 *  Read USB Endpoint Data
610 *    Parameters:      EPNum: Endpoint Number
611 *                       EPNum.0..3: Address
612 *                       EPNum.7:    Dir
613 *                     pData: Pointer to Data Buffer
614 *    Return Value:    Number of bytes read
615 */
616
617 uint32_t USB_ReadEP(uint32_t EPNum, uint8_t *pData)
618 {
619   uint32_t cnt, n;
620   DTD_T*  pDTD ;
621
622   ( void ) pData;
623
624   n = EPAdr(EPNum);
625   pDTD = (DTD_T*)&ep_TD[n];
626
627   /* return the total bytes read */
628   cnt  = (pDTD->total_bytes >> 16) & 0x7FFF;
629   cnt = ep_read_len[EPNum & 0x0F] - cnt;
630   return (cnt);
631 }
632
633 /*
634 *  Write USB Endpoint Data
635 *    Parameters:      EPNum: Endpoint Number
636 *                       EPNum.0..3: Address
637 *                       EPNum.7:    Dir
638 *                     pData: Pointer to Data Buffer
639 *                     cnt:   Number of bytes to write
640 *    Return Value:    Number of bytes written
641 */
642 uint32_t USB_WriteEP(uint32_t EPNum, uint8_t *pData, uint32_t cnt)
643 {
644   uint32_t x = 0, n = USB_EP_BITPOS(EPNum);
645
646   USB_ProgDTD(EPAdr(EPNum), (uint32_t)pData, cnt);
647   /* prime the endpoint for transmit */
648   LPC_USB->ENDPTPRIME |= (1<<n);
649    /* check if priming succeeded */
650   while ((LPC_USB->ENDPTPRIME & (1<<n))&&(++x<0xffff));/*_RB_ Fix for hang here. */
651   return (cnt);
652 }
653
654 /*
655  *  USB Interrupt Service Routine
656  */
657 #ifdef USE_USB0
658 void USB0_IRQHandler (void)
659 #else
660 void USB1_IRQHandler (void)
661 #endif
662 {
663   uint32_t disr, val, n;
664
665   disr = LPC_USB->USBSTS_D;                      /* Device Interrupt Status */
666   LPC_USB->USBSTS_D = disr;
667
668 //  printf("USB interrupt: 0x%08x\n",disr);
669
670 //      LPC_UART1->THR = 'U';
671 //      LPC_UART1->THR = 'S';
672 //      LPC_UART1->THR = 'B';
673 //      LPC_UART1->THR = '\n';
674
675
676   /* Device Status Interrupt (Reset, Connect change, Suspend/Resume) */
677   if (disr & USBSTS_URI)                      /* Reset */
678   {
679 //                                                                                                      LPC_UART1->THR = 'R';
680 //                                                                                                      LPC_UART1->THR = '\n';
681     USB_Reset();
682     if (g_drv.USB_Reset_Event)
683       g_drv.USB_Reset_Event();
684     return;
685         //goto isr_end;
686   }
687
688   if (disr & USBSTS_SLI)                   /* Suspend */
689   {
690 //                                                                                                LPC_UART1->THR = 'U';
691 //                                                                                                      LPC_UART1->THR = '\n';
692     if (g_drv.USB_Suspend_Event)
693       g_drv.USB_Suspend_Event();
694   }
695
696   if (disr & USBSTS_PCI)                  /* Resume */
697   {
698 //                                                                                                      LPC_UART1->THR = 'P';
699 //                                                                                                      LPC_UART1->THR = '\n';
700     /* check if device isoperating in HS mode or full speed */
701     if (LPC_USB->PORTSC1_D & (1<<9))
702       DevStatusFS2HS = TRUE;
703
704     if (g_drv.USB_Resume_Event)
705       g_drv.USB_Resume_Event();
706   }
707
708   /* handle setup status interrupts */
709   val = LPC_USB->ENDPTSETUPSTAT;
710   /* Only EP0 will have setup packets so call EP0 handler */
711   if (val)
712   {
713 //                                                                                                  LPC_UART1->THR = 'S';
714 //                                                                                                      LPC_UART1->THR = '\n';
715     /* Clear the endpoint complete CTRL OUT & IN when */
716     /* a Setup is received */
717     LPC_USB->ENDPTCOMPLETE = 0x00010001;
718     /* enable NAK inetrrupts */
719     LPC_USB->ENDPTNAKEN |= 0x00010001;
720     if (g_drv.USB_P_EP[0]){
721 //                                                                                                              LPC_UART1->THR = 's';
722 //                                                                                                              LPC_UART1->THR = '\n';
723         g_drv.USB_P_EP[0](USB_EVT_SETUP);
724         }
725   }
726
727   /* handle completion interrupts */
728   val = LPC_USB->ENDPTCOMPLETE;
729   if (val)
730   {
731 //                                                                                                              LPC_UART1->THR = 'C';
732 //                                                                                                              LPC_UART1->THR = '\n';
733
734     LPC_USB->ENDPTNAK = val;
735     for (n = 0; n < EP_NUM_MAX / 2; n++)
736     {
737       if (val & (1<<n))
738       {
739         if (g_drv.USB_P_EP[n])
740           g_drv.USB_P_EP[n](USB_EVT_OUT);
741
742         LPC_USB->ENDPTCOMPLETE = (1<<n);
743       }
744       if (val & (1<<(n + 16)))
745       {
746         ep_TD [(n << 1) + 1 ].total_bytes &= 0xC0;
747         if (g_drv.USB_P_EP[n])
748           g_drv.USB_P_EP[n](USB_EVT_IN);
749         LPC_USB->ENDPTCOMPLETE = (1<<(n + 16));
750       }
751     }
752   }
753
754   if (disr & USBSTS_NAKI)
755   {
756 //                                                                                                      LPC_UART1->THR = 'N';
757 //                                                                                                      LPC_UART1->THR = '\n';
758     val = LPC_USB->ENDPTNAK;
759     val &= LPC_USB->ENDPTNAKEN;
760     /* handle NAK interrupts */
761     if (val)
762     {
763       for (n = 0; n < EP_NUM_MAX / 2; n++)
764       {
765         if (val & (1<<n))
766         {
767           if (g_drv.USB_P_EP[n])
768             g_drv.USB_P_EP[n](USB_EVT_OUT_NAK);
769         }
770         if (val & (1<<(n + 16)))
771         {
772           if (g_drv.USB_P_EP[n])
773             g_drv.USB_P_EP[n](USB_EVT_IN_NAK);
774         }
775       }
776       LPC_USB->ENDPTNAK = val;
777     }
778   }
779
780   /* Start of Frame Interrupt */
781   if (disr & USBSTS_SRI)
782   {
783 //                                                                                                      LPC_UART1->THR = 'F';
784 //                                                                                                      LPC_UART1->THR = '\n';
785     if (g_drv.USB_SOF_Event)
786       g_drv.USB_SOF_Event();
787   }
788
789   /* Error Interrupt */
790   if (disr & USBSTS_UEI)
791   {
792 //                                                                                                        LPC_UART1->THR = 'E';
793 //                                                                                                              LPC_UART1->THR = '\n';
794     if (g_drv.USB_Error_Event)
795       g_drv.USB_Error_Event(disr);
796   }
797
798 //    LPC_UART1->THR = 'r';
799 //      LPC_UART1->THR = '\n';
800 //isr_end:
801 //  LPC_VIC->VectAddr = 0;                   /* Acknowledge Interrupt */
802   return;
803 }