X-TOUCH to djay bridge

Dependencies:   mbed mbed-rtos FATFileSystem

Committer:
okini3939
Date:
Wed Jun 05 04:54:37 2019 +0000
Revision:
1:0dac72ab5910
sample

Who changed what in which revision?

UserRevisionLine numberNew contents of line
okini3939 1:0dac72ab5910 1 /* mbed Microcontroller Library
okini3939 1:0dac72ab5910 2 * Copyright (c) 2015-2016 Nuvoton
okini3939 1:0dac72ab5910 3 *
okini3939 1:0dac72ab5910 4 * Licensed under the Apache License, Version 2.0 (the "License");
okini3939 1:0dac72ab5910 5 * you may not use this file except in compliance with the License.
okini3939 1:0dac72ab5910 6 * You may obtain a copy of the License at
okini3939 1:0dac72ab5910 7 *
okini3939 1:0dac72ab5910 8 * http://www.apache.org/licenses/LICENSE-2.0
okini3939 1:0dac72ab5910 9 *
okini3939 1:0dac72ab5910 10 * Unless required by applicable law or agreed to in writing, software
okini3939 1:0dac72ab5910 11 * distributed under the License is distributed on an "AS IS" BASIS,
okini3939 1:0dac72ab5910 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
okini3939 1:0dac72ab5910 13 * See the License for the specific language governing permissions and
okini3939 1:0dac72ab5910 14 * limitations under the License.
okini3939 1:0dac72ab5910 15 */
okini3939 1:0dac72ab5910 16
okini3939 1:0dac72ab5910 17 #if defined(TARGET_NUC472)
okini3939 1:0dac72ab5910 18
okini3939 1:0dac72ab5910 19 #include "mbed.h"
okini3939 1:0dac72ab5910 20 #include "USBHALHost.h"
okini3939 1:0dac72ab5910 21 #include "dbg.h"
okini3939 1:0dac72ab5910 22 #include "pinmap.h"
okini3939 1:0dac72ab5910 23
okini3939 1:0dac72ab5910 24 #define HCCA_SIZE sizeof(HCCA)
okini3939 1:0dac72ab5910 25 #define ED_SIZE sizeof(HCED)
okini3939 1:0dac72ab5910 26 #define TD_SIZE sizeof(HCTD)
okini3939 1:0dac72ab5910 27
okini3939 1:0dac72ab5910 28 #define TOTAL_SIZE (HCCA_SIZE + (MAX_ENDPOINT*ED_SIZE) + (MAX_TD*TD_SIZE))
okini3939 1:0dac72ab5910 29
okini3939 1:0dac72ab5910 30 static volatile MBED_ALIGN(256) uint8_t usb_buf[TOTAL_SIZE]; // 256 bytes aligned!
okini3939 1:0dac72ab5910 31
okini3939 1:0dac72ab5910 32 USBHALHost * USBHALHost::instHost;
okini3939 1:0dac72ab5910 33
okini3939 1:0dac72ab5910 34 USBHALHost::USBHALHost()
okini3939 1:0dac72ab5910 35 {
okini3939 1:0dac72ab5910 36 instHost = this;
okini3939 1:0dac72ab5910 37 memInit();
okini3939 1:0dac72ab5910 38 memset((void*)usb_hcca, 0, HCCA_SIZE);
okini3939 1:0dac72ab5910 39 for (int i = 0; i < MAX_ENDPOINT; i++) {
okini3939 1:0dac72ab5910 40 edBufAlloc[i] = false;
okini3939 1:0dac72ab5910 41 }
okini3939 1:0dac72ab5910 42 for (int i = 0; i < MAX_TD; i++) {
okini3939 1:0dac72ab5910 43 tdBufAlloc[i] = false;
okini3939 1:0dac72ab5910 44 }
okini3939 1:0dac72ab5910 45 }
okini3939 1:0dac72ab5910 46
okini3939 1:0dac72ab5910 47 void USBHALHost::init()
okini3939 1:0dac72ab5910 48 {
okini3939 1:0dac72ab5910 49 // Unlock protected registers
okini3939 1:0dac72ab5910 50 SYS_UnlockReg();
okini3939 1:0dac72ab5910 51
okini3939 1:0dac72ab5910 52 // NOTE: Configure as OTG device first; otherwise, program will trap in wait loop CLK_STATUS_PLL2STB_Msk below.
okini3939 1:0dac72ab5910 53 SYS->USBPHY = SYS_USBPHY_LDO33EN_Msk | SYS_USBPHY_USBROLE_ON_THE_GO;
okini3939 1:0dac72ab5910 54
okini3939 1:0dac72ab5910 55 // NOTE: Enable OTG here; otherwise, program will trap in wait loop CLK_STATUS_PLL2STB_Msk below.
okini3939 1:0dac72ab5910 56 CLK_EnableModuleClock(OTG_MODULE);
okini3939 1:0dac72ab5910 57 OTG->PHYCTL = (OTG->PHYCTL | OTG_PHYCTL_OTGPHYEN_Msk) & ~OTG_PHYCTL_IDDETEN_Msk;
okini3939 1:0dac72ab5910 58 //OTG->CTL |= OTG_CTL_OTGEN_Msk | OTG_CTL_BUSREQ_Msk;
okini3939 1:0dac72ab5910 59
okini3939 1:0dac72ab5910 60 // PB.0: USB0 external VBUS regulator status
okini3939 1:0dac72ab5910 61 // USB_OC
okini3939 1:0dac72ab5910 62 // PB.1: USB0 external VBUS regulator enable
okini3939 1:0dac72ab5910 63 // NCT3520U low active (USB_PWR_EN)
okini3939 1:0dac72ab5910 64 pin_function(PB_0, SYS_GPB_MFPL_PB0MFP_USB0_OTG5V_ST);
okini3939 1:0dac72ab5910 65 pin_function(PB_1, SYS_GPB_MFPL_PB1MFP_USB0_OTG5V_EN);
okini3939 1:0dac72ab5910 66
okini3939 1:0dac72ab5910 67 // PB.2: USB1 differential signal D-
okini3939 1:0dac72ab5910 68 // PB.3: USB1 differential signal D+
okini3939 1:0dac72ab5910 69 //pin_function(PB_2, SYS_GPB_MFPL_PB2MFP_USB1_D_N);
okini3939 1:0dac72ab5910 70 //pin_function(PB_3, SYS_GPB_MFPL_PB3MFP_USB1_D_P);
okini3939 1:0dac72ab5910 71
okini3939 1:0dac72ab5910 72 // Set PB.4 output high to enable USB power
okini3939 1:0dac72ab5910 73 //gpio_t gpio;
okini3939 1:0dac72ab5910 74 //gpio_init_out_ex(&gpio, PB_4, 1);
okini3939 1:0dac72ab5910 75
okini3939 1:0dac72ab5910 76 // NOTE:
okini3939 1:0dac72ab5910 77 // 1. Set USBH clock source to PLL2; otherwise, program will trap in wait loop CLK_STATUS_PLL2STB_Msk below.
okini3939 1:0dac72ab5910 78 // 2. Don't set CLK_PLL2CTL_PLL2CKEN_Msk. USBH will work abnormally with it enabled.
okini3939 1:0dac72ab5910 79 CLK->CLKSEL0 &= ~CLK_CLKSEL0_USBHSEL_Msk;
okini3939 1:0dac72ab5910 80 // Enable PLL2, 480 MHz / 2 / (1+4) => 48 MHz output
okini3939 1:0dac72ab5910 81 CLK->PLL2CTL = /*CLK_PLL2CTL_PLL2CKEN_Msk | */ (4 << CLK_PLL2CTL_PLL2DIV_Pos);
okini3939 1:0dac72ab5910 82 // Wait PLL2 stable ...
okini3939 1:0dac72ab5910 83 while (!(CLK->STATUS & CLK_STATUS_PLL2STB_Msk));
okini3939 1:0dac72ab5910 84
okini3939 1:0dac72ab5910 85 // Select USB Host clock source from PLL2, clock divied by 1
okini3939 1:0dac72ab5910 86 CLK_SetModuleClock(USBH_MODULE, CLK_CLKSEL0_USBHSEL_PLL2, CLK_CLKDIV0_USB(1));
okini3939 1:0dac72ab5910 87
okini3939 1:0dac72ab5910 88 // Enable USB Host clock
okini3939 1:0dac72ab5910 89 CLK_EnableModuleClock(USBH_MODULE);
okini3939 1:0dac72ab5910 90
okini3939 1:0dac72ab5910 91 // Lock protected registers
okini3939 1:0dac72ab5910 92 SYS_LockReg();
okini3939 1:0dac72ab5910 93
okini3939 1:0dac72ab5910 94 // Overcurrent flag is high active
okini3939 1:0dac72ab5910 95 USBH->HcMiscControl &= ~USBH_HcMiscControl_OCAL_Msk;
okini3939 1:0dac72ab5910 96
okini3939 1:0dac72ab5910 97 // Disable HC interrupts
okini3939 1:0dac72ab5910 98 USBH->HcInterruptDisable = OR_INTR_ENABLE_MIE;
okini3939 1:0dac72ab5910 99
okini3939 1:0dac72ab5910 100 // Needed by some controllers
okini3939 1:0dac72ab5910 101 USBH->HcControl = 0;
okini3939 1:0dac72ab5910 102
okini3939 1:0dac72ab5910 103 // Software reset
okini3939 1:0dac72ab5910 104 USBH->HcCommandStatus = OR_CMD_STATUS_HCR;
okini3939 1:0dac72ab5910 105 while (USBH->HcCommandStatus & OR_CMD_STATUS_HCR);
okini3939 1:0dac72ab5910 106
okini3939 1:0dac72ab5910 107 // Put HC in reset state
okini3939 1:0dac72ab5910 108 USBH->HcControl = (USBH->HcControl & ~OR_CONTROL_HCFS) | OR_CONTROL_HC_RSET;
okini3939 1:0dac72ab5910 109 // HCD must wait 10ms for HC reset complete
okini3939 1:0dac72ab5910 110 wait_ms(100);
okini3939 1:0dac72ab5910 111
okini3939 1:0dac72ab5910 112 USBH->HcControlHeadED = 0; // Initialize Control ED list head to 0
okini3939 1:0dac72ab5910 113 USBH->HcBulkHeadED = 0; // Initialize Bulk ED list head to 0
okini3939 1:0dac72ab5910 114 USBH->HcHCCA = (uint32_t) usb_hcca;
okini3939 1:0dac72ab5910 115
okini3939 1:0dac72ab5910 116 USBH->HcFmInterval = DEFAULT_FMINTERVAL; // Frame interval = 12000 - 1
okini3939 1:0dac72ab5910 117 // MPS = 10,104
okini3939 1:0dac72ab5910 118 USBH->HcPeriodicStart = FI * 90 / 100; // 90% of frame interval
okini3939 1:0dac72ab5910 119 USBH->HcLSThreshold = 0x628; // Low speed threshold
okini3939 1:0dac72ab5910 120
okini3939 1:0dac72ab5910 121 // Put HC in operational state
okini3939 1:0dac72ab5910 122 USBH->HcControl = (USBH->HcControl & (~OR_CONTROL_HCFS)) | OR_CONTROL_HC_OPER;
okini3939 1:0dac72ab5910 123
okini3939 1:0dac72ab5910 124 // FIXME: Ports are power switched. All ports are powered at the same time. Doesn't match BSP sample.
okini3939 1:0dac72ab5910 125 USBH->HcRhDescriptorA = USBH->HcRhDescriptorA & ~USBH_HcRhDescriptorA_NPS_Msk & ~USBH_HcRhDescriptorA_PSM_Msk;
okini3939 1:0dac72ab5910 126 // Issue SetGlobalPower command
okini3939 1:0dac72ab5910 127 USBH->HcRhStatus = USBH_HcRhStatus_LPSC_Msk;
okini3939 1:0dac72ab5910 128 // Power On To Power Good Time, in 2 ms units
okini3939 1:0dac72ab5910 129 wait_ms(((USBH->HcRhDescriptorA & USBH_HcRhDescriptorA_POTPGT_Msk) >> USBH_HcRhDescriptorA_POTPGT_Pos) * 2);
okini3939 1:0dac72ab5910 130
okini3939 1:0dac72ab5910 131 // Clear Interrrupt Status
okini3939 1:0dac72ab5910 132 USBH->HcInterruptStatus |= USBH->HcInterruptStatus;
okini3939 1:0dac72ab5910 133 // Enable interrupts we care about
okini3939 1:0dac72ab5910 134 USBH->HcInterruptEnable = OR_INTR_ENABLE_MIE | OR_INTR_ENABLE_WDH | OR_INTR_ENABLE_RHSC;
okini3939 1:0dac72ab5910 135
okini3939 1:0dac72ab5910 136
okini3939 1:0dac72ab5910 137 // Unlock protected registers
okini3939 1:0dac72ab5910 138 SYS_UnlockReg();
okini3939 1:0dac72ab5910 139
okini3939 1:0dac72ab5910 140 // NOTE: Configure as USB host after USBH init above; otherwise system will crash.
okini3939 1:0dac72ab5910 141 SYS->USBPHY = (SYS->USBPHY & ~SYS_USBPHY_USBROLE_Msk) | SYS_USBPHY_USBROLE_STD_USBH;
okini3939 1:0dac72ab5910 142
okini3939 1:0dac72ab5910 143 // Lock protected registers
okini3939 1:0dac72ab5910 144 SYS_LockReg();
okini3939 1:0dac72ab5910 145
okini3939 1:0dac72ab5910 146 NVIC_SetVector(USBH_IRQn, (uint32_t)(_usbisr));
okini3939 1:0dac72ab5910 147 NVIC_EnableIRQ(USBH_IRQn);
okini3939 1:0dac72ab5910 148
okini3939 1:0dac72ab5910 149 // Check for any connected devices
okini3939 1:0dac72ab5910 150 if (USBH->HcRhPortStatus[0] & OR_RH_PORT_CCS) {
okini3939 1:0dac72ab5910 151 // Device connected
okini3939 1:0dac72ab5910 152 wait_ms(150);
okini3939 1:0dac72ab5910 153 deviceConnected(0, 1, USBH->HcRhPortStatus[0] & OR_RH_PORT_LSDA);
okini3939 1:0dac72ab5910 154 }
okini3939 1:0dac72ab5910 155 }
okini3939 1:0dac72ab5910 156
okini3939 1:0dac72ab5910 157 uint32_t USBHALHost::controlHeadED()
okini3939 1:0dac72ab5910 158 {
okini3939 1:0dac72ab5910 159 return USBH->HcControlHeadED;
okini3939 1:0dac72ab5910 160 }
okini3939 1:0dac72ab5910 161
okini3939 1:0dac72ab5910 162 uint32_t USBHALHost::bulkHeadED()
okini3939 1:0dac72ab5910 163 {
okini3939 1:0dac72ab5910 164 return USBH->HcBulkHeadED;
okini3939 1:0dac72ab5910 165 }
okini3939 1:0dac72ab5910 166
okini3939 1:0dac72ab5910 167 uint32_t USBHALHost::interruptHeadED()
okini3939 1:0dac72ab5910 168 {
okini3939 1:0dac72ab5910 169 // FIXME: Only support one INT ED?
okini3939 1:0dac72ab5910 170 return usb_hcca->IntTable[0];
okini3939 1:0dac72ab5910 171 }
okini3939 1:0dac72ab5910 172
okini3939 1:0dac72ab5910 173 void USBHALHost::updateBulkHeadED(uint32_t addr)
okini3939 1:0dac72ab5910 174 {
okini3939 1:0dac72ab5910 175 USBH->HcBulkHeadED = addr;
okini3939 1:0dac72ab5910 176 }
okini3939 1:0dac72ab5910 177
okini3939 1:0dac72ab5910 178
okini3939 1:0dac72ab5910 179 void USBHALHost::updateControlHeadED(uint32_t addr)
okini3939 1:0dac72ab5910 180 {
okini3939 1:0dac72ab5910 181 USBH->HcControlHeadED = addr;
okini3939 1:0dac72ab5910 182 }
okini3939 1:0dac72ab5910 183
okini3939 1:0dac72ab5910 184 void USBHALHost::updateInterruptHeadED(uint32_t addr)
okini3939 1:0dac72ab5910 185 {
okini3939 1:0dac72ab5910 186 // FIXME: Only support one INT ED?
okini3939 1:0dac72ab5910 187 usb_hcca->IntTable[0] = addr;
okini3939 1:0dac72ab5910 188 }
okini3939 1:0dac72ab5910 189
okini3939 1:0dac72ab5910 190
okini3939 1:0dac72ab5910 191 void USBHALHost::enableList(ENDPOINT_TYPE type)
okini3939 1:0dac72ab5910 192 {
okini3939 1:0dac72ab5910 193 switch(type) {
okini3939 1:0dac72ab5910 194 case CONTROL_ENDPOINT:
okini3939 1:0dac72ab5910 195 USBH->HcCommandStatus = OR_CMD_STATUS_CLF;
okini3939 1:0dac72ab5910 196 USBH->HcControl |= OR_CONTROL_CLE;
okini3939 1:0dac72ab5910 197 break;
okini3939 1:0dac72ab5910 198 case ISOCHRONOUS_ENDPOINT:
okini3939 1:0dac72ab5910 199 // FIXME
okini3939 1:0dac72ab5910 200 break;
okini3939 1:0dac72ab5910 201 case BULK_ENDPOINT:
okini3939 1:0dac72ab5910 202 USBH->HcCommandStatus = OR_CMD_STATUS_BLF;
okini3939 1:0dac72ab5910 203 USBH->HcControl |= OR_CONTROL_BLE;
okini3939 1:0dac72ab5910 204 break;
okini3939 1:0dac72ab5910 205 case INTERRUPT_ENDPOINT:
okini3939 1:0dac72ab5910 206 USBH->HcControl |= OR_CONTROL_PLE;
okini3939 1:0dac72ab5910 207 break;
okini3939 1:0dac72ab5910 208 }
okini3939 1:0dac72ab5910 209 }
okini3939 1:0dac72ab5910 210
okini3939 1:0dac72ab5910 211
okini3939 1:0dac72ab5910 212 bool USBHALHost::disableList(ENDPOINT_TYPE type)
okini3939 1:0dac72ab5910 213 {
okini3939 1:0dac72ab5910 214 switch(type) {
okini3939 1:0dac72ab5910 215 case CONTROL_ENDPOINT:
okini3939 1:0dac72ab5910 216 if(USBH->HcControl & OR_CONTROL_CLE) {
okini3939 1:0dac72ab5910 217 USBH->HcControl &= ~OR_CONTROL_CLE;
okini3939 1:0dac72ab5910 218 return true;
okini3939 1:0dac72ab5910 219 }
okini3939 1:0dac72ab5910 220 return false;
okini3939 1:0dac72ab5910 221 case ISOCHRONOUS_ENDPOINT:
okini3939 1:0dac72ab5910 222 // FIXME
okini3939 1:0dac72ab5910 223 return false;
okini3939 1:0dac72ab5910 224 case BULK_ENDPOINT:
okini3939 1:0dac72ab5910 225 if(USBH->HcControl & OR_CONTROL_BLE){
okini3939 1:0dac72ab5910 226 USBH->HcControl &= ~OR_CONTROL_BLE;
okini3939 1:0dac72ab5910 227 return true;
okini3939 1:0dac72ab5910 228 }
okini3939 1:0dac72ab5910 229 return false;
okini3939 1:0dac72ab5910 230 case INTERRUPT_ENDPOINT:
okini3939 1:0dac72ab5910 231 if(USBH->HcControl & OR_CONTROL_PLE) {
okini3939 1:0dac72ab5910 232 USBH->HcControl &= ~OR_CONTROL_PLE;
okini3939 1:0dac72ab5910 233 return true;
okini3939 1:0dac72ab5910 234 }
okini3939 1:0dac72ab5910 235 return false;
okini3939 1:0dac72ab5910 236 }
okini3939 1:0dac72ab5910 237 return false;
okini3939 1:0dac72ab5910 238 }
okini3939 1:0dac72ab5910 239
okini3939 1:0dac72ab5910 240
okini3939 1:0dac72ab5910 241 void USBHALHost::memInit()
okini3939 1:0dac72ab5910 242 {
okini3939 1:0dac72ab5910 243 usb_hcca = (volatile HCCA *)usb_buf;
okini3939 1:0dac72ab5910 244 usb_edBuf = usb_buf + HCCA_SIZE;
okini3939 1:0dac72ab5910 245 usb_tdBuf = usb_buf + HCCA_SIZE + (MAX_ENDPOINT*ED_SIZE);
okini3939 1:0dac72ab5910 246 }
okini3939 1:0dac72ab5910 247
okini3939 1:0dac72ab5910 248 volatile uint8_t * USBHALHost::getED()
okini3939 1:0dac72ab5910 249 {
okini3939 1:0dac72ab5910 250 for (int i = 0; i < MAX_ENDPOINT; i++) {
okini3939 1:0dac72ab5910 251 if ( !edBufAlloc[i] ) {
okini3939 1:0dac72ab5910 252 edBufAlloc[i] = true;
okini3939 1:0dac72ab5910 253 return (volatile uint8_t *)(usb_edBuf + i*ED_SIZE);
okini3939 1:0dac72ab5910 254 }
okini3939 1:0dac72ab5910 255 }
okini3939 1:0dac72ab5910 256 perror("Could not allocate ED\r\n");
okini3939 1:0dac72ab5910 257 return NULL; //Could not alloc ED
okini3939 1:0dac72ab5910 258 }
okini3939 1:0dac72ab5910 259
okini3939 1:0dac72ab5910 260 volatile uint8_t * USBHALHost::getTD()
okini3939 1:0dac72ab5910 261 {
okini3939 1:0dac72ab5910 262 int i;
okini3939 1:0dac72ab5910 263 for (i = 0; i < MAX_TD; i++) {
okini3939 1:0dac72ab5910 264 if ( !tdBufAlloc[i] ) {
okini3939 1:0dac72ab5910 265 tdBufAlloc[i] = true;
okini3939 1:0dac72ab5910 266 return (volatile uint8_t *)(usb_tdBuf + i*TD_SIZE);
okini3939 1:0dac72ab5910 267 }
okini3939 1:0dac72ab5910 268 }
okini3939 1:0dac72ab5910 269 perror("Could not allocate TD\r\n");
okini3939 1:0dac72ab5910 270 return NULL; //Could not alloc TD
okini3939 1:0dac72ab5910 271 }
okini3939 1:0dac72ab5910 272
okini3939 1:0dac72ab5910 273
okini3939 1:0dac72ab5910 274 void USBHALHost::freeED(volatile uint8_t * ed)
okini3939 1:0dac72ab5910 275 {
okini3939 1:0dac72ab5910 276 int i;
okini3939 1:0dac72ab5910 277 i = (ed - usb_edBuf) / ED_SIZE;
okini3939 1:0dac72ab5910 278 edBufAlloc[i] = false;
okini3939 1:0dac72ab5910 279 }
okini3939 1:0dac72ab5910 280
okini3939 1:0dac72ab5910 281 void USBHALHost::freeTD(volatile uint8_t * td)
okini3939 1:0dac72ab5910 282 {
okini3939 1:0dac72ab5910 283 int i;
okini3939 1:0dac72ab5910 284 i = (td - usb_tdBuf) / TD_SIZE;
okini3939 1:0dac72ab5910 285 tdBufAlloc[i] = false;
okini3939 1:0dac72ab5910 286 }
okini3939 1:0dac72ab5910 287
okini3939 1:0dac72ab5910 288
okini3939 1:0dac72ab5910 289 void USBHALHost::resetRootHub()
okini3939 1:0dac72ab5910 290 {
okini3939 1:0dac72ab5910 291 // Reset port1
okini3939 1:0dac72ab5910 292 USBH->HcRhPortStatus[0] = OR_RH_PORT_PRS;
okini3939 1:0dac72ab5910 293 while (USBH->HcRhPortStatus[0] & OR_RH_PORT_PRS);
okini3939 1:0dac72ab5910 294 USBH->HcRhPortStatus[0] = OR_RH_PORT_PRSC;
okini3939 1:0dac72ab5910 295 }
okini3939 1:0dac72ab5910 296
okini3939 1:0dac72ab5910 297
okini3939 1:0dac72ab5910 298 void USBHALHost::_usbisr(void)
okini3939 1:0dac72ab5910 299 {
okini3939 1:0dac72ab5910 300 if (instHost) {
okini3939 1:0dac72ab5910 301 instHost->UsbIrqhandler();
okini3939 1:0dac72ab5910 302 }
okini3939 1:0dac72ab5910 303 }
okini3939 1:0dac72ab5910 304
okini3939 1:0dac72ab5910 305 void USBHALHost::UsbIrqhandler()
okini3939 1:0dac72ab5910 306 {
okini3939 1:0dac72ab5910 307 uint32_t ints = USBH->HcInterruptStatus;
okini3939 1:0dac72ab5910 308
okini3939 1:0dac72ab5910 309 // Root hub status change interrupt
okini3939 1:0dac72ab5910 310 if (ints & OR_INTR_STATUS_RHSC) {
okini3939 1:0dac72ab5910 311 uint32_t ints_roothub = USBH->HcRhStatus;
okini3939 1:0dac72ab5910 312 uint32_t ints_port1 = USBH->HcRhPortStatus[0];
okini3939 1:0dac72ab5910 313
okini3939 1:0dac72ab5910 314 // Port1: ConnectStatusChange
okini3939 1:0dac72ab5910 315 if (ints_port1 & OR_RH_PORT_CSC) {
okini3939 1:0dac72ab5910 316 if (ints_roothub & OR_RH_STATUS_DRWE) {
okini3939 1:0dac72ab5910 317 // When DRWE is on, Connect Status Change means a remote wakeup event.
okini3939 1:0dac72ab5910 318 } else {
okini3939 1:0dac72ab5910 319 if (ints_port1 & OR_RH_PORT_CCS) {
okini3939 1:0dac72ab5910 320 // Root device connected
okini3939 1:0dac72ab5910 321
okini3939 1:0dac72ab5910 322 // wait 150ms to avoid bounce
okini3939 1:0dac72ab5910 323 wait_ms(150);
okini3939 1:0dac72ab5910 324
okini3939 1:0dac72ab5910 325 //Hub 0 (root hub), Port 1 (count starts at 1), Low or High speed
okini3939 1:0dac72ab5910 326 deviceConnected(0, 1, ints_port1 & OR_RH_PORT_LSDA);
okini3939 1:0dac72ab5910 327 } else {
okini3939 1:0dac72ab5910 328 // Root device disconnected
okini3939 1:0dac72ab5910 329
okini3939 1:0dac72ab5910 330 if (!(ints & OR_INTR_STATUS_WDH)) {
okini3939 1:0dac72ab5910 331 usb_hcca->DoneHead = 0;
okini3939 1:0dac72ab5910 332 }
okini3939 1:0dac72ab5910 333
okini3939 1:0dac72ab5910 334 // wait 200ms to avoid bounce
okini3939 1:0dac72ab5910 335 wait_ms(200);
okini3939 1:0dac72ab5910 336
okini3939 1:0dac72ab5910 337 deviceDisconnected(0, 1, NULL, usb_hcca->DoneHead & 0xFFFFFFFE);
okini3939 1:0dac72ab5910 338
okini3939 1:0dac72ab5910 339 if (ints & OR_INTR_STATUS_WDH) {
okini3939 1:0dac72ab5910 340 usb_hcca->DoneHead = 0;
okini3939 1:0dac72ab5910 341 USBH->HcInterruptStatus = OR_INTR_STATUS_WDH;
okini3939 1:0dac72ab5910 342 }
okini3939 1:0dac72ab5910 343 }
okini3939 1:0dac72ab5910 344 }
okini3939 1:0dac72ab5910 345 USBH->HcRhPortStatus[0] = OR_RH_PORT_CSC;
okini3939 1:0dac72ab5910 346 }
okini3939 1:0dac72ab5910 347 // Port1: Reset completed
okini3939 1:0dac72ab5910 348 if (ints_port1 & OR_RH_PORT_PRSC) {
okini3939 1:0dac72ab5910 349 USBH->HcRhPortStatus[0] = OR_RH_PORT_PRSC;
okini3939 1:0dac72ab5910 350 }
okini3939 1:0dac72ab5910 351 // Port1: PortEnableStatusChange
okini3939 1:0dac72ab5910 352 if (ints_port1 & OR_RH_PORT_PESC) {
okini3939 1:0dac72ab5910 353 USBH->HcRhPortStatus[0] = OR_RH_PORT_PESC;
okini3939 1:0dac72ab5910 354 }
okini3939 1:0dac72ab5910 355
okini3939 1:0dac72ab5910 356 USBH->HcInterruptStatus = OR_INTR_STATUS_RHSC;
okini3939 1:0dac72ab5910 357 }
okini3939 1:0dac72ab5910 358
okini3939 1:0dac72ab5910 359 // Writeback Done Head interrupt
okini3939 1:0dac72ab5910 360 if (ints & OR_INTR_STATUS_WDH) {
okini3939 1:0dac72ab5910 361 transferCompleted(usb_hcca->DoneHead & 0xFFFFFFFE);
okini3939 1:0dac72ab5910 362 USBH->HcInterruptStatus = OR_INTR_STATUS_WDH;
okini3939 1:0dac72ab5910 363 }
okini3939 1:0dac72ab5910 364 }
okini3939 1:0dac72ab5910 365 #endif