Running multiple threads on mbed using RTOS

Dependencies:   4DGL-uLCD-SE SDFileSystem mbed-rtos mbed wave_player_appbd

Committer:
wschon
Date:
Mon Feb 29 03:46:10 2016 +0000
Revision:
4:5fdadaef5b1f
Parent:
1:2129bb91c172
fixed EVERYTHING

Who changed what in which revision?

UserRevisionLine numberNew contents of line
wschon 1:2129bb91c172 1 /* mbed USBHost Library
wschon 1:2129bb91c172 2 * Copyright (c) 2006-2013 ARM Limited
wschon 1:2129bb91c172 3 *
wschon 1:2129bb91c172 4 * Licensed under the Apache License, Version 2.0 (the "License");
wschon 1:2129bb91c172 5 * you may not use this file except in compliance with the License.
wschon 1:2129bb91c172 6 * You may obtain a copy of the License at
wschon 1:2129bb91c172 7 *
wschon 1:2129bb91c172 8 * http://www.apache.org/licenses/LICENSE-2.0
wschon 1:2129bb91c172 9 *
wschon 1:2129bb91c172 10 * Unless required by applicable law or agreed to in writing, software
wschon 1:2129bb91c172 11 * distributed under the License is distributed on an "AS IS" BASIS,
wschon 1:2129bb91c172 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
wschon 1:2129bb91c172 13 * See the License for the specific language governing permissions and
wschon 1:2129bb91c172 14 * limitations under the License.
wschon 1:2129bb91c172 15 */
wschon 1:2129bb91c172 16
wschon 1:2129bb91c172 17 #include "mbed.h"
wschon 1:2129bb91c172 18 #include "USBHALHost.h"
wschon 1:2129bb91c172 19 #include "dbg.h"
wschon 1:2129bb91c172 20
wschon 1:2129bb91c172 21 // bits of the USB/OTG clock control register
wschon 1:2129bb91c172 22 #define HOST_CLK_EN (1<<0)
wschon 1:2129bb91c172 23 #define DEV_CLK_EN (1<<1)
wschon 1:2129bb91c172 24 #define PORTSEL_CLK_EN (1<<3)
wschon 1:2129bb91c172 25 #define AHB_CLK_EN (1<<4)
wschon 1:2129bb91c172 26
wschon 1:2129bb91c172 27 // bits of the USB/OTG clock status register
wschon 1:2129bb91c172 28 #define HOST_CLK_ON (1<<0)
wschon 1:2129bb91c172 29 #define DEV_CLK_ON (1<<1)
wschon 1:2129bb91c172 30 #define PORTSEL_CLK_ON (1<<3)
wschon 1:2129bb91c172 31 #define AHB_CLK_ON (1<<4)
wschon 1:2129bb91c172 32
wschon 1:2129bb91c172 33 // we need host clock, OTG/portsel clock and AHB clock
wschon 1:2129bb91c172 34 #define CLOCK_MASK (HOST_CLK_EN | PORTSEL_CLK_EN | AHB_CLK_EN)
wschon 1:2129bb91c172 35
wschon 1:2129bb91c172 36 #define HCCA_SIZE sizeof(HCCA)
wschon 1:2129bb91c172 37 #define ED_SIZE sizeof(HCED)
wschon 1:2129bb91c172 38 #define TD_SIZE sizeof(HCTD)
wschon 1:2129bb91c172 39
wschon 1:2129bb91c172 40 #define TOTAL_SIZE (HCCA_SIZE + (MAX_ENDPOINT*ED_SIZE) + (MAX_TD*TD_SIZE))
wschon 1:2129bb91c172 41
wschon 1:2129bb91c172 42 static volatile __align(256) uint8_t usb_buf[TOTAL_SIZE] __attribute((section("AHBSRAM1"),aligned)); //256 bytes aligned!
wschon 1:2129bb91c172 43
wschon 1:2129bb91c172 44 USBHALHost * USBHALHost::instHost;
wschon 1:2129bb91c172 45
wschon 1:2129bb91c172 46 USBHALHost::USBHALHost() {
wschon 1:2129bb91c172 47 instHost = this;
wschon 1:2129bb91c172 48 memInit();
wschon 1:2129bb91c172 49 memset((void*)usb_hcca, 0, HCCA_SIZE);
wschon 1:2129bb91c172 50 for (int i = 0; i < MAX_ENDPOINT; i++) {
wschon 1:2129bb91c172 51 edBufAlloc[i] = false;
wschon 1:2129bb91c172 52 }
wschon 1:2129bb91c172 53 for (int i = 0; i < MAX_TD; i++) {
wschon 1:2129bb91c172 54 tdBufAlloc[i] = false;
wschon 1:2129bb91c172 55 }
wschon 1:2129bb91c172 56 }
wschon 1:2129bb91c172 57
wschon 1:2129bb91c172 58 void USBHALHost::init() {
wschon 1:2129bb91c172 59 NVIC_DisableIRQ(USB_IRQn);
wschon 1:2129bb91c172 60
wschon 1:2129bb91c172 61 //Cut power
wschon 1:2129bb91c172 62 LPC_SC->PCONP &= ~(1UL<<31);
wschon 1:2129bb91c172 63 wait_ms(100);
wschon 1:2129bb91c172 64
wschon 1:2129bb91c172 65 // turn on power for USB
wschon 1:2129bb91c172 66 LPC_SC->PCONP |= (1UL<<31);
wschon 1:2129bb91c172 67
wschon 1:2129bb91c172 68 // Enable USB host clock, port selection and AHB clock
wschon 1:2129bb91c172 69 LPC_USB->USBClkCtrl |= CLOCK_MASK;
wschon 1:2129bb91c172 70
wschon 1:2129bb91c172 71 // Wait for clocks to become available
wschon 1:2129bb91c172 72 while ((LPC_USB->USBClkSt & CLOCK_MASK) != CLOCK_MASK);
wschon 1:2129bb91c172 73
wschon 1:2129bb91c172 74 // it seems the bits[0:1] mean the following
wschon 1:2129bb91c172 75 // 0: U1=device, U2=host
wschon 1:2129bb91c172 76 // 1: U1=host, U2=host
wschon 1:2129bb91c172 77 // 2: reserved
wschon 1:2129bb91c172 78 // 3: U1=host, U2=device
wschon 1:2129bb91c172 79 // NB: this register is only available if OTG clock (aka "port select") is enabled!!
wschon 1:2129bb91c172 80 // since we don't care about port 2, set just bit 0 to 1 (U1=host)
wschon 1:2129bb91c172 81 LPC_USB->OTGStCtrl |= 1;
wschon 1:2129bb91c172 82
wschon 1:2129bb91c172 83 // now that we've configured the ports, we can turn off the portsel clock
wschon 1:2129bb91c172 84 LPC_USB->USBClkCtrl &= ~PORTSEL_CLK_EN;
wschon 1:2129bb91c172 85
wschon 1:2129bb91c172 86 // configure USB D+/D- pins
wschon 1:2129bb91c172 87 // P0[29] = USB_D+, 01
wschon 1:2129bb91c172 88 // P0[30] = USB_D-, 01
wschon 1:2129bb91c172 89 LPC_PINCON->PINSEL1 &= ~((3<<26) | (3<<28));
wschon 1:2129bb91c172 90 LPC_PINCON->PINSEL1 |= ((1<<26) | (1<<28));
wschon 1:2129bb91c172 91
wschon 1:2129bb91c172 92 LPC_USB->HcControl = 0; // HARDWARE RESET
wschon 1:2129bb91c172 93 LPC_USB->HcControlHeadED = 0; // Initialize Control list head to Zero
wschon 1:2129bb91c172 94 LPC_USB->HcBulkHeadED = 0; // Initialize Bulk list head to Zero
wschon 1:2129bb91c172 95
wschon 1:2129bb91c172 96 // Wait 100 ms before apply reset
wschon 1:2129bb91c172 97 wait_ms(100);
wschon 1:2129bb91c172 98
wschon 1:2129bb91c172 99 // software reset
wschon 1:2129bb91c172 100 LPC_USB->HcCommandStatus = OR_CMD_STATUS_HCR;
wschon 1:2129bb91c172 101
wschon 1:2129bb91c172 102 // Write Fm Interval and Largest Data Packet Counter
wschon 1:2129bb91c172 103 LPC_USB->HcFmInterval = DEFAULT_FMINTERVAL;
wschon 1:2129bb91c172 104 LPC_USB->HcPeriodicStart = FI * 90 / 100;
wschon 1:2129bb91c172 105
wschon 1:2129bb91c172 106 // Put HC in operational state
wschon 1:2129bb91c172 107 LPC_USB->HcControl = (LPC_USB->HcControl & (~OR_CONTROL_HCFS)) | OR_CONTROL_HC_OPER;
wschon 1:2129bb91c172 108 // Set Global Power
wschon 1:2129bb91c172 109 LPC_USB->HcRhStatus = OR_RH_STATUS_LPSC;
wschon 1:2129bb91c172 110
wschon 1:2129bb91c172 111 LPC_USB->HcHCCA = (uint32_t)(usb_hcca);
wschon 1:2129bb91c172 112
wschon 1:2129bb91c172 113 // Clear Interrrupt Status
wschon 1:2129bb91c172 114 LPC_USB->HcInterruptStatus |= LPC_USB->HcInterruptStatus;
wschon 1:2129bb91c172 115
wschon 1:2129bb91c172 116 LPC_USB->HcInterruptEnable = OR_INTR_ENABLE_MIE | OR_INTR_ENABLE_WDH | OR_INTR_ENABLE_RHSC;
wschon 1:2129bb91c172 117
wschon 1:2129bb91c172 118 // Enable the USB Interrupt
wschon 1:2129bb91c172 119 NVIC_SetVector(USB_IRQn, (uint32_t)(_usbisr));
wschon 1:2129bb91c172 120 LPC_USB->HcRhPortStatus1 = OR_RH_PORT_CSC;
wschon 1:2129bb91c172 121 LPC_USB->HcRhPortStatus1 = OR_RH_PORT_PRSC;
wschon 1:2129bb91c172 122
wschon 1:2129bb91c172 123 NVIC_EnableIRQ(USB_IRQn);
wschon 1:2129bb91c172 124
wschon 1:2129bb91c172 125 // Check for any connected devices
wschon 1:2129bb91c172 126 if (LPC_USB->HcRhPortStatus1 & OR_RH_PORT_CCS) {
wschon 1:2129bb91c172 127 //Device connected
wschon 1:2129bb91c172 128 wait_ms(150);
wschon 1:2129bb91c172 129 USB_DBG("Device connected (%08x)\n\r", LPC_USB->HcRhPortStatus1);
wschon 1:2129bb91c172 130 deviceConnected(0, 1, LPC_USB->HcRhPortStatus1 & OR_RH_PORT_LSDA);
wschon 1:2129bb91c172 131 }
wschon 1:2129bb91c172 132 }
wschon 1:2129bb91c172 133
wschon 1:2129bb91c172 134 uint32_t USBHALHost::controlHeadED() {
wschon 1:2129bb91c172 135 return LPC_USB->HcControlHeadED;
wschon 1:2129bb91c172 136 }
wschon 1:2129bb91c172 137
wschon 1:2129bb91c172 138 uint32_t USBHALHost::bulkHeadED() {
wschon 1:2129bb91c172 139 return LPC_USB->HcBulkHeadED;
wschon 1:2129bb91c172 140 }
wschon 1:2129bb91c172 141
wschon 1:2129bb91c172 142 uint32_t USBHALHost::interruptHeadED() {
wschon 1:2129bb91c172 143 return usb_hcca->IntTable[0];
wschon 1:2129bb91c172 144 }
wschon 1:2129bb91c172 145
wschon 1:2129bb91c172 146 void USBHALHost::updateBulkHeadED(uint32_t addr) {
wschon 1:2129bb91c172 147 LPC_USB->HcBulkHeadED = addr;
wschon 1:2129bb91c172 148 }
wschon 1:2129bb91c172 149
wschon 1:2129bb91c172 150
wschon 1:2129bb91c172 151 void USBHALHost::updateControlHeadED(uint32_t addr) {
wschon 1:2129bb91c172 152 LPC_USB->HcControlHeadED = addr;
wschon 1:2129bb91c172 153 }
wschon 1:2129bb91c172 154
wschon 1:2129bb91c172 155 void USBHALHost::updateInterruptHeadED(uint32_t addr) {
wschon 1:2129bb91c172 156 usb_hcca->IntTable[0] = addr;
wschon 1:2129bb91c172 157 }
wschon 1:2129bb91c172 158
wschon 1:2129bb91c172 159
wschon 1:2129bb91c172 160 void USBHALHost::enableList(ENDPOINT_TYPE type) {
wschon 1:2129bb91c172 161 switch(type) {
wschon 1:2129bb91c172 162 case CONTROL_ENDPOINT:
wschon 1:2129bb91c172 163 LPC_USB->HcCommandStatus = OR_CMD_STATUS_CLF;
wschon 1:2129bb91c172 164 LPC_USB->HcControl |= OR_CONTROL_CLE;
wschon 1:2129bb91c172 165 break;
wschon 1:2129bb91c172 166 case ISOCHRONOUS_ENDPOINT:
wschon 1:2129bb91c172 167 break;
wschon 1:2129bb91c172 168 case BULK_ENDPOINT:
wschon 1:2129bb91c172 169 LPC_USB->HcCommandStatus = OR_CMD_STATUS_BLF;
wschon 1:2129bb91c172 170 LPC_USB->HcControl |= OR_CONTROL_BLE;
wschon 1:2129bb91c172 171 break;
wschon 1:2129bb91c172 172 case INTERRUPT_ENDPOINT:
wschon 1:2129bb91c172 173 LPC_USB->HcControl |= OR_CONTROL_PLE;
wschon 1:2129bb91c172 174 break;
wschon 1:2129bb91c172 175 }
wschon 1:2129bb91c172 176 }
wschon 1:2129bb91c172 177
wschon 1:2129bb91c172 178
wschon 1:2129bb91c172 179 bool USBHALHost::disableList(ENDPOINT_TYPE type) {
wschon 1:2129bb91c172 180 switch(type) {
wschon 1:2129bb91c172 181 case CONTROL_ENDPOINT:
wschon 1:2129bb91c172 182 if(LPC_USB->HcControl & OR_CONTROL_CLE) {
wschon 1:2129bb91c172 183 LPC_USB->HcControl &= ~OR_CONTROL_CLE;
wschon 1:2129bb91c172 184 return true;
wschon 1:2129bb91c172 185 }
wschon 1:2129bb91c172 186 return false;
wschon 1:2129bb91c172 187 case ISOCHRONOUS_ENDPOINT:
wschon 1:2129bb91c172 188 return false;
wschon 1:2129bb91c172 189 case BULK_ENDPOINT:
wschon 1:2129bb91c172 190 if(LPC_USB->HcControl & OR_CONTROL_BLE){
wschon 1:2129bb91c172 191 LPC_USB->HcControl &= ~OR_CONTROL_BLE;
wschon 1:2129bb91c172 192 return true;
wschon 1:2129bb91c172 193 }
wschon 1:2129bb91c172 194 return false;
wschon 1:2129bb91c172 195 case INTERRUPT_ENDPOINT:
wschon 1:2129bb91c172 196 if(LPC_USB->HcControl & OR_CONTROL_PLE) {
wschon 1:2129bb91c172 197 LPC_USB->HcControl &= ~OR_CONTROL_PLE;
wschon 1:2129bb91c172 198 return true;
wschon 1:2129bb91c172 199 }
wschon 1:2129bb91c172 200 return false;
wschon 1:2129bb91c172 201 }
wschon 1:2129bb91c172 202 return false;
wschon 1:2129bb91c172 203 }
wschon 1:2129bb91c172 204
wschon 1:2129bb91c172 205
wschon 1:2129bb91c172 206 void USBHALHost::memInit() {
wschon 1:2129bb91c172 207 usb_hcca = (volatile HCCA *)usb_buf;
wschon 1:2129bb91c172 208 usb_edBuf = usb_buf + HCCA_SIZE;
wschon 1:2129bb91c172 209 usb_tdBuf = usb_buf + HCCA_SIZE + (MAX_ENDPOINT*ED_SIZE);
wschon 1:2129bb91c172 210 }
wschon 1:2129bb91c172 211
wschon 1:2129bb91c172 212 volatile uint8_t * USBHALHost::getED() {
wschon 1:2129bb91c172 213 for (int i = 0; i < MAX_ENDPOINT; i++) {
wschon 1:2129bb91c172 214 if ( !edBufAlloc[i] ) {
wschon 1:2129bb91c172 215 edBufAlloc[i] = true;
wschon 1:2129bb91c172 216 return (volatile uint8_t *)(usb_edBuf + i*ED_SIZE);
wschon 1:2129bb91c172 217 }
wschon 1:2129bb91c172 218 }
wschon 1:2129bb91c172 219 perror("Could not allocate ED\r\n");
wschon 1:2129bb91c172 220 return NULL; //Could not alloc ED
wschon 1:2129bb91c172 221 }
wschon 1:2129bb91c172 222
wschon 1:2129bb91c172 223 volatile uint8_t * USBHALHost::getTD() {
wschon 1:2129bb91c172 224 int i;
wschon 1:2129bb91c172 225 for (i = 0; i < MAX_TD; i++) {
wschon 1:2129bb91c172 226 if ( !tdBufAlloc[i] ) {
wschon 1:2129bb91c172 227 tdBufAlloc[i] = true;
wschon 1:2129bb91c172 228 return (volatile uint8_t *)(usb_tdBuf + i*TD_SIZE);
wschon 1:2129bb91c172 229 }
wschon 1:2129bb91c172 230 }
wschon 1:2129bb91c172 231 perror("Could not allocate TD\r\n");
wschon 1:2129bb91c172 232 return NULL; //Could not alloc TD
wschon 1:2129bb91c172 233 }
wschon 1:2129bb91c172 234
wschon 1:2129bb91c172 235
wschon 1:2129bb91c172 236 void USBHALHost::freeED(volatile uint8_t * ed) {
wschon 1:2129bb91c172 237 int i;
wschon 1:2129bb91c172 238 i = (ed - usb_edBuf) / ED_SIZE;
wschon 1:2129bb91c172 239 edBufAlloc[i] = false;
wschon 1:2129bb91c172 240 }
wschon 1:2129bb91c172 241
wschon 1:2129bb91c172 242 void USBHALHost::freeTD(volatile uint8_t * td) {
wschon 1:2129bb91c172 243 int i;
wschon 1:2129bb91c172 244 i = (td - usb_tdBuf) / TD_SIZE;
wschon 1:2129bb91c172 245 tdBufAlloc[i] = false;
wschon 1:2129bb91c172 246 }
wschon 1:2129bb91c172 247
wschon 1:2129bb91c172 248
wschon 1:2129bb91c172 249 void USBHALHost::resetRootHub() {
wschon 1:2129bb91c172 250 // Initiate port reset
wschon 1:2129bb91c172 251 LPC_USB->HcRhPortStatus1 = OR_RH_PORT_PRS;
wschon 1:2129bb91c172 252
wschon 1:2129bb91c172 253 while (LPC_USB->HcRhPortStatus1 & OR_RH_PORT_PRS);
wschon 1:2129bb91c172 254
wschon 1:2129bb91c172 255 // ...and clear port reset signal
wschon 1:2129bb91c172 256 LPC_USB->HcRhPortStatus1 = OR_RH_PORT_PRSC;
wschon 1:2129bb91c172 257 }
wschon 1:2129bb91c172 258
wschon 1:2129bb91c172 259
wschon 1:2129bb91c172 260 void USBHALHost::_usbisr(void) {
wschon 1:2129bb91c172 261 if (instHost) {
wschon 1:2129bb91c172 262 instHost->UsbIrqhandler();
wschon 1:2129bb91c172 263 }
wschon 1:2129bb91c172 264 }
wschon 1:2129bb91c172 265
wschon 1:2129bb91c172 266 void USBHALHost::UsbIrqhandler() {
wschon 1:2129bb91c172 267 if( LPC_USB->HcInterruptStatus & LPC_USB->HcInterruptEnable ) //Is there something to actually process?
wschon 1:2129bb91c172 268 {
wschon 1:2129bb91c172 269
wschon 1:2129bb91c172 270 uint32_t int_status = LPC_USB->HcInterruptStatus & LPC_USB->HcInterruptEnable;
wschon 1:2129bb91c172 271
wschon 1:2129bb91c172 272 // Root hub status change interrupt
wschon 1:2129bb91c172 273 if (int_status & OR_INTR_STATUS_RHSC) {
wschon 1:2129bb91c172 274 if (LPC_USB->HcRhPortStatus1 & OR_RH_PORT_CSC) {
wschon 1:2129bb91c172 275 if (LPC_USB->HcRhStatus & OR_RH_STATUS_DRWE) {
wschon 1:2129bb91c172 276 // When DRWE is on, Connect Status Change
wschon 1:2129bb91c172 277 // means a remote wakeup event.
wschon 1:2129bb91c172 278 } else {
wschon 1:2129bb91c172 279
wschon 1:2129bb91c172 280 //Root device connected
wschon 1:2129bb91c172 281 if (LPC_USB->HcRhPortStatus1 & OR_RH_PORT_CCS) {
wschon 1:2129bb91c172 282
wschon 1:2129bb91c172 283 // wait 150ms to avoid bounce
wschon 1:2129bb91c172 284 wait_ms(150);
wschon 1:2129bb91c172 285
wschon 1:2129bb91c172 286 //Hub 0 (root hub), Port 1 (count starts at 1), Low or High speed
wschon 1:2129bb91c172 287 deviceConnected(0, 1, LPC_USB->HcRhPortStatus1 & OR_RH_PORT_LSDA);
wschon 1:2129bb91c172 288 }
wschon 1:2129bb91c172 289
wschon 1:2129bb91c172 290 //Root device disconnected
wschon 1:2129bb91c172 291 else {
wschon 1:2129bb91c172 292
wschon 1:2129bb91c172 293 if (!(int_status & OR_INTR_STATUS_WDH)) {
wschon 1:2129bb91c172 294 usb_hcca->DoneHead = 0;
wschon 1:2129bb91c172 295 }
wschon 1:2129bb91c172 296
wschon 1:2129bb91c172 297 // wait 200ms to avoid bounce
wschon 1:2129bb91c172 298 wait_ms(200);
wschon 1:2129bb91c172 299
wschon 1:2129bb91c172 300 deviceDisconnected(0, 1, NULL, usb_hcca->DoneHead & 0xFFFFFFFE);
wschon 1:2129bb91c172 301
wschon 1:2129bb91c172 302 if (int_status & OR_INTR_STATUS_WDH) {
wschon 1:2129bb91c172 303 usb_hcca->DoneHead = 0;
wschon 1:2129bb91c172 304 LPC_USB->HcInterruptStatus = OR_INTR_STATUS_WDH;
wschon 1:2129bb91c172 305 }
wschon 1:2129bb91c172 306 }
wschon 1:2129bb91c172 307 }
wschon 1:2129bb91c172 308 LPC_USB->HcRhPortStatus1 = OR_RH_PORT_CSC;
wschon 1:2129bb91c172 309 }
wschon 1:2129bb91c172 310 if (LPC_USB->HcRhPortStatus1 & OR_RH_PORT_PRSC) {
wschon 1:2129bb91c172 311 LPC_USB->HcRhPortStatus1 = OR_RH_PORT_PRSC;
wschon 1:2129bb91c172 312 }
wschon 1:2129bb91c172 313 LPC_USB->HcInterruptStatus = OR_INTR_STATUS_RHSC;
wschon 1:2129bb91c172 314 }
wschon 1:2129bb91c172 315
wschon 1:2129bb91c172 316 // Writeback Done Head interrupt
wschon 1:2129bb91c172 317 if (int_status & OR_INTR_STATUS_WDH) {
wschon 1:2129bb91c172 318 transferCompleted(usb_hcca->DoneHead & 0xFFFFFFFE);
wschon 1:2129bb91c172 319 LPC_USB->HcInterruptStatus = OR_INTR_STATUS_WDH;
wschon 1:2129bb91c172 320 }
wschon 1:2129bb91c172 321 }
wschon 1:2129bb91c172 322 }