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) 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 << 12)) { // USB Reset 00311 // Set SNAK bits 00312 OTG_FS->OUTEP_REGS[0].DOEPCTL |= (1 << 27); 00313 OTG_FS->OUTEP_REGS[1].DOEPCTL |= (1 << 27); 00314 OTG_FS->OUTEP_REGS[2].DOEPCTL |= (1 << 27); 00315 OTG_FS->OUTEP_REGS[3].DOEPCTL |= (1 << 27); 00316 00317 OTG_FS->DREGS.DIEPMSK = (1 << 0); 00318 00319 bufferEnd = 0; 00320 00321 // Set the receive FIFO size 00322 OTG_FS->GREGS.GRXFSIZ = rxFifoSize >> 2; 00323 bufferEnd += rxFifoSize >> 2; 00324 00325 // Create the endpoints, and wait for setup packets on out EP0 00326 realiseEndpoint(EP0IN, MAX_PACKET_SIZE_EP0, 0); 00327 realiseEndpoint(EP0OUT, MAX_PACKET_SIZE_EP0, 0); 00328 endpointRead(EP0OUT, MAX_PACKET_SIZE_EP0); 00329 00330 OTG_FS->GREGS.GINTSTS = (1 << 12); 00331 } 00332 00333 if (OTG_FS->GREGS.GINTSTS & (1 << 4)) { // RX FIFO not empty 00334 uint32_t status = OTG_FS->GREGS.GRXSTSP; 00335 00336 uint32_t endpoint = (status & 0xF) << 1; 00337 uint32_t length = (status >> 4) & 0x7FF; 00338 uint32_t type = (status >> 17) & 0xF; 00339 00340 rxFifoCount = length; 00341 00342 if (type == 0x6) { 00343 // Setup packet 00344 for (uint32_t i=0; i<length; i+=4) { 00345 setupBuffer[i >> 2] = OTG_FS->FIFO[0][i >> 2]; 00346 } 00347 rxFifoCount = 0; 00348 } 00349 00350 if (type == 0x4) { 00351 // Setup complete 00352 EP0setupCallback(); 00353 endpointRead(EP0OUT, MAX_PACKET_SIZE_EP0); 00354 } 00355 00356 if (type == 0x2) { 00357 // Out packet 00358 if (endpoint == EP0OUT) { 00359 EP0out(); 00360 } 00361 else { 00362 epComplete |= (1 << endpoint); 00363 if ((instance->*(epCallback[endpoint - 2]))()) { 00364 epComplete &= (1 << endpoint); 00365 } 00366 } 00367 } 00368 00369 for (uint32_t i=0; i<rxFifoCount; i+=4) { 00370 (void) OTG_FS->FIFO[0][0]; 00371 } 00372 OTG_FS->GREGS.GINTSTS = (1 << 4); 00373 } 00374 00375 if (OTG_FS->GREGS.GINTSTS & (1 << 18)) { // In endpoint interrupt 00376 // Loop through the in endpoints 00377 for (uint32_t i=0; i<4; i++) { 00378 if (OTG_FS->DREGS.DAINT & (1 << i)) { // Interrupt is on endpoint 00379 00380 if (OTG_FS->INEP_REGS[i].DIEPINT & (1 << 7)) {// Tx FIFO empty 00381 // If the Tx FIFO is empty on EP0 we need to send a further 00382 // packet, so call EP0in() 00383 if (i == 0) { 00384 EP0in(); 00385 } 00386 // Clear the interrupt 00387 OTG_FS->INEP_REGS[i].DIEPINT = (1 << 7); 00388 // Stop firing Tx empty interrupts 00389 // Will get turned on again if another write is called 00390 OTG_FS->DREGS.DIEPEMPMSK &= ~(1 << i); 00391 } 00392 00393 // If the transfer is complete 00394 if (OTG_FS->INEP_REGS[i].DIEPINT & (1 << 0)) { // Tx Complete 00395 epComplete |= (1 << (1 + (i << 1))); 00396 OTG_FS->INEP_REGS[i].DIEPINT = (1 << 0); 00397 } 00398 } 00399 } 00400 OTG_FS->GREGS.GINTSTS = (1 << 18); 00401 } 00402 00403 if (OTG_FS->GREGS.GINTSTS & (1 << 3)) { // Start of frame 00404 SOF((OTG_FS->GREGS.GRXSTSR >> 17) & 0xF); 00405 OTG_FS->GREGS.GINTSTS = (1 << 3); 00406 } 00407 } 00408 00409 00410 #endif
Generated on Tue Jul 12 2022 20:45:31 by
 1.7.2
 1.7.2 
    