USB device stack
Dependents: blinky_max32630fthr FTHR_USB_serial FTHR_OLED HSP_RPC_GUI_3_0_1 ... more
Fork of USBDevice by
USBHAL_LPC11U.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_LPC11UXX) || defined(TARGET_LPC11U6X) || defined(TARGET_LPC1347) || defined(TARGET_LPC1549) 00020 00021 #if defined(TARGET_LPC1347) || defined(TARGET_LPC1549) 00022 #define USB_IRQ USB_IRQ_IRQn 00023 #else 00024 #define USB_IRQ USB_IRQn 00025 #endif 00026 00027 #include "USBHAL.h" 00028 00029 USBHAL * USBHAL::instance; 00030 #if defined(TARGET_LPC1549) 00031 static uint8_t usbmem[2048] __attribute__((aligned(2048))); 00032 #endif 00033 00034 // Valid physical endpoint numbers are 0 to (NUMBER_OF_PHYSICAL_ENDPOINTS-1) 00035 #define LAST_PHYSICAL_ENDPOINT (NUMBER_OF_PHYSICAL_ENDPOINTS-1) 00036 00037 // Convert physical endpoint number to register bit 00038 #define EP(endpoint) (1UL<<endpoint) 00039 00040 // Convert physical to logical 00041 #define PHY_TO_LOG(endpoint) ((endpoint)>>1) 00042 00043 // Get endpoint direction 00044 #define IN_EP(endpoint) ((endpoint) & 1U ? true : false) 00045 #define OUT_EP(endpoint) ((endpoint) & 1U ? false : true) 00046 00047 // USB RAM 00048 #if defined(TARGET_LPC1549) 00049 #define USB_RAM_START ((uint32_t)usbmem) 00050 #define USB_RAM_SIZE sizeof(usbmem) 00051 #else 00052 #define USB_RAM_START (0x20004000) 00053 #define USB_RAM_SIZE (0x00000800) 00054 #endif 00055 00056 // SYSAHBCLKCTRL 00057 #if defined(TARGET_LPC1549) 00058 #define CLK_USB (1UL<<23) 00059 #else 00060 #define CLK_USB (1UL<<14) 00061 #define CLK_USBRAM (1UL<<27) 00062 #endif 00063 00064 // USB Information register 00065 #define FRAME_NR(a) ((a) & 0x7ff) // Frame number 00066 00067 // USB Device Command/Status register 00068 #define DEV_ADDR_MASK (0x7f) // Device address 00069 #define DEV_ADDR(a) ((a) & DEV_ADDR_MASK) 00070 #define DEV_EN (1UL<<7) // Device enable 00071 #define SETUP (1UL<<8) // SETUP token received 00072 #define PLL_ON (1UL<<9) // PLL enabled in suspend 00073 #define DCON (1UL<<16) // Device status - connect 00074 #define DSUS (1UL<<17) // Device status - suspend 00075 #define DCON_C (1UL<<24) // Connect change 00076 #define DSUS_C (1UL<<25) // Suspend change 00077 #define DRES_C (1UL<<26) // Reset change 00078 #define VBUSDEBOUNCED (1UL<<28) // Vbus detected 00079 00080 // Endpoint Command/Status list 00081 #define CMDSTS_A (1UL<<31) // Active 00082 #define CMDSTS_D (1UL<<30) // Disable 00083 #define CMDSTS_S (1UL<<29) // Stall 00084 #define CMDSTS_TR (1UL<<28) // Toggle Reset 00085 #define CMDSTS_RF (1UL<<27) // Rate Feedback mode 00086 #define CMDSTS_TV (1UL<<27) // Toggle Value 00087 #define CMDSTS_T (1UL<<26) // Endpoint Type 00088 #define CMDSTS_NBYTES(n) (((n)&0x3ff)<<16) // Number of bytes 00089 #define CMDSTS_ADDRESS_OFFSET(a) (((a)>>6)&0xffff) // Buffer start address 00090 00091 #define BYTES_REMAINING(s) (((s)>>16)&0x3ff) // Bytes remaining after transfer 00092 00093 // USB Non-endpoint interrupt sources 00094 #define FRAME_INT (1UL<<30) 00095 #define DEV_INT (1UL<<31) 00096 00097 static volatile int epComplete = 0; 00098 00099 // One entry for a double-buffered logical endpoint in the endpoint 00100 // command/status list. Endpoint 0 is single buffered, out[1] is used 00101 // for the SETUP packet and in[1] is not used 00102 typedef struct { 00103 uint32_t out[2]; 00104 uint32_t in[2]; 00105 } PACKED EP_COMMAND_STATUS; 00106 00107 typedef struct { 00108 uint8_t out[MAX_PACKET_SIZE_EP0]; 00109 uint8_t in[MAX_PACKET_SIZE_EP0]; 00110 uint8_t setup[SETUP_PACKET_SIZE]; 00111 } PACKED CONTROL_TRANSFER; 00112 00113 typedef struct { 00114 uint32_t maxPacket; 00115 uint32_t buffer[2]; 00116 uint32_t options; 00117 } PACKED EP_STATE; 00118 00119 static volatile EP_STATE endpointState[NUMBER_OF_PHYSICAL_ENDPOINTS]; 00120 00121 // Pointer to the endpoint command/status list 00122 static EP_COMMAND_STATUS *ep = NULL; 00123 00124 // Pointer to endpoint 0 data (IN/OUT and SETUP) 00125 static CONTROL_TRANSFER *ct = NULL; 00126 00127 // Shadow DEVCMDSTAT register to avoid accidentally clearing flags or 00128 // initiating a remote wakeup event. 00129 static volatile uint32_t devCmdStat; 00130 00131 // Pointers used to allocate USB RAM 00132 static uint32_t usbRamPtr = USB_RAM_START; 00133 static uint32_t epRamPtr = 0; // Buffers for endpoints > 0 start here 00134 00135 #define ROUND_UP_TO_MULTIPLE(x, m) ((((x)+((m)-1))/(m))*(m)) 00136 00137 void USBMemCopy(uint8_t *dst, uint8_t *src, uint32_t size); 00138 void USBMemCopy(uint8_t *dst, uint8_t *src, uint32_t size) { 00139 if (size > 0) { 00140 do { 00141 *dst++ = *src++; 00142 } while (--size > 0); 00143 } 00144 } 00145 00146 00147 USBHAL::USBHAL(void) { 00148 NVIC_DisableIRQ(USB_IRQ); 00149 00150 // fill in callback array 00151 epCallback[0] = &USBHAL::EP1_OUT_callback; 00152 epCallback[1] = &USBHAL::EP1_IN_callback; 00153 epCallback[2] = &USBHAL::EP2_OUT_callback; 00154 epCallback[3] = &USBHAL::EP2_IN_callback; 00155 epCallback[4] = &USBHAL::EP3_OUT_callback; 00156 epCallback[5] = &USBHAL::EP3_IN_callback; 00157 epCallback[6] = &USBHAL::EP4_OUT_callback; 00158 epCallback[7] = &USBHAL::EP4_IN_callback; 00159 00160 #if defined(TARGET_LPC1549) 00161 /* Set USB PLL input to system oscillator */ 00162 LPC_SYSCON->USBPLLCLKSEL = 0x01; 00163 00164 /* Setup USB PLL (FCLKIN = 12MHz) * 4 = 48MHz 00165 MSEL = 3 (this is pre-decremented), PSEL = 1 (for P = 2) 00166 FCLKOUT = FCLKIN * (MSEL + 1) = 12MHz * 4 = 48MHz 00167 FCCO = FCLKOUT * 2 * P = 48MHz * 2 * 2 = 192MHz (within FCCO range) */ 00168 LPC_SYSCON->USBPLLCTRL = (0x3 | (1UL << 6)); 00169 00170 /* Powerup USB PLL */ 00171 LPC_SYSCON->PDRUNCFG &= ~(CLK_USB); 00172 00173 /* Wait for PLL to lock */ 00174 while(!(LPC_SYSCON->USBPLLSTAT & 0x01)); 00175 00176 /* enable USB main clock */ 00177 LPC_SYSCON->USBCLKSEL = 0x02; 00178 LPC_SYSCON->USBCLKDIV = 1; 00179 00180 /* Enable AHB clock to the USB block. */ 00181 LPC_SYSCON->SYSAHBCLKCTRL1 |= CLK_USB; 00182 00183 /* power UP USB Phy */ 00184 LPC_SYSCON->PDRUNCFG &= ~(1UL << 9); 00185 00186 /* Reset USB block */ 00187 LPC_SYSCON->PRESETCTRL1 |= (CLK_USB); 00188 LPC_SYSCON->PRESETCTRL1 &= ~(CLK_USB); 00189 00190 #else 00191 #if defined(TARGET_LPC11U35_401) || defined(TARGET_LPC11U35_501) 00192 // USB_VBUS input with pull-down 00193 LPC_IOCON->PIO0_3 = 0x00000009; 00194 #endif 00195 00196 // nUSB_CONNECT output 00197 LPC_IOCON->PIO0_6 = 0x00000001; 00198 00199 // Enable clocks (USB registers, USB RAM) 00200 LPC_SYSCON->SYSAHBCLKCTRL |= CLK_USB | CLK_USBRAM; 00201 00202 // Ensure device disconnected (DCON not set) 00203 LPC_USB->DEVCMDSTAT = 0; 00204 #endif 00205 // to ensure that the USB host sees the device as 00206 // disconnected if the target CPU is reset. 00207 wait(0.3); 00208 00209 // Reserve space in USB RAM for endpoint command/status list 00210 // Must be 256 byte aligned 00211 usbRamPtr = ROUND_UP_TO_MULTIPLE(usbRamPtr, 256); 00212 ep = (EP_COMMAND_STATUS *)usbRamPtr; 00213 usbRamPtr += (sizeof(EP_COMMAND_STATUS) * NUMBER_OF_LOGICAL_ENDPOINTS); 00214 LPC_USB->EPLISTSTART = (uint32_t)(ep) & 0xffffff00; 00215 00216 // Reserve space in USB RAM for Endpoint 0 00217 // Must be 64 byte aligned 00218 usbRamPtr = ROUND_UP_TO_MULTIPLE(usbRamPtr, 64); 00219 ct = (CONTROL_TRANSFER *)usbRamPtr; 00220 usbRamPtr += sizeof(CONTROL_TRANSFER); 00221 LPC_USB->DATABUFSTART =(uint32_t)(ct) & 0xffc00000; 00222 00223 // Setup command/status list for EP0 00224 ep[0].out[0] = 0; 00225 ep[0].in[0] = 0; 00226 ep[0].out[1] = CMDSTS_ADDRESS_OFFSET((uint32_t)ct->setup); 00227 00228 // Route all interrupts to IRQ, some can be routed to 00229 // USB_FIQ if you wish. 00230 LPC_USB->INTROUTING = 0; 00231 00232 // Set device address 0, enable USB device, no remote wakeup 00233 devCmdStat = DEV_ADDR(0) | DEV_EN | DSUS; 00234 LPC_USB->DEVCMDSTAT = devCmdStat; 00235 00236 // Enable interrupts for device events and EP0 00237 LPC_USB->INTEN = DEV_INT | EP(EP0IN) | EP(EP0OUT) | FRAME_INT; 00238 instance = this; 00239 00240 //attach IRQ handler and enable interrupts 00241 NVIC_SetVector(USB_IRQ, (uint32_t)&_usbisr); 00242 } 00243 00244 USBHAL::~USBHAL(void) { 00245 // Ensure device disconnected (DCON not set) 00246 LPC_USB->DEVCMDSTAT = 0; 00247 // Disable USB interrupts 00248 NVIC_DisableIRQ(USB_IRQ); 00249 } 00250 00251 void USBHAL::connect(void) { 00252 NVIC_EnableIRQ(USB_IRQ); 00253 devCmdStat |= DCON; 00254 LPC_USB->DEVCMDSTAT = devCmdStat; 00255 } 00256 00257 void USBHAL::disconnect(void) { 00258 NVIC_DisableIRQ(USB_IRQ); 00259 devCmdStat &= ~DCON; 00260 LPC_USB->DEVCMDSTAT = devCmdStat; 00261 } 00262 00263 void USBHAL::configureDevice(void) { 00264 // Not required 00265 } 00266 00267 void USBHAL::unconfigureDevice(void) { 00268 // Not required 00269 } 00270 00271 void USBHAL::EP0setup(uint8_t *buffer) { 00272 // Copy setup packet data 00273 USBMemCopy(buffer, ct->setup, SETUP_PACKET_SIZE); 00274 } 00275 00276 void USBHAL::EP0read(void) { 00277 // Start an endpoint 0 read 00278 00279 // The USB ISR will call USBDevice_EP0out() when a packet has been read, 00280 // the USBDevice layer then calls USBBusInterface_EP0getReadResult() to 00281 // read the data. 00282 00283 ep[0].out[0] = CMDSTS_A |CMDSTS_NBYTES(MAX_PACKET_SIZE_EP0) \ 00284 | CMDSTS_ADDRESS_OFFSET((uint32_t)ct->out); 00285 } 00286 00287 uint32_t USBHAL::EP0getReadResult(uint8_t *buffer) { 00288 // Complete an endpoint 0 read 00289 uint32_t bytesRead; 00290 00291 // Find how many bytes were read 00292 bytesRead = MAX_PACKET_SIZE_EP0 - BYTES_REMAINING(ep[0].out[0]); 00293 00294 // Copy data 00295 USBMemCopy(buffer, ct->out, bytesRead); 00296 return bytesRead; 00297 } 00298 00299 00300 void USBHAL::EP0readStage(void) { 00301 // Not required 00302 } 00303 00304 void USBHAL::EP0write(uint8_t *buffer, uint32_t size) { 00305 // Start and endpoint 0 write 00306 00307 // The USB ISR will call USBDevice_EP0in() when the data has 00308 // been written, the USBDevice layer then calls 00309 // USBBusInterface_EP0getWriteResult() to complete the transaction. 00310 00311 // Copy data 00312 USBMemCopy(ct->in, buffer, size); 00313 00314 // Start transfer 00315 ep[0].in[0] = CMDSTS_A | CMDSTS_NBYTES(size) \ 00316 | CMDSTS_ADDRESS_OFFSET((uint32_t)ct->in); 00317 } 00318 00319 00320 EP_STATUS USBHAL::endpointRead(uint8_t endpoint, uint32_t maximumSize) { 00321 uint8_t bf = 0; 00322 uint32_t flags = 0; 00323 00324 //check which buffer must be filled 00325 if (LPC_USB->EPBUFCFG & EP(endpoint)) { 00326 // Double buffered 00327 if (LPC_USB->EPINUSE & EP(endpoint)) { 00328 bf = 1; 00329 } else { 00330 bf = 0; 00331 } 00332 } 00333 00334 // if isochronous endpoint, T = 1 00335 if(endpointState[endpoint].options & ISOCHRONOUS) 00336 { 00337 flags |= CMDSTS_T; 00338 } 00339 00340 //Active the endpoint for reading 00341 ep[PHY_TO_LOG(endpoint)].out[bf] = CMDSTS_A | CMDSTS_NBYTES(maximumSize) \ 00342 | CMDSTS_ADDRESS_OFFSET((uint32_t)ct->out) | flags; 00343 return EP_PENDING; 00344 } 00345 00346 EP_STATUS USBHAL::endpointReadResult(uint8_t endpoint, uint8_t *data, uint32_t *bytesRead) { 00347 00348 uint8_t bf = 0; 00349 00350 if (!(epComplete & EP(endpoint))) 00351 return EP_PENDING; 00352 else { 00353 epComplete &= ~EP(endpoint); 00354 00355 //check which buffer has been filled 00356 if (LPC_USB->EPBUFCFG & EP(endpoint)) { 00357 // Double buffered (here we read the previous buffer which was used) 00358 if (LPC_USB->EPINUSE & EP(endpoint)) { 00359 bf = 0; 00360 } else { 00361 bf = 1; 00362 } 00363 } 00364 00365 // Find how many bytes were read 00366 *bytesRead = (uint32_t) (endpointState[endpoint].maxPacket - BYTES_REMAINING(ep[PHY_TO_LOG(endpoint)].out[bf])); 00367 00368 // Copy data 00369 USBMemCopy(data, ct->out, *bytesRead); 00370 return EP_COMPLETED; 00371 } 00372 } 00373 00374 void USBHAL::EP0getWriteResult(void) { 00375 // Not required 00376 } 00377 00378 void USBHAL::EP0stall(void) { 00379 ep[0].in[0] = CMDSTS_S; 00380 ep[0].out[0] = CMDSTS_S; 00381 } 00382 00383 void USBHAL::setAddress(uint8_t address) { 00384 devCmdStat &= ~DEV_ADDR_MASK; 00385 devCmdStat |= DEV_ADDR(address); 00386 LPC_USB->DEVCMDSTAT = devCmdStat; 00387 } 00388 00389 EP_STATUS USBHAL::endpointWrite(uint8_t endpoint, uint8_t *data, uint32_t size) { 00390 uint32_t flags = 0; 00391 uint32_t bf; 00392 00393 // Validate parameters 00394 if (data == NULL) { 00395 return EP_INVALID; 00396 } 00397 00398 if (endpoint > LAST_PHYSICAL_ENDPOINT) { 00399 return EP_INVALID; 00400 } 00401 00402 if ((endpoint==EP0IN) || (endpoint==EP0OUT)) { 00403 return EP_INVALID; 00404 } 00405 00406 if (size > endpointState[endpoint].maxPacket) { 00407 return EP_INVALID; 00408 } 00409 00410 if (LPC_USB->EPBUFCFG & EP(endpoint)) { 00411 // Double buffered 00412 if (LPC_USB->EPINUSE & EP(endpoint)) { 00413 bf = 1; 00414 } else { 00415 bf = 0; 00416 } 00417 } else { 00418 // Single buffered 00419 bf = 0; 00420 } 00421 00422 // Check if already active 00423 if (ep[PHY_TO_LOG(endpoint)].in[bf] & CMDSTS_A) { 00424 return EP_INVALID; 00425 } 00426 00427 // Check if stalled 00428 if (ep[PHY_TO_LOG(endpoint)].in[bf] & CMDSTS_S) { 00429 return EP_STALLED; 00430 } 00431 00432 // Copy data to USB RAM 00433 USBMemCopy((uint8_t *)endpointState[endpoint].buffer[bf], data, size); 00434 00435 // Add options 00436 if (endpointState[endpoint].options & RATE_FEEDBACK_MODE) { 00437 flags |= CMDSTS_RF; 00438 } 00439 00440 if (endpointState[endpoint].options & ISOCHRONOUS) { 00441 flags |= CMDSTS_T; 00442 } 00443 00444 // Add transfer 00445 ep[PHY_TO_LOG(endpoint)].in[bf] = CMDSTS_ADDRESS_OFFSET( \ 00446 endpointState[endpoint].buffer[bf]) \ 00447 | CMDSTS_NBYTES(size) | CMDSTS_A | flags; 00448 00449 return EP_PENDING; 00450 } 00451 00452 EP_STATUS USBHAL::endpointWriteResult(uint8_t endpoint) { 00453 uint32_t bf; 00454 00455 // Validate parameters 00456 if (endpoint > LAST_PHYSICAL_ENDPOINT) { 00457 return EP_INVALID; 00458 } 00459 00460 if (OUT_EP(endpoint)) { 00461 return EP_INVALID; 00462 } 00463 00464 if (LPC_USB->EPBUFCFG & EP(endpoint)) { 00465 // Double buffered // TODO: FIX THIS 00466 if (LPC_USB->EPINUSE & EP(endpoint)) { 00467 bf = 1; 00468 } else { 00469 bf = 0; 00470 } 00471 } else { 00472 // Single buffered 00473 bf = 0; 00474 } 00475 00476 // Check if endpoint still active 00477 if (ep[PHY_TO_LOG(endpoint)].in[bf] & CMDSTS_A) { 00478 return EP_PENDING; 00479 } 00480 00481 // Check if stalled 00482 if (ep[PHY_TO_LOG(endpoint)].in[bf] & CMDSTS_S) { 00483 return EP_STALLED; 00484 } 00485 00486 return EP_COMPLETED; 00487 } 00488 00489 void USBHAL::stallEndpoint(uint8_t endpoint) { 00490 00491 // FIX: should this clear active bit? 00492 if (IN_EP(endpoint)) { 00493 ep[PHY_TO_LOG(endpoint)].in[0] |= CMDSTS_S; 00494 ep[PHY_TO_LOG(endpoint)].in[1] |= CMDSTS_S; 00495 } else { 00496 ep[PHY_TO_LOG(endpoint)].out[0] |= CMDSTS_S; 00497 ep[PHY_TO_LOG(endpoint)].out[1] |= CMDSTS_S; 00498 } 00499 } 00500 00501 void USBHAL::unstallEndpoint(uint8_t endpoint) { 00502 if (LPC_USB->EPBUFCFG & EP(endpoint)) { 00503 // Double buffered 00504 if (IN_EP(endpoint)) { 00505 ep[PHY_TO_LOG(endpoint)].in[0] = 0; // S = 0 00506 ep[PHY_TO_LOG(endpoint)].in[1] = 0; // S = 0 00507 00508 if (LPC_USB->EPINUSE & EP(endpoint)) { 00509 ep[PHY_TO_LOG(endpoint)].in[1] = CMDSTS_TR; // S = 0, TR = 1, TV = 0 00510 } else { 00511 ep[PHY_TO_LOG(endpoint)].in[0] = CMDSTS_TR; // S = 0, TR = 1, TV = 0 00512 } 00513 } else { 00514 ep[PHY_TO_LOG(endpoint)].out[0] = 0; // S = 0 00515 ep[PHY_TO_LOG(endpoint)].out[1] = 0; // S = 0 00516 00517 if (LPC_USB->EPINUSE & EP(endpoint)) { 00518 ep[PHY_TO_LOG(endpoint)].out[1] = CMDSTS_TR; // S = 0, TR = 1, TV = 0 00519 } else { 00520 ep[PHY_TO_LOG(endpoint)].out[0] = CMDSTS_TR; // S = 0, TR = 1, TV = 0 00521 } 00522 } 00523 } else { 00524 // Single buffered 00525 if (IN_EP(endpoint)) { 00526 ep[PHY_TO_LOG(endpoint)].in[0] = CMDSTS_TR; // S = 0, TR = 1, TV = 0 00527 } else { 00528 ep[PHY_TO_LOG(endpoint)].out[0] = CMDSTS_TR; // S = 0, TR = 1, TV = 0 00529 } 00530 } 00531 } 00532 00533 bool USBHAL::getEndpointStallState(unsigned char endpoint) { 00534 if (IN_EP(endpoint)) { 00535 if (LPC_USB->EPINUSE & EP(endpoint)) { 00536 if (ep[PHY_TO_LOG(endpoint)].in[1] & CMDSTS_S) { 00537 return true; 00538 } 00539 } else { 00540 if (ep[PHY_TO_LOG(endpoint)].in[0] & CMDSTS_S) { 00541 return true; 00542 } 00543 } 00544 } else { 00545 if (LPC_USB->EPINUSE & EP(endpoint)) { 00546 if (ep[PHY_TO_LOG(endpoint)].out[1] & CMDSTS_S) { 00547 return true; 00548 } 00549 } else { 00550 if (ep[PHY_TO_LOG(endpoint)].out[0] & CMDSTS_S) { 00551 return true; 00552 } 00553 } 00554 } 00555 00556 return false; 00557 } 00558 00559 bool USBHAL::realiseEndpoint(uint8_t endpoint, uint32_t maxPacket, uint32_t options) { 00560 uint32_t tmpEpRamPtr; 00561 00562 if (endpoint > LAST_PHYSICAL_ENDPOINT) { 00563 return false; 00564 } 00565 00566 // Not applicable to the control endpoints 00567 if ((endpoint==EP0IN) || (endpoint==EP0OUT)) { 00568 return false; 00569 } 00570 00571 // Allocate buffers in USB RAM 00572 tmpEpRamPtr = epRamPtr; 00573 00574 // Must be 64 byte aligned 00575 tmpEpRamPtr = ROUND_UP_TO_MULTIPLE(tmpEpRamPtr, 64); 00576 00577 if ((tmpEpRamPtr + maxPacket) > (USB_RAM_START + USB_RAM_SIZE)) { 00578 // Out of memory 00579 return false; 00580 } 00581 00582 // Allocate first buffer 00583 endpointState[endpoint].buffer[0] = tmpEpRamPtr; 00584 tmpEpRamPtr += maxPacket; 00585 00586 if (!(options & SINGLE_BUFFERED)) { 00587 // Must be 64 byte aligned 00588 tmpEpRamPtr = ROUND_UP_TO_MULTIPLE(tmpEpRamPtr, 64); 00589 00590 if ((tmpEpRamPtr + maxPacket) > (USB_RAM_START + USB_RAM_SIZE)) { 00591 // Out of memory 00592 return false; 00593 } 00594 00595 // Allocate second buffer 00596 endpointState[endpoint].buffer[1] = tmpEpRamPtr; 00597 tmpEpRamPtr += maxPacket; 00598 } 00599 00600 // Commit to this USB RAM allocation 00601 epRamPtr = tmpEpRamPtr; 00602 00603 // Remaining endpoint state values 00604 endpointState[endpoint].maxPacket = maxPacket; 00605 endpointState[endpoint].options = options; 00606 00607 // Enable double buffering if required 00608 if (options & SINGLE_BUFFERED) { 00609 LPC_USB->EPBUFCFG &= ~EP(endpoint); 00610 } else { 00611 // Double buffered 00612 LPC_USB->EPBUFCFG |= EP(endpoint); 00613 } 00614 00615 // Enable interrupt 00616 LPC_USB->INTEN |= EP(endpoint); 00617 00618 // Enable endpoint 00619 unstallEndpoint(endpoint); 00620 return true; 00621 } 00622 00623 void USBHAL::remoteWakeup(void) { 00624 // Clearing DSUS bit initiates a remote wakeup if the 00625 // device is currently enabled and suspended - otherwise 00626 // it has no effect. 00627 LPC_USB->DEVCMDSTAT = devCmdStat & ~DSUS; 00628 } 00629 00630 00631 static void disableEndpoints(void) { 00632 uint32_t logEp; 00633 00634 // Ref. Table 158 "When a bus reset is received, software 00635 // must set the disable bit of all endpoints to 1". 00636 00637 for (logEp = 1; logEp < NUMBER_OF_LOGICAL_ENDPOINTS; logEp++) { 00638 ep[logEp].out[0] = CMDSTS_D; 00639 ep[logEp].out[1] = CMDSTS_D; 00640 ep[logEp].in[0] = CMDSTS_D; 00641 ep[logEp].in[1] = CMDSTS_D; 00642 } 00643 00644 // Start of USB RAM for endpoints > 0 00645 epRamPtr = usbRamPtr; 00646 } 00647 00648 00649 00650 void USBHAL::_usbisr(void) { 00651 instance->usbisr(); 00652 } 00653 00654 void USBHAL::usbisr(void) { 00655 // Start of frame 00656 if (LPC_USB->INTSTAT & FRAME_INT) { 00657 // Clear SOF interrupt 00658 LPC_USB->INTSTAT = FRAME_INT; 00659 00660 // SOF event, read frame number 00661 SOF(FRAME_NR(LPC_USB->INFO)); 00662 } 00663 00664 // Device state 00665 if (LPC_USB->INTSTAT & DEV_INT) { 00666 LPC_USB->INTSTAT = DEV_INT; 00667 00668 if (LPC_USB->DEVCMDSTAT & DSUS_C) { 00669 // Suspend status changed 00670 LPC_USB->DEVCMDSTAT = devCmdStat | DSUS_C; 00671 if (LPC_USB->DEVCMDSTAT & DSUS) { 00672 suspendStateChanged(1); 00673 } else { 00674 suspendStateChanged(0); 00675 } 00676 } 00677 00678 if (LPC_USB->DEVCMDSTAT & DRES_C) { 00679 // Bus reset 00680 LPC_USB->DEVCMDSTAT = devCmdStat | DRES_C; 00681 00682 // Disable endpoints > 0 00683 disableEndpoints(); 00684 00685 // Bus reset event 00686 busReset(); 00687 } 00688 } 00689 00690 // Endpoint 0 00691 if (LPC_USB->INTSTAT & EP(EP0OUT)) { 00692 // Clear EP0OUT/SETUP interrupt 00693 LPC_USB->INTSTAT = EP(EP0OUT); 00694 00695 // Check if SETUP 00696 if (LPC_USB->DEVCMDSTAT & SETUP) { 00697 // Clear Active and Stall bits for EP0 00698 // Documentation does not make it clear if we must use the 00699 // EPSKIP register to achieve this, Fig. 16 and NXP reference 00700 // code suggests we can just clear the Active bits - check with 00701 // NXP to be sure. 00702 ep[0].in[0] = 0; 00703 ep[0].out[0] = 0; 00704 00705 // Clear EP0IN interrupt 00706 LPC_USB->INTSTAT = EP(EP0IN); 00707 00708 // Clear SETUP (and INTONNAK_CI/O) in device status register 00709 LPC_USB->DEVCMDSTAT = devCmdStat | SETUP; 00710 00711 // EP0 SETUP event (SETUP data received) 00712 EP0setupCallback(); 00713 } else { 00714 // EP0OUT ACK event (OUT data received) 00715 EP0out(); 00716 } 00717 } 00718 00719 if (LPC_USB->INTSTAT & EP(EP0IN)) { 00720 // Clear EP0IN interrupt 00721 LPC_USB->INTSTAT = EP(EP0IN); 00722 00723 // EP0IN ACK event (IN data sent) 00724 EP0in(); 00725 } 00726 00727 for (uint8_t num = 2; num < 5*2; num++) { 00728 if (LPC_USB->INTSTAT & EP(num)) { 00729 LPC_USB->INTSTAT = EP(num); 00730 epComplete |= EP(num); 00731 if ((instance->*(epCallback[num - 2]))()) { 00732 epComplete &= ~EP(num); 00733 } 00734 } 00735 } 00736 } 00737 00738 #endif
Generated on Wed Jul 13 2022 12:44:03 by 1.7.2