USBDevice for STM support
Dependents: Nucleo_Usb_JoyMouse Nucleo_usbmouse ELEC350_1-referral-2018-usb-hid USBJoystick_HelloWorld2_wip ... more
USBHAL_Maxim.cpp
00001 /******************************************************************************* 00002 * Copyright (C) 2016 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 aligned 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 aligned. 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 // control 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 #if defined(TARGET_MAX32600) 00090 // The PLL must be enabled for USB 00091 MBED_ASSERT(MXC_CLKMAN->clk_config & MXC_F_CLKMAN_CLK_CONFIG_PLL_ENABLE); 00092 00093 // Enable the USB clock 00094 MXC_CLKMAN->clk_ctrl |= MXC_F_CLKMAN_CLK_CTRL_USB_GATE_N; 00095 #elif defined(TARGET_MAX32620) 00096 // Enable the USB clock 00097 MXC_CLKMAN->clk_ctrl |= MXC_F_CLKMAN_CLK_CTRL_USB_CLOCK_ENABLE; 00098 #endif 00099 00100 // reset the device 00101 MXC_USB->cn = 0; 00102 MXC_USB->cn = MXC_F_USB_CN_USB_EN; 00103 MXC_USB->dev_inten = 0; 00104 MXC_USB->dev_cn = 0; 00105 MXC_USB->dev_cn = MXC_F_USB_DEV_CN_URST; 00106 MXC_USB->dev_cn = 0; 00107 00108 // fill in callback arrays 00109 epCallback[EP0OUT] = NULL; 00110 epCallback[EP0IN] = NULL; 00111 epCallback[EP1OUT] = &USBHAL::EP1_OUT_callback; 00112 epCallback[EP1IN ] = &USBHAL::EP1_IN_callback; 00113 epCallback[EP2OUT] = &USBHAL::EP2_OUT_callback; 00114 epCallback[EP2IN ] = &USBHAL::EP2_IN_callback; 00115 epCallback[EP3OUT] = &USBHAL::EP3_OUT_callback; 00116 epCallback[EP3IN ] = &USBHAL::EP3_IN_callback; 00117 epCallback[EP4OUT] = &USBHAL::EP4_OUT_callback; 00118 epCallback[EP4IN ] = &USBHAL::EP4_IN_callback; 00119 epCallback[EP5OUT] = &USBHAL::EP5_OUT_callback; 00120 epCallback[EP5IN ] = &USBHAL::EP5_IN_callback; 00121 epCallback[EP6OUT] = &USBHAL::EP6_OUT_callback; 00122 epCallback[EP6IN ] = &USBHAL::EP6_IN_callback; 00123 epCallback[EP7OUT] = &USBHAL::EP7_OUT_callback; 00124 epCallback[EP7IN ] = &USBHAL::EP7_IN_callback; 00125 00126 // clear driver state 00127 control_state = CTRL_NONE; 00128 00129 // set the descriptor location 00130 MXC_USB->ep_base = (uint32_t)&ep_buffer_descriptor; 00131 00132 // enable VBUS interrupts 00133 MXC_USB->dev_inten = MXC_F_USB_DEV_INTEN_NO_VBUS | MXC_F_USB_DEV_INTEN_VBUS; 00134 00135 // attach IRQ handler and enable interrupts 00136 instance = this; 00137 NVIC_SetVector(USB_IRQn, (uint32_t)&_usbisr); 00138 NVIC_EnableIRQ(USB_IRQn); 00139 } 00140 00141 USBHAL::~USBHAL(void) 00142 { 00143 MXC_USB->dev_cn = MXC_F_USB_DEV_CN_URST; 00144 MXC_USB->dev_cn = 0; 00145 MXC_USB->cn = 0; 00146 } 00147 00148 void USBHAL::connect(void) 00149 { 00150 // enable interrupts 00151 MXC_USB->dev_inten |= CONNECT_INTS; 00152 00153 // allow interrupts on ep0 00154 MXC_USB->ep[0] |= MXC_F_USB_EP_INT_EN; 00155 00156 // pullup enable 00157 MXC_USB->dev_cn |= (MXC_F_USB_DEV_CN_CONNECT | MXC_F_USB_DEV_CN_FIFO_MODE); 00158 } 00159 00160 void USBHAL::disconnect(void) 00161 { 00162 // disable interrupts 00163 MXC_USB->dev_inten &= ~CONNECT_INTS; 00164 00165 // disable pullup 00166 MXC_USB->dev_cn &= ~MXC_F_USB_DEV_CN_CONNECT; 00167 } 00168 00169 void USBHAL::configureDevice(void) 00170 { 00171 // do nothing 00172 } 00173 00174 void USBHAL::unconfigureDevice(void) 00175 { 00176 // reset endpoints 00177 for (int i = 0; i < MXC_USB_NUM_EP; i++) { 00178 // Disable endpoint and clear the data toggle 00179 MXC_USB->ep[i] &= ~MXC_F_USB_EP_DIR; 00180 MXC_USB->ep[i] |= MXC_F_USB_EP_DT; 00181 } 00182 } 00183 00184 void USBHAL::setAddress(uint8_t address) 00185 { 00186 // do nothing 00187 } 00188 00189 void USBHAL::remoteWakeup(void) 00190 { 00191 // do nothing 00192 } 00193 00194 static ep_buffer_t *get_desc(uint8_t endpoint) 00195 { 00196 uint8_t epnum = EP_NUM(endpoint); 00197 ep_buffer_t *desc; 00198 00199 if (epnum == 0) { 00200 if (IN_EP(endpoint)) { 00201 desc = &ep_buffer_descriptor.ep0.in_buffer; 00202 } else { 00203 desc = &ep_buffer_descriptor.ep0.out_buffer; 00204 } 00205 } else { 00206 desc = &ep_buffer_descriptor.ep[epnum - 1]; 00207 } 00208 00209 return desc; 00210 } 00211 00212 void USBHAL::EP0setup(uint8_t *buffer) 00213 { 00214 // Setup packet is fixed at 8 bytes 00215 // Setup registers cannot be read in byte mode 00216 uint32_t *ptr32 = (uint32_t*)buffer; 00217 ptr32[0] = (uint32_t)MXC_USB->setup0; 00218 ptr32[1] = (uint32_t)MXC_USB->setup1; 00219 } 00220 00221 void USBHAL::EP0read(void) 00222 { 00223 if (control_state == CTRL_IN) { 00224 // This is the status stage. ACK. 00225 MXC_USB->ep[0] |= MXC_F_USB_EP_ST_ACK; 00226 control_state = CTRL_NONE; 00227 return; 00228 } 00229 00230 control_state = CTRL_OUT; 00231 00232 endpointRead(EP0OUT, MAX_PACKET_SIZE_EP0); 00233 } 00234 00235 void USBHAL::EP0readStage(void) 00236 { 00237 // do nothing 00238 } 00239 00240 uint32_t USBHAL::EP0getReadResult(uint8_t *buffer) 00241 { 00242 uint32_t size; 00243 00244 if (MXC_USB->out_owner & 1) { 00245 return 0; 00246 } 00247 00248 // get the packet length and contents 00249 ep_buffer_t *desc = get_desc(EP0OUT); 00250 size = desc->buf0_desc; 00251 memcpy(buffer, aligned_buffer[0], size); 00252 00253 return size; 00254 } 00255 00256 void USBHAL::EP0write(uint8_t *buffer, uint32_t size) 00257 { 00258 if ((size == 0) && (control_state != CTRL_IN)) { 00259 // This is a status stage ACK. Handle in hardware. 00260 MXC_USB->ep[0] |= MXC_F_USB_EP_ST_ACK; 00261 control_state = CTRL_NONE; 00262 return; 00263 } 00264 00265 control_state = CTRL_IN; 00266 00267 endpointWrite(EP0IN, buffer, size); 00268 } 00269 00270 void USBHAL::EP0stall(void) 00271 { 00272 stallEndpoint(0); 00273 } 00274 00275 EP_STATUS USBHAL::endpointRead(uint8_t endpoint, uint32_t maximumSize) 00276 { 00277 uint8_t epnum = EP_NUM(endpoint); 00278 00279 if ((endpoint >= NUMBER_OF_PHYSICAL_ENDPOINTS) || IN_EP(endpoint)) { 00280 return EP_INVALID; 00281 } 00282 00283 if (maximumSize > MXC_USB_MAX_PACKET) { 00284 return EP_INVALID; 00285 } 00286 00287 uint32_t mask = (1 << epnum); 00288 if (MXC_USB->out_owner & mask) { 00289 return EP_INVALID; 00290 } 00291 00292 ep_buffer_t *desc = get_desc(endpoint); 00293 desc->buf0_desc = maximumSize; 00294 desc->buf0_address = (uint32_t)aligned_buffer[epnum]; 00295 00296 MXC_USB->out_owner = mask; 00297 00298 return EP_PENDING; 00299 } 00300 00301 EP_STATUS USBHAL::endpointReadResult(uint8_t endpoint, uint8_t *data, uint32_t *bytesRead) 00302 { 00303 if ((endpoint >= NUMBER_OF_PHYSICAL_ENDPOINTS) || IN_EP(endpoint)) { 00304 return EP_INVALID; 00305 } 00306 00307 uint32_t mask = (1 << EP_NUM(endpoint)); 00308 if (MXC_USB->out_owner & mask) { 00309 return EP_PENDING; 00310 } 00311 00312 // get the packet length and contents 00313 ep_buffer_t *desc = get_desc(endpoint); 00314 *bytesRead = desc->buf0_desc; 00315 memcpy(data, aligned_buffer[EP_NUM(endpoint)], *bytesRead); 00316 00317 return EP_COMPLETED; 00318 } 00319 00320 EP_STATUS USBHAL::endpointWrite(uint8_t endpoint, uint8_t *data, uint32_t size) 00321 { 00322 uint8_t epnum = EP_NUM(endpoint); 00323 00324 if ((endpoint >= NUMBER_OF_PHYSICAL_ENDPOINTS) || OUT_EP(endpoint)) { 00325 return EP_INVALID; 00326 } 00327 00328 if (size > MXC_USB_MAX_PACKET) { 00329 return EP_INVALID; 00330 } 00331 00332 uint32_t mask = (1 << epnum); 00333 if (MXC_USB->in_owner & mask) { 00334 return EP_INVALID; 00335 } 00336 00337 memcpy(aligned_buffer[epnum], data, size); 00338 00339 ep_buffer_t *desc = get_desc(endpoint); 00340 desc->buf0_desc = size; 00341 desc->buf0_address = (uint32_t)aligned_buffer[epnum]; 00342 00343 // start the DMA 00344 MXC_USB->in_owner = mask; 00345 00346 return EP_PENDING; 00347 } 00348 00349 EP_STATUS USBHAL::endpointWriteResult(uint8_t endpoint) 00350 { 00351 uint32_t mask = (1 << EP_NUM(endpoint)); 00352 if (MXC_USB->in_owner & mask) { 00353 return EP_PENDING; 00354 } 00355 00356 return EP_COMPLETED; 00357 } 00358 00359 void USBHAL::stallEndpoint(uint8_t endpoint) 00360 { 00361 uint8_t epnum = EP_NUM(endpoint); 00362 00363 if (epnum == 0) { 00364 MXC_USB->ep[epnum] |= MXC_F_USB_EP_ST_STALL; 00365 } 00366 00367 MXC_USB->ep[epnum] |= MXC_F_USB_EP_STALL; 00368 } 00369 00370 void USBHAL::unstallEndpoint(uint8_t endpoint) 00371 { 00372 MXC_USB->ep[EP_NUM(endpoint)] &= ~MXC_F_USB_EP_STALL; 00373 } 00374 00375 bool USBHAL::realiseEndpoint(uint8_t endpoint, uint32_t maxPacket, uint32_t options) 00376 { 00377 uint8_t epnum = EP_NUM(endpoint); 00378 uint32_t ep_ctrl; 00379 00380 if (epnum >= NUMBER_OF_PHYSICAL_ENDPOINTS) { 00381 return false; 00382 } 00383 00384 if (IN_EP(endpoint)) { 00385 ep_ctrl = (MXC_V_USB_EP_DIR_IN << MXC_F_USB_EP_DIR_POS); 00386 } else { 00387 ep_ctrl = (MXC_S_USB_EP_DIR_OUT << MXC_F_USB_EP_DIR_POS); 00388 } 00389 00390 ep_ctrl |= (MXC_F_USB_EP_DT | MXC_F_USB_EP_INT_EN); 00391 00392 MXC_USB->ep[epnum] = ep_ctrl; 00393 00394 return true; 00395 } 00396 00397 bool USBHAL::getEndpointStallState(unsigned char endpoint) 00398 { 00399 return !!(MXC_USB->ep[endpoint] & MXC_F_USB_EP_STALL); 00400 } 00401 00402 void USBHAL::_usbisr(void) 00403 { 00404 instance->usbisr(); 00405 } 00406 00407 void USBHAL::usbisr(void) 00408 { 00409 // get and clear irqs 00410 uint32_t irq_flags = MXC_USB->dev_intfl; 00411 MXC_USB->dev_intfl = irq_flags; 00412 00413 // process only enabled interrupts 00414 irq_flags &= MXC_USB->dev_inten; 00415 00416 // suspend 00417 if (irq_flags & MXC_F_USB_DEV_INTFL_SUSP) { 00418 suspendStateChanged(1); 00419 } 00420 00421 // bus reset 00422 if (irq_flags & MXC_F_USB_DEV_INTFL_BRST) { 00423 00424 // reset endpoints 00425 for (int i = 0; i < MXC_USB_NUM_EP; i++) { 00426 // Disable endpoint and clear the data toggle 00427 MXC_USB->ep[i] &= ~MXC_F_USB_EP_DIR; 00428 MXC_USB->ep[i] |= MXC_F_USB_EP_DT; 00429 } 00430 00431 // clear driver state 00432 control_state = CTRL_NONE; 00433 00434 busReset(); 00435 00436 // no need to process events after reset 00437 return; 00438 } 00439 00440 // Setup packet 00441 if (irq_flags & MXC_F_USB_DEV_INTFL_SETUP) { 00442 control_state = CTRL_SETUP; 00443 EP0setupCallback(); 00444 } 00445 00446 // IN packets 00447 if (irq_flags & MXC_F_USB_DEV_INTFL_EP_IN) { 00448 // get and clear IN irqs 00449 uint32_t in_irqs = MXC_USB->in_int; 00450 MXC_USB->in_int = in_irqs; 00451 00452 if (in_irqs & 1) { 00453 EP0in(); 00454 } 00455 00456 for (uint8_t epnum = 1; epnum < NUMBER_OF_LOGICAL_ENDPOINTS; epnum++) { 00457 uint32_t irq_mask = (1 << epnum); 00458 if (in_irqs & irq_mask) { 00459 uint8_t endpoint = (epnum << 1) | DIR_IN; 00460 (instance->*(epCallback[endpoint]))(); 00461 } 00462 } 00463 } 00464 00465 // OUT packets 00466 if (irq_flags & MXC_F_USB_DEV_INTFL_EP_OUT) { 00467 // get and clear OUT irqs 00468 uint32_t out_irqs = MXC_USB->out_int; 00469 MXC_USB->out_int = out_irqs; 00470 00471 if (out_irqs & 1) { 00472 EP0out(); 00473 } 00474 00475 for (uint8_t epnum = 1; epnum < NUMBER_OF_LOGICAL_ENDPOINTS; epnum++) { 00476 uint32_t irq_mask = (1 << epnum); 00477 if (out_irqs & irq_mask) { 00478 uint8_t endpoint = (epnum << 1) | DIR_OUT; 00479 (instance->*(epCallback[endpoint]))(); 00480 } 00481 } 00482 } 00483 } 00484 00485 #endif
Generated on Fri Jul 15 2022 18:52:59 by 1.7.2