USB Host Library for Sprint Dongles

Fork of USBHostWANDongleSprint_bleedingedge by Donatien Garnier

Legacy Warning

This is an mbed 2 libary. To learn more about mbed OS 5, visit the docs.

Committer:
donatien
Date:
Wed Sep 12 08:15:02 2012 +0000
Revision:
0:bfed5767d0a5
Child:
2:34c976009b70
Initial Commit

Who changed what in which revision?

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