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.
Dependencies: HttpServer_snapshot_mbed-os
USBHALHost_RZ_A2.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_RZ_A2XX) 00018 00019 #include "mbed.h" 00020 #include "USBHALHost.h" 00021 #include "dbg.h" 00022 #include "pinmap.h" 00023 00024 /**** User Selection ****/ 00025 #if defined(TARGET_RZ_A2M_EVB) || defined(TARGET_RZ_A2M_EVB_HF) 00026 #define USB_HOST_CH 1 00027 #elif defined(TARGET_RZ_A2M_SBEV) 00028 #define USB_HOST_CH 0 00029 #endif 00030 00031 #if USB_HOST_CH == 0 00032 #define USB_MX USB01 00033 #define USBX0 USB00 00034 #define USBHIX_IRQn USBHI0_IRQn 00035 #else 00036 #define USB_MX USB11 00037 #define USBX0 USB10 00038 #define USBHIX_IRQn USBHI1_IRQn 00039 #endif 00040 00041 #define HCCA_SIZE sizeof(HCCA) 00042 #define ED_SIZE sizeof(HCED) 00043 #define TD_SIZE sizeof(HCTD) 00044 00045 #define TOTAL_SIZE (HCCA_SIZE + (MAX_ENDPOINT*ED_SIZE) + (MAX_TD*TD_SIZE)) 00046 00047 static volatile uint8_t usb_buf[TOTAL_SIZE] __attribute((section("NC_BSS"),aligned(256))); //256 bytes aligned! 00048 00049 USBHALHost * USBHALHost::instHost; 00050 00051 USBHALHost::USBHALHost() { 00052 instHost = this; 00053 memInit(); 00054 memset((void*)usb_hcca, 0, HCCA_SIZE); 00055 for (int i = 0; i < MAX_ENDPOINT; i++) { 00056 edBufAlloc[i] = false; 00057 } 00058 for (int i = 0; i < MAX_TD; i++) { 00059 tdBufAlloc[i] = false; 00060 } 00061 } 00062 00063 void USBHALHost::init() { 00064 volatile uint8_t dummy_8; 00065 00066 GIC_DisableIRQ(USBHIX_IRQn); 00067 00068 #if USB_HOST_CH == 0 00069 pin_function(PC_6, 1); // VBUSEN0 00070 pin_function(PC_7, 1); // OVRCUR0 00071 CPG.STBCR6.BIT.MSTP61 = 0; 00072 dummy_8 = CPG.STBCR6.BYTE; 00073 CPG.STBREQ3.BYTE &= ~0x03; 00074 dummy_8 = CPG.STBREQ3.BYTE; 00075 #else 00076 pin_function(PC_0, 1); // VBUSIN1 00077 pin_function(PC_5, 1); // VBUSEN1 00078 pin_function(P7_5, 5); // OVRCUR1 00079 CPG.STBCR6.BIT.MSTP60 = 0; 00080 dummy_8 = CPG.STBCR6.BYTE; 00081 CPG.STBREQ3.BYTE &= ~0x0C; 00082 dummy_8 = CPG.STBREQ3.BYTE; 00083 #endif 00084 (void)dummy_8; 00085 00086 #if defined(TARGET_RZ_A2M_SBEV) 00087 USBX0.PHYCLK_CTRL.BIT.UCLKSEL = 0; /* EXTAL */ 00088 #else 00089 USBX0.PHYCLK_CTRL.BIT.UCLKSEL = 1; /* USB_X1 */ 00090 #endif 00091 00092 USBX0.PHYIF_CTRL.LONG = 0x00000000; 00093 USBX0.COMMCTRL.BIT.OTG_PERI = 0; /* 0 : Host, 1 : Peri */ 00094 USB_MX.LPSTS.WORD |= 0x4000u; 00095 USBX0.USBCTR.LONG = 0x00000000; 00096 wait_ms(1); 00097 USBX0.LINECTRL1.LONG = 0; 00098 00099 USBX0.HCCONTROL.LONG = 0; // HARDWARE RESET 00100 USBX0.HCCONTROLHEADED.LONG = 0; // Initialize Control list head to Zero 00101 USBX0.HCBULKHEADED.LONG = 0; // Initialize Bulk list head to Zero 00102 00103 wait_ms(1); 00104 USBX0.HCRHPORTSTATUS1.LONG = 0x00000100; 00105 00106 // Wait 100 ms before apply reset 00107 wait_ms(100); 00108 00109 // software reset 00110 USBX0.HCCOMMANDSTATUS.LONG = OR_CMD_STATUS_HCR; 00111 00112 // Write Fm Interval and Largest Data Packet Counter 00113 USBX0.HCFMINTERVAL.LONG = DEFAULT_FMINTERVAL; 00114 USBX0.HCPERIODICSTART.LONG = FI * 90 / 100; 00115 00116 // Put HC in operational state 00117 USBX0.HCCONTROL.LONG = (USBX0.HCCONTROL.LONG & (~OR_CONTROL_HCFS)) | OR_CONTROL_HC_OPER; 00118 // Set Global Power 00119 USBX0.HCRHSTATUS.LONG = OR_RH_STATUS_LPSC; 00120 00121 USBX0.HCHCCA.LONG = (uint32_t)(usb_hcca); 00122 00123 // Clear Interrrupt Status 00124 USBX0.HCINTERRUPTSTATUS.LONG |= USBX0.HCINTERRUPTSTATUS.LONG; 00125 00126 USBX0.HCINTERRUPTENABLE.LONG = OR_INTR_ENABLE_MIE | OR_INTR_ENABLE_WDH | OR_INTR_ENABLE_RHSC; 00127 00128 // Enable the USB Interrupt 00129 InterruptHandlerRegister(USBHIX_IRQn, &_usbisr); 00130 GIC_SetConfiguration(USBHIX_IRQn, 1); 00131 GIC_SetPriority(USBHIX_IRQn, 0x80); 00132 00133 USBX0.INT_ENABLE.BIT.USBH_INTAEN = 1; 00134 USBX0.REGEN_CG_CTRL.LONG = 0; 00135 00136 USBX0.HCRHPORTSTATUS1.LONG = OR_RH_PORT_CSC; 00137 USBX0.HCRHPORTSTATUS1.LONG = OR_RH_PORT_PRSC; 00138 00139 GIC_EnableIRQ(USBHIX_IRQn); 00140 00141 // Check for any connected devices 00142 if (USBX0.HCRHPORTSTATUS1.LONG & OR_RH_PORT_CCS) { 00143 //Device connected 00144 wait_ms(150); 00145 USB_DBG("Device connected (%08x)\n\r", USBX0.HCRHPORTSTATUS1.LONG); 00146 deviceConnected(0, 1, USBX0.HCRHPORTSTATUS1.LONG & OR_RH_PORT_LSDA); 00147 } 00148 } 00149 00150 uint32_t USBHALHost::controlHeadED() { 00151 return USBX0.HCCONTROLHEADED.LONG; 00152 } 00153 00154 uint32_t USBHALHost::bulkHeadED() { 00155 return USBX0.HCBULKHEADED.LONG; 00156 } 00157 00158 uint32_t USBHALHost::interruptHeadED() { 00159 return usb_hcca->IntTable[0]; 00160 } 00161 00162 void USBHALHost::updateBulkHeadED(uint32_t addr) { 00163 USBX0.HCBULKHEADED.LONG = addr; 00164 } 00165 00166 00167 void USBHALHost::updateControlHeadED(uint32_t addr) { 00168 USBX0.HCCONTROLHEADED.LONG = addr; 00169 } 00170 00171 void USBHALHost::updateInterruptHeadED(uint32_t addr) { 00172 usb_hcca->IntTable[0] = addr; 00173 } 00174 00175 void USBHALHost::enableList(ENDPOINT_TYPE type) { 00176 switch(type) { 00177 case CONTROL_ENDPOINT: 00178 USBX0.HCCOMMANDSTATUS.LONG = OR_CMD_STATUS_CLF; 00179 USBX0.HCCONTROL.LONG |= OR_CONTROL_CLE; 00180 break; 00181 case ISOCHRONOUS_ENDPOINT: 00182 break; 00183 case BULK_ENDPOINT: 00184 USBX0.HCCOMMANDSTATUS.LONG = OR_CMD_STATUS_BLF; 00185 USBX0.HCCONTROL.LONG |= OR_CONTROL_BLE; 00186 break; 00187 case INTERRUPT_ENDPOINT: 00188 USBX0.HCCONTROL.LONG |= OR_CONTROL_PLE; 00189 break; 00190 } 00191 } 00192 00193 bool USBHALHost::disableList(ENDPOINT_TYPE type) { 00194 switch(type) { 00195 case CONTROL_ENDPOINT: 00196 if(USBX0.HCCONTROL.LONG & OR_CONTROL_CLE) { 00197 USBX0.HCCONTROL.LONG &= ~OR_CONTROL_CLE; 00198 return true; 00199 } 00200 return false; 00201 case ISOCHRONOUS_ENDPOINT: 00202 return false; 00203 case BULK_ENDPOINT: 00204 if(USBX0.HCCONTROL.LONG & OR_CONTROL_BLE){ 00205 USBX0.HCCONTROL.LONG &= ~OR_CONTROL_BLE; 00206 return true; 00207 } 00208 return false; 00209 case INTERRUPT_ENDPOINT: 00210 if(USBX0.HCCONTROL.LONG & OR_CONTROL_PLE) { 00211 USBX0.HCCONTROL.LONG &= ~OR_CONTROL_PLE; 00212 return true; 00213 } 00214 return false; 00215 } 00216 return false; 00217 } 00218 00219 void USBHALHost::memInit() { 00220 usb_hcca = (volatile HCCA *)usb_buf; 00221 usb_edBuf = usb_buf + HCCA_SIZE; 00222 usb_tdBuf = usb_buf + HCCA_SIZE + (MAX_ENDPOINT*ED_SIZE); 00223 } 00224 00225 volatile uint8_t * USBHALHost::getED() { 00226 for (int i = 0; i < MAX_ENDPOINT; i++) { 00227 if ( !edBufAlloc[i] ) { 00228 edBufAlloc[i] = true; 00229 return (volatile uint8_t *)(usb_edBuf + i*ED_SIZE); 00230 } 00231 } 00232 perror("Could not allocate ED\r\n"); 00233 return NULL; //Could not alloc ED 00234 } 00235 00236 volatile uint8_t * USBHALHost::getTD() { 00237 int i; 00238 for (i = 0; i < MAX_TD; i++) { 00239 if ( !tdBufAlloc[i] ) { 00240 tdBufAlloc[i] = true; 00241 return (volatile uint8_t *)(usb_tdBuf + i*TD_SIZE); 00242 } 00243 } 00244 perror("Could not allocate TD\r\n"); 00245 return NULL; //Could not alloc TD 00246 } 00247 00248 void USBHALHost::freeED(volatile uint8_t * ed) { 00249 int i; 00250 i = (ed - usb_edBuf) / ED_SIZE; 00251 edBufAlloc[i] = false; 00252 } 00253 00254 void USBHALHost::freeTD(volatile uint8_t * td) { 00255 int i; 00256 i = (td - usb_tdBuf) / TD_SIZE; 00257 tdBufAlloc[i] = false; 00258 } 00259 00260 void USBHALHost::resetRootHub() { 00261 // Initiate port reset 00262 USBX0.HCRHPORTSTATUS1.LONG = OR_RH_PORT_PRS; 00263 00264 while (USBX0.HCRHPORTSTATUS1.LONG & OR_RH_PORT_PRS); 00265 00266 // ...and clear port reset signal 00267 USBX0.HCRHPORTSTATUS1.LONG = OR_RH_PORT_PRSC; 00268 } 00269 00270 void USBHALHost::_usbisr(void) { 00271 if (instHost) { 00272 instHost->UsbIrqhandler(); 00273 } 00274 } 00275 00276 void USBHALHost::UsbIrqhandler() { 00277 if( USBX0.HCINTERRUPTSTATUS.LONG & USBX0.HCINTERRUPTENABLE.LONG ) //Is there something to actually process? 00278 { 00279 00280 uint32_t int_status = USBX0.HCINTERRUPTSTATUS.LONG & USBX0.HCINTERRUPTENABLE.LONG; 00281 00282 // Root hub status change interrupt 00283 if (int_status & OR_INTR_STATUS_RHSC) { 00284 if (USBX0.HCRHPORTSTATUS1.LONG & OR_RH_PORT_CSC) { 00285 if (USBX0.HCRHSTATUS.LONG & OR_RH_STATUS_DRWE) { 00286 // When DRWE is on, Connect Status Change 00287 // means a remote wakeup event. 00288 } else { 00289 00290 //Root device connected 00291 if (USBX0.HCRHPORTSTATUS1.LONG & OR_RH_PORT_CCS) { 00292 //Hub 0 (root hub), Port 1 (count starts at 1), Low or High speed 00293 deviceConnected(0, 1, USBX0.HCRHPORTSTATUS1.LONG & OR_RH_PORT_LSDA); 00294 } 00295 00296 //Root device disconnected 00297 else { 00298 deviceDisconnected(0, 1, NULL, usb_hcca->DoneHead & 0xFFFFFFFE); 00299 } 00300 } 00301 USBX0.HCRHPORTSTATUS1.LONG = OR_RH_PORT_CSC; 00302 } 00303 if (USBX0.HCRHPORTSTATUS1.LONG & OR_RH_PORT_PRSC) { 00304 USBX0.HCRHPORTSTATUS1.LONG = OR_RH_PORT_PRSC; 00305 } 00306 USBX0.HCINTERRUPTSTATUS.LONG = OR_INTR_STATUS_RHSC; 00307 } 00308 00309 // Writeback Done Head interrupt 00310 if (int_status & OR_INTR_STATUS_WDH) { 00311 transferCompleted(usb_hcca->DoneHead & 0xFFFFFFFE); 00312 USBX0.HCINTERRUPTSTATUS.LONG = OR_INTR_STATUS_WDH; 00313 } 00314 } 00315 } 00316 #endif
Generated on Wed Jul 13 2022 05:33:37 by
