Fork of https://developer.mbed.org/users/bscott/code/STM32_USBDevice/
Fork of STM32_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, const 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 Wed Jul 13 2022 00:18:45 by 1.7.2