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