X-Git-Url: http://git.asbjorn.biz/?p=rapper.git;a=blobdiff_plain;f=new_cmsis%2Fusb%2Fhw.c;fp=new_cmsis%2Fusb%2Fusbhw.c;h=e8fd5f4928f5afa30f82db3a532fc52e1ccf6674;hp=e58b2680b6e8dd69115fa8bca62ac1e3286b6dec;hb=2253dc3498d4ace7f07884ec6d40d654ca677571;hpb=678d5839c35477bcb24f2a29ebb5bce4ce5f8152 diff --git a/new_cmsis/usb/usbhw.c b/new_cmsis/usb/hw.c similarity index 95% rename from new_cmsis/usb/usbhw.c rename to new_cmsis/usb/hw.c index e58b268..e8fd5f4 100755 --- a/new_cmsis/usb/usbhw.c +++ b/new_cmsis/usb/hw.c @@ -1,811 +1,811 @@ -/*---------------------------------------------------------------------------- - * U S B - K e r n e l - *---------------------------------------------------------------------------- - * Name: usbhw.c - * Purpose: USB Hardware Layer Module for NXP's LPC17xx MCU - * Version: V1.20 - *---------------------------------------------------------------------------- - * This software is supplied "AS IS" without any warranties, express, - * implied or statutory, including but not limited to the implied - * warranties of fitness for purpose, satisfactory quality and - * noninfringement. Keil extends you a royalty-free right to reproduce - * and distribute executable files created using this software for use - * on NXP Semiconductors LPC family microcontroller devices only. Nothing - * else gives you the right to use this software. - * - * Copyright (c) 2009 Keil - An ARM Company. All rights reserved. - *---------------------------------------------------------------------------- - * History: - * V1.20 Added USB_ClearEPBuf - * V1.00 Initial Version - *----------------------------------------------------------------------------*/ -#include "../LPC17xx.h" /* LPC17xx definitions */ -#include "usb.h" -#include "usbcfg.h" -#include "usbreg.h" -#include "usbhw.h" -#include "usbcore.h" -#include "usbuser.h" - -#if defined ( __CC_ARM__ ) -#pragma diag_suppress 1441 -#endif - - -#define EP_MSK_CTRL 0x0001 /* Control Endpoint Logical Address Mask */ -#define EP_MSK_BULK 0xC924 /* Bulk Endpoint Logical Address Mask */ -#define EP_MSK_INT 0x4492 /* Interrupt Endpoint Logical Address Mask */ -#define EP_MSK_ISO 0x1248 /* Isochronous Endpoint Logical Address Mask */ - - -#if USB_DMA - -#pragma arm section zidata = "USB_RAM" -uint32_t UDCA[USB_EP_NUM]; /* UDCA in USB RAM */ -uint32_t DD_NISO_Mem[4*DD_NISO_CNT]; /* Non-Iso DMA Descriptor Memory */ -uint32_t DD_ISO_Mem [5*DD_ISO_CNT]; /* Iso DMA Descriptor Memory */ -#pragma arm section zidata -uint32_t udca[USB_EP_NUM]; /* UDCA saved values */ - -uint32_t DDMemMap[2]; /* DMA Descriptor Memory Usage */ - -#endif - - -/* - * Get Endpoint Physical Address - * Parameters: EPNum: Endpoint Number - * EPNum.0..3: Address - * EPNum.7: Dir - * Return Value: Endpoint Physical Address - */ - -uint32_t EPAdr (uint32_t EPNum) { - uint32_t val; - - val = (EPNum & 0x0F) << 1; - if (EPNum & 0x80) { - val += 1; - } - return (val); -} - - -/* - * Write Command - * Parameters: cmd: Command - * Return Value: None - */ - -void WrCmd (uint32_t cmd) { - - USB->USBDevIntClr = CCEMTY_INT; - USB->USBCmdCode = cmd; - while ((USB->USBDevIntSt & CCEMTY_INT) == 0); -} - - -/* - * Write Command Data - * Parameters: cmd: Command - * val: Data - * Return Value: None - */ - -void WrCmdDat (uint32_t cmd, uint32_t val) { - - USB->USBDevIntClr = CCEMTY_INT; - USB->USBCmdCode = cmd; - while ((USB->USBDevIntSt & CCEMTY_INT) == 0); - USB->USBDevIntClr = CCEMTY_INT; - USB->USBCmdCode = val; - while ((USB->USBDevIntSt & CCEMTY_INT) == 0); -} - - -/* - * Write Command to Endpoint - * Parameters: cmd: Command - * val: Data - * Return Value: None - */ - -void WrCmdEP (uint32_t EPNum, uint32_t cmd){ - - USB->USBDevIntClr = CCEMTY_INT; - USB->USBCmdCode = CMD_SEL_EP(EPAdr(EPNum)); - while ((USB->USBDevIntSt & CCEMTY_INT) == 0); - USB->USBDevIntClr = CCEMTY_INT; - USB->USBCmdCode = cmd; - while ((USB->USBDevIntSt & CCEMTY_INT) == 0); -} - - -/* - * Read Command Data - * Parameters: cmd: Command - * Return Value: Data Value - */ - -uint32_t RdCmdDat (uint32_t cmd) { - - USB->USBDevIntClr = CCEMTY_INT | CDFULL_INT; - USB->USBCmdCode = cmd; - while ((USB->USBDevIntSt & CDFULL_INT) == 0); - return (USB->USBCmdData); -} - - -/* - * USB Initialize Function - * Called by the User to initialize USB - * Return Value: None - */ - -void USB_Init (void) { - - PINCON->PINSEL1 &= ~((3<<26)|(3<<28)); /* P0.29 D+, P0.30 D- */ - PINCON->PINSEL1 |= ((1<<26)|(1<<28)); /* PINSEL1 26.27, 28.29 = 01 */ - - PINCON->PINSEL3 &= ~((3<< 4)|(3<<28)); /* P1.18 GoodLink, P1.30 VBUS */ - PINCON->PINSEL3 |= ((1<< 4)|(2<<28)); /* PINSEL3 4.5 = 01, 28.29 = 10 */ - - PINCON->PINSEL4 &= ~((3<<18) ); /* P2.9 SoftConnect */ - PINCON->PINSEL4 |= ((1<<18) ); /* PINSEL4 18.19 = 01 */ - - SC->PCONP |= (1UL<<31); /* USB PCLK -> enable USB Per. */ - - USB->USBClkCtrl = 0x1A; /* Dev, PortSel, AHB clock enable */ - while ((USB->USBClkSt & 0x1A) != 0x1A); - - NVIC_EnableIRQ(USB_IRQn); /* enable USB interrupt */ - - USB_Reset(); - USB_SetAddress(0); -} - - -/* - * USB Connect Function - * Called by the User to Connect/Disconnect USB - * Parameters: con: Connect/Disconnect - * Return Value: None - */ - -void USB_Connect (uint32_t con) { - WrCmdDat(CMD_SET_DEV_STAT, DAT_WR_BYTE(con ? DEV_CON : 0)); -} - - -/* - * USB Reset Function - * Called automatically on USB Reset - * Return Value: None - */ - -void USB_Reset (void) { -#if USB_DMA - uint32_t n; -#endif - - USB->USBEpInd = 0; - USB->USBMaxPSize = USB_MAX_PACKET0; - USB->USBEpInd = 1; - USB->USBMaxPSize = USB_MAX_PACKET0; - while ((USB->USBDevIntSt & EP_RLZED_INT) == 0); - - USB->USBEpIntClr = 0xFFFFFFFF; - USB->USBEpIntEn = 0xFFFFFFFF ^ USB_DMA_EP; - USB->USBDevIntClr = 0xFFFFFFFF; - USB->USBDevIntEn = DEV_STAT_INT | EP_SLOW_INT | - (USB_SOF_EVENT ? FRAME_INT : 0) | - (USB_ERROR_EVENT ? ERR_INT : 0); - -#if USB_DMA - USB->USBUDCAH = USB_RAM_ADR; - USB->USBDMARClr = 0xFFFFFFFF; - USB->USBEpDMADis = 0xFFFFFFFF; - USB->USBEpDMAEn = USB_DMA_EP; - USB->USBEoTIntClr = 0xFFFFFFFF; - USB->USBNDDRIntClr = 0xFFFFFFFF; - USB->USBSysErrIntClr = 0xFFFFFFFF; - USB->USBDMAIntEn = 0x00000007; - DDMemMap[0] = 0x00000000; - DDMemMap[1] = 0x00000000; - for (n = 0; n < USB_EP_NUM; n++) { - udca[n] = 0; - UDCA[n] = 0; - } -#endif -} - - -/* - * USB Suspend Function - * Called automatically on USB Suspend - * Return Value: None - */ - -void USB_Suspend (void) { - /* Performed by Hardware */ -} - - -/* - * USB Resume Function - * Called automatically on USB Resume - * Return Value: None - */ - -void USB_Resume (void) { - /* Performed by Hardware */ -} - - -/* - * USB Remote Wakeup Function - * Called automatically on USB Remote Wakeup - * Return Value: None - */ - -void USB_WakeUp (void) { - - if (USB_DeviceStatus & USB_GETSTATUS_REMOTE_WAKEUP) { - WrCmdDat(CMD_SET_DEV_STAT, DAT_WR_BYTE(DEV_CON)); - } -} - - -/* - * USB Remote Wakeup Configuration Function - * Parameters: cfg: Enable/Disable - * Return Value: None - */ - -void USB_WakeUpCfg (uint32_t cfg) { - /* Not needed */ -} - - -/* - * USB Set Address Function - * Parameters: adr: USB Address - * Return Value: None - */ - -void USB_SetAddress (uint32_t adr) { - WrCmdDat(CMD_SET_ADDR, DAT_WR_BYTE(DEV_EN | adr)); /* Don't wait for next */ - WrCmdDat(CMD_SET_ADDR, DAT_WR_BYTE(DEV_EN | adr)); /* Setup Status Phase */ -} - - -/* - * USB Configure Function - * Parameters: cfg: Configure/Deconfigure - * Return Value: None - */ - -void USB_Configure (uint32_t cfg) { - - WrCmdDat(CMD_CFG_DEV, DAT_WR_BYTE(cfg ? CONF_DVICE : 0)); - - USB->USBReEp = 0x00000003; - while ((USB->USBDevIntSt & EP_RLZED_INT) == 0); - USB->USBDevIntClr = EP_RLZED_INT; -} - - -/* - * Configure USB Endpoint according to Descriptor - * Parameters: pEPD: Pointer to Endpoint Descriptor - * Return Value: None - */ - -void USB_ConfigEP (USB_ENDPOINT_DESCRIPTOR *pEPD) { - uint32_t num; - - num = EPAdr(pEPD->bEndpointAddress); - USB->USBReEp |= (1 << num); - USB->USBEpInd = num; - USB->USBMaxPSize = pEPD->wMaxPacketSize; - while ((USB->USBDevIntSt & EP_RLZED_INT) == 0); - USB->USBDevIntClr = EP_RLZED_INT; -} - - -/* - * Set Direction for USB Control Endpoint - * Parameters: dir: Out (dir == 0), In (dir <> 0) - * Return Value: None - */ - -void USB_DirCtrlEP (uint32_t dir) { - /* Not needed */ -} - - -/* - * Enable USB Endpoint - * Parameters: EPNum: Endpoint Number - * EPNum.0..3: Address - * EPNum.7: Dir - * Return Value: None - */ - -void USB_EnableEP (uint32_t EPNum) { - WrCmdDat(CMD_SET_EP_STAT(EPAdr(EPNum)), DAT_WR_BYTE(0)); -} - - -/* - * Disable USB Endpoint - * Parameters: EPNum: Endpoint Number - * EPNum.0..3: Address - * EPNum.7: Dir - * Return Value: None - */ - -void USB_DisableEP (uint32_t EPNum) { - WrCmdDat(CMD_SET_EP_STAT(EPAdr(EPNum)), DAT_WR_BYTE(EP_STAT_DA)); -} - - -/* - * Reset USB Endpoint - * Parameters: EPNum: Endpoint Number - * EPNum.0..3: Address - * EPNum.7: Dir - * Return Value: None - */ - -void USB_ResetEP (uint32_t EPNum) { - WrCmdDat(CMD_SET_EP_STAT(EPAdr(EPNum)), DAT_WR_BYTE(0)); -} - - -/* - * Set Stall for USB Endpoint - * Parameters: EPNum: Endpoint Number - * EPNum.0..3: Address - * EPNum.7: Dir - * Return Value: None - */ - -void USB_SetStallEP (uint32_t EPNum) { - WrCmdDat(CMD_SET_EP_STAT(EPAdr(EPNum)), DAT_WR_BYTE(EP_STAT_ST)); -} - - -/* - * Clear Stall for USB Endpoint - * Parameters: EPNum: Endpoint Number - * EPNum.0..3: Address - * EPNum.7: Dir - * Return Value: None - */ - -void USB_ClrStallEP (uint32_t EPNum) { - WrCmdDat(CMD_SET_EP_STAT(EPAdr(EPNum)), DAT_WR_BYTE(0)); -} - - -/* - * Clear USB Endpoint Buffer - * Parameters: EPNum: Endpoint Number - * EPNum.0..3: Address - * EPNum.7: Dir - * Return Value: None - */ - -void USB_ClearEPBuf (uint32_t EPNum) { - WrCmdEP(EPNum, CMD_CLR_BUF); -} - - -/* - * Read USB Endpoint Data - * Parameters: EPNum: Endpoint Number - * EPNum.0..3: Address - * EPNum.7: Dir - * pData: Pointer to Data Buffer - * Return Value: Number of bytes read - */ - -uint32_t USB_ReadEP (uint32_t EPNum, uint8_t *pData) { - uint32_t cnt, n; - - USB->USBCtrl = ((EPNum & 0x0F) << 2) | CTRL_RD_EN; - - do { - cnt = USB->USBRxPLen; - } while ((cnt & PKT_RDY) == 0); - cnt &= PKT_LNGTH_MASK; - - for (n = 0; n < (cnt + 3) / 4; n++) { - *((__packed uint32_t *)pData) = USB->USBRxData; - pData += 4; - } - USB->USBCtrl = 0; - - if (((EP_MSK_ISO >> EPNum) & 1) == 0) { /* Non-Isochronous Endpoint */ - WrCmdEP(EPNum, CMD_CLR_BUF); - } - - return (cnt); -} - - -/* - * Write USB Endpoint Data - * Parameters: EPNum: Endpoint Number - * EPNum.0..3: Address - * EPNum.7: Dir - * pData: Pointer to Data Buffer - * cnt: Number of bytes to write - * Return Value: Number of bytes written - */ - -uint32_t USB_WriteEP (uint32_t EPNum, uint8_t *pData, uint32_t cnt) { - uint32_t n; - - USB->USBCtrl = ((EPNum & 0x0F) << 2) | CTRL_WR_EN; - - USB->USBTxPLen = cnt; - - for (n = 0; n < (cnt + 3) / 4; n++) { - USB->USBTxData = *((__packed uint32_t *)pData); - pData += 4; - } - USB->USBCtrl = 0; - WrCmdEP(EPNum, CMD_VALID_BUF); - return (cnt); -} - -#if USB_DMA - -/* DMA Descriptor Memory Layout */ -const uint32_t DDAdr[2] = { DD_NISO_ADR, DD_ISO_ADR }; -const uint32_t DDSz [2] = { 16, 20 }; - - -/* - * Setup USB DMA Transfer for selected Endpoint - * Parameters: EPNum: Endpoint Number - * pDD: Pointer to DMA Descriptor - * Return Value: TRUE - Success, FALSE - Error - */ - -uint32_t USB_DMA_Setup(uint32_t EPNum, USB_DMA_DESCRIPTOR *pDD) { - uint32_t num, ptr, nxt, iso, n; - - iso = pDD->Cfg.Type.IsoEP; /* Iso or Non-Iso Descriptor */ - num = EPAdr(EPNum); /* Endpoint's Physical Address */ - - ptr = 0; /* Current Descriptor */ - nxt = udca[num]; /* Initial Descriptor */ - while (nxt) { /* Go through Descriptor List */ - ptr = nxt; /* Current Descriptor */ - if (!pDD->Cfg.Type.Link) { /* Check for Linked Descriptors */ - n = (ptr - DDAdr[iso]) / DDSz[iso]; /* Descriptor Index */ - DDMemMap[iso] &= ~(1 << n); /* Unmark Memory Usage */ - } - nxt = *((uint32_t *)ptr); /* Next Descriptor */ - } - - for (n = 0; n < 32; n++) { /* Search for available Memory */ - if ((DDMemMap[iso] & (1 << n)) == 0) { - break; /* Memory found */ - } - } - if (n == 32) return (FALSE); /* Memory not available */ - - DDMemMap[iso] |= 1 << n; /* Mark Memory Usage */ - nxt = DDAdr[iso] + n * DDSz[iso]; /* Next Descriptor */ - - if (ptr && pDD->Cfg.Type.Link) { - *((uint32_t *)(ptr + 0)) = nxt; /* Link in new Descriptor */ - *((uint32_t *)(ptr + 4)) |= 0x00000004; /* Next DD is Valid */ - } else { - udca[num] = nxt; /* Save new Descriptor */ - UDCA[num] = nxt; /* Update UDCA in USB */ - } - - /* Fill in DMA Descriptor */ - *(((uint32_t *)nxt)++) = 0; /* Next DD Pointer */ - *(((uint32_t *)nxt)++) = pDD->Cfg.Type.ATLE | - (pDD->Cfg.Type.IsoEP << 4) | - (pDD->MaxSize << 5) | - (pDD->BufLen << 16); - *(((uint32_t *)nxt)++) = pDD->BufAdr; - *(((uint32_t *)nxt)++) = pDD->Cfg.Type.LenPos << 8; - if (iso) { - *((uint32_t *)nxt) = pDD->InfoAdr; - } - - return (TRUE); /* Success */ -} - - -/* - * Enable USB DMA Endpoint - * Parameters: EPNum: Endpoint Number - * EPNum.0..3: Address - * EPNum.7: Dir - * Return Value: None - */ - -void USB_DMA_Enable (uint32_t EPNum) { - USB->USBEpDMAEn = 1 << EPAdr(EPNum); -} - - -/* - * Disable USB DMA Endpoint - * Parameters: EPNum: Endpoint Number - * EPNum.0..3: Address - * EPNum.7: Dir - * Return Value: None - */ - -void USB_DMA_Disable (uint32_t EPNum) { - USB->USBEpDMADis = 1 << EPAdr(EPNum); -} - - -/* - * Get USB DMA Endpoint Status - * Parameters: EPNum: Endpoint Number - * EPNum.0..3: Address - * EPNum.7: Dir - * Return Value: DMA Status - */ - -uint32_t USB_DMA_Status (uint32_t EPNum) { - uint32_t ptr, val; - - ptr = UDCA[EPAdr(EPNum)]; /* Current Descriptor */ - if (ptr == 0) - return (USB_DMA_INVALID); - - val = *((uint32_t *)(ptr + 3*4)); /* Status Information */ - switch ((val >> 1) & 0x0F) { - case 0x00: /* Not serviced */ - return (USB_DMA_IDLE); - case 0x01: /* Being serviced */ - return (USB_DMA_BUSY); - case 0x02: /* Normal Completition */ - return (USB_DMA_DONE); - case 0x03: /* Data Under Run */ - return (USB_DMA_UNDER_RUN); - case 0x08: /* Data Over Run */ - return (USB_DMA_OVER_RUN); - case 0x09: /* System Error */ - return (USB_DMA_ERROR); - } - - return (USB_DMA_UNKNOWN); -} - - -/* - * Get USB DMA Endpoint Current Buffer Address - * Parameters: EPNum: Endpoint Number - * EPNum.0..3: Address - * EPNum.7: Dir - * Return Value: DMA Address (or -1 when DMA is Invalid) - */ - -uint32_t USB_DMA_BufAdr (uint32_t EPNum) { - uint32_t ptr, val; - - ptr = UDCA[EPAdr(EPNum)]; /* Current Descriptor */ - if (ptr == 0) - { - return ((uint32_t)(-1)); /* DMA Invalid */ - } - - val = *((uint32_t *)(ptr + 2*4)); /* Buffer Address */ - return (val); /* Current Address */ -} - - -/* - * Get USB DMA Endpoint Current Buffer Count - * Number of transfered Bytes or Iso Packets - * Parameters: EPNum: Endpoint Number - * EPNum.0..3: Address - * EPNum.7: Dir - * Return Value: DMA Count (or -1 when DMA is Invalid) - */ - -uint32_t USB_DMA_BufCnt (uint32_t EPNum) { - uint32_t ptr, val; - - ptr = UDCA[EPAdr(EPNum)]; /* Current Descriptor */ - if (ptr == 0) - { - return ((uint32_t)(-1)); /* DMA Invalid */ - } - val = *((uint32_t *)(ptr + 3*4)); /* Status Information */ - return (val >> 16); /* Current Count */ -} - - -#endif /* USB_DMA */ - - -/* - * Get USB Last Frame Number - * Parameters: None - * Return Value: Frame Number - */ - -uint32_t USB_GetFrame (void) { - uint32_t val; - - WrCmd(CMD_RD_FRAME); - val = RdCmdDat(DAT_RD_FRAME); - val = val | (RdCmdDat(DAT_RD_FRAME) << 8); - - return (val); -} - - -/* - * USB Interrupt Service Routine - */ - -void USB_IRQHandler (void) { - uint32_t disr, val, n, m; - uint32_t episr, episrCur; - - disr = USB->USBDevIntSt; /* Device Interrupt Status */ - - /* Device Status Interrupt (Reset, Connect change, Suspend/Resume) */ - if (disr & DEV_STAT_INT) { - USB->USBDevIntClr = DEV_STAT_INT; - WrCmd(CMD_GET_DEV_STAT); - val = RdCmdDat(DAT_GET_DEV_STAT); /* Device Status */ - if (val & DEV_RST) { /* Reset */ - USB_Reset(); -#if USB_RESET_EVENT - USB_Reset_Event(); -#endif - } - if (val & DEV_CON_CH) { /* Connect change */ -#if USB_POWER_EVENT - USB_Power_Event(val & DEV_CON); -#endif - } - if (val & DEV_SUS_CH) { /* Suspend/Resume */ - if (val & DEV_SUS) { /* Suspend */ - USB_Suspend(); -#if USB_SUSPEND_EVENT - USB_Suspend_Event(); -#endif - } else { /* Resume */ - USB_Resume(); -#if USB_RESUME_EVENT - USB_Resume_Event(); -#endif - } - } - goto isr_end; - } - -#if USB_SOF_EVENT - /* Start of Frame Interrupt */ - if (disr & FRAME_INT) { - USB_SOF_Event(); - } -#endif - -#if USB_ERROR_EVENT - /* Error Interrupt */ - if (disr & ERR_INT) { - WrCmd(CMD_RD_ERR_STAT); - val = RdCmdDat(DAT_RD_ERR_STAT); - USB_Error_Event(val); - } -#endif - - /* Endpoint's Slow Interrupt */ - if (disr & EP_SLOW_INT) { - episrCur = 0; - episr = USB->USBEpIntSt; - for (n = 0; n < USB_EP_NUM; n++) { /* Check All Endpoints */ - if (episr == episrCur) break; /* break if all EP interrupts handled */ - if (episr & (1 << n)) { - episrCur |= (1 << n); - m = n >> 1; - - USB->USBEpIntClr = (1 << n); - while ((USB->USBDevIntSt & CDFULL_INT) == 0); - val = USB->USBCmdData; - - if ((n & 1) == 0) { /* OUT Endpoint */ - if (n == 0) { /* Control OUT Endpoint */ - if (val & EP_SEL_STP) { /* Setup Packet */ - if (USB_P_EP[0]) { - USB_P_EP[0](USB_EVT_SETUP); - continue; - } - } - } - if (USB_P_EP[m]) { - USB_P_EP[m](USB_EVT_OUT); - } - } else { /* IN Endpoint */ - if (USB_P_EP[m]) { - USB_P_EP[m](USB_EVT_IN); - } - } - } - } - USB->USBDevIntClr = EP_SLOW_INT; - } - -#if USB_DMA - - if (USB->USBDMAIntSt & 0x00000001) { /* End of Transfer Interrupt */ - val = USB->USBEoTIntSt; - for (n = 2; n < USB_EP_NUM; n++) { /* Check All Endpoints */ - if (val & (1 << n)) { - m = n >> 1; - if ((n & 1) == 0) { /* OUT Endpoint */ - if (USB_P_EP[m]) { - USB_P_EP[m](USB_EVT_OUT_DMA_EOT); - } - } else { /* IN Endpoint */ - if (USB_P_EP[m]) { - USB_P_EP[m](USB_EVT_IN_DMA_EOT); - } - } - } - } - USB->USBEoTIntClr = val; - } - - if (USB->USBDMAIntSt & 0x00000002) { /* New DD Request Interrupt */ - val = USB->USBNDDRIntSt; - for (n = 2; n < USB_EP_NUM; n++) { /* Check All Endpoints */ - if (val & (1 << n)) { - m = n >> 1; - if ((n & 1) == 0) { /* OUT Endpoint */ - if (USB_P_EP[m]) { - USB_P_EP[m](USB_EVT_OUT_DMA_NDR); - } - } else { /* IN Endpoint */ - if (USB_P_EP[m]) { - USB_P_EP[m](USB_EVT_IN_DMA_NDR); - } - } - } - } - USB->USBNDDRIntClr = val; - } - - if (USB->USBDMAIntSt & 0x00000004) { /* System Error Interrupt */ - val = USB->USBSysErrIntSt; - for (n = 2; n < USB_EP_NUM; n++) { /* Check All Endpoints */ - if (val & (1 << n)) { - m = n >> 1; - if ((n & 1) == 0) { /* OUT Endpoint */ - if (USB_P_EP[m]) { - USB_P_EP[m](USB_EVT_OUT_DMA_ERR); - } - } else { /* IN Endpoint */ - if (USB_P_EP[m]) { - USB_P_EP[m](USB_EVT_IN_DMA_ERR); - } - } - } - } - USB->USBSysErrIntClr = val; - } - -#endif /* USB_DMA */ - -isr_end: - return; -} +/*---------------------------------------------------------------------------- + * U S B - K e r n e l + *---------------------------------------------------------------------------- + * Name: usbhw.c + * Purpose: USB Hardware Layer Module for NXP's LPC17xx MCU + * Version: V1.20 + *---------------------------------------------------------------------------- + * This software is supplied "AS IS" without any warranties, express, + * implied or statutory, including but not limited to the implied + * warranties of fitness for purpose, satisfactory quality and + * noninfringement. Keil extends you a royalty-free right to reproduce + * and distribute executable files created using this software for use + * on NXP Semiconductors LPC family microcontroller devices only. Nothing + * else gives you the right to use this software. + * + * Copyright (c) 2009 Keil - An ARM Company. All rights reserved. + *---------------------------------------------------------------------------- + * History: + * V1.20 Added USB_ClearEPBuf + * V1.00 Initial Version + *----------------------------------------------------------------------------*/ +#include /* LPC17xx definitions */ +#include "usb.h" +#include "cfg.h" +#include "reg.h" +#include "hw.h" +#include "core.h" +#include "user.h" + +#if defined ( __CC_ARM__ ) +#pragma diag_suppress 1441 +#endif + + +#define EP_MSK_CTRL 0x0001 /* Control Endpoint Logical Address Mask */ +#define EP_MSK_BULK 0xC924 /* Bulk Endpoint Logical Address Mask */ +#define EP_MSK_INT 0x4492 /* Interrupt Endpoint Logical Address Mask */ +#define EP_MSK_ISO 0x1248 /* Isochronous Endpoint Logical Address Mask */ + + +#if USB_DMA + +#pragma arm section zidata = "USB_RAM" +uint32_t UDCA[USB_EP_NUM]; /* UDCA in USB RAM */ +uint32_t DD_NISO_Mem[4*DD_NISO_CNT]; /* Non-Iso DMA Descriptor Memory */ +uint32_t DD_ISO_Mem [5*DD_ISO_CNT]; /* Iso DMA Descriptor Memory */ +#pragma arm section zidata +uint32_t udca[USB_EP_NUM]; /* UDCA saved values */ + +uint32_t DDMemMap[2]; /* DMA Descriptor Memory Usage */ + +#endif + + +/* + * Get Endpoint Physical Address + * Parameters: EPNum: Endpoint Number + * EPNum.0..3: Address + * EPNum.7: Dir + * Return Value: Endpoint Physical Address + */ + +uint32_t EPAdr (uint32_t EPNum) { + uint32_t val; + + val = (EPNum & 0x0F) << 1; + if (EPNum & 0x80) { + val += 1; + } + return (val); +} + + +/* + * Write Command + * Parameters: cmd: Command + * Return Value: None + */ + +void WrCmd (uint32_t cmd) { + + USB->USBDevIntClr = CCEMTY_INT; + USB->USBCmdCode = cmd; + while ((USB->USBDevIntSt & CCEMTY_INT) == 0); +} + + +/* + * Write Command Data + * Parameters: cmd: Command + * val: Data + * Return Value: None + */ + +void WrCmdDat (uint32_t cmd, uint32_t val) { + + USB->USBDevIntClr = CCEMTY_INT; + USB->USBCmdCode = cmd; + while ((USB->USBDevIntSt & CCEMTY_INT) == 0); + USB->USBDevIntClr = CCEMTY_INT; + USB->USBCmdCode = val; + while ((USB->USBDevIntSt & CCEMTY_INT) == 0); +} + + +/* + * Write Command to Endpoint + * Parameters: cmd: Command + * val: Data + * Return Value: None + */ + +void WrCmdEP (uint32_t EPNum, uint32_t cmd){ + + USB->USBDevIntClr = CCEMTY_INT; + USB->USBCmdCode = CMD_SEL_EP(EPAdr(EPNum)); + while ((USB->USBDevIntSt & CCEMTY_INT) == 0); + USB->USBDevIntClr = CCEMTY_INT; + USB->USBCmdCode = cmd; + while ((USB->USBDevIntSt & CCEMTY_INT) == 0); +} + + +/* + * Read Command Data + * Parameters: cmd: Command + * Return Value: Data Value + */ + +uint32_t RdCmdDat (uint32_t cmd) { + + USB->USBDevIntClr = CCEMTY_INT | CDFULL_INT; + USB->USBCmdCode = cmd; + while ((USB->USBDevIntSt & CDFULL_INT) == 0); + return (USB->USBCmdData); +} + + +/* + * USB Initialize Function + * Called by the User to initialize USB + * Return Value: None + */ + +void USB_Init (void) { + + PINCON->PINSEL1 &= ~((3<<26)|(3<<28)); /* P0.29 D+, P0.30 D- */ + PINCON->PINSEL1 |= ((1<<26)|(1<<28)); /* PINSEL1 26.27, 28.29 = 01 */ + + PINCON->PINSEL3 &= ~((3<< 4)|(3<<28)); /* P1.18 GoodLink, P1.30 VBUS */ + PINCON->PINSEL3 |= ((1<< 4)|(2<<28)); /* PINSEL3 4.5 = 01, 28.29 = 10 */ + + PINCON->PINSEL4 &= ~((3<<18) ); /* P2.9 SoftConnect */ + PINCON->PINSEL4 |= ((1<<18) ); /* PINSEL4 18.19 = 01 */ + + SC->PCONP |= (1UL<<31); /* USB PCLK -> enable USB Per. */ + + USB->USBClkCtrl = 0x1A; /* Dev, PortSel, AHB clock enable */ + while ((USB->USBClkSt & 0x1A) != 0x1A); + + NVIC_EnableIRQ(USB_IRQn); /* enable USB interrupt */ + + USB_Reset(); + USB_SetAddress(0); +} + + +/* + * USB Connect Function + * Called by the User to Connect/Disconnect USB + * Parameters: con: Connect/Disconnect + * Return Value: None + */ + +void USB_Connect (uint32_t con) { + WrCmdDat(CMD_SET_DEV_STAT, DAT_WR_BYTE(con ? DEV_CON : 0)); +} + + +/* + * USB Reset Function + * Called automatically on USB Reset + * Return Value: None + */ + +void USB_Reset (void) { +#if USB_DMA + uint32_t n; +#endif + + USB->USBEpInd = 0; + USB->USBMaxPSize = USB_MAX_PACKET0; + USB->USBEpInd = 1; + USB->USBMaxPSize = USB_MAX_PACKET0; + while ((USB->USBDevIntSt & EP_RLZED_INT) == 0); + + USB->USBEpIntClr = 0xFFFFFFFF; + USB->USBEpIntEn = 0xFFFFFFFF ^ USB_DMA_EP; + USB->USBDevIntClr = 0xFFFFFFFF; + USB->USBDevIntEn = DEV_STAT_INT | EP_SLOW_INT | + (USB_SOF_EVENT ? FRAME_INT : 0) | + (USB_ERROR_EVENT ? ERR_INT : 0); + +#if USB_DMA + USB->USBUDCAH = USB_RAM_ADR; + USB->USBDMARClr = 0xFFFFFFFF; + USB->USBEpDMADis = 0xFFFFFFFF; + USB->USBEpDMAEn = USB_DMA_EP; + USB->USBEoTIntClr = 0xFFFFFFFF; + USB->USBNDDRIntClr = 0xFFFFFFFF; + USB->USBSysErrIntClr = 0xFFFFFFFF; + USB->USBDMAIntEn = 0x00000007; + DDMemMap[0] = 0x00000000; + DDMemMap[1] = 0x00000000; + for (n = 0; n < USB_EP_NUM; n++) { + udca[n] = 0; + UDCA[n] = 0; + } +#endif +} + + +/* + * USB Suspend Function + * Called automatically on USB Suspend + * Return Value: None + */ + +void USB_Suspend (void) { + /* Performed by Hardware */ +} + + +/* + * USB Resume Function + * Called automatically on USB Resume + * Return Value: None + */ + +void USB_Resume (void) { + /* Performed by Hardware */ +} + + +/* + * USB Remote Wakeup Function + * Called automatically on USB Remote Wakeup + * Return Value: None + */ + +void USB_WakeUp (void) { + + if (USB_DeviceStatus & USB_GETSTATUS_REMOTE_WAKEUP) { + WrCmdDat(CMD_SET_DEV_STAT, DAT_WR_BYTE(DEV_CON)); + } +} + + +/* + * USB Remote Wakeup Configuration Function + * Parameters: cfg: Enable/Disable + * Return Value: None + */ + +void USB_WakeUpCfg (uint32_t cfg) { + /* Not needed */ +} + + +/* + * USB Set Address Function + * Parameters: adr: USB Address + * Return Value: None + */ + +void USB_SetAddress (uint32_t adr) { + WrCmdDat(CMD_SET_ADDR, DAT_WR_BYTE(DEV_EN | adr)); /* Don't wait for next */ + WrCmdDat(CMD_SET_ADDR, DAT_WR_BYTE(DEV_EN | adr)); /* Setup Status Phase */ +} + + +/* + * USB Configure Function + * Parameters: cfg: Configure/Deconfigure + * Return Value: None + */ + +void USB_Configure (uint32_t cfg) { + + WrCmdDat(CMD_CFG_DEV, DAT_WR_BYTE(cfg ? CONF_DVICE : 0)); + + USB->USBReEp = 0x00000003; + while ((USB->USBDevIntSt & EP_RLZED_INT) == 0); + USB->USBDevIntClr = EP_RLZED_INT; +} + + +/* + * Configure USB Endpoint according to Descriptor + * Parameters: pEPD: Pointer to Endpoint Descriptor + * Return Value: None + */ + +void USB_ConfigEP (USB_ENDPOINT_DESCRIPTOR *pEPD) { + uint32_t num; + + num = EPAdr(pEPD->bEndpointAddress); + USB->USBReEp |= (1 << num); + USB->USBEpInd = num; + USB->USBMaxPSize = pEPD->wMaxPacketSize; + while ((USB->USBDevIntSt & EP_RLZED_INT) == 0); + USB->USBDevIntClr = EP_RLZED_INT; +} + + +/* + * Set Direction for USB Control Endpoint + * Parameters: dir: Out (dir == 0), In (dir <> 0) + * Return Value: None + */ + +void USB_DirCtrlEP (uint32_t dir) { + /* Not needed */ +} + + +/* + * Enable USB Endpoint + * Parameters: EPNum: Endpoint Number + * EPNum.0..3: Address + * EPNum.7: Dir + * Return Value: None + */ + +void USB_EnableEP (uint32_t EPNum) { + WrCmdDat(CMD_SET_EP_STAT(EPAdr(EPNum)), DAT_WR_BYTE(0)); +} + + +/* + * Disable USB Endpoint + * Parameters: EPNum: Endpoint Number + * EPNum.0..3: Address + * EPNum.7: Dir + * Return Value: None + */ + +void USB_DisableEP (uint32_t EPNum) { + WrCmdDat(CMD_SET_EP_STAT(EPAdr(EPNum)), DAT_WR_BYTE(EP_STAT_DA)); +} + + +/* + * Reset USB Endpoint + * Parameters: EPNum: Endpoint Number + * EPNum.0..3: Address + * EPNum.7: Dir + * Return Value: None + */ + +void USB_ResetEP (uint32_t EPNum) { + WrCmdDat(CMD_SET_EP_STAT(EPAdr(EPNum)), DAT_WR_BYTE(0)); +} + + +/* + * Set Stall for USB Endpoint + * Parameters: EPNum: Endpoint Number + * EPNum.0..3: Address + * EPNum.7: Dir + * Return Value: None + */ + +void USB_SetStallEP (uint32_t EPNum) { + WrCmdDat(CMD_SET_EP_STAT(EPAdr(EPNum)), DAT_WR_BYTE(EP_STAT_ST)); +} + + +/* + * Clear Stall for USB Endpoint + * Parameters: EPNum: Endpoint Number + * EPNum.0..3: Address + * EPNum.7: Dir + * Return Value: None + */ + +void USB_ClrStallEP (uint32_t EPNum) { + WrCmdDat(CMD_SET_EP_STAT(EPAdr(EPNum)), DAT_WR_BYTE(0)); +} + + +/* + * Clear USB Endpoint Buffer + * Parameters: EPNum: Endpoint Number + * EPNum.0..3: Address + * EPNum.7: Dir + * Return Value: None + */ + +void USB_ClearEPBuf (uint32_t EPNum) { + WrCmdEP(EPNum, CMD_CLR_BUF); +} + + +/* + * Read USB Endpoint Data + * Parameters: EPNum: Endpoint Number + * EPNum.0..3: Address + * EPNum.7: Dir + * pData: Pointer to Data Buffer + * Return Value: Number of bytes read + */ + +uint32_t USB_ReadEP (uint32_t EPNum, uint8_t *pData) { + uint32_t cnt, n; + + USB->USBCtrl = ((EPNum & 0x0F) << 2) | CTRL_RD_EN; + + do { + cnt = USB->USBRxPLen; + } while ((cnt & PKT_RDY) == 0); + cnt &= PKT_LNGTH_MASK; + + for (n = 0; n < (cnt + 3) / 4; n++) { + *((__packed uint32_t *)pData) = USB->USBRxData; + pData += 4; + } + USB->USBCtrl = 0; + + if (((EP_MSK_ISO >> EPNum) & 1) == 0) { /* Non-Isochronous Endpoint */ + WrCmdEP(EPNum, CMD_CLR_BUF); + } + + return (cnt); +} + + +/* + * Write USB Endpoint Data + * Parameters: EPNum: Endpoint Number + * EPNum.0..3: Address + * EPNum.7: Dir + * pData: Pointer to Data Buffer + * cnt: Number of bytes to write + * Return Value: Number of bytes written + */ + +uint32_t USB_WriteEP (uint32_t EPNum, uint8_t *pData, uint32_t cnt) { + uint32_t n; + + USB->USBCtrl = ((EPNum & 0x0F) << 2) | CTRL_WR_EN; + + USB->USBTxPLen = cnt; + + for (n = 0; n < (cnt + 3) / 4; n++) { + USB->USBTxData = *((__packed uint32_t *)pData); + pData += 4; + } + USB->USBCtrl = 0; + WrCmdEP(EPNum, CMD_VALID_BUF); + return (cnt); +} + +#if USB_DMA + +/* DMA Descriptor Memory Layout */ +const uint32_t DDAdr[2] = { DD_NISO_ADR, DD_ISO_ADR }; +const uint32_t DDSz [2] = { 16, 20 }; + + +/* + * Setup USB DMA Transfer for selected Endpoint + * Parameters: EPNum: Endpoint Number + * pDD: Pointer to DMA Descriptor + * Return Value: TRUE - Success, FALSE - Error + */ + +uint32_t USB_DMA_Setup(uint32_t EPNum, USB_DMA_DESCRIPTOR *pDD) { + uint32_t num, ptr, nxt, iso, n; + + iso = pDD->Cfg.Type.IsoEP; /* Iso or Non-Iso Descriptor */ + num = EPAdr(EPNum); /* Endpoint's Physical Address */ + + ptr = 0; /* Current Descriptor */ + nxt = udca[num]; /* Initial Descriptor */ + while (nxt) { /* Go through Descriptor List */ + ptr = nxt; /* Current Descriptor */ + if (!pDD->Cfg.Type.Link) { /* Check for Linked Descriptors */ + n = (ptr - DDAdr[iso]) / DDSz[iso]; /* Descriptor Index */ + DDMemMap[iso] &= ~(1 << n); /* Unmark Memory Usage */ + } + nxt = *((uint32_t *)ptr); /* Next Descriptor */ + } + + for (n = 0; n < 32; n++) { /* Search for available Memory */ + if ((DDMemMap[iso] & (1 << n)) == 0) { + break; /* Memory found */ + } + } + if (n == 32) return (FALSE); /* Memory not available */ + + DDMemMap[iso] |= 1 << n; /* Mark Memory Usage */ + nxt = DDAdr[iso] + n * DDSz[iso]; /* Next Descriptor */ + + if (ptr && pDD->Cfg.Type.Link) { + *((uint32_t *)(ptr + 0)) = nxt; /* Link in new Descriptor */ + *((uint32_t *)(ptr + 4)) |= 0x00000004; /* Next DD is Valid */ + } else { + udca[num] = nxt; /* Save new Descriptor */ + UDCA[num] = nxt; /* Update UDCA in USB */ + } + + /* Fill in DMA Descriptor */ + *(((uint32_t *)nxt)++) = 0; /* Next DD Pointer */ + *(((uint32_t *)nxt)++) = pDD->Cfg.Type.ATLE | + (pDD->Cfg.Type.IsoEP << 4) | + (pDD->MaxSize << 5) | + (pDD->BufLen << 16); + *(((uint32_t *)nxt)++) = pDD->BufAdr; + *(((uint32_t *)nxt)++) = pDD->Cfg.Type.LenPos << 8; + if (iso) { + *((uint32_t *)nxt) = pDD->InfoAdr; + } + + return (TRUE); /* Success */ +} + + +/* + * Enable USB DMA Endpoint + * Parameters: EPNum: Endpoint Number + * EPNum.0..3: Address + * EPNum.7: Dir + * Return Value: None + */ + +void USB_DMA_Enable (uint32_t EPNum) { + USB->USBEpDMAEn = 1 << EPAdr(EPNum); +} + + +/* + * Disable USB DMA Endpoint + * Parameters: EPNum: Endpoint Number + * EPNum.0..3: Address + * EPNum.7: Dir + * Return Value: None + */ + +void USB_DMA_Disable (uint32_t EPNum) { + USB->USBEpDMADis = 1 << EPAdr(EPNum); +} + + +/* + * Get USB DMA Endpoint Status + * Parameters: EPNum: Endpoint Number + * EPNum.0..3: Address + * EPNum.7: Dir + * Return Value: DMA Status + */ + +uint32_t USB_DMA_Status (uint32_t EPNum) { + uint32_t ptr, val; + + ptr = UDCA[EPAdr(EPNum)]; /* Current Descriptor */ + if (ptr == 0) + return (USB_DMA_INVALID); + + val = *((uint32_t *)(ptr + 3*4)); /* Status Information */ + switch ((val >> 1) & 0x0F) { + case 0x00: /* Not serviced */ + return (USB_DMA_IDLE); + case 0x01: /* Being serviced */ + return (USB_DMA_BUSY); + case 0x02: /* Normal Completition */ + return (USB_DMA_DONE); + case 0x03: /* Data Under Run */ + return (USB_DMA_UNDER_RUN); + case 0x08: /* Data Over Run */ + return (USB_DMA_OVER_RUN); + case 0x09: /* System Error */ + return (USB_DMA_ERROR); + } + + return (USB_DMA_UNKNOWN); +} + + +/* + * Get USB DMA Endpoint Current Buffer Address + * Parameters: EPNum: Endpoint Number + * EPNum.0..3: Address + * EPNum.7: Dir + * Return Value: DMA Address (or -1 when DMA is Invalid) + */ + +uint32_t USB_DMA_BufAdr (uint32_t EPNum) { + uint32_t ptr, val; + + ptr = UDCA[EPAdr(EPNum)]; /* Current Descriptor */ + if (ptr == 0) + { + return ((uint32_t)(-1)); /* DMA Invalid */ + } + + val = *((uint32_t *)(ptr + 2*4)); /* Buffer Address */ + return (val); /* Current Address */ +} + + +/* + * Get USB DMA Endpoint Current Buffer Count + * Number of transfered Bytes or Iso Packets + * Parameters: EPNum: Endpoint Number + * EPNum.0..3: Address + * EPNum.7: Dir + * Return Value: DMA Count (or -1 when DMA is Invalid) + */ + +uint32_t USB_DMA_BufCnt (uint32_t EPNum) { + uint32_t ptr, val; + + ptr = UDCA[EPAdr(EPNum)]; /* Current Descriptor */ + if (ptr == 0) + { + return ((uint32_t)(-1)); /* DMA Invalid */ + } + val = *((uint32_t *)(ptr + 3*4)); /* Status Information */ + return (val >> 16); /* Current Count */ +} + + +#endif /* USB_DMA */ + + +/* + * Get USB Last Frame Number + * Parameters: None + * Return Value: Frame Number + */ + +uint32_t USB_GetFrame (void) { + uint32_t val; + + WrCmd(CMD_RD_FRAME); + val = RdCmdDat(DAT_RD_FRAME); + val = val | (RdCmdDat(DAT_RD_FRAME) << 8); + + return (val); +} + + +/* + * USB Interrupt Service Routine + */ + +void USB_IRQHandler (void) { + uint32_t disr, val, n, m; + uint32_t episr, episrCur; + + disr = USB->USBDevIntSt; /* Device Interrupt Status */ + + /* Device Status Interrupt (Reset, Connect change, Suspend/Resume) */ + if (disr & DEV_STAT_INT) { + USB->USBDevIntClr = DEV_STAT_INT; + WrCmd(CMD_GET_DEV_STAT); + val = RdCmdDat(DAT_GET_DEV_STAT); /* Device Status */ + if (val & DEV_RST) { /* Reset */ + USB_Reset(); +#if USB_RESET_EVENT + USB_Reset_Event(); +#endif + } + if (val & DEV_CON_CH) { /* Connect change */ +#if USB_POWER_EVENT + USB_Power_Event(val & DEV_CON); +#endif + } + if (val & DEV_SUS_CH) { /* Suspend/Resume */ + if (val & DEV_SUS) { /* Suspend */ + USB_Suspend(); +#if USB_SUSPEND_EVENT + USB_Suspend_Event(); +#endif + } else { /* Resume */ + USB_Resume(); +#if USB_RESUME_EVENT + USB_Resume_Event(); +#endif + } + } + goto isr_end; + } + +#if USB_SOF_EVENT + /* Start of Frame Interrupt */ + if (disr & FRAME_INT) { + USB_SOF_Event(); + } +#endif + +#if USB_ERROR_EVENT + /* Error Interrupt */ + if (disr & ERR_INT) { + WrCmd(CMD_RD_ERR_STAT); + val = RdCmdDat(DAT_RD_ERR_STAT); + USB_Error_Event(val); + } +#endif + + /* Endpoint's Slow Interrupt */ + if (disr & EP_SLOW_INT) { + episrCur = 0; + episr = USB->USBEpIntSt; + for (n = 0; n < USB_EP_NUM; n++) { /* Check All Endpoints */ + if (episr == episrCur) break; /* break if all EP interrupts handled */ + if (episr & (1 << n)) { + episrCur |= (1 << n); + m = n >> 1; + + USB->USBEpIntClr = (1 << n); + while ((USB->USBDevIntSt & CDFULL_INT) == 0); + val = USB->USBCmdData; + + if ((n & 1) == 0) { /* OUT Endpoint */ + if (n == 0) { /* Control OUT Endpoint */ + if (val & EP_SEL_STP) { /* Setup Packet */ + if (USB_P_EP[0]) { + USB_P_EP[0](USB_EVT_SETUP); + continue; + } + } + } + if (USB_P_EP[m]) { + USB_P_EP[m](USB_EVT_OUT); + } + } else { /* IN Endpoint */ + if (USB_P_EP[m]) { + USB_P_EP[m](USB_EVT_IN); + } + } + } + } + USB->USBDevIntClr = EP_SLOW_INT; + } + +#if USB_DMA + + if (USB->USBDMAIntSt & 0x00000001) { /* End of Transfer Interrupt */ + val = USB->USBEoTIntSt; + for (n = 2; n < USB_EP_NUM; n++) { /* Check All Endpoints */ + if (val & (1 << n)) { + m = n >> 1; + if ((n & 1) == 0) { /* OUT Endpoint */ + if (USB_P_EP[m]) { + USB_P_EP[m](USB_EVT_OUT_DMA_EOT); + } + } else { /* IN Endpoint */ + if (USB_P_EP[m]) { + USB_P_EP[m](USB_EVT_IN_DMA_EOT); + } + } + } + } + USB->USBEoTIntClr = val; + } + + if (USB->USBDMAIntSt & 0x00000002) { /* New DD Request Interrupt */ + val = USB->USBNDDRIntSt; + for (n = 2; n < USB_EP_NUM; n++) { /* Check All Endpoints */ + if (val & (1 << n)) { + m = n >> 1; + if ((n & 1) == 0) { /* OUT Endpoint */ + if (USB_P_EP[m]) { + USB_P_EP[m](USB_EVT_OUT_DMA_NDR); + } + } else { /* IN Endpoint */ + if (USB_P_EP[m]) { + USB_P_EP[m](USB_EVT_IN_DMA_NDR); + } + } + } + } + USB->USBNDDRIntClr = val; + } + + if (USB->USBDMAIntSt & 0x00000004) { /* System Error Interrupt */ + val = USB->USBSysErrIntSt; + for (n = 2; n < USB_EP_NUM; n++) { /* Check All Endpoints */ + if (val & (1 << n)) { + m = n >> 1; + if ((n & 1) == 0) { /* OUT Endpoint */ + if (USB_P_EP[m]) { + USB_P_EP[m](USB_EVT_OUT_DMA_ERR); + } + } else { /* IN Endpoint */ + if (USB_P_EP[m]) { + USB_P_EP[m](USB_EVT_IN_DMA_ERR); + } + } + } + } + USB->USBSysErrIntClr = val; + } + +#endif /* USB_DMA */ + +isr_end: + return; +}