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