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 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
