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 USBDevice by
USBHAL_KL25Z.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_KL25Z) 00020 00021 #include "USBHAL.h" 00022 00023 USBHAL * USBHAL::instance; 00024 00025 static volatile int epComplete = 0; 00026 00027 // Convert physical endpoint number to register bit 00028 #define EP(endpoint) (1<<(endpoint)) 00029 00030 // Convert physical to logical 00031 #define PHY_TO_LOG(endpoint) ((endpoint)>>1) 00032 00033 // Get endpoint direction 00034 #define IN_EP(endpoint) ((endpoint) & 1U ? true : false) 00035 #define OUT_EP(endpoint) ((endpoint) & 1U ? false : true) 00036 00037 #define BD_OWN_MASK (1<<7) 00038 #define BD_DATA01_MASK (1<<6) 00039 #define BD_KEEP_MASK (1<<5) 00040 #define BD_NINC_MASK (1<<4) 00041 #define BD_DTS_MASK (1<<3) 00042 #define BD_STALL_MASK (1<<2) 00043 00044 #define TX 1 00045 #define RX 0 00046 #define ODD 0 00047 #define EVEN 1 00048 // this macro waits a physical endpoint number 00049 #define EP_BDT_IDX(ep, dir, odd) (((ep * 4) + (2 * dir) + (1 * odd))) 00050 00051 #define SETUP_TOKEN 0x0D 00052 #define IN_TOKEN 0x09 00053 #define OUT_TOKEN 0x01 00054 #define TOK_PID(idx) ((bdt[idx].info >> 2) & 0x0F) 00055 00056 // for each endpt: 8 bytes 00057 typedef struct BDT { 00058 uint8_t info; // BD[0:7] 00059 uint8_t dummy; // RSVD: BD[8:15] 00060 uint16_t byte_count; // BD[16:32] 00061 uint32_t address; // Addr 00062 } BDT; 00063 00064 00065 // there are: 00066 // * 16 bidirectionnal endpt -> 32 physical endpt 00067 // * as there are ODD and EVEN buffer -> 32*2 bdt 00068 __attribute__((__aligned__(512))) BDT bdt[NUMBER_OF_PHYSICAL_ENDPOINTS * 2]; 00069 uint8_t endpoint_buffer[(NUMBER_OF_PHYSICAL_ENDPOINTS - 2) * 2][64]; 00070 uint8_t endpoint_buffer_iso[2*2][1023]; 00071 00072 static uint8_t set_addr = 0; 00073 static uint8_t addr = 0; 00074 00075 static uint32_t Data1 = 0x55555555; 00076 00077 static uint32_t frameNumber() { 00078 return((USB0->FRMNUML | (USB0->FRMNUMH << 8) & 0x07FF)); 00079 } 00080 00081 uint32_t USBHAL::endpointReadcore(uint8_t endpoint, uint8_t *buffer) { 00082 return 0; 00083 } 00084 00085 USBHAL::USBHAL(void) { 00086 // Disable IRQ 00087 NVIC_DisableIRQ(USB0_IRQn); 00088 00089 // fill in callback array 00090 epCallback[0] = &USBHAL::EP1_OUT_callback; 00091 epCallback[1] = &USBHAL::EP1_IN_callback; 00092 epCallback[2] = &USBHAL::EP2_OUT_callback; 00093 epCallback[3] = &USBHAL::EP2_IN_callback; 00094 epCallback[4] = &USBHAL::EP3_OUT_callback; 00095 epCallback[5] = &USBHAL::EP3_IN_callback; 00096 epCallback[6] = &USBHAL::EP4_OUT_callback; 00097 epCallback[7] = &USBHAL::EP4_IN_callback; 00098 epCallback[8] = &USBHAL::EP5_OUT_callback; 00099 epCallback[9] = &USBHAL::EP5_IN_callback; 00100 epCallback[10] = &USBHAL::EP6_OUT_callback; 00101 epCallback[11] = &USBHAL::EP6_IN_callback; 00102 epCallback[12] = &USBHAL::EP7_OUT_callback; 00103 epCallback[13] = &USBHAL::EP7_IN_callback; 00104 epCallback[14] = &USBHAL::EP8_OUT_callback; 00105 epCallback[15] = &USBHAL::EP8_IN_callback; 00106 epCallback[16] = &USBHAL::EP9_OUT_callback; 00107 epCallback[17] = &USBHAL::EP9_IN_callback; 00108 epCallback[18] = &USBHAL::EP10_OUT_callback; 00109 epCallback[19] = &USBHAL::EP10_IN_callback; 00110 epCallback[20] = &USBHAL::EP11_OUT_callback; 00111 epCallback[21] = &USBHAL::EP11_IN_callback; 00112 epCallback[22] = &USBHAL::EP12_OUT_callback; 00113 epCallback[23] = &USBHAL::EP12_IN_callback; 00114 epCallback[24] = &USBHAL::EP13_OUT_callback; 00115 epCallback[25] = &USBHAL::EP13_IN_callback; 00116 epCallback[26] = &USBHAL::EP14_OUT_callback; 00117 epCallback[27] = &USBHAL::EP14_IN_callback; 00118 epCallback[28] = &USBHAL::EP15_OUT_callback; 00119 epCallback[29] = &USBHAL::EP15_IN_callback; 00120 00121 00122 // choose usb src as PLL 00123 SIM->SOPT2 |= (SIM_SOPT2_USBSRC_MASK | SIM_SOPT2_PLLFLLSEL_MASK); 00124 00125 // enable OTG clock 00126 SIM->SCGC4 |= SIM_SCGC4_USBOTG_MASK; 00127 00128 // Attach IRQ 00129 instance = this; 00130 NVIC_SetVector(USB0_IRQn, (uint32_t)&_usbisr); 00131 NVIC_EnableIRQ(USB0_IRQn); 00132 00133 // USB Module Configuration 00134 // Reset USB Module 00135 USB0->USBTRC0 |= USB_USBTRC0_USBRESET_MASK; 00136 while(USB0->USBTRC0 & USB_USBTRC0_USBRESET_MASK); 00137 00138 // Set BDT Base Register 00139 USB0->BDTPAGE1=(uint8_t)((uint32_t)bdt>>8); 00140 USB0->BDTPAGE2=(uint8_t)((uint32_t)bdt>>16); 00141 USB0->BDTPAGE3=(uint8_t)((uint32_t)bdt>>24); 00142 00143 // Clear interrupt flag 00144 USB0->ISTAT = 0xff; 00145 00146 // USB Interrupt Enablers 00147 USB0->INTEN |= USB_INTEN_TOKDNEEN_MASK | 00148 USB_INTEN_SOFTOKEN_MASK | 00149 USB_INTEN_ERROREN_MASK | 00150 USB_INTEN_USBRSTEN_MASK; 00151 00152 // Disable weak pull downs 00153 USB0->USBCTRL &= ~(USB_USBCTRL_PDE_MASK | USB_USBCTRL_SUSP_MASK); 00154 00155 USB0->USBTRC0 |= 0x40; 00156 } 00157 00158 USBHAL::~USBHAL(void) { } 00159 00160 void USBHAL::connect(void) { 00161 // enable USB 00162 USB0->CTL |= USB_CTL_USBENSOFEN_MASK; 00163 // Pull up enable 00164 USB0->CONTROL |= USB_CONTROL_DPPULLUPNONOTG_MASK; 00165 } 00166 00167 void USBHAL::disconnect(void) { 00168 // disable USB 00169 USB0->CTL &= ~USB_CTL_USBENSOFEN_MASK; 00170 // Pull up disable 00171 USB0->CONTROL &= ~USB_CONTROL_DPPULLUPNONOTG_MASK; 00172 } 00173 00174 void USBHAL::configureDevice(void) { 00175 // not needed 00176 } 00177 00178 void USBHAL::unconfigureDevice(void) { 00179 // not needed 00180 } 00181 00182 void USBHAL::setAddress(uint8_t address) { 00183 // we don't set the address now otherwise the usb controller does not ack 00184 // we set a flag instead 00185 // see usbisr when an IN token is received 00186 set_addr = 1; 00187 addr = address; 00188 } 00189 00190 bool USBHAL::realiseEndpoint(uint8_t endpoint, uint32_t maxPacket, uint32_t flags) { 00191 uint32_t handshake_flag = 0; 00192 uint8_t * buf; 00193 00194 if (endpoint > NUMBER_OF_PHYSICAL_ENDPOINTS - 1) { 00195 return false; 00196 } 00197 00198 uint32_t log_endpoint = PHY_TO_LOG(endpoint); 00199 00200 if ((flags & ISOCHRONOUS) == 0) { 00201 handshake_flag = USB_ENDPT_EPHSHK_MASK; 00202 if (IN_EP(endpoint)) 00203 buf = &endpoint_buffer[EP_BDT_IDX(log_endpoint, TX, ODD )][0]; 00204 else 00205 buf = &endpoint_buffer[EP_BDT_IDX(log_endpoint, RX, ODD )][0]; 00206 } else { 00207 if (IN_EP(endpoint)) 00208 buf = &endpoint_buffer_iso[2][0]; 00209 else 00210 buf = &endpoint_buffer_iso[0][0]; 00211 } 00212 00213 // IN endpt -> device to host (TX) 00214 if (IN_EP(endpoint)) { 00215 USB0->ENDPOINT[log_endpoint].ENDPT |= handshake_flag | // ep handshaking (not if iso endpoint) 00216 USB_ENDPT_EPTXEN_MASK; // en TX (IN) tran 00217 bdt[EP_BDT_IDX(log_endpoint, TX, ODD )].address = (uint32_t) buf; 00218 bdt[EP_BDT_IDX(log_endpoint, TX, EVEN)].address = 0; 00219 } 00220 // OUT endpt -> host to device (RX) 00221 else { 00222 USB0->ENDPOINT[log_endpoint].ENDPT |= handshake_flag | // ep handshaking (not if iso endpoint) 00223 USB_ENDPT_EPRXEN_MASK; // en RX (OUT) tran. 00224 bdt[EP_BDT_IDX(log_endpoint, RX, ODD )].byte_count = maxPacket; 00225 bdt[EP_BDT_IDX(log_endpoint, RX, ODD )].address = (uint32_t) buf; 00226 bdt[EP_BDT_IDX(log_endpoint, RX, ODD )].info = BD_OWN_MASK | BD_DTS_MASK; 00227 bdt[EP_BDT_IDX(log_endpoint, RX, EVEN)].info = 0; 00228 } 00229 00230 Data1 |= (1 << endpoint); 00231 00232 return true; 00233 } 00234 00235 // read setup packet 00236 void USBHAL::EP0setup(uint8_t *buffer) { 00237 uint32_t sz; 00238 endpointReadResult(EP0OUT, buffer, &sz); 00239 } 00240 00241 void USBHAL::EP0readStage(void) { 00242 Data1 &= ~1UL; // set DATA0 00243 bdt[0].info = (BD_DTS_MASK | BD_OWN_MASK); 00244 } 00245 00246 void USBHAL::EP0read(void) { 00247 uint32_t idx = EP_BDT_IDX(PHY_TO_LOG(EP0OUT), RX, 0); 00248 bdt[idx].byte_count = MAX_PACKET_SIZE_EP0; 00249 } 00250 00251 uint32_t USBHAL::EP0getReadResult(uint8_t *buffer) { 00252 uint32_t sz; 00253 endpointReadResult(EP0OUT, buffer, &sz); 00254 return sz; 00255 } 00256 00257 void USBHAL::EP0write(uint8_t *buffer, uint32_t size) { 00258 endpointWrite(EP0IN, buffer, size); 00259 } 00260 00261 void USBHAL::EP0getWriteResult(void) { 00262 } 00263 00264 void USBHAL::EP0stall(void) { 00265 stallEndpoint(EP0OUT); 00266 } 00267 00268 EP_STATUS USBHAL::endpointRead(uint8_t endpoint, uint32_t maximumSize) { 00269 endpoint = PHY_TO_LOG(endpoint); 00270 uint32_t idx = EP_BDT_IDX(endpoint, RX, 0); 00271 bdt[idx].byte_count = maximumSize; 00272 return EP_PENDING; 00273 } 00274 00275 EP_STATUS USBHAL::endpointReadResult(uint8_t endpoint, uint8_t * buffer, uint32_t *bytesRead) { 00276 uint32_t n, sz, idx, setup = 0; 00277 uint8_t not_iso; 00278 uint8_t * ep_buf; 00279 00280 uint32_t log_endpoint = PHY_TO_LOG(endpoint); 00281 00282 if (endpoint > NUMBER_OF_PHYSICAL_ENDPOINTS - 1) { 00283 return EP_INVALID; 00284 } 00285 00286 // if read on a IN endpoint -> error 00287 if (IN_EP(endpoint)) { 00288 return EP_INVALID; 00289 } 00290 00291 idx = EP_BDT_IDX(log_endpoint, RX, 0); 00292 sz = bdt[idx].byte_count; 00293 not_iso = USB0->ENDPOINT[log_endpoint].ENDPT & USB_ENDPT_EPHSHK_MASK; 00294 00295 //for isochronous endpoint, we don't wait an interrupt 00296 if ((log_endpoint != 0) && not_iso && !(epComplete & EP(endpoint))) { 00297 return EP_PENDING; 00298 } 00299 00300 if ((log_endpoint == 0) && (TOK_PID(idx) == SETUP_TOKEN)) { 00301 setup = 1; 00302 } 00303 00304 // non iso endpoint 00305 if (not_iso) { 00306 ep_buf = endpoint_buffer[idx]; 00307 } else { 00308 ep_buf = endpoint_buffer_iso[0]; 00309 } 00310 00311 for (n = 0; n < sz; n++) { 00312 buffer[n] = ep_buf[n]; 00313 } 00314 00315 if (((Data1 >> endpoint) & 1) == ((bdt[idx].info >> 6) & 1)) { 00316 if (setup && (buffer[6] == 0)) // if no setup data stage, 00317 Data1 &= ~1UL; // set DATA0 00318 else 00319 Data1 ^= (1 << endpoint); 00320 } 00321 00322 if (((Data1 >> endpoint) & 1)) { 00323 bdt[idx].info = BD_DTS_MASK | BD_DATA01_MASK | BD_OWN_MASK; 00324 } 00325 else { 00326 bdt[idx].info = BD_DTS_MASK | BD_OWN_MASK; 00327 } 00328 00329 USB0->CTL &= ~USB_CTL_TXSUSPENDTOKENBUSY_MASK; 00330 *bytesRead = sz; 00331 00332 epComplete &= ~EP(endpoint); 00333 return EP_COMPLETED; 00334 } 00335 00336 EP_STATUS USBHAL::endpointWrite(uint8_t endpoint, uint8_t *data, uint32_t size) { 00337 uint32_t idx, n; 00338 uint8_t * ep_buf; 00339 00340 if (endpoint > NUMBER_OF_PHYSICAL_ENDPOINTS - 1) { 00341 return EP_INVALID; 00342 } 00343 00344 // if write on a OUT endpoint -> error 00345 if (OUT_EP(endpoint)) { 00346 return EP_INVALID; 00347 } 00348 00349 idx = EP_BDT_IDX(PHY_TO_LOG(endpoint), TX, 0); 00350 bdt[idx].byte_count = size; 00351 00352 00353 // non iso endpoint 00354 if (USB0->ENDPOINT[PHY_TO_LOG(endpoint)].ENDPT & USB_ENDPT_EPHSHK_MASK) { 00355 ep_buf = endpoint_buffer[idx]; 00356 } else { 00357 ep_buf = endpoint_buffer_iso[2]; 00358 } 00359 00360 for (n = 0; n < size; n++) { 00361 ep_buf[n] = data[n]; 00362 } 00363 00364 if ((Data1 >> endpoint) & 1) { 00365 bdt[idx].info = BD_OWN_MASK | BD_DTS_MASK; 00366 } else { 00367 bdt[idx].info = BD_OWN_MASK | BD_DTS_MASK | BD_DATA01_MASK; 00368 } 00369 00370 Data1 ^= (1 << endpoint); 00371 00372 return EP_PENDING; 00373 } 00374 00375 EP_STATUS USBHAL::endpointWriteResult(uint8_t endpoint) { 00376 if (epComplete & EP(endpoint)) { 00377 epComplete &= ~EP(endpoint); 00378 return EP_COMPLETED; 00379 } 00380 00381 return EP_PENDING; 00382 } 00383 00384 void USBHAL::stallEndpoint(uint8_t endpoint) { 00385 USB0->ENDPOINT[PHY_TO_LOG(endpoint)].ENDPT |= USB_ENDPT_EPSTALL_MASK; 00386 } 00387 00388 void USBHAL::unstallEndpoint(uint8_t endpoint) { 00389 USB0->ENDPOINT[PHY_TO_LOG(endpoint)].ENDPT &= ~USB_ENDPT_EPSTALL_MASK; 00390 } 00391 00392 bool USBHAL::getEndpointStallState(uint8_t endpoint) { 00393 uint8_t stall = (USB0->ENDPOINT[PHY_TO_LOG(endpoint)].ENDPT & USB_ENDPT_EPSTALL_MASK); 00394 return (stall) ? true : false; 00395 } 00396 00397 void USBHAL::remoteWakeup(void) { 00398 // [TODO] 00399 } 00400 00401 00402 void USBHAL::_usbisr(void) { 00403 instance->usbisr(); 00404 } 00405 00406 00407 void USBHAL::usbisr(void) { 00408 uint8_t i; 00409 uint8_t istat = USB0->ISTAT; 00410 00411 // reset interrupt 00412 if (istat & USB_ISTAT_USBRST_MASK) { 00413 // disable all endpt 00414 for(i = 0; i < 16; i++) { 00415 USB0->ENDPOINT[i].ENDPT = 0x00; 00416 } 00417 00418 // enable control endpoint 00419 realiseEndpoint(EP0OUT, MAX_PACKET_SIZE_EP0, 0); 00420 realiseEndpoint(EP0IN, MAX_PACKET_SIZE_EP0, 0); 00421 00422 Data1 = 0x55555555; 00423 USB0->CTL |= USB_CTL_ODDRST_MASK; 00424 00425 USB0->ISTAT = 0xFF; // clear all interrupt status flags 00426 USB0->ERRSTAT = 0xFF; // clear all error flags 00427 USB0->ERREN = 0xFF; // enable error interrupt sources 00428 USB0->ADDR = 0x00; // set default address 00429 00430 return; 00431 } 00432 00433 // resume interrupt 00434 if (istat & USB_ISTAT_RESUME_MASK) { 00435 USB0->ISTAT = USB_ISTAT_RESUME_MASK; 00436 } 00437 00438 // SOF interrupt 00439 if (istat & USB_ISTAT_SOFTOK_MASK) { 00440 USB0->ISTAT = USB_ISTAT_SOFTOK_MASK; 00441 // SOF event, read frame number 00442 SOF(frameNumber()); 00443 } 00444 00445 // stall interrupt 00446 if (istat & 1<<7) { 00447 if (USB0->ENDPOINT[0].ENDPT & USB_ENDPT_EPSTALL_MASK) 00448 USB0->ENDPOINT[0].ENDPT &= ~USB_ENDPT_EPSTALL_MASK; 00449 USB0->ISTAT |= USB_ISTAT_STALL_MASK; 00450 } 00451 00452 // token interrupt 00453 if (istat & 1<<3) { 00454 uint32_t num = (USB0->STAT >> 4) & 0x0F; 00455 uint32_t dir = (USB0->STAT >> 3) & 0x01; 00456 uint32_t ev_odd = (USB0->STAT >> 2) & 0x01; 00457 00458 // setup packet 00459 if ((num == 0) && (TOK_PID((EP_BDT_IDX(num, dir, ev_odd))) == SETUP_TOKEN)) { 00460 Data1 &= ~0x02; 00461 bdt[EP_BDT_IDX(0, TX, EVEN)].info &= ~BD_OWN_MASK; 00462 bdt[EP_BDT_IDX(0, TX, ODD)].info &= ~BD_OWN_MASK; 00463 00464 // EP0 SETUP event (SETUP data received) 00465 EP0setupCallback(); 00466 00467 } else { 00468 // OUT packet 00469 if (TOK_PID((EP_BDT_IDX(num, dir, ev_odd))) == OUT_TOKEN) { 00470 if (num == 0) 00471 EP0out(); 00472 else { 00473 epComplete |= (1 << EP(num)); 00474 if ((instance->*(epCallback[EP(num) - 2]))()) { 00475 epComplete &= ~(1 << EP(num)); 00476 } 00477 } 00478 } 00479 00480 // IN packet 00481 if (TOK_PID((EP_BDT_IDX(num, dir, ev_odd))) == IN_TOKEN) { 00482 if (num == 0) { 00483 EP0in(); 00484 if (set_addr == 1) { 00485 USB0->ADDR = addr & 0x7F; 00486 set_addr = 0; 00487 } 00488 } 00489 else { 00490 epComplete |= (1 << (EP(num) + 1)); 00491 if ((instance->*(epCallback[EP(num) + 1 - 2]))()) { 00492 epComplete &= ~(1 << (EP(num) + 1)); 00493 } 00494 } 00495 } 00496 } 00497 00498 USB0->ISTAT = USB_ISTAT_TOKDNE_MASK; 00499 } 00500 00501 // sleep interrupt 00502 if (istat & 1<<4) { 00503 USB0->ISTAT |= USB_ISTAT_SLEEP_MASK; 00504 } 00505 00506 // error interrupt 00507 if (istat & USB_ISTAT_ERROR_MASK) { 00508 USB0->ERRSTAT = 0xFF; 00509 USB0->ISTAT |= USB_ISTAT_ERROR_MASK; 00510 } 00511 } 00512 00513 00514 #endif
Generated on Wed Jul 20 2022 00:01:16 by
