USB device stack with Nucleo F401RE support. NOTE: the default clock config needs to be changed to in order for USB to work.
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
