USB device stack
Dependents: blinky_max32630fthr FTHR_USB_serial FTHR_OLED HSP_RPC_GUI_3_0_1 ... more
Fork of USBDevice by
USBHAL_STM32F4.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_STM32F4) 00020 00021 #include "USBHAL.h" 00022 #include "USBRegs_STM32.h" 00023 #include "pinmap.h" 00024 00025 USBHAL * USBHAL::instance; 00026 00027 static volatile int epComplete = 0; 00028 00029 static uint32_t bufferEnd = 0; 00030 static const uint32_t rxFifoSize = 512; 00031 static uint32_t rxFifoCount = 0; 00032 00033 static uint32_t setupBuffer[MAX_PACKET_SIZE_EP0 >> 2]; 00034 00035 uint32_t USBHAL::endpointReadcore(uint8_t endpoint, uint8_t *buffer) { 00036 return 0; 00037 } 00038 00039 USBHAL::USBHAL(void) { 00040 NVIC_DisableIRQ(OTG_FS_IRQn); 00041 epCallback[0] = &USBHAL::EP1_OUT_callback; 00042 epCallback[1] = &USBHAL::EP1_IN_callback; 00043 epCallback[2] = &USBHAL::EP2_OUT_callback; 00044 epCallback[3] = &USBHAL::EP2_IN_callback; 00045 epCallback[4] = &USBHAL::EP3_OUT_callback; 00046 epCallback[5] = &USBHAL::EP3_IN_callback; 00047 00048 // Enable power and clocking 00049 RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN; 00050 00051 #if defined(TARGET_STM32F407VG) || defined(TARGET_STM32F401RE) || defined(TARGET_STM32F411RE) || defined(TARGET_STM32F429ZI) 00052 pin_function(PA_8, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_FS)); 00053 pin_function(PA_9, STM_PIN_DATA(STM_MODE_INPUT, GPIO_PULLDOWN, GPIO_AF10_OTG_FS)); 00054 pin_function(PA_10, STM_PIN_DATA(STM_MODE_AF_OD, GPIO_PULLUP, GPIO_AF10_OTG_FS)); 00055 pin_function(PA_11, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_FS)); 00056 pin_function(PA_12, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_FS)); 00057 #else 00058 pin_function(PA_8, STM_PIN_DATA(2, 10)); 00059 pin_function(PA_9, STM_PIN_DATA(0, 0)); 00060 pin_function(PA_10, STM_PIN_DATA(2, 10)); 00061 pin_function(PA_11, STM_PIN_DATA(2, 10)); 00062 pin_function(PA_12, STM_PIN_DATA(2, 10)); 00063 00064 // Set ID pin to open drain with pull-up resistor 00065 pin_mode(PA_10, OpenDrain); 00066 GPIOA->PUPDR &= ~(0x3 << 20); 00067 GPIOA->PUPDR |= 1 << 20; 00068 00069 // Set VBUS pin to open drain 00070 pin_mode(PA_9, OpenDrain); 00071 #endif 00072 00073 RCC->AHB2ENR |= RCC_AHB2ENR_OTGFSEN; 00074 00075 // Enable interrupts 00076 OTG_FS->GREGS.GAHBCFG |= (1 << 0); 00077 00078 // Turnaround time to maximum value - too small causes packet loss 00079 OTG_FS->GREGS.GUSBCFG |= (0xF << 10); 00080 00081 // Unmask global interrupts 00082 OTG_FS->GREGS.GINTMSK |= (1 << 3) | // SOF 00083 (1 << 4) | // RX FIFO not empty 00084 (1 << 12); // USB reset 00085 00086 OTG_FS->DREGS.DCFG |= (0x3 << 0) | // Full speed 00087 (1 << 2); // Non-zero-length status OUT handshake 00088 00089 OTG_FS->GREGS.GCCFG |= (1 << 19) | // Enable VBUS sensing 00090 (1 << 16); // Power Up 00091 00092 instance = this; 00093 NVIC_SetVector(OTG_FS_IRQn, (uint32_t)&_usbisr); 00094 NVIC_SetPriority(OTG_FS_IRQn, 1); 00095 } 00096 00097 USBHAL::~USBHAL(void) { 00098 } 00099 00100 void USBHAL::connect(void) { 00101 NVIC_EnableIRQ(OTG_FS_IRQn); 00102 } 00103 00104 void USBHAL::disconnect(void) { 00105 NVIC_DisableIRQ(OTG_FS_IRQn); 00106 } 00107 00108 void USBHAL::configureDevice(void) { 00109 // Not needed 00110 } 00111 00112 void USBHAL::unconfigureDevice(void) { 00113 // Not needed 00114 } 00115 00116 void USBHAL::setAddress(uint8_t address) { 00117 OTG_FS->DREGS.DCFG |= (address << 4); 00118 EP0write(0, 0); 00119 } 00120 00121 bool USBHAL::realiseEndpoint(uint8_t endpoint, uint32_t maxPacket, 00122 uint32_t flags) { 00123 uint32_t epIndex = endpoint >> 1; 00124 00125 uint32_t type; 00126 switch (endpoint) { 00127 case EP0IN: 00128 case EP0OUT: 00129 type = 0; 00130 break; 00131 case EPISO_IN: 00132 case EPISO_OUT: 00133 type = 1; 00134 case EPBULK_IN: 00135 case EPBULK_OUT: 00136 type = 2; 00137 break; 00138 case EPINT_IN: 00139 case EPINT_OUT: 00140 type = 3; 00141 break; 00142 } 00143 00144 // Generic in or out EP controls 00145 uint32_t control = (maxPacket << 0) | // Packet size 00146 (1 << 15) | // Active endpoint 00147 (type << 18); // Endpoint type 00148 00149 if (endpoint & 0x1) { // In Endpoint 00150 // Set up the Tx FIFO 00151 if (endpoint == EP0IN) { 00152 OTG_FS->GREGS.DIEPTXF0_HNPTXFSIZ = ((maxPacket >> 2) << 16) | 00153 (bufferEnd << 0); 00154 } 00155 else { 00156 OTG_FS->GREGS.DIEPTXF[epIndex - 1] = ((maxPacket >> 2) << 16) | 00157 (bufferEnd << 0); 00158 } 00159 bufferEnd += maxPacket >> 2; 00160 00161 // Set the In EP specific control settings 00162 if (endpoint != EP0IN) { 00163 control |= (1 << 28); // SD0PID 00164 } 00165 00166 control |= (epIndex << 22) | // TxFIFO index 00167 (1 << 27); // SNAK 00168 OTG_FS->INEP_REGS[epIndex].DIEPCTL = control; 00169 00170 // Unmask the interrupt 00171 OTG_FS->DREGS.DAINTMSK |= (1 << epIndex); 00172 } 00173 else { // Out endpoint 00174 // Set the out EP specific control settings 00175 control |= (1 << 26); // CNAK 00176 OTG_FS->OUTEP_REGS[epIndex].DOEPCTL = control; 00177 00178 // Unmask the interrupt 00179 OTG_FS->DREGS.DAINTMSK |= (1 << (epIndex + 16)); 00180 } 00181 return true; 00182 } 00183 00184 // read setup packet 00185 void USBHAL::EP0setup(uint8_t *buffer) { 00186 memcpy(buffer, setupBuffer, MAX_PACKET_SIZE_EP0); 00187 } 00188 00189 void USBHAL::EP0readStage(void) { 00190 } 00191 00192 void USBHAL::EP0read(void) { 00193 } 00194 00195 uint32_t USBHAL::EP0getReadResult(uint8_t *buffer) { 00196 uint32_t* buffer32 = (uint32_t *) buffer; 00197 uint32_t length = rxFifoCount; 00198 for (uint32_t i = 0; i < length; i += 4) { 00199 buffer32[i >> 2] = OTG_FS->FIFO[0][0]; 00200 } 00201 00202 rxFifoCount = 0; 00203 return length; 00204 } 00205 00206 void USBHAL::EP0write(uint8_t *buffer, uint32_t size) { 00207 endpointWrite(0, buffer, size); 00208 } 00209 00210 void USBHAL::EP0getWriteResult(void) { 00211 } 00212 00213 void USBHAL::EP0stall(void) { 00214 // If we stall the out endpoint here then we have problems transferring 00215 // and setup requests after the (stalled) get device qualifier requests. 00216 // TODO: Find out if this is correct behavior, or whether we are doing 00217 // something else wrong 00218 stallEndpoint(EP0IN); 00219 // stallEndpoint(EP0OUT); 00220 } 00221 00222 EP_STATUS USBHAL::endpointRead(uint8_t endpoint, uint32_t maximumSize) { 00223 uint32_t epIndex = endpoint >> 1; 00224 uint32_t size = (1 << 19) | // 1 packet 00225 (maximumSize << 0); // Packet size 00226 // if (endpoint == EP0OUT) { 00227 size |= (1 << 29); // 1 setup packet 00228 // } 00229 OTG_FS->OUTEP_REGS[epIndex].DOEPTSIZ = size; 00230 OTG_FS->OUTEP_REGS[epIndex].DOEPCTL |= (1 << 31) | // Enable endpoint 00231 (1 << 26); // Clear NAK 00232 00233 epComplete &= ~(1 << endpoint); 00234 return EP_PENDING; 00235 } 00236 00237 EP_STATUS USBHAL::endpointReadResult(uint8_t endpoint, uint8_t * buffer, uint32_t *bytesRead) { 00238 if (!(epComplete & (1 << endpoint))) { 00239 return EP_PENDING; 00240 } 00241 00242 uint32_t* buffer32 = (uint32_t *) buffer; 00243 uint32_t length = rxFifoCount; 00244 for (uint32_t i = 0; i < length; i += 4) { 00245 buffer32[i >> 2] = OTG_FS->FIFO[endpoint >> 1][0]; 00246 } 00247 rxFifoCount = 0; 00248 *bytesRead = length; 00249 return EP_COMPLETED; 00250 } 00251 00252 EP_STATUS USBHAL::endpointWrite(uint8_t endpoint, uint8_t *data, uint32_t size) { 00253 uint32_t epIndex = endpoint >> 1; 00254 OTG_FS->INEP_REGS[epIndex].DIEPTSIZ = (1 << 19) | // 1 packet 00255 (size << 0); // Size of packet 00256 OTG_FS->INEP_REGS[epIndex].DIEPCTL |= (1 << 31) | // Enable endpoint 00257 (1 << 26); // CNAK 00258 OTG_FS->DREGS.DIEPEMPMSK = (1 << epIndex); 00259 00260 while ((OTG_FS->INEP_REGS[epIndex].DTXFSTS & 0XFFFF) < ((size + 3) >> 2)); 00261 00262 for (uint32_t i=0; i<(size + 3) >> 2; i++, data+=4) { 00263 OTG_FS->FIFO[epIndex][0] = *(uint32_t *)data; 00264 } 00265 00266 epComplete &= ~(1 << endpoint); 00267 00268 return EP_PENDING; 00269 } 00270 00271 EP_STATUS USBHAL::endpointWriteResult(uint8_t endpoint) { 00272 if (epComplete & (1 << endpoint)) { 00273 epComplete &= ~(1 << endpoint); 00274 return EP_COMPLETED; 00275 } 00276 00277 return EP_PENDING; 00278 } 00279 00280 void USBHAL::stallEndpoint(uint8_t endpoint) { 00281 if (endpoint & 0x1) { // In EP 00282 OTG_FS->INEP_REGS[endpoint >> 1].DIEPCTL |= (1 << 30) | // Disable 00283 (1 << 21); // Stall 00284 } 00285 else { // Out EP 00286 OTG_FS->DREGS.DCTL |= (1 << 9); // Set global out NAK 00287 OTG_FS->OUTEP_REGS[endpoint >> 1].DOEPCTL |= (1 << 30) | // Disable 00288 (1 << 21); // Stall 00289 } 00290 } 00291 00292 void USBHAL::unstallEndpoint(uint8_t endpoint) { 00293 00294 } 00295 00296 bool USBHAL::getEndpointStallState(uint8_t endpoint) { 00297 return false; 00298 } 00299 00300 void USBHAL::remoteWakeup(void) { 00301 } 00302 00303 00304 void USBHAL::_usbisr(void) { 00305 instance->usbisr(); 00306 } 00307 00308 00309 void USBHAL::usbisr(void) { 00310 if (OTG_FS->GREGS.GINTSTS & (1 << 11)) { // USB Suspend 00311 suspendStateChanged(1); 00312 }; 00313 00314 if (OTG_FS->GREGS.GINTSTS & (1 << 12)) { // USB Reset 00315 suspendStateChanged(0); 00316 00317 // Set SNAK bits 00318 OTG_FS->OUTEP_REGS[0].DOEPCTL |= (1 << 27); 00319 OTG_FS->OUTEP_REGS[1].DOEPCTL |= (1 << 27); 00320 OTG_FS->OUTEP_REGS[2].DOEPCTL |= (1 << 27); 00321 OTG_FS->OUTEP_REGS[3].DOEPCTL |= (1 << 27); 00322 00323 OTG_FS->DREGS.DIEPMSK = (1 << 0); 00324 00325 bufferEnd = 0; 00326 00327 // Set the receive FIFO size 00328 OTG_FS->GREGS.GRXFSIZ = rxFifoSize >> 2; 00329 bufferEnd += rxFifoSize >> 2; 00330 00331 // Create the endpoints, and wait for setup packets on out EP0 00332 realiseEndpoint(EP0IN, MAX_PACKET_SIZE_EP0, 0); 00333 realiseEndpoint(EP0OUT, MAX_PACKET_SIZE_EP0, 0); 00334 endpointRead(EP0OUT, MAX_PACKET_SIZE_EP0); 00335 00336 OTG_FS->GREGS.GINTSTS = (1 << 12); 00337 } 00338 00339 if (OTG_FS->GREGS.GINTSTS & (1 << 4)) { // RX FIFO not empty 00340 uint32_t status = OTG_FS->GREGS.GRXSTSP; 00341 00342 uint32_t endpoint = (status & 0xF) << 1; 00343 uint32_t length = (status >> 4) & 0x7FF; 00344 uint32_t type = (status >> 17) & 0xF; 00345 00346 rxFifoCount = length; 00347 00348 if (type == 0x6) { 00349 // Setup packet 00350 for (uint32_t i=0; i<length; i+=4) { 00351 setupBuffer[i >> 2] = OTG_FS->FIFO[0][i >> 2]; 00352 } 00353 rxFifoCount = 0; 00354 } 00355 00356 if (type == 0x4) { 00357 // Setup complete 00358 EP0setupCallback(); 00359 endpointRead(EP0OUT, MAX_PACKET_SIZE_EP0); 00360 } 00361 00362 if (type == 0x2) { 00363 // Out packet 00364 if (endpoint == EP0OUT) { 00365 EP0out(); 00366 } 00367 else { 00368 epComplete |= (1 << endpoint); 00369 if ((instance->*(epCallback[endpoint - 2]))()) { 00370 epComplete &= (1 << endpoint); 00371 } 00372 } 00373 } 00374 00375 for (uint32_t i=0; i<rxFifoCount; i+=4) { 00376 (void) OTG_FS->FIFO[0][0]; 00377 } 00378 OTG_FS->GREGS.GINTSTS = (1 << 4); 00379 } 00380 00381 if (OTG_FS->GREGS.GINTSTS & (1 << 18)) { // In endpoint interrupt 00382 // Loop through the in endpoints 00383 for (uint32_t i=0; i<4; i++) { 00384 if (OTG_FS->DREGS.DAINT & (1 << i)) { // Interrupt is on endpoint 00385 00386 if (OTG_FS->INEP_REGS[i].DIEPINT & (1 << 7)) {// Tx FIFO empty 00387 // If the Tx FIFO is empty on EP0 we need to send a further 00388 // packet, so call EP0in() 00389 if (i == 0) { 00390 EP0in(); 00391 } 00392 // Clear the interrupt 00393 OTG_FS->INEP_REGS[i].DIEPINT = (1 << 7); 00394 // Stop firing Tx empty interrupts 00395 // Will get turned on again if another write is called 00396 OTG_FS->DREGS.DIEPEMPMSK &= ~(1 << i); 00397 } 00398 00399 // If the transfer is complete 00400 if (OTG_FS->INEP_REGS[i].DIEPINT & (1 << 0)) { // Tx Complete 00401 epComplete |= (1 << (1 + (i << 1))); 00402 OTG_FS->INEP_REGS[i].DIEPINT = (1 << 0); 00403 } 00404 } 00405 } 00406 OTG_FS->GREGS.GINTSTS = (1 << 18); 00407 } 00408 00409 if (OTG_FS->GREGS.GINTSTS & (1 << 3)) { // Start of frame 00410 SOF((OTG_FS->GREGS.GRXSTSR >> 17) & 0xF); 00411 OTG_FS->GREGS.GINTSTS = (1 << 3); 00412 } 00413 } 00414 00415 00416 #endif
Generated on Wed Jul 13 2022 12:44:03 by 1.7.2