USBHOST lib for STM

Dependents:   door-access-controller-dev

Committer:
jamike
Date:
Wed Apr 26 20:08:31 2017 +0000
Revision:
6:d3ac9e1c0035
Parent:
1:ab240722d7ef
fix error in read and write

Who changed what in which revision?

UserRevisionLine numberNew 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