USB Host WAN Dongle library

Fork of USBHostWANDongle_bleedingedge by Donatien Garnier

Committer:
ashleymills
Date:
Fri Sep 20 10:40:15 2013 +0000
Revision:
27:980fe31c14f7
Parent:
14:4344ce758b88
Added support for Ublox LISA U200 module

Who changed what in which revision?

UserRevisionLine numberNew contents of line
donatien 10:08bce4cd973a 1 /* Copyright (c) 2010-2012 mbed.org, MIT License
donatien 0:ae46a0638b2c 2 *
donatien 0:ae46a0638b2c 3 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
donatien 0:ae46a0638b2c 4 * and associated documentation files (the "Software"), to deal in the Software without
donatien 0:ae46a0638b2c 5 * restriction, including without limitation the rights to use, copy, modify, merge, publish,
donatien 0:ae46a0638b2c 6 * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
donatien 0:ae46a0638b2c 7 * Software is furnished to do so, subject to the following conditions:
donatien 0:ae46a0638b2c 8 *
donatien 0:ae46a0638b2c 9 * The above copyright notice and this permission notice shall be included in all copies or
donatien 0:ae46a0638b2c 10 * substantial portions of the Software.
donatien 0:ae46a0638b2c 11 *
donatien 0:ae46a0638b2c 12 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
donatien 0:ae46a0638b2c 13 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
donatien 0:ae46a0638b2c 14 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
donatien 0:ae46a0638b2c 15 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
donatien 10:08bce4cd973a 16 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
donatien 10:08bce4cd973a 17 */
donatien 0:ae46a0638b2c 18
donatien 0:ae46a0638b2c 19 #define __DEBUG__ 0 //WARN: ENABLING DEBUGGING HERE WILL PRINTF IN IRQS!! UNEXPECTED BEHAVIOUR MAY RESULT...
donatien 0:ae46a0638b2c 20 #ifndef __MODULE__
donatien 0:ae46a0638b2c 21 #define __MODULE__ "USBHALHost.cpp"
donatien 0:ae46a0638b2c 22 #endif
donatien 0:ae46a0638b2c 23
donatien 12:a712bad7a979 24 #include "core/dbg.h"
donatien 0:ae46a0638b2c 25 #include <cstdint>
donatien 0:ae46a0638b2c 26
donatien 0:ae46a0638b2c 27 #include "mbed.h"
donatien 0:ae46a0638b2c 28 #include "USBHALHost.h"
donatien 0:ae46a0638b2c 29
donatien 0:ae46a0638b2c 30 // bits of the USB/OTG clock control register
donatien 0:ae46a0638b2c 31 #define HOST_CLK_EN (1<<0)
donatien 0:ae46a0638b2c 32 #define DEV_CLK_EN (1<<1)
donatien 0:ae46a0638b2c 33 #define PORTSEL_CLK_EN (1<<3)
donatien 0:ae46a0638b2c 34 #define AHB_CLK_EN (1<<4)
donatien 0:ae46a0638b2c 35
donatien 0:ae46a0638b2c 36 // bits of the USB/OTG clock status register
donatien 0:ae46a0638b2c 37 #define HOST_CLK_ON (1<<0)
donatien 0:ae46a0638b2c 38 #define DEV_CLK_ON (1<<1)
donatien 0:ae46a0638b2c 39 #define PORTSEL_CLK_ON (1<<3)
donatien 0:ae46a0638b2c 40 #define AHB_CLK_ON (1<<4)
donatien 0:ae46a0638b2c 41
donatien 0:ae46a0638b2c 42 // we need host clock, OTG/portsel clock and AHB clock
donatien 0:ae46a0638b2c 43 #define CLOCK_MASK (HOST_CLK_EN | PORTSEL_CLK_EN | AHB_CLK_EN)
donatien 0:ae46a0638b2c 44
donatien 0:ae46a0638b2c 45
donatien 0:ae46a0638b2c 46
donatien 0:ae46a0638b2c 47 #define HCCA_SIZE 0x100
donatien 0:ae46a0638b2c 48 #define ED_SIZE 0x10
donatien 0:ae46a0638b2c 49 #define TD_SIZE 0x10
donatien 0:ae46a0638b2c 50
donatien 0:ae46a0638b2c 51 #define TOTAL_SIZE (HCCA_SIZE + (MAX_ENDPOINT*ED_SIZE) + (MAX_TD*TD_SIZE))
donatien 0:ae46a0638b2c 52
donatien 14:4344ce758b88 53 static volatile uint8_t usb_buf[TOTAL_SIZE] __attribute((section("AHBSRAM1"),aligned(256))); //256 bytes aligned!
donatien 0:ae46a0638b2c 54
donatien 0:ae46a0638b2c 55 USBHALHost * USBHALHost::instHost;
donatien 0:ae46a0638b2c 56
donatien 0:ae46a0638b2c 57 USBHALHost::USBHALHost() : thread(USBHALHost::staticCb, (void*)this, osPriorityNormal, 4*128) {
donatien 0:ae46a0638b2c 58 instHost = this;
donatien 0:ae46a0638b2c 59 memInit();
donatien 0:ae46a0638b2c 60 memset((void*)usb_hcca, 0, HCCA_SIZE);
donatien 0:ae46a0638b2c 61 for (int i = 0; i < MAX_ENDPOINT; i++) {
donatien 0:ae46a0638b2c 62 edBufAlloc[i] = false;
donatien 0:ae46a0638b2c 63 }
donatien 0:ae46a0638b2c 64 for (int i = 0; i < MAX_TD; i++) {
donatien 0:ae46a0638b2c 65 tdBufAlloc[i] = false;
donatien 0:ae46a0638b2c 66 }
donatien 0:ae46a0638b2c 67 }
donatien 0:ae46a0638b2c 68
donatien 0:ae46a0638b2c 69
donatien 0:ae46a0638b2c 70 void USBHALHost::init() {
donatien 0:ae46a0638b2c 71 thread.signal_set(USBHALHOST_SIG_INIT);
donatien 0:ae46a0638b2c 72 }
donatien 0:ae46a0638b2c 73
donatien 0:ae46a0638b2c 74
donatien 0:ae46a0638b2c 75 uint32_t USBHALHost::controlHeadED() {
donatien 0:ae46a0638b2c 76 return LPC_USB->HcControlHeadED;
donatien 0:ae46a0638b2c 77 }
donatien 0:ae46a0638b2c 78
donatien 0:ae46a0638b2c 79 uint32_t USBHALHost::bulkHeadED() {
donatien 0:ae46a0638b2c 80 return LPC_USB->HcBulkHeadED;
donatien 0:ae46a0638b2c 81 }
donatien 0:ae46a0638b2c 82
donatien 0:ae46a0638b2c 83 uint32_t USBHALHost::interruptHeadED() {
donatien 0:ae46a0638b2c 84 return usb_hcca->IntTable[0];
donatien 0:ae46a0638b2c 85 }
donatien 0:ae46a0638b2c 86
donatien 0:ae46a0638b2c 87 void USBHALHost::updateBulkHeadED(uint32_t addr) {
donatien 0:ae46a0638b2c 88 LPC_USB->HcBulkHeadED = addr;
donatien 0:ae46a0638b2c 89 }
donatien 0:ae46a0638b2c 90
donatien 0:ae46a0638b2c 91
donatien 0:ae46a0638b2c 92 void USBHALHost::updateControlHeadED(uint32_t addr) {
donatien 0:ae46a0638b2c 93 LPC_USB->HcControlHeadED = addr;
donatien 0:ae46a0638b2c 94 }
donatien 0:ae46a0638b2c 95
donatien 0:ae46a0638b2c 96 void USBHALHost::updateInterruptHeadED(uint32_t addr) {
donatien 0:ae46a0638b2c 97 usb_hcca->IntTable[0] = addr;
donatien 0:ae46a0638b2c 98 }
donatien 0:ae46a0638b2c 99
donatien 0:ae46a0638b2c 100
donatien 0:ae46a0638b2c 101 void USBHALHost::enableControlList() {
donatien 0:ae46a0638b2c 102 LPC_USB->HcCommandStatus = OR_CMD_STATUS_CLF;
donatien 0:ae46a0638b2c 103 LPC_USB->HcControl |= OR_CONTROL_CLE; //Enable control list
donatien 0:ae46a0638b2c 104 }
donatien 0:ae46a0638b2c 105
donatien 0:ae46a0638b2c 106 void USBHALHost::enableBulkList() {
donatien 0:ae46a0638b2c 107 LPC_USB->HcCommandStatus = OR_CMD_STATUS_BLF;
donatien 0:ae46a0638b2c 108 LPC_USB->HcControl |= OR_CONTROL_BLE; //Enable bulk list
donatien 0:ae46a0638b2c 109 }
donatien 0:ae46a0638b2c 110
donatien 0:ae46a0638b2c 111 void USBHALHost::enableInterruptList() {
donatien 0:ae46a0638b2c 112 LPC_USB->HcControl |= OR_CONTROL_PLE;
donatien 0:ae46a0638b2c 113 }
donatien 0:ae46a0638b2c 114
donatien 0:ae46a0638b2c 115 bool USBHALHost::disableControlList() {
donatien 0:ae46a0638b2c 116 if(LPC_USB->HcControl & OR_CONTROL_CLE)
donatien 0:ae46a0638b2c 117 {
donatien 0:ae46a0638b2c 118 LPC_USB->HcControl &= ~OR_CONTROL_CLE; //Disable control list
donatien 0:ae46a0638b2c 119 return true;
donatien 0:ae46a0638b2c 120 }
donatien 0:ae46a0638b2c 121 else
donatien 0:ae46a0638b2c 122 {
donatien 0:ae46a0638b2c 123 return false;
donatien 0:ae46a0638b2c 124 }
donatien 0:ae46a0638b2c 125 }
donatien 0:ae46a0638b2c 126
donatien 0:ae46a0638b2c 127 bool USBHALHost::disableBulkList() {
donatien 0:ae46a0638b2c 128 if(LPC_USB->HcControl & OR_CONTROL_BLE)
donatien 0:ae46a0638b2c 129 {
donatien 0:ae46a0638b2c 130 LPC_USB->HcControl &= ~OR_CONTROL_BLE; //Disable bulk list
donatien 0:ae46a0638b2c 131 return true;
donatien 0:ae46a0638b2c 132 }
donatien 0:ae46a0638b2c 133 else
donatien 0:ae46a0638b2c 134 {
donatien 0:ae46a0638b2c 135 return false;
donatien 0:ae46a0638b2c 136 }
donatien 0:ae46a0638b2c 137 }
donatien 0:ae46a0638b2c 138
donatien 0:ae46a0638b2c 139 bool USBHALHost::disableInterruptList() {
donatien 0:ae46a0638b2c 140 if(LPC_USB->HcControl & OR_CONTROL_PLE)
donatien 0:ae46a0638b2c 141 {
donatien 0:ae46a0638b2c 142 LPC_USB->HcControl &= ~OR_CONTROL_PLE; //Disable interrupt list
donatien 0:ae46a0638b2c 143 return true;
donatien 0:ae46a0638b2c 144 }
donatien 0:ae46a0638b2c 145 else
donatien 0:ae46a0638b2c 146 {
donatien 0:ae46a0638b2c 147 return false;
donatien 0:ae46a0638b2c 148 }
donatien 0:ae46a0638b2c 149 }
donatien 0:ae46a0638b2c 150
donatien 0:ae46a0638b2c 151 //Lock processing
donatien 0:ae46a0638b2c 152 void USBHALHost::lock()
donatien 0:ae46a0638b2c 153 {
donatien 0:ae46a0638b2c 154 mtx.lock();
donatien 0:ae46a0638b2c 155 }
donatien 0:ae46a0638b2c 156
donatien 0:ae46a0638b2c 157 void USBHALHost::unlock()
donatien 0:ae46a0638b2c 158 {
donatien 0:ae46a0638b2c 159 mtx.unlock();
donatien 0:ae46a0638b2c 160 }
donatien 0:ae46a0638b2c 161
donatien 0:ae46a0638b2c 162 void USBHALHost::memInit() {
donatien 0:ae46a0638b2c 163 usb_hcca = (volatile HCCA *)usb_buf;
donatien 0:ae46a0638b2c 164 usb_edBuf = usb_buf + HCCA_SIZE;
donatien 0:ae46a0638b2c 165 usb_tdBuf = usb_buf + HCCA_SIZE + (MAX_ENDPOINT*ED_SIZE);
donatien 0:ae46a0638b2c 166 }
donatien 0:ae46a0638b2c 167
donatien 0:ae46a0638b2c 168 volatile uint8_t * USBHALHost::getED() {
donatien 0:ae46a0638b2c 169 for (int i = 0; i < MAX_ENDPOINT; i++) {
donatien 0:ae46a0638b2c 170 if ( !edBufAlloc[i] ) {
donatien 0:ae46a0638b2c 171 edBufAlloc[i] = true;
donatien 0:ae46a0638b2c 172 return (volatile uint8_t *)(usb_edBuf + i*ED_SIZE);
donatien 0:ae46a0638b2c 173 }
donatien 0:ae46a0638b2c 174 }
donatien 0:ae46a0638b2c 175 perror("Could not allocate ED\r\n");
donatien 0:ae46a0638b2c 176 return NULL; //Could not alloc ED
donatien 0:ae46a0638b2c 177 }
donatien 0:ae46a0638b2c 178
donatien 0:ae46a0638b2c 179 volatile uint8_t * USBHALHost::getTD() {
donatien 0:ae46a0638b2c 180 int i;
donatien 0:ae46a0638b2c 181 for (i = 0; i < MAX_TD; i++) {
donatien 0:ae46a0638b2c 182 if ( !tdBufAlloc[i] ) {
donatien 0:ae46a0638b2c 183 tdBufAlloc[i] = true;
donatien 0:ae46a0638b2c 184 return (volatile uint8_t *)(usb_tdBuf + i*TD_SIZE);
donatien 0:ae46a0638b2c 185 }
donatien 0:ae46a0638b2c 186 }
donatien 0:ae46a0638b2c 187 perror("Could not allocate TD\r\n");
donatien 0:ae46a0638b2c 188 return NULL; //Could not alloc TD
donatien 0:ae46a0638b2c 189 }
donatien 0:ae46a0638b2c 190
donatien 0:ae46a0638b2c 191
donatien 0:ae46a0638b2c 192 void USBHALHost::freeED(volatile uint8_t * ed) {
donatien 0:ae46a0638b2c 193 int i;
donatien 0:ae46a0638b2c 194 i = (ed - usb_edBuf) / ED_SIZE;
donatien 0:ae46a0638b2c 195 edBufAlloc[i] = false;
donatien 0:ae46a0638b2c 196 }
donatien 0:ae46a0638b2c 197
donatien 0:ae46a0638b2c 198 void USBHALHost::freeTD(volatile uint8_t * td) {
donatien 0:ae46a0638b2c 199 int i;
donatien 0:ae46a0638b2c 200 i = (td - usb_tdBuf) / TD_SIZE;
donatien 0:ae46a0638b2c 201 tdBufAlloc[i] = false;
donatien 0:ae46a0638b2c 202 }
donatien 0:ae46a0638b2c 203
donatien 0:ae46a0638b2c 204
donatien 0:ae46a0638b2c 205 void USBHALHost::resetPort(int hub, int port) {
donatien 0:ae46a0638b2c 206 DBG("Resetting hub %d, port %d\n", hub, port);
donatien 0:ae46a0638b2c 207 if (hub == 0) { //Root hub
donatien 0:ae46a0638b2c 208 // USB 2.0 spec says at least 50ms delay before port reset
donatien 0:ae46a0638b2c 209 Thread::wait(200);
donatien 0:ae46a0638b2c 210 LPC_USB->HcRhPortStatus1 = OR_RH_PORT_PRS; // Initiate port reset
donatien 0:ae46a0638b2c 211 while (LPC_USB->HcRhPortStatus1 & OR_RH_PORT_PRS);
donatien 0:ae46a0638b2c 212 LPC_USB->HcRhPortStatus1 = OR_RH_PORT_PRSC; // ...and clear port reset signal
donatien 0:ae46a0638b2c 213 // Wait for 100 MS after port reset
donatien 0:ae46a0638b2c 214 Thread::wait(200);
donatien 0:ae46a0638b2c 215 } else {
donatien 0:ae46a0638b2c 216 //TODO: Hubs
donatien 0:ae46a0638b2c 217 }
donatien 0:ae46a0638b2c 218 }
donatien 0:ae46a0638b2c 219
donatien 0:ae46a0638b2c 220
donatien 0:ae46a0638b2c 221 void USBHALHost::_usbisr(void) {
donatien 0:ae46a0638b2c 222 if (instHost) {
donatien 0:ae46a0638b2c 223 instHost->UsbIrqhandler();
donatien 0:ae46a0638b2c 224 }
donatien 0:ae46a0638b2c 225 }
donatien 0:ae46a0638b2c 226
donatien 0:ae46a0638b2c 227 void USBHALHost::UsbIrqhandler() {
donatien 0:ae46a0638b2c 228 if( LPC_USB->HcInterruptStatus & LPC_USB->HcInterruptEnable ) //Is there something to actually process?
donatien 0:ae46a0638b2c 229 {
donatien 0:ae46a0638b2c 230 NVIC_DisableIRQ(USB_IRQn);
donatien 0:ae46a0638b2c 231 NVIC_ClearPendingIRQ(USB_IRQn);
donatien 0:ae46a0638b2c 232 thread.signal_set(USBHALHOST_SIG_IRQ); //Signal processing thread
donatien 0:ae46a0638b2c 233 }
donatien 0:ae46a0638b2c 234
donatien 0:ae46a0638b2c 235 }
donatien 0:ae46a0638b2c 236
donatien 0:ae46a0638b2c 237 void USBHALHost::process()
donatien 0:ae46a0638b2c 238 {
donatien 0:ae46a0638b2c 239 DBG("USB Process started");
donatien 0:ae46a0638b2c 240
donatien 0:ae46a0638b2c 241 lock();
donatien 0:ae46a0638b2c 242 Thread::signal_wait(USBHALHOST_SIG_INIT);
donatien 0:ae46a0638b2c 243
donatien 0:ae46a0638b2c 244 NVIC_DisableIRQ(USB_IRQn); // Disable the USB interrupt source
donatien 0:ae46a0638b2c 245
donatien 0:ae46a0638b2c 246 LPC_SC->PCONP &= ~(1UL<<31); //Cut power
donatien 0:ae46a0638b2c 247 Thread::wait(200);
donatien 0:ae46a0638b2c 248
donatien 0:ae46a0638b2c 249 // turn on power for USB
donatien 0:ae46a0638b2c 250 LPC_SC->PCONP |= (1UL<<31);
donatien 0:ae46a0638b2c 251
donatien 0:ae46a0638b2c 252 // Enable USB host clock, port selection and AHB clock
donatien 0:ae46a0638b2c 253 LPC_USB->USBClkCtrl |= CLOCK_MASK;
donatien 0:ae46a0638b2c 254
donatien 0:ae46a0638b2c 255 // Wait for clocks to become available
donatien 0:ae46a0638b2c 256 while ((LPC_USB->USBClkSt & CLOCK_MASK) != CLOCK_MASK);
donatien 0:ae46a0638b2c 257
donatien 0:ae46a0638b2c 258 // it seems the bits[0:1] mean the following
donatien 0:ae46a0638b2c 259 // 0: U1=device, U2=host
donatien 0:ae46a0638b2c 260 // 1: U1=host, U2=host
donatien 0:ae46a0638b2c 261 // 2: reserved
donatien 0:ae46a0638b2c 262 // 3: U1=host, U2=device
donatien 0:ae46a0638b2c 263 // NB: this register is only available if OTG clock (aka "port select") is enabled!!
donatien 0:ae46a0638b2c 264 // since we don't care about port 2, set just bit 0 to 1 (U1=host)
donatien 0:ae46a0638b2c 265 LPC_USB->OTGStCtrl |= 1;
donatien 0:ae46a0638b2c 266
donatien 0:ae46a0638b2c 267 // now that we've configured the ports, we can turn off the portsel clock
donatien 0:ae46a0638b2c 268 LPC_USB->USBClkCtrl &= ~PORTSEL_CLK_EN;
donatien 0:ae46a0638b2c 269
donatien 0:ae46a0638b2c 270 // configure USB D+/D- pins
donatien 0:ae46a0638b2c 271 // P0[29] = USB_D+, 01
donatien 0:ae46a0638b2c 272 // P0[30] = USB_D-, 01
donatien 0:ae46a0638b2c 273 LPC_PINCON->PINSEL1 &= ~((3<<26) | (3<<28));
donatien 0:ae46a0638b2c 274 LPC_PINCON->PINSEL1 |= ((1<<26)|(1<<28)); // 0x14000000
donatien 0:ae46a0638b2c 275
donatien 0:ae46a0638b2c 276 LPC_USB->HcControl = 0; // HARDWARE RESET
donatien 0:ae46a0638b2c 277 LPC_USB->HcControlHeadED = 0; // Initialize Control list head to Zero
donatien 0:ae46a0638b2c 278 LPC_USB->HcBulkHeadED = 0; // Initialize Bulk list head to Zero
donatien 0:ae46a0638b2c 279
donatien 0:ae46a0638b2c 280 //wait_ms(100); // Wait 50 ms before apply reset
donatien 0:ae46a0638b2c 281 Thread::wait(100);
donatien 0:ae46a0638b2c 282
donatien 0:ae46a0638b2c 283 // SOFTWARE RESET
donatien 0:ae46a0638b2c 284 LPC_USB->HcCommandStatus = OR_CMD_STATUS_HCR;
donatien 0:ae46a0638b2c 285 LPC_USB->HcFmInterval = DEFAULT_FMINTERVAL; // Write Fm Interval and Largest Data Packet Counter
donatien 0:ae46a0638b2c 286 LPC_USB->HcPeriodicStart = FI * 90 / 100;
donatien 0:ae46a0638b2c 287
donatien 0:ae46a0638b2c 288 // Put HC in operational state
donatien 0:ae46a0638b2c 289 LPC_USB->HcControl = (LPC_USB->HcControl & (~OR_CONTROL_HCFS)) | OR_CONTROL_HC_OPER;
donatien 0:ae46a0638b2c 290 LPC_USB->HcRhStatus = OR_RH_STATUS_LPSC; // Set Global Power
donatien 0:ae46a0638b2c 291
donatien 0:ae46a0638b2c 292 LPC_USB->HcHCCA = (uint32_t)(usb_hcca);
donatien 0:ae46a0638b2c 293 LPC_USB->HcInterruptStatus |= LPC_USB->HcInterruptStatus; // Clear Interrrupt Status
donatien 0:ae46a0638b2c 294
donatien 0:ae46a0638b2c 295 LPC_USB->HcInterruptEnable = OR_INTR_ENABLE_MIE | OR_INTR_ENABLE_WDH | OR_INTR_ENABLE_RHSC;
donatien 0:ae46a0638b2c 296
donatien 0:ae46a0638b2c 297 //DG: Do not set prio
donatien 0:ae46a0638b2c 298 //NVIC_SetPriority(USB_IRQn, 0); // highest priority
donatien 0:ae46a0638b2c 299 // Enable the USB Interrupt
donatien 0:ae46a0638b2c 300 NVIC_SetVector(USB_IRQn, (uint32_t)(_usbisr));
donatien 0:ae46a0638b2c 301 LPC_USB->HcRhPortStatus1 = OR_RH_PORT_CSC;
donatien 0:ae46a0638b2c 302 LPC_USB->HcRhPortStatus1 = OR_RH_PORT_PRSC;
donatien 0:ae46a0638b2c 303
donatien 0:ae46a0638b2c 304 NVIC_EnableIRQ(USB_IRQn);
donatien 0:ae46a0638b2c 305
donatien 0:ae46a0638b2c 306
donatien 0:ae46a0638b2c 307 // Check for any connected devices
donatien 0:ae46a0638b2c 308 if (LPC_USB->HcRhPortStatus1 & OR_RH_PORT_CCS) { //Root device connected
donatien 0:ae46a0638b2c 309 //Device connected
donatien 0:ae46a0638b2c 310 Thread::wait(500);
donatien 0:ae46a0638b2c 311 DBG("Device connected (%08x)\n\r", LPC_USB->HcRhPortStatus1);
donatien 0:ae46a0638b2c 312 deviceConnected(0, 1, LPC_USB->HcRhPortStatus1 & OR_RH_PORT_LSDA); //Hub 0 (root hub), Port 1 (count starts at 1), Low or High speed
donatien 0:ae46a0638b2c 313 }
donatien 0:ae46a0638b2c 314
donatien 0:ae46a0638b2c 315 unlock();
donatien 0:ae46a0638b2c 316
donatien 0:ae46a0638b2c 317
donatien 0:ae46a0638b2c 318 for(;;)
donatien 0:ae46a0638b2c 319 {
donatien 0:ae46a0638b2c 320 Thread::signal_wait(USBHALHOST_SIG_IRQ); //Wait for IRQ to process
donatien 0:ae46a0638b2c 321
donatien 0:ae46a0638b2c 322 lock();
donatien 0:ae46a0638b2c 323 DBG("Locked");
donatien 0:ae46a0638b2c 324
donatien 0:ae46a0638b2c 325 WARN("isr %08x [EN %08x]", LPC_USB->HcInterruptStatus, LPC_USB->HcInterruptEnable);
donatien 0:ae46a0638b2c 326
donatien 0:ae46a0638b2c 327 //Now process IRQ
donatien 0:ae46a0638b2c 328 uint32_t int_status = LPC_USB->HcInterruptStatus & LPC_USB->HcInterruptEnable;
donatien 0:ae46a0638b2c 329
donatien 0:ae46a0638b2c 330 if (int_status & OR_INTR_STATUS_RHSC)
donatien 0:ae46a0638b2c 331 { // Root hub status change interrupt
donatien 0:ae46a0638b2c 332 WARN("Port status %08x", LPC_USB->HcRhPortStatus1);
donatien 0:ae46a0638b2c 333 if (LPC_USB->HcRhPortStatus1 & OR_RH_PORT_CSC)
donatien 0:ae46a0638b2c 334 {
donatien 0:ae46a0638b2c 335 if (LPC_USB->HcRhStatus & OR_RH_STATUS_DRWE)
donatien 0:ae46a0638b2c 336 {
donatien 0:ae46a0638b2c 337
donatien 0:ae46a0638b2c 338 // When DRWE is on, Connect Status Change
donatien 0:ae46a0638b2c 339 // means a remote wakeup event.
donatien 0:ae46a0638b2c 340
donatien 0:ae46a0638b2c 341 }
donatien 0:ae46a0638b2c 342 else
donatien 0:ae46a0638b2c 343 {
donatien 0:ae46a0638b2c 344
donatien 0:ae46a0638b2c 345 // When DRWE is off, Connect Status Change
donatien 0:ae46a0638b2c 346 // is NOT a remote wakeup event
donatien 0:ae46a0638b2c 347
donatien 0:ae46a0638b2c 348 if (LPC_USB->HcRhPortStatus1 & OR_RH_PORT_CCS)
donatien 0:ae46a0638b2c 349 { //Root device connected
donatien 0:ae46a0638b2c 350 //Device connected
donatien 0:ae46a0638b2c 351 WARN("Device connected!!");
donatien 0:ae46a0638b2c 352 // Thread::wait(500);
donatien 0:ae46a0638b2c 353 deviceConnected(0, 1, LPC_USB->HcRhPortStatus1 & OR_RH_PORT_LSDA); //Hub 0 (root hub), Port 1 (count starts at 1), Low or High speed
donatien 0:ae46a0638b2c 354 }
donatien 0:ae46a0638b2c 355 else
donatien 0:ae46a0638b2c 356 { //Root device disconnected
donatien 0:ae46a0638b2c 357 //Device disconnected
donatien 0:ae46a0638b2c 358 WARN("Device disconnected!!");
donatien 0:ae46a0638b2c 359 Thread::wait(500);
donatien 0:ae46a0638b2c 360 if (!(int_status & OR_INTR_STATUS_WDH))
donatien 0:ae46a0638b2c 361 {
donatien 0:ae46a0638b2c 362 usb_hcca->DoneHead = 0;
donatien 0:ae46a0638b2c 363 }
donatien 0:ae46a0638b2c 364 deviceDisconnected(0, 1, usb_hcca->DoneHead & 0xFFFFFFFE);
donatien 0:ae46a0638b2c 365 if (int_status & OR_INTR_STATUS_WDH)
donatien 0:ae46a0638b2c 366 {
donatien 0:ae46a0638b2c 367 usb_hcca->DoneHead = 0;
donatien 0:ae46a0638b2c 368 LPC_USB->HcInterruptStatus = OR_INTR_STATUS_WDH;
donatien 0:ae46a0638b2c 369 }
donatien 0:ae46a0638b2c 370
donatien 0:ae46a0638b2c 371 }
donatien 0:ae46a0638b2c 372 //TODO: HUBS
donatien 0:ae46a0638b2c 373 }
donatien 0:ae46a0638b2c 374 LPC_USB->HcRhPortStatus1 = OR_RH_PORT_CSC;
donatien 0:ae46a0638b2c 375 }
donatien 0:ae46a0638b2c 376 if (LPC_USB->HcRhPortStatus1 & OR_RH_PORT_PRSC)
donatien 0:ae46a0638b2c 377 {
donatien 0:ae46a0638b2c 378 LPC_USB->HcRhPortStatus1 = OR_RH_PORT_PRSC;
donatien 0:ae46a0638b2c 379 //int_status &= ~OR_RH_PORT_PRSC;
donatien 0:ae46a0638b2c 380 }
donatien 0:ae46a0638b2c 381 LPC_USB->HcInterruptStatus = OR_INTR_STATUS_RHSC;
donatien 0:ae46a0638b2c 382 }
donatien 0:ae46a0638b2c 383
donatien 0:ae46a0638b2c 384 if (int_status & OR_INTR_STATUS_WDH)
donatien 0:ae46a0638b2c 385 { // Writeback Done Head interrupt
donatien 0:ae46a0638b2c 386 transferCompleted(usb_hcca->DoneHead & 0xFFFFFFFE);
donatien 0:ae46a0638b2c 387 LPC_USB->HcInterruptStatus = OR_INTR_STATUS_WDH;
donatien 0:ae46a0638b2c 388 }
donatien 0:ae46a0638b2c 389
donatien 0:ae46a0638b2c 390 //IRQ Processed
donatien 0:ae46a0638b2c 391
donatien 0:ae46a0638b2c 392 DBG("Unlocked");
donatien 0:ae46a0638b2c 393
donatien 0:ae46a0638b2c 394 NVIC_EnableIRQ(USB_IRQn);
donatien 0:ae46a0638b2c 395
donatien 0:ae46a0638b2c 396 unlock();
donatien 0:ae46a0638b2c 397
donatien 0:ae46a0638b2c 398 }
donatien 0:ae46a0638b2c 399 }
donatien 0:ae46a0638b2c 400
donatien 0:ae46a0638b2c 401 /*static*/ void USBHALHost::staticCb(void const* p)
donatien 0:ae46a0638b2c 402 {
donatien 0:ae46a0638b2c 403 ((USBHALHost*)p)->process();
donatien 0:ae46a0638b2c 404 }