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 gr-peach-opencv-project-sd-card by
USBHALHost_LPC17.cpp
00001 /* mbed USBHost Library 00002 * Copyright (c) 2006-2013 ARM Limited 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 00017 #if defined(TARGET_LPC1768) || defined(TARGET_LPC2460) 00018 00019 #include "mbed.h" 00020 #include "USBHALHost.h" 00021 #include "dbg.h" 00022 00023 // bits of the USB/OTG clock control register 00024 #define HOST_CLK_EN (1<<0) 00025 #define DEV_CLK_EN (1<<1) 00026 #define PORTSEL_CLK_EN (1<<3) 00027 #define AHB_CLK_EN (1<<4) 00028 00029 // bits of the USB/OTG clock status register 00030 #define HOST_CLK_ON (1<<0) 00031 #define DEV_CLK_ON (1<<1) 00032 #define PORTSEL_CLK_ON (1<<3) 00033 #define AHB_CLK_ON (1<<4) 00034 00035 // we need host clock, OTG/portsel clock and AHB clock 00036 #define CLOCK_MASK (HOST_CLK_EN | PORTSEL_CLK_EN | AHB_CLK_EN) 00037 00038 #define HCCA_SIZE sizeof(HCCA) 00039 #define ED_SIZE sizeof(HCED) 00040 #define TD_SIZE sizeof(HCTD) 00041 00042 #define TOTAL_SIZE (HCCA_SIZE + (MAX_ENDPOINT*ED_SIZE) + (MAX_TD*TD_SIZE)) 00043 00044 static volatile uint8_t usb_buf[TOTAL_SIZE] __attribute((section("AHBSRAM1"),aligned(256))); //256 bytes aligned! 00045 00046 USBHALHost * USBHALHost::instHost; 00047 00048 USBHALHost::USBHALHost() { 00049 instHost = this; 00050 memInit(); 00051 memset((void*)usb_hcca, 0, HCCA_SIZE); 00052 for (int i = 0; i < MAX_ENDPOINT; i++) { 00053 edBufAlloc[i] = false; 00054 } 00055 for (int i = 0; i < MAX_TD; i++) { 00056 tdBufAlloc[i] = false; 00057 } 00058 } 00059 00060 void USBHALHost::init() { 00061 NVIC_DisableIRQ(USB_IRQn); 00062 00063 //Cut power 00064 LPC_SC->PCONP &= ~(1UL<<31); 00065 wait_ms(100); 00066 00067 // turn on power for USB 00068 LPC_SC->PCONP |= (1UL<<31); 00069 00070 // Enable USB host clock, port selection and AHB clock 00071 LPC_USB->USBClkCtrl |= CLOCK_MASK; 00072 00073 // Wait for clocks to become available 00074 while ((LPC_USB->USBClkSt & CLOCK_MASK) != CLOCK_MASK); 00075 00076 // it seems the bits[0:1] mean the following 00077 // 0: U1=device, U2=host 00078 // 1: U1=host, U2=host 00079 // 2: reserved 00080 // 3: U1=host, U2=device 00081 // NB: this register is only available if OTG clock (aka "port select") is enabled!! 00082 // since we don't care about port 2, set just bit 0 to 1 (U1=host) 00083 LPC_USB->OTGStCtrl |= 1; 00084 00085 // now that we've configured the ports, we can turn off the portsel clock 00086 LPC_USB->USBClkCtrl &= ~PORTSEL_CLK_EN; 00087 00088 // configure USB D+/D- pins 00089 // P0[29] = USB_D+, 01 00090 // P0[30] = USB_D-, 01 00091 LPC_PINCON->PINSEL1 &= ~((3<<26) | (3<<28)); 00092 LPC_PINCON->PINSEL1 |= ((1<<26) | (1<<28)); 00093 00094 LPC_USB->HcControl = 0; // HARDWARE RESET 00095 LPC_USB->HcControlHeadED = 0; // Initialize Control list head to Zero 00096 LPC_USB->HcBulkHeadED = 0; // Initialize Bulk list head to Zero 00097 00098 // Wait 100 ms before apply reset 00099 wait_ms(100); 00100 00101 // software reset 00102 LPC_USB->HcCommandStatus = OR_CMD_STATUS_HCR; 00103 00104 // Write Fm Interval and Largest Data Packet Counter 00105 LPC_USB->HcFmInterval = DEFAULT_FMINTERVAL; 00106 LPC_USB->HcPeriodicStart = FI * 90 / 100; 00107 00108 // Put HC in operational state 00109 LPC_USB->HcControl = (LPC_USB->HcControl & (~OR_CONTROL_HCFS)) | OR_CONTROL_HC_OPER; 00110 // Set Global Power 00111 LPC_USB->HcRhStatus = OR_RH_STATUS_LPSC; 00112 00113 LPC_USB->HcHCCA = (uint32_t)(usb_hcca); 00114 00115 // Clear Interrrupt Status 00116 LPC_USB->HcInterruptStatus |= LPC_USB->HcInterruptStatus; 00117 00118 LPC_USB->HcInterruptEnable = OR_INTR_ENABLE_MIE | OR_INTR_ENABLE_WDH | OR_INTR_ENABLE_RHSC; 00119 00120 // Enable the USB Interrupt 00121 NVIC_SetVector(USB_IRQn, (uint32_t)(_usbisr)); 00122 LPC_USB->HcRhPortStatus1 = OR_RH_PORT_CSC; 00123 LPC_USB->HcRhPortStatus1 = OR_RH_PORT_PRSC; 00124 00125 NVIC_EnableIRQ(USB_IRQn); 00126 00127 // Check for any connected devices 00128 if (LPC_USB->HcRhPortStatus1 & OR_RH_PORT_CCS) { 00129 //Device connected 00130 wait_ms(150); 00131 USB_DBG("Device connected (%08x)\n\r", LPC_USB->HcRhPortStatus1); 00132 deviceConnected(0, 1, LPC_USB->HcRhPortStatus1 & OR_RH_PORT_LSDA); 00133 } 00134 } 00135 00136 uint32_t USBHALHost::controlHeadED() { 00137 return LPC_USB->HcControlHeadED; 00138 } 00139 00140 uint32_t USBHALHost::bulkHeadED() { 00141 return LPC_USB->HcBulkHeadED; 00142 } 00143 00144 uint32_t USBHALHost::interruptHeadED() { 00145 return usb_hcca->IntTable[0]; 00146 } 00147 00148 void USBHALHost::updateBulkHeadED(uint32_t addr) { 00149 LPC_USB->HcBulkHeadED = addr; 00150 } 00151 00152 00153 void USBHALHost::updateControlHeadED(uint32_t addr) { 00154 LPC_USB->HcControlHeadED = addr; 00155 } 00156 00157 void USBHALHost::updateInterruptHeadED(uint32_t addr) { 00158 usb_hcca->IntTable[0] = addr; 00159 } 00160 00161 00162 void USBHALHost::enableList(ENDPOINT_TYPE type) { 00163 switch(type) { 00164 case CONTROL_ENDPOINT: 00165 LPC_USB->HcCommandStatus = OR_CMD_STATUS_CLF; 00166 LPC_USB->HcControl |= OR_CONTROL_CLE; 00167 break; 00168 case ISOCHRONOUS_ENDPOINT: 00169 break; 00170 case BULK_ENDPOINT: 00171 LPC_USB->HcCommandStatus = OR_CMD_STATUS_BLF; 00172 LPC_USB->HcControl |= OR_CONTROL_BLE; 00173 break; 00174 case INTERRUPT_ENDPOINT: 00175 LPC_USB->HcControl |= OR_CONTROL_PLE; 00176 break; 00177 } 00178 } 00179 00180 00181 bool USBHALHost::disableList(ENDPOINT_TYPE type) { 00182 switch(type) { 00183 case CONTROL_ENDPOINT: 00184 if(LPC_USB->HcControl & OR_CONTROL_CLE) { 00185 LPC_USB->HcControl &= ~OR_CONTROL_CLE; 00186 return true; 00187 } 00188 return false; 00189 case ISOCHRONOUS_ENDPOINT: 00190 return false; 00191 case BULK_ENDPOINT: 00192 if(LPC_USB->HcControl & OR_CONTROL_BLE){ 00193 LPC_USB->HcControl &= ~OR_CONTROL_BLE; 00194 return true; 00195 } 00196 return false; 00197 case INTERRUPT_ENDPOINT: 00198 if(LPC_USB->HcControl & OR_CONTROL_PLE) { 00199 LPC_USB->HcControl &= ~OR_CONTROL_PLE; 00200 return true; 00201 } 00202 return false; 00203 } 00204 return false; 00205 } 00206 00207 00208 void USBHALHost::memInit() { 00209 usb_hcca = (volatile HCCA *)usb_buf; 00210 usb_edBuf = usb_buf + HCCA_SIZE; 00211 usb_tdBuf = usb_buf + HCCA_SIZE + (MAX_ENDPOINT*ED_SIZE); 00212 } 00213 00214 volatile uint8_t * USBHALHost::getED() { 00215 for (int i = 0; i < MAX_ENDPOINT; i++) { 00216 if ( !edBufAlloc[i] ) { 00217 edBufAlloc[i] = true; 00218 return (volatile uint8_t *)(usb_edBuf + i*ED_SIZE); 00219 } 00220 } 00221 perror("Could not allocate ED\r\n"); 00222 return NULL; //Could not alloc ED 00223 } 00224 00225 volatile uint8_t * USBHALHost::getTD() { 00226 int i; 00227 for (i = 0; i < MAX_TD; i++) { 00228 if ( !tdBufAlloc[i] ) { 00229 tdBufAlloc[i] = true; 00230 return (volatile uint8_t *)(usb_tdBuf + i*TD_SIZE); 00231 } 00232 } 00233 perror("Could not allocate TD\r\n"); 00234 return NULL; //Could not alloc TD 00235 } 00236 00237 00238 void USBHALHost::freeED(volatile uint8_t * ed) { 00239 int i; 00240 i = (ed - usb_edBuf) / ED_SIZE; 00241 edBufAlloc[i] = false; 00242 } 00243 00244 void USBHALHost::freeTD(volatile uint8_t * td) { 00245 int i; 00246 i = (td - usb_tdBuf) / TD_SIZE; 00247 tdBufAlloc[i] = false; 00248 } 00249 00250 00251 void USBHALHost::resetRootHub() { 00252 // Initiate port reset 00253 LPC_USB->HcRhPortStatus1 = OR_RH_PORT_PRS; 00254 00255 while (LPC_USB->HcRhPortStatus1 & OR_RH_PORT_PRS); 00256 00257 // ...and clear port reset signal 00258 LPC_USB->HcRhPortStatus1 = OR_RH_PORT_PRSC; 00259 } 00260 00261 00262 void USBHALHost::_usbisr(void) { 00263 if (instHost) { 00264 instHost->UsbIrqhandler(); 00265 } 00266 } 00267 00268 void USBHALHost::UsbIrqhandler() { 00269 if( LPC_USB->HcInterruptStatus & LPC_USB->HcInterruptEnable ) //Is there something to actually process? 00270 { 00271 00272 uint32_t int_status = LPC_USB->HcInterruptStatus & LPC_USB->HcInterruptEnable; 00273 00274 // Root hub status change interrupt 00275 if (int_status & OR_INTR_STATUS_RHSC) { 00276 if (LPC_USB->HcRhPortStatus1 & OR_RH_PORT_CSC) { 00277 if (LPC_USB->HcRhStatus & OR_RH_STATUS_DRWE) { 00278 // When DRWE is on, Connect Status Change 00279 // means a remote wakeup event. 00280 } else { 00281 00282 //Root device connected 00283 if (LPC_USB->HcRhPortStatus1 & OR_RH_PORT_CCS) { 00284 00285 // wait 150ms to avoid bounce 00286 wait_ms(150); 00287 00288 //Hub 0 (root hub), Port 1 (count starts at 1), Low or High speed 00289 deviceConnected(0, 1, LPC_USB->HcRhPortStatus1 & OR_RH_PORT_LSDA); 00290 } 00291 00292 //Root device disconnected 00293 else { 00294 00295 if (!(int_status & OR_INTR_STATUS_WDH)) { 00296 usb_hcca->DoneHead = 0; 00297 } 00298 00299 // wait 200ms to avoid bounce 00300 wait_ms(200); 00301 00302 deviceDisconnected(0, 1, NULL, usb_hcca->DoneHead & 0xFFFFFFFE); 00303 00304 if (int_status & OR_INTR_STATUS_WDH) { 00305 usb_hcca->DoneHead = 0; 00306 LPC_USB->HcInterruptStatus = OR_INTR_STATUS_WDH; 00307 } 00308 } 00309 } 00310 LPC_USB->HcRhPortStatus1 = OR_RH_PORT_CSC; 00311 } 00312 if (LPC_USB->HcRhPortStatus1 & OR_RH_PORT_PRSC) { 00313 LPC_USB->HcRhPortStatus1 = OR_RH_PORT_PRSC; 00314 } 00315 LPC_USB->HcInterruptStatus = OR_INTR_STATUS_RHSC; 00316 } 00317 00318 // Writeback Done Head interrupt 00319 if (int_status & OR_INTR_STATUS_WDH) { 00320 transferCompleted(usb_hcca->DoneHead & 0xFFFFFFFE); 00321 LPC_USB->HcInterruptStatus = OR_INTR_STATUS_WDH; 00322 } 00323 } 00324 } 00325 #endif
Generated on Tue Jul 12 2022 14:47:46 by
1.7.2
