Fork of Smoothie to port to mbed non-LPC targets.
Fork of Smoothie 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 (__LPC17XX__) 00020 00021 // void setled(int, bool); 00022 #define setled(a, b) do {} while (0) 00023 00024 #include "USBHAL.h" 00025 00026 #include <cstdio> 00027 #include <LPC17xx.h> 00028 00029 #ifdef MBED 00030 #include <score_cm3.h> 00031 #else 00032 #include <lpc17xx_nvic.h> 00033 #endif 00034 00035 #include "wait_api.h" 00036 00037 #include "debug.h" 00038 00039 #ifndef ENTER_ISR 00040 #define ENTER_ISR() do {} while (0) 00041 #endif 00042 00043 #ifndef LEAVE_ISR 00044 #define LEAVE_ISR() do {} while (0) 00045 #endif 00046 00047 #define iprintf(...) 00048 00049 // Get endpoint direction 00050 #define IN_EP(endpoint) ((endpoint) & 1U ? true : false) 00051 #define OUT_EP(endpoint) ((endpoint) & 1U ? false : true) 00052 00053 #define IN_BEP(endpoint) ((endpoint) & 0x80 ? true : false) 00054 #define OUT_BEP(endpoint) ((endpoint) & 0x80 ? false : true) 00055 00056 // Convert physical endpoint number to register bit 00057 #define EP(endpoint) (1UL<<endpoint) 00058 00059 #define ISOCHRONOUS_ENDPOINTS ((1UL << 3) | (1UL << 6) | (1UL << 9) | (1UL << 12)) 00060 00061 #define IS_ISOCHRONOUS(bEP) ((1UL << (bEP & 0x0F)) & ISOCHRONOUS_ENDPOINTS) 00062 00063 // Power Control for Peripherals register 00064 #define PCUSB (1UL<<31) 00065 00066 // USB Clock Control register 00067 #define DEV_CLK_EN (1UL<<1) 00068 #define AHB_CLK_EN (1UL<<4) 00069 00070 // USB Clock Status register 00071 #define DEV_CLK_ON (1UL<<1) 00072 #define AHB_CLK_ON (1UL<<4) 00073 00074 // USB Device Interupt registers 00075 #define FRAME (1UL<<0) 00076 #define EP_FAST (1UL<<1) 00077 #define EP_SLOW (1UL<<2) 00078 #define DEV_STAT (1UL<<3) 00079 #define CCEMPTY (1UL<<4) 00080 #define CDFULL (1UL<<5) 00081 #define RxENDPKT (1UL<<6) 00082 #define TxENDPKT (1UL<<7) 00083 #define EP_RLZED (1UL<<8) 00084 #define ERR_INT (1UL<<9) 00085 00086 /* USBRxPLen bits */ 00087 #define PKT_LNGTH (1<<0) 00088 #define PKT_LNGTH_MASK 0x3FF 00089 #define DV (1<<10) 00090 #define PKT_RDY (1<<11) 00091 00092 /* Select Endpoint command read bits */ 00093 #define EPSTAT_FE (1<<0) 00094 #define EPSTAT_ST (1<<1) 00095 #define EPSTAT_STP (1<<2) 00096 #define EPSTAT_PO (1<<3) 00097 #define EPSTAT_EPN (1<<4) 00098 #define EPSTAT_B1FULL (1<<5) 00099 #define EPSTAT_B2FULL (1<<6) 00100 00101 // endpoint status sent through callback 00102 #define EP_STATUS_DATA (1<<0) /**< EP has data */ 00103 #define EP_STATUS_STALLED (1<<1) /**< EP is stalled */ 00104 #define EP_STATUS_SETUP (1<<2) /**< EP received setup packet */ 00105 #define EP_STATUS_ERROR (1<<3) /**< EP data was overwritten by setup packet */ 00106 #define EP_STATUS_NACKED (1<<4) /**< EP sent NAK */ 00107 00108 // USB Control register 00109 #define RD_EN (1<<0) 00110 #define WR_EN (1<<1) 00111 #define LOG_ENDPOINT(endpoint) ((endpoint>>1)<<2) 00112 00113 // USB Receive Packet Length register 00114 // #define DV (1UL<<10) 00115 // #define PKT_RDY (1UL<<11) 00116 // #define PKT_LNGTH_MASK (0x3ff) 00117 00118 // Serial Interface Engine (SIE) 00119 #define SIE_WRITE (0x01) 00120 #define SIE_READ (0x02) 00121 #define SIE_COMMAND (0x05) 00122 #define SIE_CMD_CODE(phase, data) ((phase<<8)|(data<<16)) 00123 00124 // SIE Command codes 00125 #define SIE_CMD_SET_ADDRESS (0xD0) 00126 #define SIE_CMD_CONFIGURE_DEVICE (0xD8) 00127 #define SIE_CMD_SET_MODE (0xF3) 00128 #define SIE_CMD_READ_FRAME_NUMBER (0xF5) 00129 #define SIE_CMD_READ_TEST_REGISTER (0xFD) 00130 #define SIE_CMD_SET_DEVICE_STATUS (0xFE) 00131 #define SIE_CMD_GET_DEVICE_STATUS (0xFE) 00132 #define SIE_CMD_GET_ERROR_CODE (0xFF) 00133 #define SIE_CMD_READ_ERROR_STATUS (0xFB) 00134 00135 #define SIE_CMD_SELECT_ENDPOINT(endpoint) (0x00+endpoint) 00136 #define SIE_CMD_SELECT_ENDPOINT_CLEAR_INTERRUPT(endpoint) (0x40+endpoint) 00137 #define SIE_CMD_SET_ENDPOINT_STATUS(endpoint) (0x40+endpoint) 00138 00139 #define SIE_CMD_CLEAR_BUFFER (0xF2) 00140 #define SIE_CMD_VALIDATE_BUFFER (0xFA) 00141 00142 // SIE Device Status register 00143 #define SIE_DS_CON (1<<0) 00144 #define SIE_DS_CON_CH (1<<1) 00145 #define SIE_DS_SUS (1<<2) 00146 #define SIE_DS_SUS_CH (1<<3) 00147 #define SIE_DS_RST (1<<4) 00148 00149 // SIE Device Set Address register 00150 #define SIE_DSA_DEV_EN (1<<7) 00151 00152 // SIE Configue Device register 00153 #define SIE_CONF_DEVICE (1<<0) 00154 00155 // Select Endpoint register 00156 #define SIE_SE_FE (1<<0) 00157 #define SIE_SE_ST (1<<1) 00158 #define SIE_SE_STP (1<<2) 00159 #define SIE_SE_PO (1<<3) 00160 #define SIE_SE_EPN (1<<4) 00161 #define SIE_SE_B_1_FULL (1<<5) 00162 #define SIE_SE_B_2_FULL (1<<6) 00163 00164 // Set Endpoint Status command 00165 #define SIE_SES_ST (1<<0) 00166 #define SIE_SES_DA (1<<5) 00167 #define SIE_SES_RF_MO (1<<6) 00168 #define SIE_SES_CND_ST (1<<7) 00169 00170 // endpoint modes 00171 #define SIE_MODE_AP_CLK (1<<0) 00172 #define SIE_MODE_INAK_CI (1<<1) 00173 #define SIE_MODE_INAK_CO (1<<2) 00174 #define SIE_MODE_INAK_II (1<<3) 00175 #define SIE_MODE_INAK_IO (1<<4) 00176 #define SIE_MODE_INAK_BI (1<<5) 00177 #define SIE_MODE_INAK_BO (1<<6) 00178 00179 USBHAL * USBHAL::instance; 00180 00181 // volatile uint32_t epComplete; 00182 volatile uint32_t USBEpIntEn; 00183 uint32_t endpointStallState; 00184 00185 static void SIECommand(uint32_t command) { 00186 // The command phase of a SIE transaction 00187 LPC_USB->USBDevIntClr = CCEMPTY; 00188 LPC_USB->USBCmdCode = SIE_CMD_CODE(SIE_COMMAND, command); 00189 setled(4, 1); while (!(LPC_USB->USBDevIntSt & CCEMPTY)); setled(4, 0); 00190 } 00191 00192 static void SIEWriteData(uint8_t data) { 00193 // The data write phase of a SIE transaction 00194 LPC_USB->USBDevIntClr = CCEMPTY; 00195 LPC_USB->USBCmdCode = SIE_CMD_CODE(SIE_WRITE, data); 00196 setled(4, 1); while (!(LPC_USB->USBDevIntSt & CCEMPTY)); setled(4, 0); 00197 } 00198 00199 static uint8_t SIEReadData(uint32_t command) { 00200 // The data read phase of a SIE transaction 00201 LPC_USB->USBDevIntClr = CDFULL; 00202 LPC_USB->USBCmdCode = SIE_CMD_CODE(SIE_READ, command); 00203 setled(4, 1); while (!(LPC_USB->USBDevIntSt & CDFULL)); setled(4, 0); 00204 return (uint8_t)LPC_USB->USBCmdData; 00205 } 00206 00207 static void SIEsetDeviceStatus(uint8_t status) { 00208 // Write SIE device status register 00209 // iprintf("SIEsetDeviceStatus: %02X\n", status); 00210 SIECommand(SIE_CMD_SET_DEVICE_STATUS); 00211 // iprintf("SIEsetDeviceStatus Write\n"); 00212 SIEWriteData(status); 00213 // iprintf("SIEsetDeviceStatus OK\n"); 00214 } 00215 00216 static uint8_t SIEgetDeviceStatus(void) { 00217 // Read SIE device status register 00218 SIECommand(SIE_CMD_GET_DEVICE_STATUS); 00219 return SIEReadData(SIE_CMD_GET_DEVICE_STATUS); 00220 } 00221 00222 static void SIEsetMode(uint8_t mode) { 00223 SIECommand(SIE_CMD_SET_MODE); 00224 SIEWriteData(mode); 00225 } 00226 00227 static void SIEsetAddress(uint8_t address) { 00228 // Write SIE device address register 00229 SIECommand(SIE_CMD_SET_ADDRESS); 00230 SIEWriteData((address & 0x7f) | SIE_DSA_DEV_EN); 00231 } 00232 00233 static uint8_t SIEselectEndpoint(uint8_t bEP) { 00234 uint8_t endpoint = EP2IDX(bEP); 00235 00236 // SIE select endpoint command 00237 SIECommand(SIE_CMD_SELECT_ENDPOINT(endpoint)); 00238 return SIEReadData(SIE_CMD_SELECT_ENDPOINT(endpoint)); 00239 } 00240 00241 static uint8_t SIEclearBuffer(void) { 00242 // SIE clear buffer command 00243 SIECommand(SIE_CMD_CLEAR_BUFFER); 00244 return SIEReadData(SIE_CMD_CLEAR_BUFFER); 00245 } 00246 00247 static void SIEvalidateBuffer(void) { 00248 // SIE validate buffer command 00249 SIECommand(SIE_CMD_VALIDATE_BUFFER); 00250 } 00251 00252 static void SIEsetEndpointStatus(uint8_t bEP, uint8_t status) { 00253 uint8_t endpoint = EP2IDX(bEP); 00254 00255 // SIE set endpoint status command 00256 SIECommand(SIE_CMD_SET_ENDPOINT_STATUS(endpoint)); 00257 SIEWriteData(status); 00258 } 00259 00260 static uint16_t SIEgetFrameNumber(void) __attribute__ ((unused)); 00261 static uint16_t SIEgetFrameNumber(void) { 00262 // Read current frame number 00263 uint16_t lowByte; 00264 uint16_t highByte; 00265 00266 SIECommand(SIE_CMD_READ_FRAME_NUMBER); 00267 lowByte = SIEReadData(SIE_CMD_READ_FRAME_NUMBER); 00268 highByte = SIEReadData(SIE_CMD_READ_FRAME_NUMBER); 00269 00270 return (highByte << 8) | lowByte; 00271 } 00272 00273 static void SIEconfigureDevice(void) { 00274 // SIE Configure device command 00275 SIECommand(SIE_CMD_CONFIGURE_DEVICE); 00276 SIEWriteData(SIE_CONF_DEVICE); 00277 } 00278 00279 static void SIEunconfigureDevice(void) { 00280 // SIE Configure device command 00281 SIECommand(SIE_CMD_CONFIGURE_DEVICE); 00282 SIEWriteData(0); 00283 } 00284 00285 static void SIEconnect(void) { 00286 // Connect USB device 00287 uint8_t status; 00288 00289 status = SIEgetDeviceStatus(); 00290 // iprintf("USBHAL::SIEconnect status is %02X\n", status); 00291 SIEsetDeviceStatus(status | SIE_DS_CON); 00292 // iprintf("USBHAL::SIEconnect ok\n"); 00293 } 00294 00295 00296 static void SIEdisconnect(void) { 00297 // Disconnect USB device 00298 uint8_t status; 00299 00300 status = SIEgetDeviceStatus(); 00301 SIEsetDeviceStatus(status & ~SIE_DS_CON); 00302 } 00303 00304 00305 static uint8_t selectEndpointClearInterrupt(uint8_t bEP) { 00306 uint8_t endpoint = EP2IDX(bEP); 00307 00308 // Implemented using using EP_INT_CL 00309 LPC_USB->USBEpIntClr = EP(endpoint); 00310 setled(4, 1); while (!(LPC_USB->USBDevIntSt & CDFULL)); setled(4, 0); 00311 return (uint8_t)LPC_USB->USBCmdData; 00312 } 00313 00314 static void enableEndpointEvent(uint8_t bEP) { 00315 uint8_t endpoint = EP2IDX(bEP); 00316 00317 // Enable an endpoint interrupt 00318 LPC_USB->USBEpIntEn |= EP(endpoint); 00319 } 00320 00321 static void disableEndpointEvent(uint8_t bEP) __attribute__ ((unused)); 00322 static void disableEndpointEvent(uint8_t bEP) { 00323 uint8_t endpoint = EP2IDX(bEP); 00324 00325 // Disable an endpoint interrupt 00326 LPC_USB->USBEpIntEn &= ~EP(endpoint); 00327 } 00328 00329 static volatile uint32_t __attribute__((used)) dummyRead; 00330 00331 00332 uint32_t USBHAL::endpointReadcore(uint8_t bEP, uint8_t *buffer) 00333 { 00334 // Read from an OUT endpoint 00335 uint32_t size; 00336 uint32_t i; 00337 uint32_t data = 0; 00338 uint8_t offset; 00339 uint8_t endpoint = EP2IDX(bEP); 00340 00341 uint8_t irq = NVIC_GetActive(USB_IRQn); 00342 NVIC_DisableIRQ(USB_IRQn); 00343 00344 // iprintf("epReadCore 0x%02X = %d, 0x%02X\n", bEP, endpoint, LOG_ENDPOINT(endpoint)); 00345 00346 LPC_USB->USBCtrl = LOG_ENDPOINT(endpoint) | RD_EN; 00347 00348 // iprintf("0x%02lX\n", LPC_USB->USBCtrl); 00349 00350 setled(4, 1); while (!(LPC_USB->USBRxPLen & PKT_RDY)) 00351 { 00352 // iprintf("ep not ready, Waiting for data...\n"); 00353 } 00354 setled(4, 0); 00355 00356 // iprintf("0x%02lX 0x%02lX\n", LPC_USB->USBCtrl, LPC_USB->USBRxPLen); 00357 00358 size = LPC_USB->USBRxPLen & PKT_LNGTH_MASK; 00359 00360 if ((IS_ISOCHRONOUS(bEP) == 0) && (size > 64)) 00361 { 00362 // iprintf("BOGUS SIZE FOR EP 0x%02X! Got %ld, max is 64!\n", bEP, size); 00363 size = 64; 00364 } 00365 00366 // iprintf("Reading %ld bytes\n", size); 00367 00368 offset = 0; 00369 00370 if (size > 0) 00371 { 00372 for (i = 0; i < size; i++) 00373 { 00374 if (offset==0) 00375 { 00376 // Fetch up to four bytes of data as a word 00377 data = LPC_USB->USBRxData; 00378 } 00379 00380 // extract a byte 00381 *buffer = (data>>offset) & 0xff; 00382 buffer++; 00383 00384 // move on to the next byte 00385 offset = (offset + 8) & 24; 00386 } 00387 } else 00388 { 00389 dummyRead = LPC_USB->USBRxData; 00390 } 00391 00392 setled(4, 1); while ((LPC_USB->USBDevIntSt & RxENDPKT) == 0) 00393 dummyRead = LPC_USB->USBRxData; 00394 setled(4, 0); 00395 00396 // iprintf("Read %ld\n", size); 00397 00398 if (can_transfer[endpoint] != 0) 00399 can_transfer[endpoint]--; 00400 00401 LPC_USB->USBCtrl = 0; 00402 00403 if (IS_ISOCHRONOUS(bEP) == 0) 00404 { 00405 // iprintf("Buffer Clear 0x%02X\n", bEP); 00406 SIEselectEndpoint(bEP); 00407 if (SIEclearBuffer()) 00408 { 00409 // iprintf("EP%dIN OVERRUN\n", bEP & 0x0F); 00410 } 00411 } 00412 00413 if (irq) 00414 NVIC_EnableIRQ(USB_IRQn); 00415 00416 return size; 00417 } 00418 00419 static void endpointWritecore(uint8_t bEP, uint8_t *buffer, uint32_t size) 00420 { 00421 // Write to an IN endpoint 00422 // uint32_t temp, data; 00423 // uint8_t offset; 00424 uint8_t endpoint = EP2IDX(bEP); 00425 00426 LPC_USB->USBCtrl = LOG_ENDPOINT(endpoint) | WR_EN; 00427 00428 LPC_USB->USBTxPLen = size; 00429 // offset = 0; 00430 // data = 0; 00431 // iprintf("EP%d%s(%d) W:", (endpoint >> 1), ((endpoint & 1)?"IN":"OUT"), endpoint); 00432 while (LPC_USB->USBCtrl & WR_EN) 00433 { 00434 // iprintf("0x%02X 0x%02X 0x%02X 0x%02X ", buffer[0], buffer[1], buffer[2], buffer[3]); 00435 LPC_USB->USBTxData = (buffer[3] << 24) | (buffer[2] << 16) | (buffer[1] << 8) | buffer[0]; 00436 buffer += 4; 00437 } 00438 00439 // iprintf("!_(%ld)>", size); 00440 00441 // Clear WR_EN to cover zero length packet case 00442 LPC_USB->USBCtrl = 0; 00443 00444 SIEselectEndpoint(bEP); 00445 SIEvalidateBuffer(); 00446 00447 uint8_t status __attribute__ ((unused)) = SIEselectEndpoint(bEP); 00448 // iprintf("EP 0x%02X ST 0x%02X\n", bEP, status); 00449 } 00450 00451 00452 USBHAL::USBHAL(void) { 00453 instance = this; 00454 } 00455 00456 void USBHAL::init() { 00457 // Disable IRQ 00458 NVIC_DisableIRQ(USB_IRQn); 00459 00460 // Enable power to USB device controller 00461 LPC_SC->PCONP |= PCUSB; 00462 00463 // Enable USB clocks 00464 LPC_USB->USBClkCtrl |= DEV_CLK_EN | AHB_CLK_EN; 00465 setled(4, 1); while (LPC_USB->USBClkSt != (DEV_CLK_ON | AHB_CLK_ON)); setled(4, 0); 00466 00467 // Configure pins P0.29 and P0.30 to be USB D+ and USB D- 00468 LPC_PINCON->PINSEL1 &= 0xc3ffffff; 00469 LPC_PINCON->PINSEL1 |= 0x14000000; 00470 00471 // Configure pin P2.9 to be Connect 00472 LPC_PINCON->PINSEL4 &= 0xfffcffff; 00473 LPC_PINCON->PINSEL4 |= 0x00040000; 00474 00475 // Disconnect USB device 00476 SIEdisconnect(); 00477 00478 // work around OSX behaviour where if the device disconnects and quickly reconnects, it assumes it's the same device instead of checking 00479 wait_ms(1000); 00480 00481 // Connect must be low for at least 2.5uS 00482 // wait(0.3); 00483 00484 // Set the maximum packet size for the control endpoints 00485 realiseEndpoint(IDX2EP(EP0IN), MAX_PACKET_SIZE_EP0, 0); 00486 realiseEndpoint(IDX2EP(EP0OUT), MAX_PACKET_SIZE_EP0, 0); 00487 00488 // Attach IRQ 00489 // instance = this; 00490 // NVIC_SetVector(USB_IRQn, (uint32_t)&_usbisr); 00491 // NVIC_EnableIRQ(USB_IRQn); 00492 00493 USBEpIntEn = 0x3; 00494 00495 // Enable interrupts for device events and EP0 00496 // LPC_USB->USBDevIntEn = EP_SLOW | DEV_STAT | FRAME; 00497 LPC_USB->USBDevIntEn = EP_SLOW | DEV_STAT; 00498 // enableEndpointEvent(EP0IN); 00499 // enableEndpointEvent(EP0OUT); 00500 } 00501 00502 USBHAL::~USBHAL(void) { 00503 // Ensure device disconnected 00504 SIEdisconnect(); 00505 00506 // Disable USB interrupts 00507 NVIC_DisableIRQ(USB_IRQn); 00508 } 00509 00510 uint32_t USBHAL::getSerialNumber(int length, uint32_t *buf) { 00511 #define IAP_LOCATION 0x1FFF1FF1 00512 uint32_t command[1]; 00513 uint32_t result[5]; 00514 typedef void (*IAP)(uint32_t*, uint32_t*); 00515 IAP iap = (IAP) IAP_LOCATION; 00516 00517 __disable_irq(); 00518 00519 command[0] = 58; 00520 // iprintf("Getting Serial...\n"); 00521 iap(command, result); 00522 // iprintf("HW Serial Number: %08lX %08lX %08lX %08lX\n", result[1], result[2], result[3], result[4]); 00523 int i; 00524 for (i = 0; i < 4; i++) { 00525 if (i < length) { 00526 buf[i] = result[i + 1]; 00527 } 00528 } 00529 00530 __enable_irq(); 00531 00532 return i; 00533 } 00534 00535 void USBHAL::connect(void) { 00536 // Connect USB device 00537 // iprintf("USBHAL::connect\n"); 00538 // NVIC_EnableIRQ(USB_IRQn); 00539 SIEconnect(); 00540 // iprintf("USBHAL::connect OK\n"); 00541 } 00542 00543 void USBHAL::disconnect(void) { 00544 // Disconnect USB device 00545 SIEdisconnect(); 00546 } 00547 00548 void USBHAL::configureDevice(void) { 00549 SIEconfigureDevice(); 00550 } 00551 00552 void USBHAL::unconfigureDevice(void) { 00553 SIEunconfigureDevice(); 00554 } 00555 00556 void USBHAL::setAddress(uint8_t address) { 00557 SIEsetAddress(address); 00558 // SIEsetMode(SIE_MODE_INAK_CI | SIE_MODE_INAK_CO | SIE_MODE_INAK_BI | SIE_MODE_INAK_BO); 00559 SIEsetMode(SIE_MODE_INAK_CI | SIE_MODE_INAK_CO); 00560 } 00561 00562 void USBHAL::EP0setup(uint8_t *buffer) { 00563 endpointReadcore(IDX2EP(EP0OUT), buffer); 00564 } 00565 00566 void USBHAL::EP0read(void) { 00567 // Not required 00568 } 00569 00570 uint32_t USBHAL::EP0getReadResult(uint8_t *buffer) { 00571 return endpointReadcore(IDX2EP(EP0OUT), buffer); 00572 } 00573 00574 void USBHAL::EP0write(uint8_t *buffer, uint32_t size) { 00575 endpointWritecore(IDX2EP(EP0IN), buffer, size); 00576 } 00577 00578 void USBHAL::EP0getWriteResult(void) { 00579 // Not required 00580 } 00581 00582 void USBHAL::EP0stall(void) { 00583 // This will stall both control endpoints 00584 stallEndpoint(IDX2EP(EP0OUT)); 00585 } 00586 00587 EP_STATUS USBHAL::endpointRead(uint8_t bEP, uint32_t maximumSize) { 00588 return EP_PENDING; 00589 } 00590 00591 EP_STATUS USBHAL::endpointReadResult(uint8_t bEP, uint8_t * buffer, uint32_t *bytesRead) 00592 { 00593 uint8_t endpoint = EP2IDX(bEP); 00594 00595 // iprintf("epReadResult 0x%02X = %d\n", bEP, endpoint); 00596 00597 //for isochronous endpoint, we don't wait an interrupt 00598 if (IS_ISOCHRONOUS(bEP) == 0) { 00599 // iprintf("not Isochronous\n"); 00600 // if (!(epComplete & EP(endpoint))) 00601 if (can_transfer[endpoint] == 0) 00602 { 00603 // iprintf("Pending\n"); 00604 return EP_PENDING; 00605 } 00606 } 00607 00608 // iprintf("reading...\n"); 00609 00610 __disable_irq(); 00611 __ISB(); 00612 00613 if (can_transfer[endpoint]) 00614 { 00615 can_transfer[endpoint]--; 00616 __enable_irq(); 00617 *bytesRead = endpointReadcore(bEP, buffer); 00618 } 00619 else { 00620 __enable_irq(); 00621 *bytesRead = 0; 00622 } 00623 // epComplete &= ~EP(endpoint); 00624 00625 // iprintf("OK\n"); 00626 00627 return EP_COMPLETED; 00628 } 00629 00630 EP_STATUS USBHAL::endpointWrite(uint8_t bEP, uint8_t *data, uint32_t size) 00631 { 00632 uint8_t endpoint = EP2IDX(bEP); 00633 00634 if (getEndpointStallState(bEP)) { 00635 return EP_STALLED; 00636 } 00637 00638 do { 00639 __disable_irq(); 00640 __ISB(); 00641 00642 if (can_transfer[endpoint]) 00643 { 00644 can_transfer[endpoint]--; 00645 __enable_irq(); 00646 endpointWritecore(bEP, data, size); 00647 return EP_PENDING; 00648 } 00649 __enable_irq(); 00650 endpointSetInterrupt(bEP, true); 00651 } while (1); 00652 } 00653 00654 EP_STATUS USBHAL::endpointWriteResult(uint8_t bEP) 00655 { 00656 uint8_t endpoint = EP2IDX(bEP); 00657 00658 // if (epComplete & EP(endpoint)) { 00659 if (can_transfer[endpoint] < 2) { 00660 // epComplete &= ~EP(endpoint); 00661 return EP_COMPLETED; 00662 } 00663 00664 return EP_PENDING; 00665 } 00666 00667 uint8_t USBHAL::endpointStatus(uint8_t bEP) 00668 { 00669 uint8_t bEPStat = SIEselectEndpoint(EP2IDX(bEP)); 00670 00671 uint8_t bStat __attribute__ ((unused)) 00672 = ((bEPStat & EPSTAT_FE ) ? EP_STATUS_DATA : 0) | 00673 ((bEPStat & EPSTAT_ST ) ? EP_STATUS_STALLED : 0) | 00674 ((bEPStat & EPSTAT_STP) ? EP_STATUS_SETUP : 0) | 00675 ((bEPStat & EPSTAT_EPN) ? EP_STATUS_NACKED : 0) | 00676 ((bEPStat & EPSTAT_PO ) ? EP_STATUS_ERROR : 0); 00677 00678 return bEPStat; 00679 } 00680 00681 bool USBHAL::realiseEndpoint(uint8_t bEP, uint32_t maxPacket, uint32_t flags) 00682 { 00683 uint8_t endpoint = EP2IDX(bEP); 00684 00685 // Realise an endpoint 00686 LPC_USB->USBDevIntClr = EP_RLZED; 00687 LPC_USB->USBReEp |= EP(endpoint); 00688 LPC_USB->USBEpInd = endpoint; 00689 LPC_USB->USBMaxPSize = maxPacket; 00690 00691 setled(4, 1); while (!(LPC_USB->USBDevIntSt & EP_RLZED)); setled(4, 0); 00692 LPC_USB->USBDevIntClr = EP_RLZED; 00693 00694 // Clear stall state 00695 // endpointStallState &= ~EP(endpoint); 00696 unstallEndpoint(bEP); 00697 00698 enableEndpointEvent(bEP); 00699 00700 /* 00701 * if this is an OUT endpoint, enable interrupts so we can receive any 00702 * data the host sends to us. 00703 * 00704 * if this is an IN endpoint, don't enable interrupts just yet, but have 00705 * an event waiting so we can immediately interrupt later on when the 00706 * user app calls endpointSetInterrupt(bEP, true) 00707 */ 00708 00709 if (IN_BEP(bEP)) 00710 { 00711 // epComplete |= EP(endpoint); 00712 can_transfer[endpoint] = 2; 00713 } 00714 else 00715 { 00716 can_transfer[endpoint] = 0; 00717 endpointSetInterrupt(bEP, true); 00718 } 00719 00720 // iprintf("EP 0x%02X realised @%ld!\n", bEP, maxPacket); 00721 return true; 00722 } 00723 00724 void USBHAL::stallEndpoint(uint8_t bEP) 00725 { 00726 uint8_t endpoint = EP2IDX(bEP); 00727 00728 // Stall an endpoint 00729 if ( (endpoint==EP0IN) || (endpoint==EP0OUT) ) { 00730 // Conditionally stall both control endpoints 00731 SIEsetEndpointStatus(IDX2EP(EP0OUT), SIE_SES_CND_ST); 00732 } else { 00733 SIEsetEndpointStatus(bEP, SIE_SES_ST); 00734 00735 // Update stall state 00736 endpointStallState |= EP(endpoint); 00737 } 00738 } 00739 00740 void USBHAL::unstallEndpoint(uint8_t bEP) 00741 { 00742 uint8_t endpoint = EP2IDX(bEP); 00743 00744 // Unstall an endpoint. The endpoint will also be reinitialised 00745 SIEsetEndpointStatus(bEP, 0); 00746 00747 // Update stall state 00748 endpointStallState &= ~EP(endpoint); 00749 } 00750 00751 bool USBHAL::getEndpointStallState(uint8_t bEP) 00752 { 00753 // Returns true if endpoint stalled 00754 return endpointStallState & EP(EP2IDX(bEP)); 00755 } 00756 00757 void USBHAL::remoteWakeup(void) 00758 { 00759 // Remote wakeup 00760 uint8_t status; 00761 00762 // Enable USB clocks 00763 LPC_USB->USBClkCtrl |= DEV_CLK_EN | AHB_CLK_EN; 00764 setled(4, 1); while (LPC_USB->USBClkSt != (DEV_CLK_ON | AHB_CLK_ON)); setled(4, 0); 00765 00766 status = SIEgetDeviceStatus(); 00767 SIEsetDeviceStatus(status & ~SIE_DS_SUS); 00768 } 00769 00770 uint16_t USBHAL::lastFrame(void) 00771 { 00772 return SIEgetFrameNumber(); 00773 } 00774 00775 extern "C" { 00776 __attribute__ ((interrupt)) void USB_IRQHandler() { 00777 // iprintf("!0x%08lX/0x%08lX:", LPC_USB->USBDevIntSt, LPC_USB->USBDevIntEn); 00778 ENTER_ISR(); 00779 USBHAL::_usbisr(); 00780 LEAVE_ISR(); 00781 } 00782 } 00783 00784 void USBHAL::_usbisr(void) { 00785 instance->usbisr(); 00786 } 00787 00788 bool USBHAL::endpointSetInterrupt(uint8_t bEP, bool enabled) 00789 { 00790 uint8_t endpoint = EP2IDX(bEP); 00791 00792 bool r = USBEpIntEn | EP(endpoint); 00793 00794 if (enabled) 00795 { 00796 __disable_irq(); 00797 USBEpIntEn |= EP(endpoint); 00798 if (can_transfer[endpoint]) 00799 endpointTriggerInterrupt(bEP); 00800 // LPC_USB->USBEpIntSet = EP(endpoint); 00801 __enable_irq(); 00802 } 00803 else 00804 { 00805 USBEpIntEn &= ~EP(endpoint); 00806 } 00807 00808 return r; 00809 } 00810 00811 bool USBHAL::endpointGetInterrupt(uint8_t bEP) 00812 { 00813 uint8_t endpoint = EP2IDX(bEP); 00814 00815 return USBEpIntEn | EP(endpoint); 00816 } 00817 00818 void USBHAL::endpointTriggerInterrupt(uint8_t bEP) 00819 { 00820 uint8_t endpoint = EP2IDX(bEP); 00821 00822 LPC_USB->USBEpIntSet = EP(endpoint); 00823 } 00824 00825 void USBHAL::usbisr(void) 00826 { 00827 uint8_t devStat; 00828 00829 if (LPC_USB->USBDevIntSt & FRAME) 00830 { 00831 // iprintf("F"); 00832 // Start of frame event 00833 // SOF(SIEgetFrameNumber()); 00834 USBEvent_Frame(SIEgetFrameNumber()); 00835 // Clear interrupt status flag 00836 LPC_USB->USBDevIntClr = FRAME; 00837 00838 // static uint8_t lst; 00839 // uint8_t st = SIEselectEndpoint(0x80); 00840 // if (st != lst) 00841 // { 00842 // iprintf("EP1S:%02X\n", st); 00843 // lst = st; 00844 // } 00845 } 00846 00847 if (LPC_USB->USBDevIntSt & DEV_STAT) 00848 { 00849 iprintf("D"); 00850 // Device Status interrupt 00851 // Must clear the interrupt status flag before reading the device status from the SIE 00852 LPC_USB->USBDevIntClr = DEV_STAT; 00853 00854 // Read device status from SIE 00855 devStat = SIEgetDeviceStatus(); 00856 //printf("devStat: %d\r\n", devStat); 00857 00858 if (devStat & SIE_DS_SUS_CH) 00859 { 00860 // Suspend status changed 00861 // if((devStat & SIE_DS_SUS) != 0) { 00862 // USBEvent_suspendStateChanged(false); 00863 // } 00864 USBEvent_suspendStateChanged(devStat & SIE_DS_SUS); 00865 } 00866 00867 if (devStat & SIE_DS_RST) 00868 { 00869 // Bus reset 00870 // if((devStat & SIE_DS_SUS) == 0) { 00871 // USBEvent_suspendStateChanged(true); 00872 // } 00873 USBEvent_busReset(); 00874 00875 realiseEndpoint(IDX2EP(EP0IN), MAX_PACKET_SIZE_EP0, 0); 00876 realiseEndpoint(IDX2EP(EP0OUT), MAX_PACKET_SIZE_EP0, 0); 00877 00878 SIEsetMode(SIE_MODE_INAK_CI | SIE_MODE_INAK_CO | SIE_MODE_INAK_BI | SIE_MODE_INAK_BO); 00879 } 00880 00881 if (devStat & SIE_DS_CON_CH) 00882 { 00883 USBEvent_connectStateChanged(devStat & SIE_DS_CON); 00884 } 00885 } 00886 00887 if (LPC_USB->USBDevIntSt & EP_SLOW) 00888 { 00889 // (Slow) Endpoint Interrupt 00890 00891 // Process each endpoint interrupt 00892 if (LPC_USB->USBEpIntSt & EP(EP0OUT)) 00893 { 00894 uint8_t bEPStat = selectEndpointClearInterrupt(IDX2EP(EP0OUT)); 00895 if (bEPStat & SIE_SE_STP) 00896 { 00897 // this is a setup packet 00898 EP0setupCallback(); 00899 } 00900 else if (bEPStat & EPSTAT_FE) // OUT endpoint, FE = 1 - data in buffer 00901 { 00902 EP0out(); 00903 } 00904 } 00905 if (LPC_USB->USBEpIntSt & EP(EP0IN)) 00906 { 00907 uint8_t bEPStat = selectEndpointClearInterrupt(IDX2EP(EP0IN)); 00908 if ((bEPStat & EPSTAT_FE) == 0) // IN endpoint, FE = 0 - empty space in buffer 00909 EP0in(); 00910 } 00911 00912 if (USBEpIntEn & ~(3UL)) 00913 { 00914 int i; 00915 uint32_t bitmask; 00916 00917 for (i = 2, bitmask = 4; i < 32; i++, bitmask <<= 1) 00918 { 00919 uint8_t bEPStat = 255; 00920 uint8_t ep = IDX2EP(i); 00921 if (LPC_USB->USBEpIntSt & bitmask) 00922 { 00923 bEPStat = selectEndpointClearInterrupt(ep); 00924 if (can_transfer[i] < 2) 00925 can_transfer[i]++; 00926 } 00927 00928 if ((USBEpIntEn & bitmask) && (can_transfer[i])) 00929 { 00930 if (bEPStat == 255) 00931 bEPStat = SIEselectEndpoint(ep); 00932 00933 iprintf("!02X", ep); 00934 00935 uint8_t bStat = ((bEPStat & EPSTAT_FE ) ? EP_STATUS_DATA : 0) | 00936 ((bEPStat & EPSTAT_ST ) ? EP_STATUS_STALLED : 0) | 00937 ((bEPStat & EPSTAT_STP) ? EP_STATUS_SETUP : 0) | 00938 ((bEPStat & EPSTAT_EPN) ? EP_STATUS_NACKED : 0) | 00939 ((bEPStat & EPSTAT_PO ) ? EP_STATUS_ERROR : 0); 00940 00941 bool r = true; 00942 00943 if (IN_EP(i)) 00944 { 00945 // iprintf("IN[%02X]:", IDX2EP(i)); 00946 if ((bEPStat & EPSTAT_FE) == 0) // IN endpoint, FE = 0 - empty space in buffer 00947 r = USBEvent_EPIn(ep, bStat); 00948 } 00949 else 00950 { 00951 // iprintf("OUT[%02X]:", IDX2EP(i)); 00952 if (bEPStat & EPSTAT_FE) // OUT endpoint, FE = 1 - data in buffer 00953 r = USBEvent_EPOut(ep, bStat); 00954 } 00955 00956 if (!r) 00957 { 00958 USBEpIntEn &= ~bitmask; 00959 } 00960 // iprintf("\n"); 00961 } 00962 } 00963 iprintf("\n"); 00964 } 00965 00966 LPC_USB->USBDevIntClr = EP_SLOW; 00967 } 00968 } 00969 00970 #endif
Generated on Tue Jul 12 2022 20:09:03 by 1.7.2