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_Maxim.cpp
00001 /******************************************************************************* 00002 * Copyright (C) 2015 Maxim Integrated Products, Inc., All Rights Reserved. 00003 * 00004 * Permission is hereby granted, free of charge, to any person obtaining a 00005 * copy of this software and associated documentation files (the "Software"), 00006 * to deal in the Software without restriction, including without limitation 00007 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 00008 * and/or sell copies of the Software, and to permit persons to whom the 00009 * Software is furnished to do so, subject to the following conditions: 00010 * 00011 * The above copyright notice and this permission notice shall be included 00012 * in all copies or substantial portions of the Software. 00013 * 00014 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 00015 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 00016 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 00017 * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES 00018 * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 00019 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 00020 * OTHER DEALINGS IN THE SOFTWARE. 00021 * 00022 * Except as contained in this notice, the name of Maxim Integrated 00023 * Products, Inc. shall not be used except as stated in the Maxim Integrated 00024 * Products, Inc. Branding Policy. 00025 * 00026 * The mere transfer of this software does not imply any licenses 00027 * of trade secrets, proprietary technology, copyrights, patents, 00028 * trademarks, maskwork rights, or any other form of intellectual 00029 * property whatsoever. Maxim Integrated Products, Inc. retains all 00030 * ownership rights. 00031 ******************************************************************************* 00032 */ 00033 00034 #if defined(TARGET_Maxim) 00035 00036 #include "USBHAL.h" 00037 #include "usb_regs.h" 00038 #include "clkman_regs.h" 00039 00040 #define CONNECT_INTS (MXC_F_USB_DEV_INTEN_BRST | MXC_F_USB_DEV_INTEN_SETUP | MXC_F_USB_DEV_INTEN_EP_IN | MXC_F_USB_DEV_INTEN_EP_OUT | MXC_F_USB_DEV_INTEN_DMA_ERR) 00041 00042 USBHAL *USBHAL::instance; 00043 00044 typedef struct { 00045 volatile uint32_t buf0_desc; 00046 volatile uint32_t buf0_address; 00047 volatile uint32_t buf1_desc; 00048 volatile uint32_t buf1_address; 00049 } ep_buffer_t; 00050 00051 typedef struct { 00052 ep_buffer_t out_buffer; 00053 ep_buffer_t in_buffer; 00054 } ep0_buffer_t; 00055 00056 typedef struct { 00057 ep0_buffer_t ep0; 00058 ep_buffer_t ep[MXC_USB_NUM_EP - 1]; 00059 } ep_buffer_descriptor_t; 00060 00061 // Static storage for endpoint buffer descriptor table. Must be 512 byte alligned for DMA. 00062 #ifdef __IAR_SYSTEMS_ICC__ 00063 #pragma data_alignment = 512 00064 #else 00065 __attribute__ ((aligned (512))) 00066 #endif 00067 ep_buffer_descriptor_t ep_buffer_descriptor; 00068 00069 // static storage for temporary data buffers. Must be 32 byte alligned. 00070 #ifdef __IAR_SYSTEMS_ICC__ 00071 #pragma data_alignment = 4 00072 #else 00073 __attribute__ ((aligned (4))) 00074 #endif 00075 static uint8_t aligned_buffer[NUMBER_OF_LOGICAL_ENDPOINTS][MXC_USB_MAX_PACKET]; 00076 00077 // contorl packet state 00078 static enum { 00079 CTRL_NONE = 0, 00080 CTRL_SETUP, 00081 CTRL_OUT, 00082 CTRL_IN, 00083 } control_state; 00084 00085 USBHAL::USBHAL(void) 00086 { 00087 NVIC_DisableIRQ(USB_IRQn); 00088 00089 // The PLL must be enabled for USB 00090 MBED_ASSERT(MXC_CLKMAN->clk_config & MXC_F_CLKMAN_CLK_CONFIG_PLL_ENABLE); 00091 00092 // Enable the USB clock 00093 MXC_CLKMAN->clk_ctrl |= MXC_F_CLKMAN_CLK_CTRL_USB_GATE_N; 00094 00095 // reset the device 00096 MXC_USB->cn = 0; 00097 MXC_USB->cn = 1; 00098 MXC_USB->dev_inten = 0; 00099 MXC_USB->dev_cn = 0; 00100 MXC_USB->dev_cn = MXC_F_USB_DEV_CN_URST; 00101 MXC_USB->dev_cn = 0; 00102 00103 // fill in callback arrays 00104 epCallback[EP0OUT] = NULL; 00105 epCallback[EP0IN] = NULL; 00106 epCallback[EP1OUT] = &USBHAL::EP1_OUT_callback; 00107 epCallback[EP1IN ] = &USBHAL::EP1_IN_callback; 00108 epCallback[EP2OUT] = &USBHAL::EP2_OUT_callback; 00109 epCallback[EP2IN ] = &USBHAL::EP2_IN_callback; 00110 epCallback[EP3OUT] = &USBHAL::EP3_OUT_callback; 00111 epCallback[EP3IN ] = &USBHAL::EP3_IN_callback; 00112 epCallback[EP4OUT] = &USBHAL::EP4_OUT_callback; 00113 epCallback[EP4IN ] = &USBHAL::EP4_IN_callback; 00114 epCallback[EP5OUT] = &USBHAL::EP5_OUT_callback; 00115 epCallback[EP5IN ] = &USBHAL::EP5_IN_callback; 00116 epCallback[EP6OUT] = &USBHAL::EP6_OUT_callback; 00117 epCallback[EP6IN ] = &USBHAL::EP6_IN_callback; 00118 epCallback[EP7OUT] = &USBHAL::EP7_OUT_callback; 00119 epCallback[EP7IN ] = &USBHAL::EP7_IN_callback; 00120 00121 // clear driver state 00122 control_state = CTRL_NONE; 00123 00124 // set the descriptor location 00125 MXC_USB->ep_base = (uint32_t)&ep_buffer_descriptor; 00126 00127 // attach IRQ handler and enable interrupts 00128 instance = this; 00129 NVIC_SetVector(USB_IRQn, (uint32_t)&_usbisr); 00130 NVIC_EnableIRQ(USB_IRQn); 00131 } 00132 00133 USBHAL::~USBHAL(void) 00134 { 00135 MXC_USB->dev_cn = MXC_F_USB_DEV_CN_URST; 00136 MXC_USB->dev_cn = 0; 00137 MXC_USB->cn = 0; 00138 } 00139 00140 void USBHAL::connect(void) 00141 { 00142 // enable interrupts 00143 MXC_USB->dev_inten |= CONNECT_INTS; 00144 00145 // allow interrupts on ep0 00146 MXC_USB->ep[0] |= MXC_F_USB_EP_INT_EN; 00147 00148 // pullup enable 00149 MXC_USB->dev_cn |= (MXC_F_USB_DEV_CN_CONNECT | MXC_F_USB_DEV_CN_FIFO_MODE); 00150 } 00151 00152 void USBHAL::disconnect(void) 00153 { 00154 // disable interrupts 00155 MXC_USB->dev_inten &= ~CONNECT_INTS; 00156 00157 // disable pullup 00158 MXC_USB->dev_cn &= ~MXC_F_USB_DEV_CN_CONNECT; 00159 } 00160 00161 void USBHAL::configureDevice(void) 00162 { 00163 // do nothing 00164 } 00165 00166 void USBHAL::unconfigureDevice(void) 00167 { 00168 // reset endpoints 00169 for (int i = 0; i < MXC_USB_NUM_EP; i++) { 00170 // Disable endpoint and clear the data toggle 00171 MXC_USB->ep[i] &= ~MXC_F_USB_EP_DIR; 00172 MXC_USB->ep[i] |= MXC_F_USB_EP_DT; 00173 } 00174 } 00175 00176 void USBHAL::setAddress(uint8_t address) 00177 { 00178 // do nothing 00179 } 00180 00181 void USBHAL::remoteWakeup(void) 00182 { 00183 // do nothing 00184 } 00185 00186 static ep_buffer_t *get_desc(uint8_t endpoint) 00187 { 00188 uint8_t epnum = EP_NUM(endpoint); 00189 ep_buffer_t *desc; 00190 00191 if (epnum == 0) { 00192 if (IN_EP(endpoint)) { 00193 desc = &ep_buffer_descriptor.ep0.in_buffer; 00194 } else { 00195 desc = &ep_buffer_descriptor.ep0.out_buffer; 00196 } 00197 } else { 00198 desc = &ep_buffer_descriptor.ep[epnum - 1]; 00199 } 00200 00201 return desc; 00202 } 00203 00204 void USBHAL::EP0setup(uint8_t *buffer) 00205 { 00206 memcpy(buffer, (void*)&MXC_USB->setup0, 8); // setup packet is fixed at 8 bytes 00207 } 00208 00209 void USBHAL::EP0read(void) 00210 { 00211 if (control_state == CTRL_IN) { 00212 // This is the status stage. ACK. 00213 MXC_USB->ep[0] |= MXC_F_USB_EP_ST_ACK; 00214 control_state = CTRL_NONE; 00215 return; 00216 } 00217 00218 control_state = CTRL_OUT; 00219 00220 endpointRead(EP0OUT, MAX_PACKET_SIZE_EP0); 00221 } 00222 00223 void USBHAL::EP0readStage(void) 00224 { 00225 // do nothing 00226 } 00227 00228 uint32_t USBHAL::EP0getReadResult(uint8_t *buffer) 00229 { 00230 uint32_t size; 00231 00232 if (MXC_USB->out_owner & 1) { 00233 return 0; 00234 } 00235 00236 // get the packet length and contents 00237 ep_buffer_t *desc = get_desc(EP0OUT); 00238 size = desc->buf0_desc; 00239 memcpy(buffer, aligned_buffer[0], size); 00240 00241 return size; 00242 } 00243 00244 void USBHAL::EP0write(uint8_t *buffer, uint32_t size) 00245 { 00246 if ((size == 0) && (control_state != CTRL_IN)) { 00247 // This is a status stage ACK. Handle in hardware. 00248 MXC_USB->ep[0] |= MXC_F_USB_EP_ST_ACK; 00249 control_state = CTRL_NONE; 00250 return; 00251 } 00252 00253 control_state = CTRL_IN; 00254 00255 endpointWrite(EP0IN, buffer, size); 00256 } 00257 00258 void USBHAL::EP0stall(void) 00259 { 00260 stallEndpoint(0); 00261 } 00262 00263 EP_STATUS USBHAL::endpointRead(uint8_t endpoint, uint32_t maximumSize) 00264 { 00265 uint8_t epnum = EP_NUM(endpoint); 00266 00267 if ((endpoint >= NUMBER_OF_PHYSICAL_ENDPOINTS) || IN_EP(endpoint)) { 00268 return EP_INVALID; 00269 } 00270 00271 if (maximumSize > MXC_USB_MAX_PACKET) { 00272 return EP_INVALID; 00273 } 00274 00275 uint32_t mask = (1 << epnum); 00276 if (MXC_USB->out_owner & mask) { 00277 return EP_INVALID; 00278 } 00279 00280 ep_buffer_t *desc = get_desc(endpoint); 00281 desc->buf0_desc = maximumSize; 00282 desc->buf0_address = (uint32_t)aligned_buffer[epnum]; 00283 00284 MXC_USB->out_owner = mask; 00285 00286 return EP_PENDING; 00287 } 00288 00289 EP_STATUS USBHAL::endpointReadResult(uint8_t endpoint, uint8_t *data, uint32_t *bytesRead) 00290 { 00291 if ((endpoint >= NUMBER_OF_PHYSICAL_ENDPOINTS) || IN_EP(endpoint)) { 00292 return EP_INVALID; 00293 } 00294 00295 uint32_t mask = (1 << EP_NUM(endpoint)); 00296 if (MXC_USB->out_owner & mask) { 00297 return EP_PENDING; 00298 } 00299 00300 // get the packet length and contents 00301 ep_buffer_t *desc = get_desc(endpoint); 00302 *bytesRead = desc->buf0_desc; 00303 memcpy(data, aligned_buffer[EP_NUM(endpoint)], *bytesRead); 00304 00305 return EP_COMPLETED; 00306 } 00307 00308 EP_STATUS USBHAL::endpointWrite(uint8_t endpoint, uint8_t *data, uint32_t size) 00309 { 00310 uint8_t epnum = EP_NUM(endpoint); 00311 00312 if ((endpoint >= NUMBER_OF_PHYSICAL_ENDPOINTS) || OUT_EP(endpoint)) { 00313 return EP_INVALID; 00314 } 00315 00316 if (size > MXC_USB_MAX_PACKET) { 00317 return EP_INVALID; 00318 } 00319 00320 uint32_t mask = (1 << epnum); 00321 if (MXC_USB->in_owner & mask) { 00322 return EP_INVALID; 00323 } 00324 00325 memcpy(aligned_buffer[epnum], data, size); 00326 00327 ep_buffer_t *desc = get_desc(endpoint); 00328 desc->buf0_desc = size; 00329 desc->buf0_address = (uint32_t)aligned_buffer[epnum]; 00330 00331 // start the DMA 00332 MXC_USB->in_owner = mask; 00333 00334 return EP_PENDING; 00335 } 00336 00337 EP_STATUS USBHAL::endpointWriteResult(uint8_t endpoint) 00338 { 00339 uint32_t mask = (1 << EP_NUM(endpoint)); 00340 if (MXC_USB->in_owner & mask) { 00341 return EP_PENDING; 00342 } 00343 00344 return EP_COMPLETED; 00345 } 00346 00347 void USBHAL::stallEndpoint(uint8_t endpoint) 00348 { 00349 uint8_t epnum = EP_NUM(endpoint); 00350 00351 if (epnum == 0) { 00352 MXC_USB->ep[epnum] |= MXC_F_USB_EP_ST_STALL; 00353 } 00354 00355 MXC_USB->ep[epnum] |= MXC_F_USB_EP_STALL; 00356 } 00357 00358 void USBHAL::unstallEndpoint(uint8_t endpoint) 00359 { 00360 MXC_USB->ep[EP_NUM(endpoint)] &= ~MXC_F_USB_EP_STALL; 00361 } 00362 00363 bool USBHAL::realiseEndpoint(uint8_t endpoint, uint32_t maxPacket, uint32_t options) 00364 { 00365 uint8_t epnum = EP_NUM(endpoint); 00366 uint32_t ep_ctrl; 00367 00368 if (epnum >= NUMBER_OF_PHYSICAL_ENDPOINTS) { 00369 return false; 00370 } 00371 00372 if (IN_EP(endpoint)) { 00373 ep_ctrl = (MXC_V_USB_EP_DIR_IN << MXC_F_USB_EP_DIR_POS); 00374 } else { 00375 ep_ctrl = (MXC_S_USB_EP_DIR_OUT << MXC_F_USB_EP_DIR_POS); 00376 } 00377 00378 ep_ctrl |= (MXC_F_USB_EP_DT | MXC_F_USB_EP_INT_EN); 00379 00380 MXC_USB->ep[epnum] = ep_ctrl; 00381 00382 return true; 00383 } 00384 00385 bool USBHAL::getEndpointStallState(unsigned char endpoint) 00386 { 00387 return !!(MXC_USB->ep[endpoint] & MXC_F_USB_EP_STALL); 00388 } 00389 00390 void USBHAL::_usbisr(void) 00391 { 00392 instance->usbisr(); 00393 } 00394 00395 void USBHAL::usbisr(void) 00396 { 00397 // get and clear irqs 00398 uint32_t irq_flags = MXC_USB->dev_intfl; 00399 MXC_USB->dev_intfl = irq_flags; 00400 00401 // process only enabled interrupts 00402 irq_flags &= MXC_USB->dev_inten; 00403 00404 // suspend 00405 if (irq_flags & MXC_F_USB_DEV_INTFL_SUSP) { 00406 suspendStateChanged(1); 00407 } 00408 00409 // bus reset 00410 if (irq_flags & MXC_F_USB_DEV_INTFL_BRST) { 00411 00412 // reset endpoints 00413 for (int i = 0; i < MXC_USB_NUM_EP; i++) { 00414 // Disable endpoint and clear the data toggle 00415 MXC_USB->ep[i] &= ~MXC_F_USB_EP_DIR; 00416 MXC_USB->ep[i] |= MXC_F_USB_EP_DT; 00417 } 00418 00419 // clear driver state 00420 control_state = CTRL_NONE; 00421 00422 busReset(); 00423 00424 // no need to process events after reset 00425 return; 00426 } 00427 00428 // Setup packet 00429 if (irq_flags & MXC_F_USB_DEV_INTFL_SETUP) { 00430 control_state = CTRL_SETUP; 00431 EP0setupCallback(); 00432 } 00433 00434 // IN packets 00435 if (irq_flags & MXC_F_USB_DEV_INTFL_EP_IN) { 00436 // get and clear IN irqs 00437 uint32_t in_irqs = MXC_USB->in_int; 00438 MXC_USB->in_int = in_irqs; 00439 00440 if (in_irqs & 1) { 00441 EP0in(); 00442 } 00443 00444 for (uint8_t epnum = 1; epnum < NUMBER_OF_LOGICAL_ENDPOINTS; epnum++) { 00445 uint32_t irq_mask = (1 << epnum); 00446 if (in_irqs & irq_mask) { 00447 uint8_t endpoint = (epnum << 1) | DIR_IN; 00448 (instance->*(epCallback[endpoint]))(); 00449 } 00450 } 00451 } 00452 00453 // OUT packets 00454 if (irq_flags & MXC_F_USB_DEV_INTFL_EP_OUT) { 00455 // get and clear OUT irqs 00456 uint32_t out_irqs = MXC_USB->out_int; 00457 MXC_USB->out_int = out_irqs; 00458 00459 if (out_irqs & 1) { 00460 EP0out(); 00461 } 00462 00463 for (uint8_t epnum = 1; epnum < NUMBER_OF_LOGICAL_ENDPOINTS; epnum++) { 00464 uint32_t irq_mask = (1 << epnum); 00465 if (out_irqs & irq_mask) { 00466 uint8_t endpoint = (epnum << 1) | DIR_OUT; 00467 (instance->*(epCallback[endpoint]))(); 00468 } 00469 } 00470 } 00471 } 00472 00473 #endif
Generated on Tue Jul 12 2022 14:14:02 by
