Fork of Smoothie to port to mbed non-LPC targets.

Dependencies:   mbed

Fork of Smoothie by Stéphane Cachat

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers USBHAL_LPC17.cpp Source File

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