4180 final project
Fork of USBDevice by
Revision 8:335f2506f422, committed 2013-03-01
- Comitter:
- samux
- Date:
- Fri Mar 01 13:10:29 2013 +0000
- Parent:
- 7:f8f057664123
- Child:
- 9:354942d2fa38
- Child:
- 60:d29ac157bf32
- Commit message:
- add FRDM-KL25Z support
Changed in this revision
--- a/USBDevice/USBDevice.cpp Mon Jan 21 10:41:28 2013 +0000 +++ b/USBDevice/USBDevice.cpp Fri Mar 01 13:10:29 2013 +0000 @@ -250,6 +250,7 @@ } EP0read(); + EP0readStage(); /* Completed */ return true;
--- a/USBDevice/USBEndpoints.h Mon Jan 21 10:41:28 2013 +0000 +++ b/USBDevice/USBEndpoints.h Fri Mar 01 13:10:29 2013 +0000 @@ -41,6 +41,8 @@ #include "USBEndpoints_LPC17_LPC23.h" #elif defined(TARGET_LPC11U24) #include "USBEndpoints_LPC11U.h" +#elif defined(TARGET_KL25Z) +#include "USBEndpoints_KL25Z.h" #else #error "Unknown target type" #endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBDevice/USBEndpoints_KL25Z.h Fri Mar 01 13:10:29 2013 +0000 @@ -0,0 +1,93 @@ +/* Copyright (c) 2010-2011 mbed.org, MIT License +* +* Permission is hereby granted, free of charge, to any person obtaining a copy of this software +* and associated documentation files (the "Software"), to deal in the Software without +* restriction, including without limitation the rights to use, copy, modify, merge, publish, +* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in all copies or +* substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#define NUMBER_OF_LOGICAL_ENDPOINTS (16) +#define NUMBER_OF_PHYSICAL_ENDPOINTS (NUMBER_OF_LOGICAL_ENDPOINTS * 2) + +/* Define physical endpoint numbers */ + +/* Endpoint No. */ +/* ---------------- */ +#define EP0OUT (0) +#define EP0IN (1) +#define EP1OUT (2) +#define EP1IN (3) +#define EP2OUT (4) +#define EP2IN (5) +#define EP3OUT (6) +#define EP3IN (7) +#define EP4OUT (8) +#define EP4IN (9) +#define EP5OUT (10) +#define EP5IN (11) +#define EP6OUT (12) +#define EP6IN (13) +#define EP7OUT (14) +#define EP7IN (15) +#define EP8OUT (16) +#define EP8IN (17) +#define EP9OUT (18) +#define EP9IN (19) +#define EP10OUT (20) +#define EP10IN (21) +#define EP11OUT (22) +#define EP11IN (23) +#define EP12OUT (24) +#define EP12IN (25) +#define EP13OUT (26) +#define EP13IN (27) +#define EP14OUT (28) +#define EP14IN (29) +#define EP15OUT (30) +#define EP15IN (31) + +/* Maximum Packet sizes */ + +#define MAX_PACKET_SIZE_EP0 (64) +#define MAX_PACKET_SIZE_EP1 (64) +#define MAX_PACKET_SIZE_EP2 (64) +#define MAX_PACKET_SIZE_EP3 (1023) +#define MAX_PACKET_SIZE_EP4 (64) +#define MAX_PACKET_SIZE_EP5 (64) +#define MAX_PACKET_SIZE_EP6 (64) +#define MAX_PACKET_SIZE_EP7 (64) +#define MAX_PACKET_SIZE_EP8 (64) +#define MAX_PACKET_SIZE_EP9 (64) +#define MAX_PACKET_SIZE_EP10 (64) +#define MAX_PACKET_SIZE_EP11 (64) +#define MAX_PACKET_SIZE_EP12 (64) +#define MAX_PACKET_SIZE_EP13 (64) +#define MAX_PACKET_SIZE_EP14 (64) +#define MAX_PACKET_SIZE_EP15 (64) + +/* Generic endpoints - intended to be portable accross devices */ +/* and be suitable for simple USB devices. */ + +/* Bulk endpoints */ +#define EPBULK_OUT (EP2OUT) +#define EPBULK_IN (EP2IN) +/* Interrupt endpoints */ +#define EPINT_OUT (EP1OUT) +#define EPINT_IN (EP1IN) +/* Isochronous endpoints */ +#define EPISO_OUT (EP3OUT) +#define EPISO_IN (EP3IN) + +#define MAX_PACKET_SIZE_EPBULK (MAX_PACKET_SIZE_EP2) +#define MAX_PACKET_SIZE_EPINT (MAX_PACKET_SIZE_EP1) +#define MAX_PACKET_SIZE_EPISO (MAX_PACKET_SIZE_EP3)
--- a/USBDevice/USBHAL.h Mon Jan 21 10:41:28 2013 +0000 +++ b/USBDevice/USBHAL.h Fri Mar 01 13:10:29 2013 +0000 @@ -37,6 +37,7 @@ /* Endpoint 0 */ void EP0setup(uint8_t *buffer); void EP0read(void); + void EP0readStage(void); uint32_t EP0getReadResult(uint8_t *buffer); void EP0write(uint8_t *buffer, uint32_t size); void EP0getWriteResult(void); @@ -61,17 +62,52 @@ virtual void connectStateChanged(unsigned int connected){}; virtual void suspendStateChanged(unsigned int suspended){}; virtual void SOF(int frameNumber){}; + virtual bool EP1_OUT_callback(){return false;}; virtual bool EP1_IN_callback(){return false;}; virtual bool EP2_OUT_callback(){return false;}; virtual bool EP2_IN_callback(){return false;}; virtual bool EP3_OUT_callback(){return false;}; virtual bool EP3_IN_callback(){return false;}; + virtual bool EP4_OUT_callback(){return false;}; + virtual bool EP4_IN_callback(){return false;}; + +#if !defined(TARGET_LPC11U24) + virtual bool EP5_OUT_callback(){return false;}; + virtual bool EP5_IN_callback(){return false;}; + virtual bool EP6_OUT_callback(){return false;}; + virtual bool EP6_IN_callback(){return false;}; + virtual bool EP7_OUT_callback(){return false;}; + virtual bool EP7_IN_callback(){return false;}; + virtual bool EP8_OUT_callback(){return false;}; + virtual bool EP8_IN_callback(){return false;}; + virtual bool EP9_OUT_callback(){return false;}; + virtual bool EP9_IN_callback(){return false;}; + virtual bool EP10_OUT_callback(){return false;}; + virtual bool EP10_IN_callback(){return false;}; + virtual bool EP11_OUT_callback(){return false;}; + virtual bool EP11_IN_callback(){return false;}; + virtual bool EP12_OUT_callback(){return false;}; + virtual bool EP12_IN_callback(){return false;}; + virtual bool EP13_OUT_callback(){return false;}; + virtual bool EP13_IN_callback(){return false;}; + virtual bool EP14_OUT_callback(){return false;}; + virtual bool EP14_IN_callback(){return false;}; + virtual bool EP15_OUT_callback(){return false;}; + virtual bool EP15_IN_callback(){return false;}; +#endif private: void usbisr(void); static void _usbisr(void); static USBHAL * instance; + +#if defined(TARGET_LPC11U24) + bool (USBHAL::*epCallback[10 - 2])(void); +#else + bool (USBHAL::*epCallback[32 - 2])(void); +#endif + + }; #endif -
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBDevice/USBHAL_KL25Z.cpp Fri Mar 01 13:10:29 2013 +0000 @@ -0,0 +1,514 @@ +/* Copyright (c) 2010-2011 mbed.org, MIT License +* +* Permission is hereby granted, free of charge, to any person obtaining a copy of this software +* and associated documentation files (the "Software"), to deal in the Software without +* restriction, including without limitation the rights to use, copy, modify, merge, publish, +* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in all copies or +* substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#if defined(TARGET_KL25Z) + +#include "USBHAL.h" + +USBHAL * USBHAL::instance; + +static volatile int epComplete = 0; + +// Convert physical endpoint number to register bit +#define EP(endpoint) (1<<(endpoint)) + +// Convert physical to logical +#define PHY_TO_LOG(endpoint) ((endpoint)>>1) + +// Get endpoint direction +#define IN_EP(endpoint) ((endpoint) & 1U ? true : false) +#define OUT_EP(endpoint) ((endpoint) & 1U ? false : true) + +#define BD_OWN_MASK (1<<7) +#define BD_DATA01_MASK (1<<6) +#define BD_KEEP_MASK (1<<5) +#define BD_NINC_MASK (1<<4) +#define BD_DTS_MASK (1<<3) +#define BD_STALL_MASK (1<<2) + +#define TX 1 +#define RX 0 +#define ODD 0 +#define EVEN 1 +// this macro waits a physical endpoint number +#define EP_BDT_IDX(ep, dir, odd) (((ep * 4) + (2 * dir) + (1 * odd))) + +#define SETUP_TOKEN 0x0D +#define IN_TOKEN 0x09 +#define OUT_TOKEN 0x01 +#define TOK_PID(idx) ((bdt[idx].info >> 2) & 0x0F) + +// for each endpt: 8 bytes +typedef struct BDT { + uint8_t info; // BD[0:7] + uint8_t dummy; // RSVD: BD[8:15] + uint16_t byte_count; // BD[16:32] + uint32_t address; // Addr +} BDT; + + +// there are: +// * 16 bidirectionnal endpt -> 32 physical endpt +// * as there are ODD and EVEN buffer -> 32*2 bdt +__attribute__((__aligned__(512))) BDT bdt[NUMBER_OF_PHYSICAL_ENDPOINTS * 2]; +uint8_t endpoint_buffer[(NUMBER_OF_PHYSICAL_ENDPOINTS - 2) * 2][64]; +uint8_t endpoint_buffer_iso[2*2][1023]; + +static uint8_t set_addr = 0; +static uint8_t addr = 0; + +static uint32_t Data1 = 0x55555555; + +static uint32_t frameNumber() { + return((USB0->FRMNUML | (USB0->FRMNUMH << 8) & 0x07FF)); +} + +uint32_t USBHAL::endpointReadcore(uint8_t endpoint, uint8_t *buffer) { + return 0; +} + +USBHAL::USBHAL(void) { + // Disable IRQ + NVIC_DisableIRQ(USB0_IRQn); + + // fill in callback array + epCallback[0] = &USBHAL::EP1_OUT_callback; + epCallback[1] = &USBHAL::EP1_IN_callback; + epCallback[2] = &USBHAL::EP2_OUT_callback; + epCallback[3] = &USBHAL::EP2_IN_callback; + epCallback[4] = &USBHAL::EP3_OUT_callback; + epCallback[5] = &USBHAL::EP3_IN_callback; + epCallback[6] = &USBHAL::EP4_OUT_callback; + epCallback[7] = &USBHAL::EP4_IN_callback; + epCallback[8] = &USBHAL::EP5_OUT_callback; + epCallback[9] = &USBHAL::EP5_IN_callback; + epCallback[10] = &USBHAL::EP6_OUT_callback; + epCallback[11] = &USBHAL::EP6_IN_callback; + epCallback[12] = &USBHAL::EP7_OUT_callback; + epCallback[13] = &USBHAL::EP7_IN_callback; + epCallback[14] = &USBHAL::EP8_OUT_callback; + epCallback[15] = &USBHAL::EP8_IN_callback; + epCallback[16] = &USBHAL::EP9_OUT_callback; + epCallback[17] = &USBHAL::EP9_IN_callback; + epCallback[18] = &USBHAL::EP10_OUT_callback; + epCallback[19] = &USBHAL::EP10_IN_callback; + epCallback[20] = &USBHAL::EP11_OUT_callback; + epCallback[21] = &USBHAL::EP11_IN_callback; + epCallback[22] = &USBHAL::EP12_OUT_callback; + epCallback[23] = &USBHAL::EP12_IN_callback; + epCallback[24] = &USBHAL::EP13_OUT_callback; + epCallback[25] = &USBHAL::EP13_IN_callback; + epCallback[26] = &USBHAL::EP14_OUT_callback; + epCallback[27] = &USBHAL::EP14_IN_callback; + epCallback[28] = &USBHAL::EP15_OUT_callback; + epCallback[29] = &USBHAL::EP15_IN_callback; + + + // choose usb src as PLL + SIM->SOPT2 |= (SIM_SOPT2_USBSRC_MASK | SIM_SOPT2_PLLFLLSEL_MASK); + + // enable OTG clock + SIM->SCGC4 |= SIM_SCGC4_USBOTG_MASK; + + // Attach IRQ + instance = this; + NVIC_SetVector(USB0_IRQn, (uint32_t)&_usbisr); + NVIC_EnableIRQ(USB0_IRQn); + + // USB Module Configuration + // Reset USB Module + USB0->USBTRC0 |= USB_USBTRC0_USBRESET_MASK; + while(USB0->USBTRC0 & USB_USBTRC0_USBRESET_MASK); + + // Set BDT Base Register + USB0->BDTPAGE1=(uint8_t)((uint32_t)bdt>>8); + USB0->BDTPAGE2=(uint8_t)((uint32_t)bdt>>16); + USB0->BDTPAGE3=(uint8_t)((uint32_t)bdt>>24); + + // Clear interrupt flag + USB0->ISTAT = 0xff; + + // USB Interrupt Enablers + USB0->INTEN |= USB_INTEN_TOKDNEEN_MASK | + USB_INTEN_SOFTOKEN_MASK | + USB_INTEN_ERROREN_MASK | + USB_INTEN_USBRSTEN_MASK; + + // Disable weak pull downs + USB0->USBCTRL &= ~(USB_USBCTRL_PDE_MASK | USB_USBCTRL_SUSP_MASK); + + USB0->USBTRC0 |= 0x40; +} + +USBHAL::~USBHAL(void) { } + +void USBHAL::connect(void) { + // enable USB + USB0->CTL |= USB_CTL_USBENSOFEN_MASK; + // Pull up enable + USB0->CONTROL |= USB_CONTROL_DPPULLUPNONOTG_MASK; +} + +void USBHAL::disconnect(void) { + // disable USB + USB0->CTL &= ~USB_CTL_USBENSOFEN_MASK; + // Pull up disable + USB0->CONTROL &= ~USB_CONTROL_DPPULLUPNONOTG_MASK; +} + +void USBHAL::configureDevice(void) { + // not needed +} + +void USBHAL::unconfigureDevice(void) { + // not needed +} + +void USBHAL::setAddress(uint8_t address) { + // we don't set the address now otherwise the usb controller does not ack + // we set a flag instead + // see usbisr when an IN token is received + set_addr = 1; + addr = address; +} + +bool USBHAL::realiseEndpoint(uint8_t endpoint, uint32_t maxPacket, uint32_t flags) { + uint32_t handshake_flag = 0; + uint8_t * buf; + + if (endpoint > NUMBER_OF_PHYSICAL_ENDPOINTS - 1) { + return false; + } + + uint32_t log_endpoint = PHY_TO_LOG(endpoint); + + if ((flags & ISOCHRONOUS) == 0) { + handshake_flag = USB_ENDPT_EPHSHK_MASK; + if (IN_EP(endpoint)) + buf = &endpoint_buffer[EP_BDT_IDX(log_endpoint, TX, ODD )][0]; + else + buf = &endpoint_buffer[EP_BDT_IDX(log_endpoint, RX, ODD )][0]; + } else { + if (IN_EP(endpoint)) + buf = &endpoint_buffer_iso[2][0]; + else + buf = &endpoint_buffer_iso[0][0]; + } + + // IN endpt -> device to host (TX) + if (IN_EP(endpoint)) { + USB0->ENDPOINT[log_endpoint].ENDPT |= handshake_flag | // ep handshaking (not if iso endpoint) + USB_ENDPT_EPTXEN_MASK; // en TX (IN) tran + bdt[EP_BDT_IDX(log_endpoint, TX, ODD )].address = (uint32_t) buf; + bdt[EP_BDT_IDX(log_endpoint, TX, EVEN)].address = 0; + } + // OUT endpt -> host to device (RX) + else { + USB0->ENDPOINT[log_endpoint].ENDPT |= handshake_flag | // ep handshaking (not if iso endpoint) + USB_ENDPT_EPRXEN_MASK; // en RX (OUT) tran. + bdt[EP_BDT_IDX(log_endpoint, RX, ODD )].byte_count = maxPacket; + bdt[EP_BDT_IDX(log_endpoint, RX, ODD )].address = (uint32_t) buf; + bdt[EP_BDT_IDX(log_endpoint, RX, ODD )].info = BD_OWN_MASK | BD_DTS_MASK; + bdt[EP_BDT_IDX(log_endpoint, RX, EVEN)].info = 0; + } + + Data1 |= (1 << endpoint); + + return true; +} + +// read setup packet +void USBHAL::EP0setup(uint8_t *buffer) { + uint32_t sz; + endpointReadResult(EP0OUT, buffer, &sz); +} + +void USBHAL::EP0readStage(void) { + Data1 &= ~1UL; // set DATA0 + bdt[0].info = (BD_DTS_MASK | BD_OWN_MASK); +} + +void USBHAL::EP0read(void) { + uint32_t idx = EP_BDT_IDX(PHY_TO_LOG(EP0OUT), RX, 0); + bdt[idx].byte_count = MAX_PACKET_SIZE_EP0; +} + +uint32_t USBHAL::EP0getReadResult(uint8_t *buffer) { + uint32_t sz; + endpointReadResult(EP0OUT, buffer, &sz); + return sz; +} + +void USBHAL::EP0write(uint8_t *buffer, uint32_t size) { + endpointWrite(EP0IN, buffer, size); +} + +void USBHAL::EP0getWriteResult(void) { +} + +void USBHAL::EP0stall(void) { + stallEndpoint(EP0OUT); +} + +EP_STATUS USBHAL::endpointRead(uint8_t endpoint, uint32_t maximumSize) { + endpoint = PHY_TO_LOG(endpoint); + uint32_t idx = EP_BDT_IDX(endpoint, RX, 0); + bdt[idx].byte_count = maximumSize; + return EP_PENDING; +} + +EP_STATUS USBHAL::endpointReadResult(uint8_t endpoint, uint8_t * buffer, uint32_t *bytesRead) { + uint32_t n, sz, idx, setup = 0; + uint8_t not_iso; + uint8_t * ep_buf; + + uint32_t log_endpoint = PHY_TO_LOG(endpoint); + + if (endpoint > NUMBER_OF_PHYSICAL_ENDPOINTS - 1) { + return EP_INVALID; + } + + // if read on a IN endpoint -> error + if (IN_EP(endpoint)) { + return EP_INVALID; + } + + idx = EP_BDT_IDX(log_endpoint, RX, 0); + sz = bdt[idx].byte_count; + not_iso = USB0->ENDPOINT[log_endpoint].ENDPT & USB_ENDPT_EPHSHK_MASK; + + //for isochronous endpoint, we don't wait an interrupt + if ((log_endpoint != 0) && not_iso && !(epComplete & EP(endpoint))) { + return EP_PENDING; + } + + if ((log_endpoint == 0) && (TOK_PID(idx) == SETUP_TOKEN)) { + setup = 1; + } + + // non iso endpoint + if (not_iso) { + ep_buf = endpoint_buffer[idx]; + } else { + ep_buf = endpoint_buffer_iso[0]; + } + + for (n = 0; n < sz; n++) { + buffer[n] = ep_buf[n]; + } + + if (((Data1 >> endpoint) & 1) == ((bdt[idx].info >> 6) & 1)) { + if (setup && (buffer[6] == 0)) // if no setup data stage, + Data1 &= ~1UL; // set DATA0 + else + Data1 ^= (1 << endpoint); + } + + if (((Data1 >> endpoint) & 1)) { + bdt[idx].info = BD_DTS_MASK | BD_DATA01_MASK | BD_OWN_MASK; + } + else { + bdt[idx].info = BD_DTS_MASK | BD_OWN_MASK; + } + + USB0->CTL &= ~USB_CTL_TXSUSPENDTOKENBUSY_MASK; + *bytesRead = sz; + + epComplete &= ~EP(endpoint); + return EP_COMPLETED; +} + +EP_STATUS USBHAL::endpointWrite(uint8_t endpoint, uint8_t *data, uint32_t size) { + uint32_t idx, n; + uint8_t * ep_buf; + + if (endpoint > NUMBER_OF_PHYSICAL_ENDPOINTS - 1) { + return EP_INVALID; + } + + // if write on a OUT endpoint -> error + if (OUT_EP(endpoint)) { + return EP_INVALID; + } + + idx = EP_BDT_IDX(PHY_TO_LOG(endpoint), TX, 0); + bdt[idx].byte_count = size; + + + // non iso endpoint + if (USB0->ENDPOINT[PHY_TO_LOG(endpoint)].ENDPT & USB_ENDPT_EPHSHK_MASK) { + ep_buf = endpoint_buffer[idx]; + } else { + ep_buf = endpoint_buffer_iso[2]; + } + + for (n = 0; n < size; n++) { + ep_buf[n] = data[n]; + } + + if ((Data1 >> endpoint) & 1) { + bdt[idx].info = BD_OWN_MASK | BD_DTS_MASK; + } else { + bdt[idx].info = BD_OWN_MASK | BD_DTS_MASK | BD_DATA01_MASK; + } + + Data1 ^= (1 << endpoint); + + return EP_PENDING; +} + +EP_STATUS USBHAL::endpointWriteResult(uint8_t endpoint) { + if (epComplete & EP(endpoint)) { + epComplete &= ~EP(endpoint); + return EP_COMPLETED; + } + + return EP_PENDING; +} + +void USBHAL::stallEndpoint(uint8_t endpoint) { + USB0->ENDPOINT[PHY_TO_LOG(endpoint)].ENDPT |= USB_ENDPT_EPSTALL_MASK; +} + +void USBHAL::unstallEndpoint(uint8_t endpoint) { + USB0->ENDPOINT[PHY_TO_LOG(endpoint)].ENDPT &= ~USB_ENDPT_EPSTALL_MASK; +} + +bool USBHAL::getEndpointStallState(uint8_t endpoint) { + uint8_t stall = (USB0->ENDPOINT[PHY_TO_LOG(endpoint)].ENDPT & USB_ENDPT_EPSTALL_MASK); + return (stall) ? true : false; +} + +void USBHAL::remoteWakeup(void) { + // [TODO] +} + + +void USBHAL::_usbisr(void) { + instance->usbisr(); +} + + +void USBHAL::usbisr(void) { + uint8_t i; + uint8_t istat = USB0->ISTAT; + + // reset interrupt + if (istat & USB_ISTAT_USBRST_MASK) { + // disable all endpt + for(i = 0; i < 16; i++) { + USB0->ENDPOINT[i].ENDPT = 0x00; + } + + // enable control endpoint + realiseEndpoint(EP0OUT, MAX_PACKET_SIZE_EP0, 0); + realiseEndpoint(EP0IN, MAX_PACKET_SIZE_EP0, 0); + + Data1 = 0x55555555; + USB0->CTL |= USB_CTL_ODDRST_MASK; + + USB0->ISTAT = 0xFF; // clear all interrupt status flags + USB0->ERRSTAT = 0xFF; // clear all error flags + USB0->ERREN = 0xFF; // enable error interrupt sources + USB0->ADDR = 0x00; // set default address + + return; + } + + // resume interrupt + if (istat & USB_ISTAT_RESUME_MASK) { + USB0->ISTAT = USB_ISTAT_RESUME_MASK; + } + + // SOF interrupt + if (istat & USB_ISTAT_SOFTOK_MASK) { + USB0->ISTAT = USB_ISTAT_SOFTOK_MASK; + // SOF event, read frame number + SOF(frameNumber()); + } + + // stall interrupt + if (istat & 1<<7) { + if (USB0->ENDPOINT[0].ENDPT & USB_ENDPT_EPSTALL_MASK) + USB0->ENDPOINT[0].ENDPT &= ~USB_ENDPT_EPSTALL_MASK; + USB0->ISTAT |= USB_ISTAT_STALL_MASK; + } + + // token interrupt + if (istat & 1<<3) { + uint32_t num = (USB0->STAT >> 4) & 0x0F; + uint32_t dir = (USB0->STAT >> 3) & 0x01; + uint32_t ev_odd = (USB0->STAT >> 2) & 0x01; + + // setup packet + if ((num == 0) && (TOK_PID((EP_BDT_IDX(num, dir, ev_odd))) == SETUP_TOKEN)) { + Data1 &= ~0x02; + bdt[EP_BDT_IDX(0, TX, EVEN)].info &= ~BD_OWN_MASK; + bdt[EP_BDT_IDX(0, TX, ODD)].info &= ~BD_OWN_MASK; + + // EP0 SETUP event (SETUP data received) + EP0setupCallback(); + + } else { + // OUT packet + if (TOK_PID((EP_BDT_IDX(num, dir, ev_odd))) == OUT_TOKEN) { + if (num == 0) + EP0out(); + else { + epComplete |= (1 << EP(num)); + if ((instance->*(epCallback[EP(num) - 2]))()) { + epComplete &= ~(1 << EP(num)); + } + } + } + + // IN packet + if (TOK_PID((EP_BDT_IDX(num, dir, ev_odd))) == IN_TOKEN) { + if (num == 0) { + EP0in(); + if (set_addr == 1) { + USB0->ADDR = addr & 0x7F; + set_addr = 0; + } + } + else { + epComplete |= (1 << (EP(num) + 1)); + if ((instance->*(epCallback[EP(num) + 1 - 2]))()) { + epComplete &= ~(1 << (EP(num) + 1)); + } + } + } + } + + USB0->ISTAT = USB_ISTAT_TOKDNE_MASK; + } + + // sleep interrupt + if (istat & 1<<4) { + USB0->ISTAT |= USB_ISTAT_SLEEP_MASK; + } + + // error interrupt + if (istat & USB_ISTAT_ERROR_MASK) { + USB0->ERRSTAT = 0xFF; + USB0->ISTAT |= USB_ISTAT_ERROR_MASK; + } +} + + +#endif
--- a/USBDevice/USBHAL_LPC11U.cpp Mon Jan 21 10:41:28 2013 +0000 +++ b/USBDevice/USBHAL_LPC11U.cpp Fri Mar 01 13:10:29 2013 +0000 @@ -22,7 +22,6 @@ USBHAL * USBHAL::instance; - // Valid physical endpoint numbers are 0 to (NUMBER_OF_PHYSICAL_ENDPOINTS-1) #define LAST_PHYSICAL_ENDPOINT (NUMBER_OF_PHYSICAL_ENDPOINTS-1) @@ -129,6 +128,16 @@ USBHAL::USBHAL(void) { NVIC_DisableIRQ(USB_IRQn); + + // fill in callback array + epCallback[0] = &USBHAL::EP1_OUT_callback; + epCallback[1] = &USBHAL::EP1_IN_callback; + epCallback[2] = &USBHAL::EP2_OUT_callback; + epCallback[3] = &USBHAL::EP2_IN_callback; + epCallback[4] = &USBHAL::EP3_OUT_callback; + epCallback[5] = &USBHAL::EP3_IN_callback; + epCallback[6] = &USBHAL::EP4_OUT_callback; + epCallback[7] = &USBHAL::EP4_IN_callback; // nUSB_CONNECT output LPC_IOCON->PIO0_6 = 0x00000001; @@ -181,7 +190,6 @@ USBHAL::~USBHAL(void) { // Ensure device disconnected (DCON not set) LPC_USB->DEVCMDSTAT = 0; - // Disable USB interrupts NVIC_DisableIRQ(USB_IRQn); } @@ -199,9 +207,11 @@ } void USBHAL::configureDevice(void) { + // Not required } void USBHAL::unconfigureDevice(void) { + // Not required } void USBHAL::EP0setup(uint8_t *buffer) { @@ -232,6 +242,11 @@ return bytesRead; } + +void USBHAL::EP0readStage(void) { + // Not required +} + void USBHAL::EP0write(uint8_t *buffer, uint32_t size) { // Start and endpoint 0 write @@ -303,10 +318,7 @@ } void USBHAL::EP0getWriteResult(void) { - // Complete an endpoint 0 write - - // Nothing required for this target - return; + // Not required } void USBHAL::EP0stall(void) { @@ -385,8 +397,8 @@ EP_STATUS USBHAL::endpointWriteResult(uint8_t endpoint) { uint32_t bf; + // Validate parameters - if (endpoint > LAST_PHYSICAL_ENDPOINT) { return EP_INVALID; } @@ -422,8 +434,7 @@ void USBHAL::stallEndpoint(uint8_t endpoint) { - // TODO: should this clear active bit? - + // FIX: should this clear active bit? if (IN_EP(endpoint)) { ep[PHY_TO_LOG(endpoint)].in[0] |= CMDSTS_S; ep[PHY_TO_LOG(endpoint)].in[1] |= CMDSTS_S; @@ -441,26 +452,26 @@ ep[PHY_TO_LOG(endpoint)].in[1] = 0; // S = 0 if (LPC_USB->EPINUSE & EP(endpoint)) { - ep[PHY_TO_LOG(endpoint)].in[1] = CMDSTS_TR; // S =0, TR=1, TV = 0 + ep[PHY_TO_LOG(endpoint)].in[1] = CMDSTS_TR; // S = 0, TR = 1, TV = 0 } else { - ep[PHY_TO_LOG(endpoint)].in[0] = CMDSTS_TR; // S =0, TR=1, TV = 0 + ep[PHY_TO_LOG(endpoint)].in[0] = CMDSTS_TR; // S = 0, TR = 1, TV = 0 } } else { ep[PHY_TO_LOG(endpoint)].out[0] = 0; // S = 0 ep[PHY_TO_LOG(endpoint)].out[1] = 0; // S = 0 if (LPC_USB->EPINUSE & EP(endpoint)) { - ep[PHY_TO_LOG(endpoint)].out[1] = CMDSTS_TR; // S =0, TR=1, TV = 0 + ep[PHY_TO_LOG(endpoint)].out[1] = CMDSTS_TR; // S = 0, TR = 1, TV = 0 } else { - ep[PHY_TO_LOG(endpoint)].out[0] = CMDSTS_TR; // S =0, TR=1, TV = 0 + ep[PHY_TO_LOG(endpoint)].out[0] = CMDSTS_TR; // S = 0, TR = 1, TV = 0 } } } else { // Single buffered if (IN_EP(endpoint)) { - ep[PHY_TO_LOG(endpoint)].in[0] = CMDSTS_TR; // S=0, TR=1, TV = 0 + ep[PHY_TO_LOG(endpoint)].in[0] = CMDSTS_TR; // S = 0, TR = 1, TV = 0 } else { - ep[PHY_TO_LOG(endpoint)].out[0] = CMDSTS_TR; // S=0, TR=1, TV = 0 + ep[PHY_TO_LOG(endpoint)].out[0] = CMDSTS_TR; // S = 0, TR = 1, TV = 0 } } } @@ -658,55 +669,15 @@ // EP0IN ACK event (IN data sent) EP0in(); } - - if (LPC_USB->INTSTAT & EP(EP1IN)) { - // Clear EP1IN interrupt - LPC_USB->INTSTAT = EP(EP1IN); - epComplete |= EP(EP1IN); - if (EP1_IN_callback()) - epComplete &= ~EP(EP1IN); - } - - if (LPC_USB->INTSTAT & EP(EP1OUT)) { - // Clear EP1OUT interrupt - LPC_USB->INTSTAT = EP(EP1OUT); - epComplete |= EP(EP1OUT); - if (EP1_OUT_callback()) - epComplete &= ~EP(EP1OUT); - } - - if (LPC_USB->INTSTAT & EP(EP2IN)) { - // Clear EPBULK_IN interrupt - LPC_USB->INTSTAT = EP(EP2IN); - epComplete |= EP(EP2IN); - if (EP2_IN_callback()) - epComplete &= ~EP(EP2IN); - } - - if (LPC_USB->INTSTAT & EP(EP2OUT)) { - // Clear EPBULK_OUT interrupt - LPC_USB->INTSTAT = EP(EP2OUT); - epComplete |= EP(EP2OUT); - //Call callback function. If true, clear epComplete - if (EP2_OUT_callback()) - epComplete &= ~EP(EP2OUT); - } - - if (LPC_USB->INTSTAT & EP(EP3IN)) { - // Clear EP3_IN interrupt - LPC_USB->INTSTAT = EP(EP3IN); - epComplete |= EP(EP3IN); - if (EP3_IN_callback()) - epComplete &= ~EP(EP3IN); - } - - if (LPC_USB->INTSTAT & EP(EP3OUT)) { - // Clear EP3_OUT interrupt - LPC_USB->INTSTAT = EP(EP3OUT); - epComplete |= EP(EP3OUT); - //Call callback function. If true, clear epComplete - if (EP3_OUT_callback()) - epComplete &= ~EP(EP3OUT); + + for (uint8_t num = 2; num < 5*2; num++) { + if (LPC_USB->INTSTAT & EP(num)) { + LPC_USB->INTSTAT = EP(num); + epComplete |= EP(num); + if ((instance->*(epCallback[num - 2]))()) { + epComplete &= ~EP(num); + } + } } }
--- a/USBDevice/USBHAL_LPC17.cpp Mon Jan 21 10:41:28 2013 +0000 +++ b/USBDevice/USBHAL_LPC17.cpp Fri Mar 01 13:10:29 2013 +0000 @@ -16,7 +16,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifdef TARGET_LPC1768 +#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) #include "USBHAL.h" @@ -116,8 +116,8 @@ USBHAL * USBHAL::instance; -volatile int epComplete; -uint32_t endpointStallState; +static volatile int epComplete; +static uint32_t endpointStallState; static void SIECommand(uint32_t command) { // The command phase of a SIE transaction @@ -209,18 +209,14 @@ static void SIEconnect(void) { // Connect USB device - uint8_t status; - - status = SIEgetDeviceStatus(); + uint8_t status = SIEgetDeviceStatus(); SIEsetDeviceStatus(status | SIE_DS_CON); } static void SIEdisconnect(void) { // Disconnect USB device - uint8_t status; - - status = SIEgetDeviceStatus(); + uint8_t status = SIEgetDeviceStatus(); SIEsetDeviceStatus(status & ~SIE_DS_CON); } @@ -233,9 +229,6 @@ } - - - static void enableEndpointEvent(uint8_t endpoint) { // Enable an endpoint interrupt LPC_USB->USBEpIntEn |= EP(endpoint); @@ -248,8 +241,6 @@ } static volatile uint32_t __attribute__((used)) dummyRead; - - uint32_t USBHAL::endpointReadcore(uint8_t endpoint, uint8_t *buffer) { // Read from an OUT endpoint uint32_t size; @@ -333,15 +324,41 @@ SIEvalidateBuffer(); } - - - - - - USBHAL::USBHAL(void) { // Disable IRQ NVIC_DisableIRQ(USB_IRQn); + + // fill in callback array + epCallback[0] = &USBHAL::EP1_OUT_callback; + epCallback[1] = &USBHAL::EP1_IN_callback; + epCallback[2] = &USBHAL::EP2_OUT_callback; + epCallback[3] = &USBHAL::EP2_IN_callback; + epCallback[4] = &USBHAL::EP3_OUT_callback; + epCallback[5] = &USBHAL::EP3_IN_callback; + epCallback[6] = &USBHAL::EP4_OUT_callback; + epCallback[7] = &USBHAL::EP4_IN_callback; + epCallback[8] = &USBHAL::EP5_OUT_callback; + epCallback[9] = &USBHAL::EP5_IN_callback; + epCallback[10] = &USBHAL::EP6_OUT_callback; + epCallback[11] = &USBHAL::EP6_IN_callback; + epCallback[12] = &USBHAL::EP7_OUT_callback; + epCallback[13] = &USBHAL::EP7_IN_callback; + epCallback[14] = &USBHAL::EP8_OUT_callback; + epCallback[15] = &USBHAL::EP8_IN_callback; + epCallback[16] = &USBHAL::EP9_OUT_callback; + epCallback[17] = &USBHAL::EP9_IN_callback; + epCallback[18] = &USBHAL::EP10_OUT_callback; + epCallback[19] = &USBHAL::EP10_IN_callback; + epCallback[20] = &USBHAL::EP11_OUT_callback; + epCallback[21] = &USBHAL::EP11_IN_callback; + epCallback[22] = &USBHAL::EP12_OUT_callback; + epCallback[23] = &USBHAL::EP12_IN_callback; + epCallback[24] = &USBHAL::EP13_OUT_callback; + epCallback[25] = &USBHAL::EP13_IN_callback; + epCallback[26] = &USBHAL::EP14_OUT_callback; + epCallback[27] = &USBHAL::EP14_IN_callback; + epCallback[28] = &USBHAL::EP15_OUT_callback; + epCallback[29] = &USBHAL::EP15_IN_callback; // Enable power to USB device controller LPC_SC->PCONP |= PCUSB; @@ -381,7 +398,6 @@ USBHAL::~USBHAL(void) { // Ensure device disconnected SIEdisconnect(); - // Disable USB interrupts NVIC_DisableIRQ(USB_IRQn); } @@ -418,6 +434,10 @@ // Not required } +void USBHAL::EP0readStage(void) { + // Not required +} + uint32_t USBHAL::EP0getReadResult(uint8_t *buffer) { return endpointReadcore(EP0OUT, buffer); } @@ -527,10 +547,6 @@ SIEsetDeviceStatus(status & ~SIE_DS_SUS); } - - - - void USBHAL::_usbisr(void) { instance->usbisr(); } @@ -590,54 +606,16 @@ LPC_USB->USBDevIntClr = EP_SLOW; EP0in(); } - - // TODO: This should cover all endpoints, not just EP1,2,3: - if (LPC_USB->USBEpIntSt & EP(EP1IN)) { - selectEndpointClearInterrupt(EP1IN); - epComplete |= EP(EP1IN); - LPC_USB->USBDevIntClr = EP_SLOW; - if (EP1_IN_callback()) - epComplete &= ~EP(EP1IN); - } - - if (LPC_USB->USBEpIntSt & EP(EP1OUT)) { - selectEndpointClearInterrupt(EP1OUT); - epComplete |= EP(EP1OUT); - LPC_USB->USBDevIntClr = EP_SLOW; - if (EP1_OUT_callback()) - epComplete &= ~EP(EP1OUT); - } - - if (LPC_USB->USBEpIntSt & EP(EP2IN)) { - selectEndpointClearInterrupt(EP2IN); - epComplete |= EP(EP2IN); - LPC_USB->USBDevIntClr = EP_SLOW; - if (EP2_IN_callback()) - epComplete &= ~EP(EP2IN); - } - - if (LPC_USB->USBEpIntSt & EP(EP2OUT)) { - selectEndpointClearInterrupt(EP2OUT); - epComplete |= EP(EP2OUT); - LPC_USB->USBDevIntClr = EP_SLOW; - if (EP2_OUT_callback()) - epComplete &= ~EP(EP2OUT); - } - - if (LPC_USB->USBEpIntSt & EP(EP3IN)) { - selectEndpointClearInterrupt(EP3IN); - epComplete |= EP(EP3IN); - LPC_USB->USBDevIntClr = EP_SLOW; - if (EP3_IN_callback()) - epComplete &= ~EP(EP3IN); - } - - if (LPC_USB->USBEpIntSt & EP(EP3OUT)) { - selectEndpointClearInterrupt(EP3OUT); - epComplete |= EP(EP3OUT); - LPC_USB->USBDevIntClr = EP_SLOW; - if (EP3_OUT_callback()) - epComplete &= ~EP(EP3OUT); + + for (uint8_t num = 2; num < 16*2; num++) { + if (LPC_USB->USBEpIntSt & EP(num)) { + selectEndpointClearInterrupt(num); + epComplete |= EP(num); + LPC_USB->USBDevIntClr = EP_SLOW; + if ((instance->*(epCallback[num - 2]))()) { + epComplete &= ~EP(num); + } + } } } }
--- a/USBMSD/USBMSD.cpp Mon Jan 21 10:41:28 2013 +0000 +++ b/USBMSD/USBMSD.cpp Fri Mar 01 13:10:29 2013 +0000 @@ -642,4 +642,4 @@ 0 // bInterval }; return configDescriptor; -} \ No newline at end of file +}
--- a/USBMSD/USBMSD.h Mon Jan 21 10:41:28 2013 +0000 +++ b/USBMSD/USBMSD.h Fri Mar 01 13:10:29 2013 +0000 @@ -236,4 +236,4 @@ void fail(); }; -#endif \ No newline at end of file +#endif
--- a/USBSerial/USBCDC.cpp Mon Jan 21 10:41:28 2013 +0000 +++ b/USBSerial/USBCDC.cpp Fri Mar 01 13:10:29 2013 +0000 @@ -56,8 +56,7 @@ terminal_connected = true; break; case CDC_SET_CONTROL_LINE_STATE: - if (terminal_connected) - terminal_connected = false; + terminal_connected = false; success = true; break; default: @@ -147,12 +146,13 @@ } -#define CONFIG1_DESC_SIZE (9+9+5+5+4+5+7+9+7+7) +#define CONFIG1_DESC_SIZE (9+8+9+5+5+4+5+7+9+7+7) uint8_t * USBCDC::configurationDesc() { static uint8_t configDescriptor[] = { - 9, // bLength; - 2, // bDescriptorType; + // configuration descriptor + 9, // bLength + 2, // bDescriptorType LSB(CONFIG1_DESC_SIZE), // wTotalLength MSB(CONFIG1_DESC_SIZE), 2, // bNumInterfaces @@ -160,6 +160,16 @@ 0, // iConfiguration 0x80, // bmAttributes 50, // bMaxPower + + // IAD to associate the two CDC interfaces + 0x08, // bLength + 0x0b, // bDescriptorType + 0x00, // bFirstInterface + 0x02, // bInterfaceCount + 0x02, // bFunctionClass + 0x02, // bFunctionSubClass + 0, // bFunctionProtocol + 0, // iFunction // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 9, // bLength @@ -211,33 +221,33 @@ // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 - 9, // bLength - 4, // bDescriptorType - 1, // bInterfaceNumber - 0, // bAlternateSetting - 2, // bNumEndpoints - 0x0A, // bInterfaceClass - 0x00, // bInterfaceSubClass - 0x00, // bInterfaceProtocol - 0, // iInterface + 9, // bLength + 4, // bDescriptorType + 1, // bInterfaceNumber + 0, // bAlternateSetting + 2, // bNumEndpoints + 0x0A, // bInterfaceClass + 0x00, // bInterfaceSubClass + 0x00, // bInterfaceProtocol + 0, // iInterface // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 - 7, // bLength - 5, // bDescriptorType - PHY_TO_DESC(EPBULK_IN), // bEndpointAddress - 0x02, // bmAttributes (0x02=bulk) - LSB(MAX_PACKET_SIZE_EPBULK), // wMaxPacketSize (LSB) - MSB(MAX_PACKET_SIZE_EPBULK), // wMaxPacketSize (MSB) - 0, // bInterval + ENDPOINT_DESCRIPTOR_LENGTH, // bLength + ENDPOINT_DESCRIPTOR, // bDescriptorType + PHY_TO_DESC(EPBULK_IN), // bEndpointAddress + E_BULK, // bmAttributes (0x02=bulk) + LSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (LSB) + MSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (MSB) + 0, // bInterval // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 - 7, // bLength - 5, // bDescriptorType - PHY_TO_DESC(EPBULK_OUT),// bEndpointAddress - 0x02, // bmAttributes (0x02=bulk) - LSB(MAX_PACKET_SIZE_EPBULK), // wMaxPacketSize (LSB) - MSB(MAX_PACKET_SIZE_EPBULK), // wMaxPacketSize (MSB) - 0 // bInterval + ENDPOINT_DESCRIPTOR_LENGTH, // bLength + ENDPOINT_DESCRIPTOR, // bDescriptorType + PHY_TO_DESC(EPBULK_OUT), // bEndpointAddress + E_BULK, // bmAttributes (0x02=bulk) + LSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (LSB) + MSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (MSB) + 0 // bInterval }; return configDescriptor; }