/** 'Realizes' an endpoint, meaning that buffer space is reserved for it. An endpoint needs to be realised before it can be used. From experiments, it appears that a USB reset causes USBReEP to re-initialise to 3 (= just the control endpoints). However, a USB bus reset does not disturb the USBMaxPSize settings. @param [in] idx Endpoint index @param [in] wMaxPSize Maximum packet size for this endpoint */ static void USBHwEPRealize(int idx, unsigned short wMaxPSize) { LPC_USB->USBReEP |= (1 << idx); LPC_USB->USBEpInd = idx; LPC_USB->USBMaxPSize = wMaxPSize; Wait4DevInt(EP_RLZED); }
/** 'Realizes' an endpoint, meaning that buffer space is reserved for it. An endpoint needs to be realised before it can be used. From experiments, it appears that a USB reset causes USBReEP to re-initialise to 3 (= just the control endpoints). However, a USB bus reset does not disturb the USBMaxPSize settings. @param [in] idx Endpoint index @param [in] wMaxPSize Maximum packet size for this endpoint */ static void USBHwEPRealize(int idx, U16 wMaxPSize) { USBReEP |= (1 << idx); USBEpInd = idx; USBMaxPSize = wMaxPSize; Wait4DevInt(EP_RLZED); }
/** Local function to send a command to the USB protocol engine @param [in] bCmd Command to send */ static void USBHwCmd(unsigned char bCmd) { // clear CDFULL/CCEMTY LPC_USB->USBDevIntClr = CDFULL | CCEMTY; // write command code LPC_USB->USBCmdCode = 0x00000500 | (bCmd << 16); Wait4DevInt(CCEMTY); }
/** Local function to send a command to the USB protocol engine @param [in] bCmd Command to send */ static void USBHwCmd(U8 bCmd) { // clear CDFULL/CCEMTY USBDevIntClr = CDFULL | CCEMTY; // write command code USBCmdCode = 0x00000500 | (bCmd << 16); Wait4DevInt(CCEMTY); }
/** Local function to send a command + data to the USB protocol engine @param [in] bCmd Command to send @param [in] bData Data to send */ static void USBHwCmdWrite(unsigned char bCmd, unsigned short bData) { // write command code USBHwCmd(bCmd); // write command data LPC_USB->USBCmdCode = 0x00000100 | (bData << 16); Wait4DevInt(CCEMTY); }
/** Local function to send a command + data to the USB protocol engine @param [in] bCmd Command to send @param [in] bData Data to send */ static void USBHwCmdWrite(U8 bCmd, U16 bData) { // write command code USBHwCmd(bCmd); // write command data USBCmdCode = 0x00000100 | (bData << 16); Wait4DevInt(CCEMTY); }
/** Local function to send a command to the USB protocol engine and read data @param [in] bCmd Command to send @return the data */ static unsigned char USBHwCmdRead(unsigned char bCmd) { // write command code USBHwCmd(bCmd); // get data LPC_USB->USBCmdCode = 0x00000200 | (bCmd << 16); Wait4DevInt(CDFULL); return LPC_USB->USBCmdData; }
/** Local function to send a command to the USB protocol engine and read data @param [in] bCmd Command to send @return the data */ static U8 USBHwCmdRead(U8 bCmd) { // write command code USBHwCmd(bCmd); // get data USBCmdCode = 0x00000200 | (bCmd << 16); Wait4DevInt(CDFULL); return USBCmdData; }
/** USB interrupt handler @todo Get all 11 bits of frame number instead of just 8 Endpoint interrupts are mapped to the slow interrupt */ void USBHwISR(void) { unsigned long dwStatus; unsigned long dwIntBit; unsigned char bEPStat, bDevStat, bStat; int i; unsigned short wFrame; // handle device interrupts dwStatus = LPC_USB->USBDevIntSt; // frame interrupt if (dwStatus & FRAME) { // clear int LPC_USB->USBDevIntClr = FRAME; // call handler if (_pfnFrameHandler != NULL) { wFrame = USBHwCmdRead(CMD_DEV_READ_CUR_FRAME_NR); _pfnFrameHandler(wFrame); } } // device status interrupt if (dwStatus & DEV_STAT) { /* Clear DEV_STAT interrupt before reading DEV_STAT register. This prevents corrupted device status reads, see LPC2148 User manual revision 2, 25 july 2006. */ LPC_USB->USBDevIntClr = DEV_STAT; bDevStat = USBHwCmdRead(CMD_DEV_STATUS); if (bDevStat & (CON_CH | SUS_CH | RST)) { // convert device status into something HW independent bStat = ((bDevStat & CON) ? DEV_STATUS_CONNECT : 0) | ((bDevStat & SUS) ? DEV_STATUS_SUSPEND : 0) | ((bDevStat & RST) ? DEV_STATUS_RESET : 0); // call handler if (_pfnDevIntHandler != NULL) { _pfnDevIntHandler(bStat); } } } // endpoint interrupt if (dwStatus & EP_SLOW) { // clear EP_SLOW LPC_USB->USBDevIntClr = EP_SLOW; // check all endpoints for (i = 0; i < 32; i++) { dwIntBit = (1 << i); if (LPC_USB->USBEpIntSt & dwIntBit) { // clear int (and retrieve status) LPC_USB->USBEpIntClr = dwIntBit; Wait4DevInt(CDFULL); bEPStat = LPC_USB->USBCmdData; // convert EP pipe stat into something HW independent bStat = ((bEPStat & EPSTAT_FE) ? EP_STATUS_DATA : 0) | ((bEPStat & EPSTAT_ST) ? EP_STATUS_STALLED : 0) | ((bEPStat & EPSTAT_STP) ? EP_STATUS_SETUP : 0) | ((bEPStat & EPSTAT_EPN) ? EP_STATUS_NACKED : 0) | ((bEPStat & EPSTAT_PO) ? EP_STATUS_ERROR : 0); // call handler if (_apfnEPIntHandlers[i / 2] != NULL) { _apfnEPIntHandlers[i / 2](IDX2EP(i), bStat); } } } } }