These are the examples provided for [[/users/frank26080115/libraries/LPC1700CMSIS_Lib/]] Note, the entire "program" is not compilable!

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers usbhw.c Source File

usbhw.c

00001 /*----------------------------------------------------------------------------
00002  *      U S B  -  K e r n e l
00003  *----------------------------------------------------------------------------
00004  * Name:    usbhw.c
00005  * Purpose: USB Hardware Layer Module for NXP's LPC17xx MCU
00006  * Version: V1.20
00007  *----------------------------------------------------------------------------
00008  *      This software is supplied "AS IS" without any warranties, express,
00009  *      implied or statutory, including but not limited to the implied
00010  *      warranties of fitness for purpose, satisfactory quality and
00011  *      noninfringement. Keil extends you a royalty-free right to reproduce
00012  *      and distribute executable files created using this software for use
00013  *      on NXP Semiconductors LPC family microcontroller devices only. Nothing 
00014  *      else gives you the right to use this software.
00015  *
00016  * Copyright (c) 2009 Keil - An ARM Company. All rights reserved.
00017  *----------------------------------------------------------------------------
00018  * History:
00019  *          V1.20 Added USB_ClearEPBuf
00020  *          V1.00 Initial Version
00021  *----------------------------------------------------------------------------*/
00022 #include "LPC17xx.h"                        /* LPC17xx definitions */
00023 #include "usb.h"
00024 #include "usbcfg.h"
00025 #include "usbreg.h"
00026 #include "usbhw.h"
00027 #include "usbcore.h"
00028 #include "usbuser.h"
00029 
00030 #if defined (  __CC_ARM__  )
00031 #pragma diag_suppress 1441
00032 #endif
00033 
00034 
00035 #define EP_MSK_CTRL 0x0001      /* Control Endpoint Logical Address Mask */
00036 #define EP_MSK_BULK 0xC924      /* Bulk Endpoint Logical Address Mask */
00037 #define EP_MSK_INT  0x4492      /* Interrupt Endpoint Logical Address Mask */
00038 #define EP_MSK_ISO  0x1248      /* Isochronous Endpoint Logical Address Mask */
00039 
00040 
00041 #if USB_DMA
00042 
00043 #pragma arm section zidata = "USB_RAM"
00044 uint32_t UDCA[USB_EP_NUM];                     /* UDCA in USB RAM */
00045 uint32_t DD_NISO_Mem[4*DD_NISO_CNT];           /* Non-Iso DMA Descriptor Memory */
00046 uint32_t DD_ISO_Mem [5*DD_ISO_CNT];            /* Iso DMA Descriptor Memory */
00047 #pragma arm section zidata
00048 uint32_t udca[USB_EP_NUM];                     /* UDCA saved values */
00049 
00050 uint32_t DDMemMap[2];                          /* DMA Descriptor Memory Usage */
00051 
00052 #endif
00053 
00054 
00055 /*
00056  *  Get Endpoint Physical Address
00057  *    Parameters:      EPNum: Endpoint Number
00058  *                       EPNum.0..3: Address
00059  *                       EPNum.7:    Dir
00060  *    Return Value:    Endpoint Physical Address
00061  */
00062 
00063 uint32_t EPAdr (uint32_t EPNum) {
00064   uint32_t val;
00065 
00066   val = (EPNum & 0x0F) << 1;
00067   if (EPNum & 0x80) {
00068     val += 1;
00069   }
00070   return (val);
00071 }
00072 
00073 
00074 /*
00075  *  Write Command
00076  *    Parameters:      cmd:   Command
00077  *    Return Value:    None
00078  */
00079 
00080 void WrCmd (uint32_t cmd) {
00081 
00082   LPC_USB->USBDevIntClr = CCEMTY_INT;
00083   LPC_USB->USBCmdCode = cmd;
00084   while ((LPC_USB->USBDevIntSt & CCEMTY_INT) == 0);
00085 }
00086 
00087 
00088 /*
00089  *  Write Command Data
00090  *    Parameters:      cmd:   Command
00091  *                     val:   Data
00092  *    Return Value:    None
00093  */
00094 
00095 void WrCmdDat (uint32_t cmd, uint32_t val) {
00096 
00097   LPC_USB->USBDevIntClr = CCEMTY_INT;
00098   LPC_USB->USBCmdCode = cmd;
00099   while ((LPC_USB->USBDevIntSt & CCEMTY_INT) == 0);
00100   LPC_USB->USBDevIntClr = CCEMTY_INT;
00101   LPC_USB->USBCmdCode = val;
00102   while ((LPC_USB->USBDevIntSt & CCEMTY_INT) == 0);
00103 }
00104 
00105 
00106 /*
00107  *  Write Command to Endpoint
00108  *    Parameters:      cmd:   Command
00109  *                     val:   Data
00110  *    Return Value:    None
00111  */
00112 
00113 void WrCmdEP (uint32_t EPNum, uint32_t cmd){
00114 
00115   LPC_USB->USBDevIntClr = CCEMTY_INT;
00116   LPC_USB->USBCmdCode = CMD_SEL_EP(EPAdr(EPNum));
00117   while ((LPC_USB->USBDevIntSt & CCEMTY_INT) == 0);
00118   LPC_USB->USBDevIntClr = CCEMTY_INT;
00119   LPC_USB->USBCmdCode = cmd;
00120   while ((LPC_USB->USBDevIntSt & CCEMTY_INT) == 0);
00121 }
00122 
00123 
00124 /*
00125  *  Read Command Data
00126  *    Parameters:      cmd:   Command
00127  *    Return Value:    Data Value
00128  */
00129 
00130 uint32_t RdCmdDat (uint32_t cmd) {
00131 
00132   LPC_USB->USBDevIntClr = CCEMTY_INT | CDFULL_INT;
00133   LPC_USB->USBCmdCode = cmd;
00134   while ((LPC_USB->USBDevIntSt & CDFULL_INT) == 0);
00135   return (LPC_USB->USBCmdData);
00136 }
00137 
00138 
00139 /*
00140  *  USB Initialize Function
00141  *   Called by the User to initialize USB
00142  *    Return Value:    None
00143  */
00144 
00145 void USB_Init (void) {
00146 
00147   LPC_PINCON->PINSEL1 &= ~((3<<26)|(3<<28));   /* P0.29 D+, P0.30 D- */
00148   LPC_PINCON->PINSEL1 |=  ((1<<26)|(1<<28));   /* PINSEL1 26.27, 28.29  = 01 */
00149 
00150   LPC_PINCON->PINSEL3 &= ~((3<< 4)|(3<<28));   /* P1.18 GoodLink, P1.30 VBUS */
00151   LPC_PINCON->PINSEL3 |=  ((1<< 4)|(2<<28));   /* PINSEL3 4.5 = 01, 28.29 = 10 */
00152 
00153   LPC_PINCON->PINSEL4 &= ~((3<<18)        );   /* P2.9 SoftConnect */
00154   LPC_PINCON->PINSEL4 |=  ((1<<18)        );   /* PINSEL4 18.19 = 01 */
00155 
00156   LPC_SC->PCONP |= (1UL<<31);                /* USB PCLK -> enable USB Per.       */
00157 
00158   LPC_USB->USBClkCtrl = 0x1A;                /* Dev, PortSel, AHB clock enable */
00159   while ((LPC_USB->USBClkSt & 0x1A) != 0x1A); 
00160 
00161   NVIC_EnableIRQ(USB_IRQn);               /* enable USB interrupt */
00162 
00163   USB_Reset();
00164   USB_SetAddress(0);
00165 }
00166 
00167 
00168 /*
00169  *  USB Connect Function
00170  *   Called by the User to Connect/Disconnect USB
00171  *    Parameters:      con:   Connect/Disconnect
00172  *    Return Value:    None
00173  */
00174 
00175 void USB_Connect (uint32_t con) {
00176   WrCmdDat(CMD_SET_DEV_STAT, DAT_WR_BYTE(con ? DEV_CON : 0));
00177 }
00178 
00179 
00180 /*
00181  *  USB Reset Function
00182  *   Called automatically on USB Reset
00183  *    Return Value:    None
00184  */
00185 
00186 void USB_Reset (void) {
00187 #if USB_DMA
00188   uint32_t n;
00189 #endif
00190 
00191   LPC_USB->USBEpInd = 0;
00192   LPC_USB->USBMaxPSize = USB_MAX_PACKET0;
00193   LPC_USB->USBEpInd = 1;
00194   LPC_USB->USBMaxPSize = USB_MAX_PACKET0;
00195   while ((LPC_USB->USBDevIntSt & EP_RLZED_INT) == 0);
00196 
00197   LPC_USB->USBEpIntClr  = 0xFFFFFFFF;
00198   LPC_USB->USBEpIntEn   = 0xFFFFFFFF ^ USB_DMA_EP;
00199   LPC_USB->USBDevIntClr = 0xFFFFFFFF;
00200   LPC_USB->USBDevIntEn  = DEV_STAT_INT    | EP_SLOW_INT    |
00201                (USB_SOF_EVENT   ? FRAME_INT : 0) |
00202                (USB_ERROR_EVENT ? ERR_INT   : 0);
00203 
00204 #if USB_DMA
00205   LPC_USB->USBUDCAH   = USB_RAM_ADR;
00206   LPC_USB->USBDMARClr = 0xFFFFFFFF;
00207   LPC_USB->USBEpDMADis  = 0xFFFFFFFF;
00208   LPC_USB->USBEpDMAEn   = USB_DMA_EP;
00209   LPC_USB->USBEoTIntClr = 0xFFFFFFFF;
00210   LPC_USB->USBNDDRIntClr = 0xFFFFFFFF;
00211   LPC_USB->USBSysErrIntClr = 0xFFFFFFFF;
00212   LPC_USB->USBDMAIntEn  = 0x00000007;
00213   DDMemMap[0] = 0x00000000;
00214   DDMemMap[1] = 0x00000000;
00215   for (n = 0; n < USB_EP_NUM; n++) {
00216     udca[n] = 0;
00217     UDCA[n] = 0;
00218   }
00219 #endif
00220 }
00221 
00222 
00223 /*
00224  *  USB Suspend Function
00225  *   Called automatically on USB Suspend
00226  *    Return Value:    None
00227  */
00228 
00229 void USB_Suspend (void) {
00230   /* Performed by Hardware */
00231 }
00232 
00233 
00234 /*
00235  *  USB Resume Function
00236  *   Called automatically on USB Resume
00237  *    Return Value:    None
00238  */
00239 
00240 void USB_Resume (void) {
00241   /* Performed by Hardware */
00242 }
00243 
00244 
00245 /*
00246  *  USB Remote Wakeup Function
00247  *   Called automatically on USB Remote Wakeup
00248  *    Return Value:    None
00249  */
00250 
00251 void USB_WakeUp (void) {
00252 
00253   if (USB_DeviceStatus & USB_GETSTATUS_REMOTE_WAKEUP) {
00254     WrCmdDat(CMD_SET_DEV_STAT, DAT_WR_BYTE(DEV_CON));
00255   }
00256 }
00257 
00258 
00259 /*
00260  *  USB Remote Wakeup Configuration Function
00261  *    Parameters:      cfg:   Enable/Disable
00262  *    Return Value:    None
00263  */
00264 
00265 void USB_WakeUpCfg (uint32_t cfg) {
00266   /* Not needed */
00267 }
00268 
00269 
00270 /*
00271  *  USB Set Address Function
00272  *    Parameters:      adr:   USB Address
00273  *    Return Value:    None
00274  */
00275 
00276 void USB_SetAddress (uint32_t adr) {
00277   WrCmdDat(CMD_SET_ADDR, DAT_WR_BYTE(DEV_EN | adr)); /* Don't wait for next */
00278   WrCmdDat(CMD_SET_ADDR, DAT_WR_BYTE(DEV_EN | adr)); /*  Setup Status Phase */
00279 }
00280 
00281 
00282 /*
00283  *  USB Configure Function
00284  *    Parameters:      cfg:   Configure/Deconfigure
00285  *    Return Value:    None
00286  */
00287 
00288 void USB_Configure (uint32_t cfg) {
00289 
00290   WrCmdDat(CMD_CFG_DEV, DAT_WR_BYTE(cfg ? CONF_DVICE : 0));
00291 
00292   LPC_USB->USBReEp = 0x00000003;
00293   while ((LPC_USB->USBDevIntSt & EP_RLZED_INT) == 0);
00294   LPC_USB->USBDevIntClr = EP_RLZED_INT;
00295 }
00296 
00297 
00298 /*
00299  *  Configure USB Endpoint according to Descriptor
00300  *    Parameters:      pEPD:  Pointer to Endpoint Descriptor
00301  *    Return Value:    None
00302  */
00303 
00304 void USB_ConfigEP (USB_ENDPOINT_DESCRIPTOR *pEPD) {
00305   uint32_t num;
00306 
00307   num = EPAdr(pEPD->bEndpointAddress);
00308   LPC_USB->USBReEp |= (1 << num);
00309   LPC_USB->USBEpInd = num;
00310   LPC_USB->USBMaxPSize = pEPD->wMaxPacketSize;
00311   while ((LPC_USB->USBDevIntSt & EP_RLZED_INT) == 0);
00312   LPC_USB->USBDevIntClr = EP_RLZED_INT;
00313 }
00314 
00315 
00316 /*
00317  *  Set Direction for USB Control Endpoint
00318  *    Parameters:      dir:   Out (dir == 0), In (dir <> 0)
00319  *    Return Value:    None
00320  */
00321 
00322 void USB_DirCtrlEP (uint32_t dir) {
00323   /* Not needed */
00324 }
00325 
00326 
00327 /*
00328  *  Enable USB Endpoint
00329  *    Parameters:      EPNum: Endpoint Number
00330  *                       EPNum.0..3: Address
00331  *                       EPNum.7:    Dir
00332  *    Return Value:    None
00333  */
00334 
00335 void USB_EnableEP (uint32_t EPNum) {
00336   WrCmdDat(CMD_SET_EP_STAT(EPAdr(EPNum)), DAT_WR_BYTE(0));
00337 }
00338 
00339 
00340 /*
00341  *  Disable USB Endpoint
00342  *    Parameters:      EPNum: Endpoint Number
00343  *                       EPNum.0..3: Address
00344  *                       EPNum.7:    Dir
00345  *    Return Value:    None
00346  */
00347 
00348 void USB_DisableEP (uint32_t EPNum) {
00349   WrCmdDat(CMD_SET_EP_STAT(EPAdr(EPNum)), DAT_WR_BYTE(EP_STAT_DA));
00350 }
00351 
00352 
00353 /*
00354  *  Reset USB Endpoint
00355  *    Parameters:      EPNum: Endpoint Number
00356  *                       EPNum.0..3: Address
00357  *                       EPNum.7:    Dir
00358  *    Return Value:    None
00359  */
00360 
00361 void USB_ResetEP (uint32_t EPNum) {
00362   WrCmdDat(CMD_SET_EP_STAT(EPAdr(EPNum)), DAT_WR_BYTE(0));
00363 }
00364 
00365 
00366 /*
00367  *  Set Stall for USB Endpoint
00368  *    Parameters:      EPNum: Endpoint Number
00369  *                       EPNum.0..3: Address
00370  *                       EPNum.7:    Dir
00371  *    Return Value:    None
00372  */
00373 
00374 void USB_SetStallEP (uint32_t EPNum) {
00375   WrCmdDat(CMD_SET_EP_STAT(EPAdr(EPNum)), DAT_WR_BYTE(EP_STAT_ST));
00376 }
00377 
00378 
00379 /*
00380  *  Clear Stall for USB Endpoint
00381  *    Parameters:      EPNum: Endpoint Number
00382  *                       EPNum.0..3: Address
00383  *                       EPNum.7:    Dir
00384  *    Return Value:    None
00385  */
00386 
00387 void USB_ClrStallEP (uint32_t EPNum) {
00388   WrCmdDat(CMD_SET_EP_STAT(EPAdr(EPNum)), DAT_WR_BYTE(0));
00389 }
00390 
00391 
00392 /*
00393  *  Clear USB Endpoint Buffer
00394  *    Parameters:      EPNum: Endpoint Number
00395  *                       EPNum.0..3: Address
00396  *                       EPNum.7:    Dir
00397  *    Return Value:    None
00398  */
00399 
00400 void USB_ClearEPBuf (uint32_t EPNum) {
00401   WrCmdEP(EPNum, CMD_CLR_BUF);
00402 }
00403 
00404 
00405 /*
00406  *  Read USB Endpoint Data
00407  *    Parameters:      EPNum: Endpoint Number
00408  *                       EPNum.0..3: Address
00409  *                       EPNum.7:    Dir
00410  *                     pData: Pointer to Data Buffer
00411  *    Return Value:    Number of bytes read
00412  */
00413 
00414 uint32_t USB_ReadEP (uint32_t EPNum, uint8_t *pData) {
00415   uint32_t cnt, n;
00416 
00417   LPC_USB->USBCtrl = ((EPNum & 0x0F) << 2) | CTRL_RD_EN;
00418 
00419   do {
00420     cnt = LPC_USB->USBRxPLen;
00421   } while ((cnt & PKT_RDY) == 0);
00422   cnt &= PKT_LNGTH_MASK;
00423 
00424   for (n = 0; n < (cnt + 3) / 4; n++) {
00425     *((__packed uint32_t *)pData) = LPC_USB->USBRxData;
00426     pData += 4;
00427   }
00428   LPC_USB->USBCtrl = 0;
00429 
00430   if (((EP_MSK_ISO >> EPNum) & 1) == 0) {   /* Non-Isochronous Endpoint */
00431     WrCmdEP(EPNum, CMD_CLR_BUF);
00432   }
00433 
00434   return (cnt);
00435 }
00436 
00437 
00438 /*
00439  *  Write USB Endpoint Data
00440  *    Parameters:      EPNum: Endpoint Number
00441  *                       EPNum.0..3: Address
00442  *                       EPNum.7:    Dir
00443  *                     pData: Pointer to Data Buffer
00444  *                     cnt:   Number of bytes to write
00445  *    Return Value:    Number of bytes written
00446  */
00447 
00448 uint32_t USB_WriteEP (uint32_t EPNum, uint8_t *pData, uint32_t cnt) {
00449   uint32_t n;
00450 
00451   LPC_USB->USBCtrl = ((EPNum & 0x0F) << 2) | CTRL_WR_EN;
00452 
00453   LPC_USB->USBTxPLen = cnt;
00454 
00455   for (n = 0; n < (cnt + 3) / 4; n++) {
00456     LPC_USB->USBTxData = *((__packed uint32_t *)pData);
00457     pData += 4;
00458   }
00459   LPC_USB->USBCtrl = 0;
00460   WrCmdEP(EPNum, CMD_VALID_BUF);
00461   return (cnt);
00462 }
00463 
00464 #if USB_DMA
00465 
00466 /* DMA Descriptor Memory Layout */
00467 const uint32_t DDAdr[2] = { DD_NISO_ADR, DD_ISO_ADR };
00468 const uint32_t DDSz [2] = { 16,          20         };
00469 
00470 
00471 /*
00472  *  Setup USB DMA Transfer for selected Endpoint
00473  *    Parameters:      EPNum: Endpoint Number
00474  *                     pDD: Pointer to DMA Descriptor
00475  *    Return Value:    TRUE - Success, FALSE - Error
00476  */
00477 
00478 uint32_t USB_DMA_Setup(uint32_t EPNum, USB_DMA_DESCRIPTOR *pDD) {
00479   uint32_t num, ptr, nxt, iso, n;
00480 
00481   iso = pDD->Cfg.Type.IsoEP;                /* Iso or Non-Iso Descriptor */
00482   num = EPAdr(EPNum);                       /* Endpoint's Physical Address */
00483 
00484   ptr = 0;                                  /* Current Descriptor */
00485   nxt = udca[num];                          /* Initial Descriptor */
00486   while (nxt) {                             /* Go through Descriptor List */
00487     ptr = nxt;                              /* Current Descriptor */
00488     if (!pDD->Cfg.Type.Link) {              /* Check for Linked Descriptors */
00489       n = (ptr - DDAdr[iso]) / DDSz[iso];   /* Descriptor Index */
00490       DDMemMap[iso] &= ~(1 << n);           /* Unmark Memory Usage */
00491     }
00492     nxt = *((uint32_t *)ptr);                  /* Next Descriptor */
00493   }
00494 
00495   for (n = 0; n < 32; n++) {                /* Search for available Memory */
00496     if ((DDMemMap[iso] & (1 << n)) == 0) {
00497       break;                                /* Memory found */
00498     }
00499   }
00500   if (n == 32) return (FALSE);              /* Memory not available */
00501 
00502   DDMemMap[iso] |= 1 << n;                  /* Mark Memory Usage */
00503   nxt = DDAdr[iso] + n * DDSz[iso];         /* Next Descriptor */
00504 
00505   if (ptr && pDD->Cfg.Type.Link) {
00506     *((uint32_t *)(ptr + 0))  = nxt;           /* Link in new Descriptor */
00507     *((uint32_t *)(ptr + 4)) |= 0x00000004;    /* Next DD is Valid */
00508   } else {
00509     udca[num] = nxt;                        /* Save new Descriptor */
00510     UDCA[num] = nxt;                        /* Update UDCA in USB */
00511   }
00512 
00513   /* Fill in DMA Descriptor */
00514   *(((uint32_t *)nxt)++) =  0;                 /* Next DD Pointer */
00515   *(((uint32_t *)nxt)++) =  pDD->Cfg.Type.ATLE |
00516                        (pDD->Cfg.Type.IsoEP << 4) |
00517                        (pDD->MaxSize <<  5) |
00518                        (pDD->BufLen  << 16);
00519   *(((uint32_t *)nxt)++) =  pDD->BufAdr;
00520   *(((uint32_t *)nxt)++) =  pDD->Cfg.Type.LenPos << 8;
00521   if (iso) {
00522     *((uint32_t *)nxt) =  pDD->InfoAdr;
00523   }
00524 
00525   return (TRUE); /* Success */
00526 }
00527 
00528 
00529 /*
00530  *  Enable USB DMA Endpoint
00531  *    Parameters:      EPNum: Endpoint Number
00532  *                       EPNum.0..3: Address
00533  *                       EPNum.7:    Dir
00534  *    Return Value:    None
00535  */
00536 
00537 void USB_DMA_Enable (uint32_t EPNum) {
00538   LPC_USB->USBEpDMAEn = 1 << EPAdr(EPNum);
00539 }
00540 
00541 
00542 /*
00543  *  Disable USB DMA Endpoint
00544  *    Parameters:      EPNum: Endpoint Number
00545  *                       EPNum.0..3: Address
00546  *                       EPNum.7:    Dir
00547  *    Return Value:    None
00548  */
00549 
00550 void USB_DMA_Disable (uint32_t EPNum) {
00551   LPC_USB->USBEpDMADis = 1 << EPAdr(EPNum);
00552 }
00553 
00554 
00555 /*
00556  *  Get USB DMA Endpoint Status
00557  *    Parameters:      EPNum: Endpoint Number
00558  *                       EPNum.0..3: Address
00559  *                       EPNum.7:    Dir
00560  *    Return Value:    DMA Status
00561  */
00562 
00563 uint32_t USB_DMA_Status (uint32_t EPNum) {
00564   uint32_t ptr, val;
00565           
00566   ptr = UDCA[EPAdr(EPNum)];                 /* Current Descriptor */
00567   if (ptr == 0) 
00568     return (USB_DMA_INVALID);
00569 
00570   val = *((uint32_t *)(ptr + 3*4));            /* Status Information */
00571   switch ((val >> 1) & 0x0F) {
00572     case 0x00:                              /* Not serviced */
00573       return (USB_DMA_IDLE);
00574     case 0x01:                              /* Being serviced */
00575       return (USB_DMA_BUSY);
00576     case 0x02:                              /* Normal Completition */
00577       return (USB_DMA_DONE);
00578     case 0x03:                              /* Data Under Run */
00579       return (USB_DMA_UNDER_RUN);
00580     case 0x08:                              /* Data Over Run */
00581       return (USB_DMA_OVER_RUN);
00582     case 0x09:                              /* System Error */
00583       return (USB_DMA_ERROR);
00584   }
00585 
00586   return (USB_DMA_UNKNOWN);
00587 }
00588 
00589 
00590 /*
00591  *  Get USB DMA Endpoint Current Buffer Address
00592  *    Parameters:      EPNum: Endpoint Number
00593  *                       EPNum.0..3: Address
00594  *                       EPNum.7:    Dir
00595  *    Return Value:    DMA Address (or -1 when DMA is Invalid)
00596  */
00597 
00598 uint32_t USB_DMA_BufAdr (uint32_t EPNum) {
00599   uint32_t ptr, val;
00600 
00601   ptr = UDCA[EPAdr(EPNum)];                 /* Current Descriptor */
00602   if (ptr == 0)
00603   {
00604     return ((uint32_t)(-1));                /* DMA Invalid */
00605   }
00606 
00607   val = *((uint32_t *)(ptr + 2*4));         /* Buffer Address */
00608   return (val);                             /* Current Address */
00609 }
00610 
00611 
00612 /*
00613  *  Get USB DMA Endpoint Current Buffer Count
00614  *   Number of transfered Bytes or Iso Packets
00615  *    Parameters:      EPNum: Endpoint Number
00616  *                       EPNum.0..3: Address
00617  *                       EPNum.7:    Dir
00618  *    Return Value:    DMA Count (or -1 when DMA is Invalid)
00619  */
00620 
00621 uint32_t USB_DMA_BufCnt (uint32_t EPNum) {
00622   uint32_t ptr, val;
00623 
00624   ptr = UDCA[EPAdr(EPNum)];                 /* Current Descriptor */
00625   if (ptr == 0)
00626   { 
00627     return ((uint32_t)(-1));                /* DMA Invalid */
00628   }
00629   val = *((uint32_t *)(ptr + 3*4));         /* Status Information */
00630   return (val >> 16);                       /* Current Count */
00631 }
00632 
00633 
00634 #endif /* USB_DMA */
00635 
00636 
00637 /*
00638  *  Get USB Last Frame Number
00639  *    Parameters:      None
00640  *    Return Value:    Frame Number
00641  */
00642 
00643 uint32_t USB_GetFrame (void) {
00644   uint32_t val;
00645 
00646   WrCmd(CMD_RD_FRAME);
00647   val = RdCmdDat(DAT_RD_FRAME);
00648   val = val | (RdCmdDat(DAT_RD_FRAME) << 8);
00649 
00650   return (val);
00651 }
00652 
00653 
00654 /*
00655  *  USB Interrupt Service Routine
00656  */
00657 
00658 void USB_IRQHandler (void) {
00659   uint32_t disr, val, n, m;
00660   uint32_t episr, episrCur;
00661 
00662   disr = LPC_USB->USBDevIntSt;       /* Device Interrupt Status */
00663 
00664   /* Device Status Interrupt (Reset, Connect change, Suspend/Resume) */
00665   if (disr & DEV_STAT_INT) {
00666     LPC_USB->USBDevIntClr = DEV_STAT_INT;
00667     WrCmd(CMD_GET_DEV_STAT);
00668     val = RdCmdDat(DAT_GET_DEV_STAT);       /* Device Status */
00669     if (val & DEV_RST) {                    /* Reset */
00670       USB_Reset();
00671 #if   USB_RESET_EVENT
00672       USB_Reset_Event();
00673 #endif
00674     }
00675     if (val & DEV_CON_CH) {                 /* Connect change */
00676 #if   USB_POWER_EVENT
00677       USB_Power_Event(val & DEV_CON);
00678 #endif
00679     }
00680     if (val & DEV_SUS_CH) {                 /* Suspend/Resume */
00681       if (val & DEV_SUS) {                  /* Suspend */
00682         USB_Suspend();
00683 #if     USB_SUSPEND_EVENT
00684         USB_Suspend_Event();
00685 #endif
00686       } else {                              /* Resume */
00687         USB_Resume();
00688 #if     USB_RESUME_EVENT
00689         USB_Resume_Event();
00690 #endif
00691       }
00692     }
00693     goto isr_end;
00694   }
00695 
00696 #if USB_SOF_EVENT
00697   /* Start of Frame Interrupt */
00698   if (disr & FRAME_INT) {
00699     USB_SOF_Event();
00700   }
00701 #endif
00702 
00703 #if USB_ERROR_EVENT
00704   /* Error Interrupt */
00705   if (disr & ERR_INT) {
00706     WrCmd(CMD_RD_ERR_STAT);
00707     val = RdCmdDat(DAT_RD_ERR_STAT);
00708     USB_Error_Event(val);
00709   }
00710 #endif
00711 
00712   /* Endpoint's Slow Interrupt */
00713   if (disr & EP_SLOW_INT) {
00714     episrCur = 0;
00715     episr    = LPC_USB->USBEpIntSt;
00716     for (n = 0; n < USB_EP_NUM; n++) {      /* Check All Endpoints */
00717       if (episr == episrCur) break;         /* break if all EP interrupts handled */
00718       if (episr & (1 << n)) {
00719         episrCur |= (1 << n);
00720         m = n >> 1;
00721   
00722         LPC_USB->USBEpIntClr = (1 << n);
00723         while ((LPC_USB->USBDevIntSt & CDFULL_INT) == 0);
00724         val = LPC_USB->USBCmdData;
00725   
00726         if ((n & 1) == 0) {                 /* OUT Endpoint */
00727           if (n == 0) {                     /* Control OUT Endpoint */
00728             if (val & EP_SEL_STP) {         /* Setup Packet */
00729               if (USB_P_EP[0]) {
00730                 USB_P_EP[0](USB_EVT_SETUP);
00731                 continue;
00732               }
00733             }
00734           }
00735           if (USB_P_EP[m]) {
00736             USB_P_EP[m](USB_EVT_OUT);
00737           }
00738         } else {                            /* IN Endpoint */
00739           if (USB_P_EP[m]) {
00740             USB_P_EP[m](USB_EVT_IN);
00741           }
00742         }
00743       }
00744     }
00745     LPC_USB->USBDevIntClr = EP_SLOW_INT;
00746   }
00747 
00748 #if USB_DMA
00749 
00750   if (LPC_USB->USBDMAIntSt & 0x00000001) {          /* End of Transfer Interrupt */
00751     val = LPC_USB->USBEoTIntSt;
00752     for (n = 2; n < USB_EP_NUM; n++) {      /* Check All Endpoints */
00753       if (val & (1 << n)) {
00754         m = n >> 1;
00755         if ((n & 1) == 0) {                 /* OUT Endpoint */
00756           if (USB_P_EP[m]) {
00757             USB_P_EP[m](USB_EVT_OUT_DMA_EOT);
00758           }
00759         } else {                            /* IN Endpoint */
00760           if (USB_P_EP[m]) {
00761             USB_P_EP[m](USB_EVT_IN_DMA_EOT);
00762           }
00763         }
00764       }
00765     }
00766     LPC_USB->USBEoTIntClr = val;
00767   }
00768 
00769   if (LPC_USB->USBDMAIntSt & 0x00000002) {          /* New DD Request Interrupt */
00770     val = LPC_USB->USBNDDRIntSt;
00771     for (n = 2; n < USB_EP_NUM; n++) {      /* Check All Endpoints */
00772       if (val & (1 << n)) {
00773         m = n >> 1;
00774         if ((n & 1) == 0) {                 /* OUT Endpoint */
00775           if (USB_P_EP[m]) {
00776             USB_P_EP[m](USB_EVT_OUT_DMA_NDR);
00777           }
00778         } else {                            /* IN Endpoint */
00779           if (USB_P_EP[m]) {
00780             USB_P_EP[m](USB_EVT_IN_DMA_NDR);
00781           }
00782         }
00783       }
00784     }
00785     LPC_USB->USBNDDRIntClr = val;
00786   }
00787 
00788   if (LPC_USB->USBDMAIntSt & 0x00000004) {          /* System Error Interrupt */
00789     val = LPC_USB->USBSysErrIntSt;
00790     for (n = 2; n < USB_EP_NUM; n++) {      /* Check All Endpoints */
00791       if (val & (1 << n)) {
00792         m = n >> 1;
00793         if ((n & 1) == 0) {                 /* OUT Endpoint */
00794           if (USB_P_EP[m]) {
00795             USB_P_EP[m](USB_EVT_OUT_DMA_ERR);
00796           }
00797         } else {                            /* IN Endpoint */
00798           if (USB_P_EP[m]) {
00799             USB_P_EP[m](USB_EVT_IN_DMA_ERR);
00800           }
00801         }
00802       }
00803     }
00804     LPC_USB->USBSysErrIntClr = val;
00805   }
00806 
00807 #endif /* USB_DMA */
00808 
00809 isr_end:
00810   return;
00811 }