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