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