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_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 Tue Jul 12 2022 14:14:02 by
