Anh Tran / Mbed OS GR-Boards_WebCamera

Dependencies:   HttpServer_snapshot_mbed-os

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers USBHALHost_RZ_A2.cpp Source File

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