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