Fixing issues with library dependencies
Dependencies: FATFileSystem mbed-rtos
Fork of USBHost 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) 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 Wed Jul 13 2022 21:33:35 by
![doxygen](doxygen.png)