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]; 00070 uint8_t * endpoint_buffer_iso[2*2]; 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 endpoint_buffer[EP_BDT_IDX(log_endpoint, TX, ODD )] = (uint8_t *) malloc (64*2); 00204 buf = &endpoint_buffer[EP_BDT_IDX(log_endpoint, TX, ODD )][0]; 00205 } else { 00206 endpoint_buffer[EP_BDT_IDX(log_endpoint, RX, ODD )] = (uint8_t *) malloc (64*2); 00207 buf = &endpoint_buffer[EP_BDT_IDX(log_endpoint, RX, ODD )][0]; 00208 } 00209 } else { 00210 if (IN_EP(endpoint)) { 00211 endpoint_buffer_iso[2] = (uint8_t *) malloc (1023*2); 00212 buf = &endpoint_buffer_iso[2][0]; 00213 } else { 00214 endpoint_buffer_iso[0] = (uint8_t *) malloc (1023*2); 00215 buf = &endpoint_buffer_iso[0][0]; 00216 } 00217 } 00218 00219 // IN endpt -> device to host (TX) 00220 if (IN_EP(endpoint)) { 00221 USB0->ENDPOINT[log_endpoint].ENDPT |= handshake_flag | // ep handshaking (not if iso endpoint) 00222 USB_ENDPT_EPTXEN_MASK; // en TX (IN) tran 00223 bdt[EP_BDT_IDX(log_endpoint, TX, ODD )].address = (uint32_t) buf; 00224 bdt[EP_BDT_IDX(log_endpoint, TX, EVEN)].address = 0; 00225 } 00226 // OUT endpt -> host to device (RX) 00227 else { 00228 USB0->ENDPOINT[log_endpoint].ENDPT |= handshake_flag | // ep handshaking (not if iso endpoint) 00229 USB_ENDPT_EPRXEN_MASK; // en RX (OUT) tran. 00230 bdt[EP_BDT_IDX(log_endpoint, RX, ODD )].byte_count = maxPacket; 00231 bdt[EP_BDT_IDX(log_endpoint, RX, ODD )].address = (uint32_t) buf; 00232 bdt[EP_BDT_IDX(log_endpoint, RX, ODD )].info = BD_OWN_MASK | BD_DTS_MASK; 00233 bdt[EP_BDT_IDX(log_endpoint, RX, EVEN)].info = 0; 00234 } 00235 00236 Data1 |= (1 << endpoint); 00237 00238 return true; 00239 } 00240 00241 // read setup packet 00242 void USBHAL::EP0setup(uint8_t *buffer) { 00243 uint32_t sz; 00244 endpointReadResult(EP0OUT, buffer, &sz); 00245 } 00246 00247 void USBHAL::EP0readStage(void) { 00248 Data1 &= ~1UL; // set DATA0 00249 bdt[0].info = (BD_DTS_MASK | BD_OWN_MASK); 00250 } 00251 00252 void USBHAL::EP0read(void) { 00253 uint32_t idx = EP_BDT_IDX(PHY_TO_LOG(EP0OUT), RX, 0); 00254 bdt[idx].byte_count = MAX_PACKET_SIZE_EP0; 00255 } 00256 00257 uint32_t USBHAL::EP0getReadResult(uint8_t *buffer) { 00258 uint32_t sz; 00259 endpointReadResult(EP0OUT, buffer, &sz); 00260 return sz; 00261 } 00262 00263 void USBHAL::EP0write(uint8_t *buffer, uint32_t size) { 00264 endpointWrite(EP0IN, buffer, size); 00265 } 00266 00267 void USBHAL::EP0getWriteResult(void) { 00268 } 00269 00270 void USBHAL::EP0stall(void) { 00271 stallEndpoint(EP0OUT); 00272 } 00273 00274 EP_STATUS USBHAL::endpointRead(uint8_t endpoint, uint32_t maximumSize) { 00275 endpoint = PHY_TO_LOG(endpoint); 00276 uint32_t idx = EP_BDT_IDX(endpoint, RX, 0); 00277 bdt[idx].byte_count = maximumSize; 00278 return EP_PENDING; 00279 } 00280 00281 EP_STATUS USBHAL::endpointReadResult(uint8_t endpoint, uint8_t * buffer, uint32_t *bytesRead) { 00282 uint32_t n, sz, idx, setup = 0; 00283 uint8_t not_iso; 00284 uint8_t * ep_buf; 00285 00286 uint32_t log_endpoint = PHY_TO_LOG(endpoint); 00287 00288 if (endpoint > NUMBER_OF_PHYSICAL_ENDPOINTS - 1) { 00289 return EP_INVALID; 00290 } 00291 00292 // if read on a IN endpoint -> error 00293 if (IN_EP(endpoint)) { 00294 return EP_INVALID; 00295 } 00296 00297 idx = EP_BDT_IDX(log_endpoint, RX, 0); 00298 sz = bdt[idx].byte_count; 00299 not_iso = USB0->ENDPOINT[log_endpoint].ENDPT & USB_ENDPT_EPHSHK_MASK; 00300 00301 //for isochronous endpoint, we don't wait an interrupt 00302 if ((log_endpoint != 0) && not_iso && !(epComplete & EP(endpoint))) { 00303 return EP_PENDING; 00304 } 00305 00306 if ((log_endpoint == 0) && (TOK_PID(idx) == SETUP_TOKEN)) { 00307 setup = 1; 00308 } 00309 00310 // non iso endpoint 00311 if (not_iso) { 00312 ep_buf = endpoint_buffer[idx]; 00313 } else { 00314 ep_buf = endpoint_buffer_iso[0]; 00315 } 00316 00317 for (n = 0; n < sz; n++) { 00318 buffer[n] = ep_buf[n]; 00319 } 00320 00321 if (((Data1 >> endpoint) & 1) == ((bdt[idx].info >> 6) & 1)) { 00322 if (setup && (buffer[6] == 0)) // if no setup data stage, 00323 Data1 &= ~1UL; // set DATA0 00324 else 00325 Data1 ^= (1 << endpoint); 00326 } 00327 00328 if (((Data1 >> endpoint) & 1)) { 00329 bdt[idx].info = BD_DTS_MASK | BD_DATA01_MASK | BD_OWN_MASK; 00330 } 00331 else { 00332 bdt[idx].info = BD_DTS_MASK | BD_OWN_MASK; 00333 } 00334 00335 USB0->CTL &= ~USB_CTL_TXSUSPENDTOKENBUSY_MASK; 00336 *bytesRead = sz; 00337 00338 epComplete &= ~EP(endpoint); 00339 return EP_COMPLETED; 00340 } 00341 00342 EP_STATUS USBHAL::endpointWrite(uint8_t endpoint, uint8_t *data, uint32_t size) { 00343 uint32_t idx, n; 00344 uint8_t * ep_buf; 00345 00346 if (endpoint > NUMBER_OF_PHYSICAL_ENDPOINTS - 1) { 00347 return EP_INVALID; 00348 } 00349 00350 // if write on a OUT endpoint -> error 00351 if (OUT_EP(endpoint)) { 00352 return EP_INVALID; 00353 } 00354 00355 idx = EP_BDT_IDX(PHY_TO_LOG(endpoint), TX, 0); 00356 bdt[idx].byte_count = size; 00357 00358 00359 // non iso endpoint 00360 if (USB0->ENDPOINT[PHY_TO_LOG(endpoint)].ENDPT & USB_ENDPT_EPHSHK_MASK) { 00361 ep_buf = endpoint_buffer[idx]; 00362 } else { 00363 ep_buf = endpoint_buffer_iso[2]; 00364 } 00365 00366 for (n = 0; n < size; n++) { 00367 ep_buf[n] = data[n]; 00368 } 00369 00370 if ((Data1 >> endpoint) & 1) { 00371 bdt[idx].info = BD_OWN_MASK | BD_DTS_MASK; 00372 } else { 00373 bdt[idx].info = BD_OWN_MASK | BD_DTS_MASK | BD_DATA01_MASK; 00374 } 00375 00376 Data1 ^= (1 << endpoint); 00377 00378 return EP_PENDING; 00379 } 00380 00381 EP_STATUS USBHAL::endpointWriteResult(uint8_t endpoint) { 00382 if (epComplete & EP(endpoint)) { 00383 epComplete &= ~EP(endpoint); 00384 return EP_COMPLETED; 00385 } 00386 00387 return EP_PENDING; 00388 } 00389 00390 void USBHAL::stallEndpoint(uint8_t endpoint) { 00391 USB0->ENDPOINT[PHY_TO_LOG(endpoint)].ENDPT |= USB_ENDPT_EPSTALL_MASK; 00392 } 00393 00394 void USBHAL::unstallEndpoint(uint8_t endpoint) { 00395 USB0->ENDPOINT[PHY_TO_LOG(endpoint)].ENDPT &= ~USB_ENDPT_EPSTALL_MASK; 00396 } 00397 00398 bool USBHAL::getEndpointStallState(uint8_t endpoint) { 00399 uint8_t stall = (USB0->ENDPOINT[PHY_TO_LOG(endpoint)].ENDPT & USB_ENDPT_EPSTALL_MASK); 00400 return (stall) ? true : false; 00401 } 00402 00403 void USBHAL::remoteWakeup(void) { 00404 // [TODO] 00405 } 00406 00407 00408 void USBHAL::_usbisr(void) { 00409 instance->usbisr(); 00410 } 00411 00412 00413 void USBHAL::usbisr(void) { 00414 uint8_t i; 00415 uint8_t istat = USB0->ISTAT; 00416 00417 // reset interrupt 00418 if (istat & USB_ISTAT_USBRST_MASK) { 00419 // disable all endpt 00420 for(i = 0; i < 16; i++) { 00421 USB0->ENDPOINT[i].ENDPT = 0x00; 00422 } 00423 00424 // enable control endpoint 00425 realiseEndpoint(EP0OUT, MAX_PACKET_SIZE_EP0, 0); 00426 realiseEndpoint(EP0IN, MAX_PACKET_SIZE_EP0, 0); 00427 00428 Data1 = 0x55555555; 00429 USB0->CTL |= USB_CTL_ODDRST_MASK; 00430 00431 USB0->ISTAT = 0xFF; // clear all interrupt status flags 00432 USB0->ERRSTAT = 0xFF; // clear all error flags 00433 USB0->ERREN = 0xFF; // enable error interrupt sources 00434 USB0->ADDR = 0x00; // set default address 00435 00436 return; 00437 } 00438 00439 // resume interrupt 00440 if (istat & USB_ISTAT_RESUME_MASK) { 00441 USB0->ISTAT = USB_ISTAT_RESUME_MASK; 00442 } 00443 00444 // SOF interrupt 00445 if (istat & USB_ISTAT_SOFTOK_MASK) { 00446 USB0->ISTAT = USB_ISTAT_SOFTOK_MASK; 00447 // SOF event, read frame number 00448 SOF(frameNumber()); 00449 } 00450 00451 // stall interrupt 00452 if (istat & 1<<7) { 00453 if (USB0->ENDPOINT[0].ENDPT & USB_ENDPT_EPSTALL_MASK) 00454 USB0->ENDPOINT[0].ENDPT &= ~USB_ENDPT_EPSTALL_MASK; 00455 USB0->ISTAT |= USB_ISTAT_STALL_MASK; 00456 } 00457 00458 // token interrupt 00459 if (istat & 1<<3) { 00460 uint32_t num = (USB0->STAT >> 4) & 0x0F; 00461 uint32_t dir = (USB0->STAT >> 3) & 0x01; 00462 uint32_t ev_odd = (USB0->STAT >> 2) & 0x01; 00463 00464 // setup packet 00465 if ((num == 0) && (TOK_PID((EP_BDT_IDX(num, dir, ev_odd))) == SETUP_TOKEN)) { 00466 Data1 &= ~0x02; 00467 bdt[EP_BDT_IDX(0, TX, EVEN)].info &= ~BD_OWN_MASK; 00468 bdt[EP_BDT_IDX(0, TX, ODD)].info &= ~BD_OWN_MASK; 00469 00470 // EP0 SETUP event (SETUP data received) 00471 EP0setupCallback(); 00472 00473 } else { 00474 // OUT packet 00475 if (TOK_PID((EP_BDT_IDX(num, dir, ev_odd))) == OUT_TOKEN) { 00476 if (num == 0) 00477 EP0out(); 00478 else { 00479 epComplete |= (1 << EP(num)); 00480 if ((instance->*(epCallback[EP(num) - 2]))()) { 00481 epComplete &= ~(1 << EP(num)); 00482 } 00483 } 00484 } 00485 00486 // IN packet 00487 if (TOK_PID((EP_BDT_IDX(num, dir, ev_odd))) == IN_TOKEN) { 00488 if (num == 0) { 00489 EP0in(); 00490 if (set_addr == 1) { 00491 USB0->ADDR = addr & 0x7F; 00492 set_addr = 0; 00493 } 00494 } 00495 else { 00496 epComplete |= (1 << (EP(num) + 1)); 00497 if ((instance->*(epCallback[EP(num) + 1 - 2]))()) { 00498 epComplete &= ~(1 << (EP(num) + 1)); 00499 } 00500 } 00501 } 00502 } 00503 00504 USB0->ISTAT = USB_ISTAT_TOKDNE_MASK; 00505 } 00506 00507 // sleep interrupt 00508 if (istat & 1<<4) { 00509 USB0->ISTAT |= USB_ISTAT_SLEEP_MASK; 00510 } 00511 00512 // error interrupt 00513 if (istat & USB_ISTAT_ERROR_MASK) { 00514 USB0->ERRSTAT = 0xFF; 00515 USB0->ISTAT |= USB_ISTAT_ERROR_MASK; 00516 } 00517 } 00518 00519 00520 #endif
Generated on Tue Jul 12 2022 19:04:15 by
1.7.2
