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