Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of USBDevice by
USBHAL_LPC17.cpp
00001 /* Copyright (c) 2010-2011 mbed.org, MIT License 00002 * 00003 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software 00004 * and associated documentation files (the "Software"), to deal in the Software without 00005 * restriction, including without limitation the rights to use, copy, modify, merge, publish, 00006 * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the 00007 * Software is furnished to do so, subject to the following conditions: 00008 * 00009 * The above copyright notice and this permission notice shall be included in all copies or 00010 * substantial portions of the Software. 00011 * 00012 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 00013 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 00014 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 00015 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00016 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 00017 */ 00018 00019 #if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) || defined(TARGET_LPC2460) 00020 00021 #include "USBHAL.h" 00022 00023 00024 // Get endpoint direction 00025 #define IN_EP(endpoint) ((endpoint) & 1U ? true : false) 00026 #define OUT_EP(endpoint) ((endpoint) & 1U ? false : true) 00027 00028 // Convert physical endpoint number to register bit 00029 #define EP(endpoint) (1UL<<endpoint) 00030 00031 // Power Control for Peripherals register 00032 #define PCUSB (1UL<<31) 00033 00034 // USB Clock Control register 00035 #define DEV_CLK_EN (1UL<<1) 00036 #define AHB_CLK_EN (1UL<<4) 00037 00038 // USB Clock Status register 00039 #define DEV_CLK_ON (1UL<<1) 00040 #define AHB_CLK_ON (1UL<<4) 00041 00042 // USB Device Interupt registers 00043 #define FRAME (1UL<<0) 00044 #define EP_FAST (1UL<<1) 00045 #define EP_SLOW (1UL<<2) 00046 #define DEV_STAT (1UL<<3) 00047 #define CCEMPTY (1UL<<4) 00048 #define CDFULL (1UL<<5) 00049 #define RxENDPKT (1UL<<6) 00050 #define TxENDPKT (1UL<<7) 00051 #define EP_RLZED (1UL<<8) 00052 #define ERR_INT (1UL<<9) 00053 00054 // USB Control register 00055 #define RD_EN (1<<0) 00056 #define WR_EN (1<<1) 00057 #define LOG_ENDPOINT(endpoint) ((endpoint>>1)<<2) 00058 00059 // USB Receive Packet Length register 00060 #define DV (1UL<<10) 00061 #define PKT_RDY (1UL<<11) 00062 #define PKT_LNGTH_MASK (0x3ff) 00063 00064 // Serial Interface Engine (SIE) 00065 #define SIE_WRITE (0x01) 00066 #define SIE_READ (0x02) 00067 #define SIE_COMMAND (0x05) 00068 #define SIE_CMD_CODE(phase, data) ((phase<<8)|(data<<16)) 00069 00070 // SIE Command codes 00071 #define SIE_CMD_SET_ADDRESS (0xD0) 00072 #define SIE_CMD_CONFIGURE_DEVICE (0xD8) 00073 #define SIE_CMD_SET_MODE (0xF3) 00074 #define SIE_CMD_READ_FRAME_NUMBER (0xF5) 00075 #define SIE_CMD_READ_TEST_REGISTER (0xFD) 00076 #define SIE_CMD_SET_DEVICE_STATUS (0xFE) 00077 #define SIE_CMD_GET_DEVICE_STATUS (0xFE) 00078 #define SIE_CMD_GET_ERROR_CODE (0xFF) 00079 #define SIE_CMD_READ_ERROR_STATUS (0xFB) 00080 00081 #define SIE_CMD_SELECT_ENDPOINT(endpoint) (0x00+endpoint) 00082 #define SIE_CMD_SELECT_ENDPOINT_CLEAR_INTERRUPT(endpoint) (0x40+endpoint) 00083 #define SIE_CMD_SET_ENDPOINT_STATUS(endpoint) (0x40+endpoint) 00084 00085 #define SIE_CMD_CLEAR_BUFFER (0xF2) 00086 #define SIE_CMD_VALIDATE_BUFFER (0xFA) 00087 00088 // SIE Device Status register 00089 #define SIE_DS_CON (1<<0) 00090 #define SIE_DS_CON_CH (1<<1) 00091 #define SIE_DS_SUS (1<<2) 00092 #define SIE_DS_SUS_CH (1<<3) 00093 #define SIE_DS_RST (1<<4) 00094 00095 // SIE Device Set Address register 00096 #define SIE_DSA_DEV_EN (1<<7) 00097 00098 // SIE Configue Device register 00099 #define SIE_CONF_DEVICE (1<<0) 00100 00101 // Select Endpoint register 00102 #define SIE_SE_FE (1<<0) 00103 #define SIE_SE_ST (1<<1) 00104 #define SIE_SE_STP (1<<2) 00105 #define SIE_SE_PO (1<<3) 00106 #define SIE_SE_EPN (1<<4) 00107 #define SIE_SE_B_1_FULL (1<<5) 00108 #define SIE_SE_B_2_FULL (1<<6) 00109 00110 // Set Endpoint Status command 00111 #define SIE_SES_ST (1<<0) 00112 #define SIE_SES_DA (1<<5) 00113 #define SIE_SES_RF_MO (1<<6) 00114 #define SIE_SES_CND_ST (1<<7) 00115 00116 00117 USBHAL * USBHAL::instance; 00118 00119 static volatile int epComplete; 00120 static uint32_t endpointStallState; 00121 00122 static void SIECommand(uint32_t command) { 00123 // The command phase of a SIE transaction 00124 LPC_USB->USBDevIntClr = CCEMPTY; 00125 LPC_USB->USBCmdCode = SIE_CMD_CODE(SIE_COMMAND, command); 00126 while (!(LPC_USB->USBDevIntSt & CCEMPTY)); 00127 } 00128 00129 static void SIEWriteData(uint8_t data) { 00130 // The data write phase of a SIE transaction 00131 LPC_USB->USBDevIntClr = CCEMPTY; 00132 LPC_USB->USBCmdCode = SIE_CMD_CODE(SIE_WRITE, data); 00133 while (!(LPC_USB->USBDevIntSt & CCEMPTY)); 00134 } 00135 00136 static uint8_t SIEReadData(uint32_t command) { 00137 // The data read phase of a SIE transaction 00138 LPC_USB->USBDevIntClr = CDFULL; 00139 LPC_USB->USBCmdCode = SIE_CMD_CODE(SIE_READ, command); 00140 while (!(LPC_USB->USBDevIntSt & CDFULL)); 00141 return (uint8_t)LPC_USB->USBCmdData; 00142 } 00143 00144 static void SIEsetDeviceStatus(uint8_t status) { 00145 // Write SIE device status register 00146 SIECommand(SIE_CMD_SET_DEVICE_STATUS); 00147 SIEWriteData(status); 00148 } 00149 00150 static uint8_t SIEgetDeviceStatus(void) { 00151 // Read SIE device status register 00152 SIECommand(SIE_CMD_GET_DEVICE_STATUS); 00153 return SIEReadData(SIE_CMD_GET_DEVICE_STATUS); 00154 } 00155 00156 void SIEsetAddress(uint8_t address) { 00157 // Write SIE device address register 00158 SIECommand(SIE_CMD_SET_ADDRESS); 00159 SIEWriteData((address & 0x7f) | SIE_DSA_DEV_EN); 00160 } 00161 00162 static uint8_t SIEselectEndpoint(uint8_t endpoint) { 00163 // SIE select endpoint command 00164 SIECommand(SIE_CMD_SELECT_ENDPOINT(endpoint)); 00165 return SIEReadData(SIE_CMD_SELECT_ENDPOINT(endpoint)); 00166 } 00167 00168 static uint8_t SIEclearBuffer(void) { 00169 // SIE clear buffer command 00170 SIECommand(SIE_CMD_CLEAR_BUFFER); 00171 return SIEReadData(SIE_CMD_CLEAR_BUFFER); 00172 } 00173 00174 static void SIEvalidateBuffer(void) { 00175 // SIE validate buffer command 00176 SIECommand(SIE_CMD_VALIDATE_BUFFER); 00177 } 00178 00179 static void SIEsetEndpointStatus(uint8_t endpoint, uint8_t status) { 00180 // SIE set endpoint status command 00181 SIECommand(SIE_CMD_SET_ENDPOINT_STATUS(endpoint)); 00182 SIEWriteData(status); 00183 } 00184 00185 static uint16_t SIEgetFrameNumber(void) __attribute__ ((unused)); 00186 static uint16_t SIEgetFrameNumber(void) { 00187 // Read current frame number 00188 uint16_t lowByte; 00189 uint16_t highByte; 00190 00191 SIECommand(SIE_CMD_READ_FRAME_NUMBER); 00192 lowByte = SIEReadData(SIE_CMD_READ_FRAME_NUMBER); 00193 highByte = SIEReadData(SIE_CMD_READ_FRAME_NUMBER); 00194 00195 return (highByte << 8) | lowByte; 00196 } 00197 00198 static void SIEconfigureDevice(void) { 00199 // SIE Configure device command 00200 SIECommand(SIE_CMD_CONFIGURE_DEVICE); 00201 SIEWriteData(SIE_CONF_DEVICE); 00202 } 00203 00204 static void SIEunconfigureDevice(void) { 00205 // SIE Configure device command 00206 SIECommand(SIE_CMD_CONFIGURE_DEVICE); 00207 SIEWriteData(0); 00208 } 00209 00210 static void SIEconnect(void) { 00211 // Connect USB device 00212 uint8_t status = SIEgetDeviceStatus(); 00213 SIEsetDeviceStatus(status | SIE_DS_CON); 00214 } 00215 00216 00217 static void SIEdisconnect(void) { 00218 // Disconnect USB device 00219 uint8_t status = SIEgetDeviceStatus(); 00220 SIEsetDeviceStatus(status & ~SIE_DS_CON); 00221 } 00222 00223 00224 static uint8_t selectEndpointClearInterrupt(uint8_t endpoint) { 00225 // Implemented using using EP_INT_CLR. 00226 LPC_USB->USBEpIntClr = EP(endpoint); 00227 while (!(LPC_USB->USBDevIntSt & CDFULL)); 00228 return (uint8_t)LPC_USB->USBCmdData; 00229 } 00230 00231 00232 static void enableEndpointEvent(uint8_t endpoint) { 00233 // Enable an endpoint interrupt 00234 LPC_USB->USBEpIntEn |= EP(endpoint); 00235 } 00236 00237 static void disableEndpointEvent(uint8_t endpoint) __attribute__ ((unused)); 00238 static void disableEndpointEvent(uint8_t endpoint) { 00239 // Disable an endpoint interrupt 00240 LPC_USB->USBEpIntEn &= ~EP(endpoint); 00241 } 00242 00243 static volatile uint32_t __attribute__((used)) dummyRead; 00244 uint32_t USBHAL::endpointReadcore(uint8_t endpoint, uint8_t *buffer) { 00245 // Read from an OUT endpoint 00246 uint32_t size; 00247 uint32_t i; 00248 uint32_t data = 0; 00249 uint8_t offset; 00250 00251 LPC_USB->USBCtrl = LOG_ENDPOINT(endpoint) | RD_EN; 00252 while (!(LPC_USB->USBRxPLen & PKT_RDY)); 00253 00254 size = LPC_USB->USBRxPLen & PKT_LNGTH_MASK; 00255 00256 offset = 0; 00257 00258 if (size > 0) { 00259 for (i=0; i<size; i++) { 00260 if (offset==0) { 00261 // Fetch up to four bytes of data as a word 00262 data = LPC_USB->USBRxData; 00263 } 00264 00265 // extract a byte 00266 *buffer = (data>>offset) & 0xff; 00267 buffer++; 00268 00269 // move on to the next byte 00270 offset = (offset + 8) % 32; 00271 } 00272 } else { 00273 dummyRead = LPC_USB->USBRxData; 00274 } 00275 00276 LPC_USB->USBCtrl = 0; 00277 00278 if ((endpoint >> 1) % 3 || (endpoint >> 1) == 0) { 00279 SIEselectEndpoint(endpoint); 00280 SIEclearBuffer(); 00281 } 00282 00283 return size; 00284 } 00285 00286 static void endpointWritecore(uint8_t endpoint, uint8_t *buffer, uint32_t size) { 00287 // Write to an IN endpoint 00288 uint32_t temp, data; 00289 uint8_t offset; 00290 00291 LPC_USB->USBCtrl = LOG_ENDPOINT(endpoint) | WR_EN; 00292 00293 LPC_USB->USBTxPLen = size; 00294 offset = 0; 00295 data = 0; 00296 00297 if (size>0) { 00298 do { 00299 // Fetch next data byte into a word-sized temporary variable 00300 temp = *buffer++; 00301 00302 // Add to current data word 00303 temp = temp << offset; 00304 data = data | temp; 00305 00306 // move on to the next byte 00307 offset = (offset + 8) % 32; 00308 size--; 00309 00310 if ((offset==0) || (size==0)) { 00311 // Write the word to the endpoint 00312 LPC_USB->USBTxData = data; 00313 data = 0; 00314 } 00315 } while (size>0); 00316 } else { 00317 LPC_USB->USBTxData = 0; 00318 } 00319 00320 // Clear WR_EN to cover zero length packet case 00321 LPC_USB->USBCtrl=0; 00322 00323 SIEselectEndpoint(endpoint); 00324 SIEvalidateBuffer(); 00325 } 00326 00327 USBHAL::USBHAL(void) { 00328 // Disable IRQ 00329 NVIC_DisableIRQ(USB_IRQn); 00330 00331 // fill in callback array 00332 epCallback[0] = &USBHAL::EP1_OUT_callback; 00333 epCallback[1] = &USBHAL::EP1_IN_callback; 00334 epCallback[2] = &USBHAL::EP2_OUT_callback; 00335 epCallback[3] = &USBHAL::EP2_IN_callback; 00336 epCallback[4] = &USBHAL::EP3_OUT_callback; 00337 epCallback[5] = &USBHAL::EP3_IN_callback; 00338 epCallback[6] = &USBHAL::EP4_OUT_callback; 00339 epCallback[7] = &USBHAL::EP4_IN_callback; 00340 epCallback[8] = &USBHAL::EP5_OUT_callback; 00341 epCallback[9] = &USBHAL::EP5_IN_callback; 00342 epCallback[10] = &USBHAL::EP6_OUT_callback; 00343 epCallback[11] = &USBHAL::EP6_IN_callback; 00344 epCallback[12] = &USBHAL::EP7_OUT_callback; 00345 epCallback[13] = &USBHAL::EP7_IN_callback; 00346 epCallback[14] = &USBHAL::EP8_OUT_callback; 00347 epCallback[15] = &USBHAL::EP8_IN_callback; 00348 epCallback[16] = &USBHAL::EP9_OUT_callback; 00349 epCallback[17] = &USBHAL::EP9_IN_callback; 00350 epCallback[18] = &USBHAL::EP10_OUT_callback; 00351 epCallback[19] = &USBHAL::EP10_IN_callback; 00352 epCallback[20] = &USBHAL::EP11_OUT_callback; 00353 epCallback[21] = &USBHAL::EP11_IN_callback; 00354 epCallback[22] = &USBHAL::EP12_OUT_callback; 00355 epCallback[23] = &USBHAL::EP12_IN_callback; 00356 epCallback[24] = &USBHAL::EP13_OUT_callback; 00357 epCallback[25] = &USBHAL::EP13_IN_callback; 00358 epCallback[26] = &USBHAL::EP14_OUT_callback; 00359 epCallback[27] = &USBHAL::EP14_IN_callback; 00360 epCallback[28] = &USBHAL::EP15_OUT_callback; 00361 epCallback[29] = &USBHAL::EP15_IN_callback; 00362 00363 // Enable power to USB device controller 00364 LPC_SC->PCONP |= PCUSB; 00365 00366 // Enable USB clocks 00367 LPC_USB->USBClkCtrl |= DEV_CLK_EN | AHB_CLK_EN; 00368 while (LPC_USB->USBClkSt != (DEV_CLK_ON | AHB_CLK_ON)); 00369 00370 // Configure pins P0.29 and P0.30 to be USB D+ and USB D- 00371 LPC_PINCON->PINSEL1 &= 0xc3ffffff; 00372 LPC_PINCON->PINSEL1 |= 0x14000000; 00373 00374 // Disconnect USB device 00375 SIEdisconnect(); 00376 00377 // Configure pin P2.9 to be Connect 00378 LPC_PINCON->PINSEL4 &= 0xfffcffff; 00379 LPC_PINCON->PINSEL4 |= 0x00040000; 00380 00381 // Connect must be low for at least 2.5uS 00382 wait(0.3); 00383 00384 // Set the maximum packet size for the control endpoints 00385 realiseEndpoint(EP0IN, MAX_PACKET_SIZE_EP0, 0); 00386 realiseEndpoint(EP0OUT, MAX_PACKET_SIZE_EP0, 0); 00387 00388 // Attach IRQ 00389 instance = this; 00390 NVIC_SetVector(USB_IRQn, (uint32_t)&_usbisr); 00391 00392 // Enable interrupts for device events and EP0 00393 LPC_USB->USBDevIntEn = EP_SLOW | DEV_STAT | FRAME; 00394 enableEndpointEvent(EP0IN); 00395 enableEndpointEvent(EP0OUT); 00396 } 00397 00398 USBHAL::~USBHAL(void) { 00399 // Ensure device disconnected 00400 SIEdisconnect(); 00401 // Disable USB interrupts 00402 NVIC_DisableIRQ(USB_IRQn); 00403 } 00404 00405 void USBHAL::connect(void) { 00406 NVIC_EnableIRQ(USB_IRQn); 00407 // Connect USB device 00408 SIEconnect(); 00409 } 00410 00411 void USBHAL::disconnect(void) { 00412 NVIC_DisableIRQ(USB_IRQn); 00413 // Disconnect USB device 00414 SIEdisconnect(); 00415 } 00416 00417 void USBHAL::configureDevice(void) { 00418 SIEconfigureDevice(); 00419 } 00420 00421 void USBHAL::unconfigureDevice(void) { 00422 SIEunconfigureDevice(); 00423 } 00424 00425 void USBHAL::setAddress(uint8_t address) { 00426 SIEsetAddress(address); 00427 } 00428 00429 void USBHAL::EP0setup(uint8_t *buffer) { 00430 endpointReadcore(EP0OUT, buffer); 00431 } 00432 00433 void USBHAL::EP0read(void) { 00434 // Not required 00435 } 00436 00437 void USBHAL::EP0readStage(void) { 00438 // Not required 00439 } 00440 00441 uint32_t USBHAL::EP0getReadResult(uint8_t *buffer) { 00442 return endpointReadcore(EP0OUT, buffer); 00443 } 00444 00445 void USBHAL::EP0write(uint8_t *buffer, uint32_t size) { 00446 endpointWritecore(EP0IN, buffer, size); 00447 } 00448 00449 void USBHAL::EP0getWriteResult(void) { 00450 // Not required 00451 } 00452 00453 void USBHAL::EP0stall(void) { 00454 // This will stall both control endpoints 00455 stallEndpoint(EP0OUT); 00456 } 00457 00458 EP_STATUS USBHAL::endpointRead(uint8_t endpoint, uint32_t maximumSize) { 00459 return EP_PENDING; 00460 } 00461 00462 EP_STATUS USBHAL::endpointReadResult(uint8_t endpoint, uint8_t * buffer, uint32_t *bytesRead) { 00463 00464 //for isochronous endpoint, we don't wait an interrupt 00465 if ((endpoint >> 1) % 3 || (endpoint >> 1) == 0) { 00466 if (!(epComplete & EP(endpoint))) 00467 return EP_PENDING; 00468 } 00469 00470 *bytesRead = endpointReadcore(endpoint, buffer); 00471 epComplete &= ~EP(endpoint); 00472 return EP_COMPLETED; 00473 } 00474 00475 EP_STATUS USBHAL::endpointWrite(uint8_t endpoint, uint8_t *data, uint32_t size) { 00476 if (getEndpointStallState(endpoint)) { 00477 return EP_STALLED; 00478 } 00479 00480 epComplete &= ~EP(endpoint); 00481 00482 endpointWritecore(endpoint, data, size); 00483 return EP_PENDING; 00484 } 00485 00486 EP_STATUS USBHAL::endpointWriteResult(uint8_t endpoint) { 00487 if (epComplete & EP(endpoint)) { 00488 epComplete &= ~EP(endpoint); 00489 return EP_COMPLETED; 00490 } 00491 00492 return EP_PENDING; 00493 } 00494 00495 bool USBHAL::realiseEndpoint(uint8_t endpoint, uint32_t maxPacket, uint32_t flags) { 00496 // Realise an endpoint 00497 LPC_USB->USBDevIntClr = EP_RLZED; 00498 LPC_USB->USBReEp |= EP(endpoint); 00499 LPC_USB->USBEpInd = endpoint; 00500 LPC_USB->USBMaxPSize = maxPacket; 00501 00502 while (!(LPC_USB->USBDevIntSt & EP_RLZED)); 00503 LPC_USB->USBDevIntClr = EP_RLZED; 00504 00505 // Clear stall state 00506 endpointStallState &= ~EP(endpoint); 00507 00508 enableEndpointEvent(endpoint); 00509 return true; 00510 } 00511 00512 void USBHAL::stallEndpoint(uint8_t endpoint) { 00513 // Stall an endpoint 00514 if ( (endpoint==EP0IN) || (endpoint==EP0OUT) ) { 00515 // Conditionally stall both control endpoints 00516 SIEsetEndpointStatus(EP0OUT, SIE_SES_CND_ST); 00517 } else { 00518 SIEsetEndpointStatus(endpoint, SIE_SES_ST); 00519 00520 // Update stall state 00521 endpointStallState |= EP(endpoint); 00522 } 00523 } 00524 00525 void USBHAL::unstallEndpoint(uint8_t endpoint) { 00526 // Unstall an endpoint. The endpoint will also be reinitialised 00527 SIEsetEndpointStatus(endpoint, 0); 00528 00529 // Update stall state 00530 endpointStallState &= ~EP(endpoint); 00531 } 00532 00533 bool USBHAL::getEndpointStallState(uint8_t endpoint) { 00534 // Returns true if endpoint stalled 00535 return endpointStallState & EP(endpoint); 00536 } 00537 00538 void USBHAL::remoteWakeup(void) { 00539 // Remote wakeup 00540 uint8_t status; 00541 00542 // Enable USB clocks 00543 LPC_USB->USBClkCtrl |= DEV_CLK_EN | AHB_CLK_EN; 00544 while (LPC_USB->USBClkSt != (DEV_CLK_ON | AHB_CLK_ON)); 00545 00546 status = SIEgetDeviceStatus(); 00547 SIEsetDeviceStatus(status & ~SIE_DS_SUS); 00548 } 00549 00550 void USBHAL::_usbisr(void) { 00551 instance->usbisr(); 00552 } 00553 00554 00555 void USBHAL::usbisr(void) { 00556 uint8_t devStat; 00557 00558 if (LPC_USB->USBDevIntSt & FRAME) { 00559 // Start of frame event 00560 SOF(SIEgetFrameNumber()); 00561 // Clear interrupt status flag 00562 LPC_USB->USBDevIntClr = FRAME; 00563 } 00564 00565 if (LPC_USB->USBDevIntSt & DEV_STAT) { 00566 // Device Status interrupt 00567 // Must clear the interrupt status flag before reading the device status from the SIE 00568 LPC_USB->USBDevIntClr = DEV_STAT; 00569 00570 // Read device status from SIE 00571 devStat = SIEgetDeviceStatus(); 00572 //printf("devStat: %d\r\n", devStat); 00573 00574 if (devStat & SIE_DS_SUS_CH) { 00575 // Suspend status changed 00576 if((devStat & SIE_DS_SUS) != 0) { 00577 suspendStateChanged(0); 00578 } 00579 } 00580 00581 if (devStat & SIE_DS_RST) { 00582 // Bus reset 00583 if((devStat & SIE_DS_SUS) == 0) { 00584 suspendStateChanged(1); 00585 } 00586 busReset(); 00587 } 00588 } 00589 00590 if (LPC_USB->USBDevIntSt & EP_SLOW) { 00591 // (Slow) Endpoint Interrupt 00592 00593 // Process each endpoint interrupt 00594 if (LPC_USB->USBEpIntSt & EP(EP0OUT)) { 00595 if (selectEndpointClearInterrupt(EP0OUT) & SIE_SE_STP) { 00596 // this is a setup packet 00597 EP0setupCallback(); 00598 } else { 00599 EP0out(); 00600 } 00601 LPC_USB->USBDevIntClr = EP_SLOW; 00602 } 00603 00604 if (LPC_USB->USBEpIntSt & EP(EP0IN)) { 00605 selectEndpointClearInterrupt(EP0IN); 00606 LPC_USB->USBDevIntClr = EP_SLOW; 00607 EP0in(); 00608 } 00609 00610 for (uint8_t num = 2; num < 16*2; num++) { 00611 if (LPC_USB->USBEpIntSt & EP(num)) { 00612 selectEndpointClearInterrupt(num); 00613 epComplete |= EP(num); 00614 LPC_USB->USBDevIntClr = EP_SLOW; 00615 if ((instance->*(epCallback[num - 2]))()) { 00616 epComplete &= ~EP(num); 00617 } 00618 } 00619 } 00620 } 00621 } 00622 00623 #endif
Generated on Tue Jul 12 2022 14:14:02 by
