void Host_Init (void) { USB_INT32U pinsel; PCONP |= 0x80000000; VICIntEnClr = (1 << 22); /* Enable the USB interrupt source */ OTG_CLK_CTRL = 0x00000009; while ((OTG_CLK_STAT & 0x00000009) == 0) { ; } /* Set port func bits so that both U1 and U2 can be hosts. */ OTG_STAT_CTRL &= ~0x03; OTG_STAT_CTRL |= 0x01; /* P0[12] = USB_PPWR2 01 */ pinsel = PINSEL0; pinsel &= 0xFCFFFFFF; pinsel |= 0x01000000; PINSEL0 = pinsel; /* P0[29] = USB_D+1 */ /* P0[30] = USB_D-1 */ /* P0[31] = USB_D+2 */ pinsel = PINSEL1; pinsel &= 0x03FFFFFF; pinsel |= 0x54000000; PINSEL1 = pinsel; /* P1[19] = USB_PPWR1 10 */ /* P1[22] = USB_PWRD1 10 */ /* P1[27] = USB_OVRCR1 10 */ /* P1[31] = USB_OVRCR2 01 */ pinsel = PINSEL3; pinsel &= 0x3F3FCF3F; pinsel |= 0x40802080; PINSEL3 = pinsel; Hcca = (volatile HCCA *)(HOST_BASE_ADDR+0x000); TDHead = (volatile HCTD *)(HOST_BASE_ADDR+0x100); TDTail = (volatile HCTD *)(HOST_BASE_ADDR+0x110); EDCtrl = (volatile HCED *)(HOST_BASE_ADDR+0x120); EDIntIn = (volatile HCED *)(HOST_BASE_ADDR+0x130); EDIntOut = (volatile HCED *)(HOST_BASE_ADDR+0x140); TDBuffer = (volatile USB_INT08U *)(HOST_BASE_ADDR+0x150); /* Initialize all the TDs, EDs and HCCA to 0 */ Host_EDInit(EDCtrl); Host_EDInit(EDIntIn); Host_EDInit(EDIntOut); Host_TDInit(TDHead); Host_TDInit(TDTail); Host_HCCAInit(Hcca); Host_DelayMS(50); /* Wait 50 ms before apply reset */ HcControl = 0; /* HARDWARE RESET */ HcControlHeadED = 0; /* Initialize Control list head to Zero */ HcPeriodCurrentED = 0; /* SOFTWARE RESET */ HcCommandStatus = OR_CMD_STATUS_HCR; HcFmInterval = DEFAULT_FMINTERVAL; /* Write Fm Interval and Largest Data Packet Counter */ HC_LS_THRHLD = 0x628; /* Put HC in operational state */ HcControl = (HcControl & (~OR_CONTROL_HCFS)) | OR_CONTROL_HC_OPER; HcRhStatus = OR_RH_STATUS_LPSC; /* Set Global Power */ HcHCCA = (USB_INT32U)Hcca; HcInterruptStatus |= HcInterruptStatus; /* Clear Interrrupt Status */ /* Enable interrupts */ HcInterruptEnable = OR_INTR_ENABLE_MIE | OR_INTR_ENABLE_WDH | OR_INTR_ENABLE_RHSC | OR_INTR_ENABLE_SO | OR_INTR_ENABLE_RD | OR_INTR_ENABLE_UE | OR_INTR_ENABLE_FNO | OR_INTR_ENABLE_OC; VICIntSelect &= ~(1 << 22); /* Configure the ISR handler */ VICVectAddr22 = (USB_INT32U)Host_Isr; /* Set the vector address */ VICIntEnable = (1 << 22); /* Enable the USB interrupt source */ VICVectPriority22 &= 0xFFFFFFF0; }
/* ************************************************************************************************************** * INITIALIZE THE HOST CONTROLLER * * Description: This function initializes lpc17xx host controller * * Arguments : None * * Returns : * ************************************************************************************************************** */ void Host_Init (void) { PRINT_Log("In Host_Init\n"); NVIC_DisableIRQ(USB_IRQn); /* Disable the USB interrupt source */ // turn on power for USB LPC_SC->PCONP |= (1UL<<31); // Enable USB host clock, port selection and AHB clock LPC_USB->USBClkCtrl |= CLOCK_MASK; // Wait for clocks to become available while ((LPC_USB->USBClkSt & CLOCK_MASK) != CLOCK_MASK) ; // it seems the bits[0:1] mean the following // 0: U1=device, U2=host // 1: U1=host, U2=host // 2: reserved // 3: U1=host, U2=device // NB: this register is only available if OTG clock (aka "port select") is enabled!! // since we don't care about port 2, set just bit 0 to 1 (U1=host) LPC_USB->OTGStCtrl |= 1; // now that we've configured the ports, we can turn off the portsel clock LPC_USB->USBClkCtrl &= ~PORTSEL_CLK_EN; // power pins are not connected on mbed, so we can skip them /* P1[18] = USB_UP_LED, 01 */ /* P1[19] = /USB_PPWR, 10 */ /* P1[22] = USB_PWRD, 10 */ /* P1[27] = /USB_OVRCR, 10 */ /*LPC_PINCON->PINSEL3 &= ~((3<<4) | (3<<6) | (3<<12) | (3<<22)); LPC_PINCON->PINSEL3 |= ((1<<4)|(2<<6) | (2<<12) | (2<<22)); // 0x00802080 */ // configure USB D+/D- pins /* P0[29] = USB_D+, 01 */ /* P0[30] = USB_D-, 01 */ LPC_PINCON->PINSEL1 &= ~((3<<26) | (3<<28)); LPC_PINCON->PINSEL1 |= ((1<<26)|(1<<28)); // 0x14000000 PRINT_Log("Initializing Host Stack\n"); Hcca = (volatile HCCA *)(HostBuf+0x000); TDHead = (volatile HCTD *)(HostBuf+0x100); TDTail = (volatile HCTD *)(HostBuf+0x110); EDCtrl = (volatile HCED *)(HostBuf+0x120); EDBulkIn = (volatile HCED *)(HostBuf+0x130); EDBulkOut = (volatile HCED *)(HostBuf+0x140); TDBuffer = (volatile USB_INT08U *)(HostBuf+0x150); /* Initialize all the TDs, EDs and HCCA to 0 */ Host_EDInit(EDCtrl); Host_EDInit(EDBulkIn); Host_EDInit(EDBulkOut); Host_TDInit(TDHead); Host_TDInit(TDTail); Host_HCCAInit(Hcca); Host_DelayMS(50); /* Wait 50 ms before apply reset */ LPC_USB->HcControl = 0; /* HARDWARE RESET */ LPC_USB->HcControlHeadED = 0; /* Initialize Control list head to Zero */ LPC_USB->HcBulkHeadED = 0; /* Initialize Bulk list head to Zero */ /* SOFTWARE RESET */ LPC_USB->HcCommandStatus = OR_CMD_STATUS_HCR; LPC_USB->HcFmInterval = DEFAULT_FMINTERVAL; /* Write Fm Interval and Largest Data Packet Counter */ /* Put HC in operational state */ LPC_USB->HcControl = (LPC_USB->HcControl & (~OR_CONTROL_HCFS)) | OR_CONTROL_HC_OPER; LPC_USB->HcRhStatus = OR_RH_STATUS_LPSC; /* Set Global Power */ LPC_USB->HcHCCA = (USB_INT32U)Hcca; LPC_USB->HcInterruptStatus |= LPC_USB->HcInterruptStatus; /* Clear Interrrupt Status */ LPC_USB->HcInterruptEnable = OR_INTR_ENABLE_MIE | OR_INTR_ENABLE_WDH | OR_INTR_ENABLE_RHSC; NVIC_SetPriority(USB_IRQn, 0); /* highest priority */ /* Enable the USB Interrupt */ NVIC_EnableIRQ(USB_IRQn); PRINT_Log("Host Initialized\n"); }
/*---------------------------------------------------------------------------* * Routine: Host_Init *---------------------------------------------------------------------------* * Description: * Initializes the LPC17xx_40xx host controller with buffers * Inputs: * void *aWorkspace -- USB Host controller workspace *---------------------------------------------------------------------------*/ static T_uezError Host_Init(void *aWorkspace) { extern void USBSharedInterruptSetup(void); T_LPC17xx_40xx_USBHost_Workspace *p = (T_LPC17xx_40xx_USBHost_Workspace *)aWorkspace; // Setup memory from start p->iAllocBase = G_usbHostMemory; p->iAllocRemaining = sizeof(G_usbHostMemory); // Ensure power to the USB is on LPC17xx_40xxPowerOn(1UL<<31); // Enable the USB interrupt source if (p->iPortIndex == USB_HOST_PORT_INDEX_PORT_A) { LPC_USB->OTGClkCtrl = 0x0000001B; while ((LPC_USB->OTGClkSt & 0x0000001B) != 0x1B) { ; } LPC_USB->OTGStCtrl = 0x00000003; } else if (p->iPortIndex == USB_HOST_PORT_INDEX_PORT_B) { LPC_USB->OTGClkCtrl = 0x00000001; while ((LPC_USB->OTGClkSt & 0x00000001) == 0) { ; } } // Allocate standard buffers Hcca = IAllocBuffer(p, sizeof(HCCA)); TDHead = IAllocBuffer(p, sizeof(HCTD)); TDTail = IAllocBuffer(p, sizeof(HCTD)); EDCtrl = IAllocBuffer(p, sizeof(HCED)); EDBulkIn = IAllocBuffer(p, sizeof(HCED)); EDBulkOut = IAllocBuffer(p, sizeof(HCED)); TDBuffer = IAllocBuffer(p, 128); // And then initialize those buffers IHost_EDInit(EDCtrl); IHost_EDInit(EDBulkIn); IHost_EDInit(EDBulkOut); IHost_TDInit(TDHead); IHost_TDInit(TDTail); IHost_HCCAInit(Hcca); // About to reset, first delay Host_DelayMS(50); LPC_USB->HcControl = 0; LPC_USB->HcControlHeadED = 0; LPC_USB->HcBulkHeadED = 0; // Now do the software reset and go back to the largest packet size LPC_USB->HcCommandStatus = OR_CMD_STATUS_HCR; LPC_USB->HcFmInterval = DEFAULT_FMINTERVAL; // Put HC in operational state and set global power LPC_USB->HcControl = (LPC_USB->HcControl & (~OR_CONTROL_HCFS)) | OR_CONTROL_HC_OPER; LPC_USB->HcRhStatus = OR_RH_STATUS_LPSC; LPC_USB->HcHCCA = (TUInt32)Hcca; // Remember the workspace for the interrupt routine // This also indirectly flags the interrupt routine by letting // the system know that we can now process interrupts. if (p->iPortIndex == USB_HOST_PORT_INDEX_PORT_A) { G_usbHostWorkspacePortA = p; } else { G_usbHostWorkspacePortB = p; } // Enable these interrupts LPC_USB->HcInterruptStatus |= LPC_USB->HcInterruptStatus; LPC_USB->HcInterruptEnable = OR_INTR_ENABLE_MIE | OR_INTR_ENABLE_WDH | OR_INTR_ENABLE_RHSC; p->iState = USB_HOST_STATE_CLEAR; USBSharedInterruptSetup(); // Remember the reset condition p->iResetAllocBase = p->iAllocBase; p->iResetAllocRemaining = p->iAllocRemaining; return UEZ_ERROR_NONE; }