blob: 01c222d67e668cfe139cdddaa6022768af262791 [file] [log] [blame]
/**********************************************************************
* $Id$ usbhw.c 2011-06-02
*//**
* @file usbhw.c
* @brief USB Hardware Layer Module for NXP's lpc43xx MCU
* @version 1.0
* @date 02. June. 2011
* @author NXP MCU SW Application Team
*
* Copyright(C) 2011, NXP Semiconductor
* All rights reserved.
*
***********************************************************************
* Software that is described herein is for illustrative purposes only
* which provides customers with programming information regarding the
* products. This software is supplied "AS IS" without any warranties.
* NXP Semiconductors assumes no responsibility or liability for the
* use of the software, conveys no license or title under any patent,
* copyright, or mask work right to the product. NXP Semiconductors
* reserves the right to make changes in the software without
* notification. NXP Semiconductors also make no representation or
* warranty that such application will be suitable for the specified
* use without further testing or modification.
**********************************************************************/
#include <string.h>
#include "lpc18xx.H" /* lpc43xx definitions */
#include "lpc_types.h"
#include "usb.h"
#include "usbhw.h"
#include "usbcfg.h"
#include "usbcore.h"
#include "lpc18xx_scu.h"
#include "lpc18xx_cgu.h"
#include "FreeRTOS.h"
#ifdef __CC_ARM
#pragma diag_suppress 1441
#endif
#ifdef __ICCARM__
#pragma data_alignment=2048
DQH_T ep_QH[EP_NUM_MAX];
#pragma data_alignment=32
DTD_T ep_TD[EP_NUM_MAX];
#pragma data_alignment=4
#elif defined ( __GNUC__ )
#define __align(x) __attribute__((aligned(x)))
DQH_T ep_QH[EP_NUM_MAX] __attribute__((aligned(2048)));
DTD_T ep_TD[EP_NUM_MAX] __attribute__((aligned(32)));
#else
DQH_T __align(2048) ep_QH[EP_NUM_MAX];
DTD_T __align(32) ep_TD[EP_NUM_MAX];
#endif
static uint32_t ep_read_len[4];
volatile uint32_t DevStatusFS2HS = FALSE;
LPC_USBDRV_INIT_T g_drv;
/*
* 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);
}
/*
* USB Initialize Function
* Called by the User to initialize USB
* Return Value: None
*/
void USB_Init (LPC_USBDRV_INIT_T* cbs)
{
memcpy(&g_drv, cbs, sizeof(LPC_USBDRV_INIT_T));
/*maxp for EP0 should be atleast 8 */
if( g_drv.ep0_maxp == 0)
g_drv.ep0_maxp = 64;
#ifdef USE_USB0
scu_pinmux(0x8,1,MD_PLN_FAST,FUNC1); // 0: motocon pcap0_1 1: usb0 usb0_ind1 2: nc 3: gpio4 gpio4_1
scu_pinmux(0x8,2,MD_PLN_FAST,FUNC1); // 0: motocon pcap0_0 1: usb0 usb0_ind0 2: nc 3: gpio4 gpio4_2
#endif
#ifdef USE_USB0
CGU_SetPLL0();
CGU_EnableEntity(CGU_CLKSRC_PLL0, ENABLE);
CGU_EntityConnect(CGU_CLKSRC_PLL0, CGU_BASE_USB0);
#else
CGU_SetPLL1(5);
CGU_EnableEntity(CGU_CLKSRC_PLL1, ENABLE);
CGU_EntityConnect(CGU_CLKSRC_PLL1, CGU_BASE_USB1);
/* enable USB phy */
LPC_CREG->CREG0 &= ~(1 << 5);
/* enable USB1_DP and USB1_DN on chip FS phy */
LPC_SCU->SFSUSB = 0x12;
/* enable USB1_VBUS */
scu_pinmux(0x2, 5, MD_PLN | MD_EZI | MD_ZI, FUNC2);
#endif
/* Turn on the phy */
#ifdef USE_USB0
LPC_CREG->CREG0 &= ~(1<<5);
#endif
/* reset the controller */
LPC_USB->USBCMD_D = USBCMD_RST;
/* wait for reset to complete */
while (LPC_USB->USBCMD_D & USBCMD_RST);
/* Program the controller to be the USB device controller */
LPC_USB->USBMODE_D = USBMODE_CM_DEV
| USBMODE_SDIS
| USBMODE_SLOM ;
/* set OTG transcever in proper state, device is present
on the port(CCS=1), port enable/disable status change(PES=1). */
#ifdef USE_USB0
LPC_USB->OTGSC = (1<<3) | (1<<0) /*| (1<<16)| (1<<24)| (1<<25)| (1<<26)| (1<<27)| (1<<28)| (1<<29)| (1<<30)*/;
#else
/* force full speed */
LPC_USB->PORTSC1_D |= (1<<24);
#endif
#ifdef USE_USB0
NVIC_EnableIRQ(USB0_IRQn); // enable USB0 interrrupts
NVIC_SetPriority(USB0_IRQn, configMIN_LIBRARY_INTERRUPT_PRIORITY );
#else
NVIC_EnableIRQ(USB1_IRQn); // enable USB1 interrrupts
NVIC_SetPriority(USB0_IRQn, configMIN_LIBRARY_INTERRUPT_PRIORITY );
#endif
USB_Reset();
USB_SetAddress(0);
return;
}
/*
* USB Connect Function
* Called by the User to Connect/Disconnect USB
* Parameters: con: Connect/Disconnect
* Return Value: None
*/
void USB_Connect (uint32_t con) {
if (con)
LPC_USB->USBCMD_D |= USBCMD_RS;
else
LPC_USB->USBCMD_D &= ~USBCMD_RS;
}
/*
* USB Reset Function
* Called automatically on USB Reset
* Return Value: None
*/
void USB_Reset (void)
{
uint32_t i;
DevStatusFS2HS = FALSE;
/* disable all EPs */
LPC_USB->ENDPTCTRL0 &= ~(EPCTRL_RXE | EPCTRL_TXE);
LPC_USB->ENDPTCTRL2 &= ~(EPCTRL_RXE | EPCTRL_TXE);
LPC_USB->ENDPTCTRL3 &= ~(EPCTRL_RXE | EPCTRL_TXE);
/* Clear all pending interrupts */
LPC_USB->ENDPTNAK = 0xFFFFFFFF;
LPC_USB->ENDPTNAKEN = 0;
LPC_USB->USBSTS_D = 0xFFFFFFFF;
LPC_USB->ENDPTSETUPSTAT = LPC_USB->ENDPTSETUPSTAT;
LPC_USB->ENDPTCOMPLETE = LPC_USB->ENDPTCOMPLETE;
while (LPC_USB->ENDPTPRIME) /* Wait until all bits are 0 */
{
}
LPC_USB->ENDPTFLUSH = 0xFFFFFFFF;
while (LPC_USB->ENDPTFLUSH); /* Wait until all bits are 0 */
/* Set the interrupt Threshold control interval to 0 */
LPC_USB->USBCMD_D &= ~0x00FF0000;
/* Zero out the Endpoint queue heads */
memset((void*)ep_QH, 0, EP_NUM_MAX * sizeof(DQH_T));
/* Zero out the device transfer descriptors */
memset((void*)ep_TD, 0, EP_NUM_MAX * sizeof(DTD_T));
memset((void*)ep_read_len, 0, sizeof(ep_read_len));
/* Configure the Endpoint List Address */
/* make sure it in on 64 byte boundary !!! */
/* init list address */
LPC_USB->ENDPOINTLISTADDR = (uint32_t)ep_QH;
/* Initialize device queue heads for non ISO endpoint only */
for (i = 0; i < EP_NUM_MAX; i++)
{
ep_QH[i].next_dTD = (uint32_t)&ep_TD[i];
}
/* Enable interrupts */
LPC_USB->USBINTR_D = USBSTS_UI
| USBSTS_UEI
| USBSTS_PCI
| USBSTS_URI
| USBSTS_SLI
| USBSTS_NAKI;
// LPC_USB->usbintr |= (0x1<<7); /* Test SOF */
/* enable ep0 IN and ep0 OUT */
ep_QH[0].cap = QH_MAXP(g_drv.ep0_maxp)
| QH_IOS
| QH_ZLT;
ep_QH[1].cap = QH_MAXP(g_drv.ep0_maxp)
| QH_IOS
| QH_ZLT;
/* enable EP0 */
LPC_USB->ENDPTCTRL0 = EPCTRL_RXE | EPCTRL_RXR | EPCTRL_TXE | EPCTRL_TXR;
return;
}
/*
* 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)
{
/* Set FPR bit in PORTSCX reg p63 */
LPC_USB->PORTSC1_D |= USBPRTS_FPR ;
}
}
/*
* USB Remote Wakeup Configuration Function
* Parameters: cfg: Enable/Disable
* Return Value: None
*/
void USB_WakeUpCfg (uint32_t cfg) {
( void ) cfg;
/* Not needed */
}
/*
* USB Set Address Function
* Parameters: adr: USB Address
* Return Value: None
*/
void USB_SetAddress (uint32_t adr) {
LPC_USB->DEVICEADDR = USBDEV_ADDR(adr);
LPC_USB->DEVICEADDR |= USBDEV_ADDR_AD;
}
/*
* USB set test mode Function
* Parameters: mode: test mode
* Return Value: TRUE if supported else FALSE
*/
uint32_t USB_SetTestMode(uint8_t mode)
{
uint32_t portsc;
if ((mode > 0) && (mode < 8))
{
portsc = LPC_USB->PORTSC1_D & ~(0xF << 16);
LPC_USB->PORTSC1_D = portsc | (mode << 16);
return TRUE;
}
return (FALSE);
}
/*
* USB Configure Function
* Parameters: cfg: Configure/Deconfigure
* Return Value: None
*/
void USB_Configure (uint32_t cfg) {
( void ) cfg;
}
/*
* 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, lep;
uint32_t ep_cfg;
uint8_t bmAttributes;
lep = pEPD->bEndpointAddress & 0x7F;
num = EPAdr(pEPD->bEndpointAddress);
ep_cfg = ((uint32_t*)&(LPC_USB->ENDPTCTRL0))[lep];
/* mask the attributes we are not-intersetd in */
bmAttributes = pEPD->bmAttributes & USB_ENDPOINT_TYPE_MASK;
/* set EP type */
if (bmAttributes != USB_ENDPOINT_TYPE_ISOCHRONOUS)
{
/* init EP capabilities */
ep_QH[num].cap = QH_MAXP(pEPD->wMaxPacketSize)
| QH_IOS | QH_ZLT ;
/* The next DTD pointer is INVALID */
ep_TD[num].next_dTD = 0x01 ;
}
else
{
/* init EP capabilities */
ep_QH[num].cap = QH_MAXP(0x400) | QH_ZLT;
}
/* setup EP control register */
if (pEPD->bEndpointAddress & 0x80)
{
ep_cfg &= ~0xFFFF0000;
ep_cfg |= EPCTRL_TX_TYPE(bmAttributes)
| EPCTRL_TXR;
}
else
{
ep_cfg &= ~0xFFFF;
ep_cfg |= EPCTRL_RX_TYPE(bmAttributes)
| EPCTRL_RXR;
}
((uint32_t*)&(LPC_USB->ENDPTCTRL0))[lep] = ep_cfg;
return;
}
/*
* 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 */
( void ) dir;
}
/*
* Enable USB Endpoint
* Parameters: EPNum: Endpoint Number
* EPNum.0..3: Address
* EPNum.7: Dir
* Return Value: None
*/
void USB_EnableEP (uint32_t EPNum) {
uint32_t lep, bitpos;
lep = EPNum & 0x0F;
if (EPNum & 0x80)
{
((uint32_t*)&(LPC_USB->ENDPTCTRL0))[lep] |= EPCTRL_TXE;
}
else
{
((uint32_t*)&(LPC_USB->ENDPTCTRL0))[lep] |= EPCTRL_RXE;
/* enable NAK interrupt */
bitpos = USB_EP_BITPOS(EPNum);
LPC_USB->ENDPTNAKEN |= (1<<bitpos);
}
}
/*
* Disable USB Endpoint
* Parameters: EPNum: Endpoint Number
* EPNum.0..3: Address
* EPNum.7: Dir
* Return Value: None
*/
void USB_DisableEP (uint32_t EPNum) {
uint32_t lep, bitpos;
lep = EPNum & 0x0F;
if (EPNum & 0x80)
{
((uint32_t*)&(LPC_USB->ENDPTCTRL0))[lep] &= ~EPCTRL_TXE;
}
else
{
/* disable NAK interrupt */
bitpos = USB_EP_BITPOS(EPNum);
LPC_USB->ENDPTNAKEN &= ~(1<<bitpos);
((uint32_t*)&(LPC_USB->ENDPTCTRL0))[lep] &= ~EPCTRL_RXE;
}
}
/*
* Reset USB Endpoint
* Parameters: EPNum: Endpoint Number
* EPNum.0..3: Address
* EPNum.7: Dir
* Return Value: None
*/
void USB_ResetEP (uint32_t EPNum) {
uint32_t bit_pos = USB_EP_BITPOS(EPNum);
uint32_t lep = EPNum & 0x0F;
/* flush EP buffers */
LPC_USB->ENDPTFLUSH = (1<<bit_pos);
while (LPC_USB->ENDPTFLUSH & (1<<bit_pos));
/* reset data toggles */
if (EPNum & 0x80)
{
((uint32_t*)&(LPC_USB->ENDPTCTRL0))[lep] |= EPCTRL_TXR;
}
else
{
((uint32_t*)&(LPC_USB->ENDPTCTRL0))[lep] |= EPCTRL_RXR;
}
}
/*
* 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) {
uint32_t lep;
lep = EPNum & 0x0F;
if (EPNum & 0x80)
{
((uint32_t*)&(LPC_USB->ENDPTCTRL0))[lep] |= EPCTRL_TXS;
}
else
{
((uint32_t*)&(LPC_USB->ENDPTCTRL0))[lep] |= EPCTRL_RXS;
}
}
/*
* 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) {
uint32_t lep;
lep = EPNum & 0x0F;
if (EPNum & 0x80)
{
((uint32_t*)&(LPC_USB->ENDPTCTRL0))[lep] &= ~EPCTRL_TXS;
/* reset data toggle */
((uint32_t*)&(LPC_USB->ENDPTCTRL0))[lep] |= EPCTRL_TXR;
}
else
{
((uint32_t*)&(LPC_USB->ENDPTCTRL0))[lep] &= ~EPCTRL_RXS;
/* reset data toggle */
((uint32_t*)&(LPC_USB->ENDPTCTRL0))[lep] |= EPCTRL_RXR;
}
}
/*
* Process DTD
* Parameters: EPNum: Endpoint Number
* EPNum.0..3: Address
* EPNum.7: Dir
* Buffer pointer
* Transfer buffer size
* Return Value: None
*/
void USB_ProgDTD(uint32_t Edpt, uint32_t ptrBuff, uint32_t TsfSize)
{
DTD_T* pDTD;
pDTD = (DTD_T*)&ep_TD[ Edpt ];
/* Zero out the device transfer descriptors */
memset((void*)pDTD, 0, sizeof(DTD_T));
/* The next DTD pointer is INVALID */
pDTD->next_dTD = 0x01 ;
/* Length */
pDTD->total_bytes = ((TsfSize & 0x7fff) << 16);
pDTD->total_bytes |= TD_IOC ;
pDTD->total_bytes |= 0x80 ;
pDTD->buffer0 = ptrBuff;
pDTD->buffer1 = (ptrBuff + 0x1000) & 0xfffff000;
pDTD->buffer2 = (ptrBuff + 0x2000) & 0xfffff000;
pDTD->buffer3 = (ptrBuff + 0x3000) & 0xfffff000;
pDTD->buffer4 = (ptrBuff + 0x4000) & 0xfffff000;
ep_QH[Edpt].next_dTD = (uint32_t)(&ep_TD[ Edpt ]);
ep_QH[Edpt].total_bytes &= (~0xC0) ;
}
/*
* 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_ReadSetupPkt(uint32_t EPNum, uint32_t *pData)
{
uint32_t setup_int, cnt = 0;
uint32_t num = EPAdr(EPNum);
setup_int = LPC_USB->ENDPTSETUPSTAT ;
/* Clear the setup interrupt */
LPC_USB->ENDPTSETUPSTAT = setup_int;
/* ********************************** */
/* Check if we have received a setup */
/* ********************************** */
if (setup_int & (1<<0)) /* Check only for bit 0 */
/* No setup are admitted on other endpoints than 0 */
{
do
{
/* Setup in a setup - must considere only the second setup */
/*- Set the tripwire */
LPC_USB->USBCMD_D |= USBCMD_SUTW ;
/* Transfer Set-up data to the gtmudsCore_Request buffer */
pData[0] = ep_QH[num].setup[0];
pData[1] = ep_QH[num].setup[1];
cnt = 8;
}
while (!(LPC_USB->USBCMD_D & USBCMD_SUTW)) ;
/* setup in a setup - Clear the tripwire */
LPC_USB->USBCMD_D &= (~USBCMD_SUTW);
}
while ((setup_int = LPC_USB->ENDPTSETUPSTAT) != 0)
{
/* Clear the setup interrupt */
LPC_USB->ENDPTSETUPSTAT = setup_int;
}
return cnt;
}
/*
* Enque read request
* 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_ReadReqEP(uint32_t EPNum, uint8_t *pData, uint32_t len)
{
uint32_t num = EPAdr(EPNum);
uint32_t n = USB_EP_BITPOS(EPNum);
USB_ProgDTD(num, (uint32_t)pData, len);
ep_read_len[EPNum & 0x0F] = len;
/* prime the endpoint for read */
LPC_USB->ENDPTPRIME |= (1<<n);
return len;
}
/*
* 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;
DTD_T* pDTD ;
( void ) pData;
n = EPAdr(EPNum);
pDTD = (DTD_T*)&ep_TD[n];
/* return the total bytes read */
cnt = (pDTD->total_bytes >> 16) & 0x7FFF;
cnt = ep_read_len[EPNum & 0x0F] - cnt;
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 x = 0, n = USB_EP_BITPOS(EPNum);
USB_ProgDTD(EPAdr(EPNum), (uint32_t)pData, cnt);
/* prime the endpoint for transmit */
LPC_USB->ENDPTPRIME |= (1<<n);
/* check if priming succeeded */
while ((LPC_USB->ENDPTPRIME & (1<<n))&&(++x<0xffff));/*_RB_ Fix for hang here. */
return (cnt);
}
/*
* USB Interrupt Service Routine
*/
#ifdef USE_USB0
void USB0_IRQHandler (void)
#else
void USB1_IRQHandler (void)
#endif
{
uint32_t disr, val, n;
disr = LPC_USB->USBSTS_D; /* Device Interrupt Status */
LPC_USB->USBSTS_D = disr;
// printf("USB interrupt: 0x%08x\n",disr);
// LPC_UART1->THR = 'U';
// LPC_UART1->THR = 'S';
// LPC_UART1->THR = 'B';
// LPC_UART1->THR = '\n';
/* Device Status Interrupt (Reset, Connect change, Suspend/Resume) */
if (disr & USBSTS_URI) /* Reset */
{
// LPC_UART1->THR = 'R';
// LPC_UART1->THR = '\n';
USB_Reset();
if (g_drv.USB_Reset_Event)
g_drv.USB_Reset_Event();
return;
//goto isr_end;
}
if (disr & USBSTS_SLI) /* Suspend */
{
// LPC_UART1->THR = 'U';
// LPC_UART1->THR = '\n';
if (g_drv.USB_Suspend_Event)
g_drv.USB_Suspend_Event();
}
if (disr & USBSTS_PCI) /* Resume */
{
// LPC_UART1->THR = 'P';
// LPC_UART1->THR = '\n';
/* check if device isoperating in HS mode or full speed */
if (LPC_USB->PORTSC1_D & (1<<9))
DevStatusFS2HS = TRUE;
if (g_drv.USB_Resume_Event)
g_drv.USB_Resume_Event();
}
/* handle setup status interrupts */
val = LPC_USB->ENDPTSETUPSTAT;
/* Only EP0 will have setup packets so call EP0 handler */
if (val)
{
// LPC_UART1->THR = 'S';
// LPC_UART1->THR = '\n';
/* Clear the endpoint complete CTRL OUT & IN when */
/* a Setup is received */
LPC_USB->ENDPTCOMPLETE = 0x00010001;
/* enable NAK inetrrupts */
LPC_USB->ENDPTNAKEN |= 0x00010001;
if (g_drv.USB_P_EP[0]){
// LPC_UART1->THR = 's';
// LPC_UART1->THR = '\n';
g_drv.USB_P_EP[0](USB_EVT_SETUP);
}
}
/* handle completion interrupts */
val = LPC_USB->ENDPTCOMPLETE;
if (val)
{
// LPC_UART1->THR = 'C';
// LPC_UART1->THR = '\n';
LPC_USB->ENDPTNAK = val;
for (n = 0; n < EP_NUM_MAX / 2; n++)
{
if (val & (1<<n))
{
if (g_drv.USB_P_EP[n])
g_drv.USB_P_EP[n](USB_EVT_OUT);
LPC_USB->ENDPTCOMPLETE = (1<<n);
}
if (val & (1<<(n + 16)))
{
ep_TD [(n << 1) + 1 ].total_bytes &= 0xC0;
if (g_drv.USB_P_EP[n])
g_drv.USB_P_EP[n](USB_EVT_IN);
LPC_USB->ENDPTCOMPLETE = (1<<(n + 16));
}
}
}
if (disr & USBSTS_NAKI)
{
// LPC_UART1->THR = 'N';
// LPC_UART1->THR = '\n';
val = LPC_USB->ENDPTNAK;
val &= LPC_USB->ENDPTNAKEN;
/* handle NAK interrupts */
if (val)
{
for (n = 0; n < EP_NUM_MAX / 2; n++)
{
if (val & (1<<n))
{
if (g_drv.USB_P_EP[n])
g_drv.USB_P_EP[n](USB_EVT_OUT_NAK);
}
if (val & (1<<(n + 16)))
{
if (g_drv.USB_P_EP[n])
g_drv.USB_P_EP[n](USB_EVT_IN_NAK);
}
}
LPC_USB->ENDPTNAK = val;
}
}
/* Start of Frame Interrupt */
if (disr & USBSTS_SRI)
{
// LPC_UART1->THR = 'F';
// LPC_UART1->THR = '\n';
if (g_drv.USB_SOF_Event)
g_drv.USB_SOF_Event();
}
/* Error Interrupt */
if (disr & USBSTS_UEI)
{
// LPC_UART1->THR = 'E';
// LPC_UART1->THR = '\n';
if (g_drv.USB_Error_Event)
g_drv.USB_Error_Event(disr);
}
// LPC_UART1->THR = 'r';
// LPC_UART1->THR = '\n';
//isr_end:
// LPC_VIC->VectAddr = 0; /* Acknowledge Interrupt */
return;
}