?? usbhw.c
字號:
/*----------------------------------------------------------------------------
* U S B - K e r n e l
*----------------------------------------------------------------------------
* Name: USBHW.C
* Purpose: USB Hardware Layer Module for Philips LPC214x
* Version: V1.10
*----------------------------------------------------------------------------
* This software is supplied "AS IS" without any warranties, express,
* implied or statutory, including but not limited to the implied
* warranties of fitness for purpose, satisfactory quality and
* noninfringement. Keil extends you a royalty-free right to reproduce
* and distribute executable files created using this software for use
* on Philips LPC microcontroller devices only. Nothing else gives you
* the right to use this software.
*
* Copyright (c) 2005-2006 Keil Software.
*---------------------------------------------------------------------------*/
#include "LPC288x.h" /* LPC288x definitions */
#include "type.h"
#include "target.h"
#include "timer.h"
#include "usb.h"
#include "usbcfg.h"
#include "usbhw.h"
#include "usbcore.h"
#include "usbuser.h"
#include "timer.h"
extern DWORD USB_EndPointHalt;
volatile DWORD DevStatusFS2HS = FALSE;
volatile DWORD SuspendFlag = FALSE;
#if USB_DMA
volatile DWORD DMACh0EOT = 0;
volatile DWORD DMACh1EOT = 0;
#endif
/*
* USB Initialize Function
* Called by the User to initialize USB
* Return Value: None
*/
void USB_Init (void) {
SuspendFlag = FALSE;
USBClkEn = 1; // Documentation error in USB chapter
// On master reset, this bit needs to set again.
USBDevAdr = 0x00;
USBIntCfg = 0xFC;
// USBTest |= (0x1<<4); // For test only, force to full-speed,
// remove this before certification
USB_Connect( FALSE );
USB_Reset();
USBLock = 0xAA37;
USBClkEn = 1; // Documentation error in USB chapter
// On master reset, this bit needs to set again.
USB_SetAddress(0);
#if USB_LOW_POWER_EVENT
/* If the CLKAON is set, the device won't receive a RESUME
interrupt. To test USB SUSPEND to set to low-power mode and
USB RESUME to wake the uC to normal operation, CLKAON needs to
be disabled. */
USBMode |= (0x1<<3); // Set GIE
#else
/* If the CLKAON is disabled, USBCV Remote Wakeup test will
fail. To be investigated. */
USBMode |= ((0x1<<3)|(0x1<<7)); // Set GIE, CLKAON
#endif
return;
}
/*
* USB Connect Function
* Called by the User to Connect/Disconnect USB
* Parameters: con: Connect/Disconnect
* Return Value: None
*/
void USB_Connect (BOOL con) {
if (con) {
USBMode |= (0x1<<0);
} else {
USBMode &= ~(0x1<<0);
}
}
/*
* USB Reset Function
* Called automatically on USB Reset
* Return Value: None
*/
void USB_Reset (void) {
USB_Configuration = 0;
DevStatusFS2HS = FALSE;
USBClkEn = 1; // Documentation error in USB chapter
// On master reset, this bit needs to set again.
USBEIX = EIX_SEL_EP0SET; // EP0 set up register
USBIntClr = 0x000000FF;
USBEIntClr = 0xFFFF;
USBEIntE |= 0xFFFF;
#if USB_DMA
UDMACtrl = 0x01; // Enable DMA operation
UDMASoftRes = 0x03; // Soft reset to both DMA channel
UDMAIntClr = 0x00000066; // clear EOT and Error for CH0 and CH1
while ( UDMAStat & 0x0707 ); // Wait if both channels are not idle.
UDMAIntEn = 0x44; /* Due to the nature of the RAM drive,
polling on the EOT make the code more
readable and easy to maintain. */
// UDMAIntEn = 0x66; // Enable both EOT and Error
#endif
#if USB_SOF_EVENT
USBIntE = 0x000000BB; /* no PSOF, and DMA, SOF is enabled */
#else
USBIntE = 0x000000B9; /* no SOF, PSOF, and DMA */
#endif
#if USB_DMA
USBIntE |= 0x40; /* Enable DMA bit */
#endif
}
/*
* USB Suspend Function
* Called automatically on USB Suspend
* Return Value: None
*/
void USB_Suspend (void) {
USBMode |= (0x1<<1); // Set Power off before suspend
USBMode |= (0x1<<5);
#if USB_LOW_POWER_EVENT
start_timer();
SuspendFlag = TRUE;
#endif
}
/*
* USB Resume Function
* Called automatically on USB Resume
* Return Value: None
*/
void USB_Resume (void) {
USBMode &= ~(0x1<<1); // Clear power off bit after resume
USBMode |= (0x1<<6);
USBMode &= ~(0x1<<6);
#if USB_LOW_POWER_EVENT
stop_timer();
SuspendFlag = FALSE;
#endif
}
/*
* USB Remote Wakeup Function
* Called automatically on USB Remote Wakeup
* Return Value: None
*/
void USB_WakeUp (void) {
if (USB_DeviceStatus & USB_GETSTATUS_REMOTE_WAKEUP) {
USBMode |= (0x1<<2);
}
}
/*
* USB Remote Wakeup Configuration Function
* Parameters: cfg: Enable/Disable
* Return Value: None
*/
void USB_WakeUpCfg (BOOL cfg) {
if ( cfg == TRUE )
{
USBMode |= (1<<2);
}
else
{
USBMode &= ~(1<<2);
}
}
/*
* USB Set Address Function
* Parameters: adr: USB Address
* Return Value: None
*/
void USB_SetAddress (DWORD adr) {
USBDevAdr = (0x1<<7)|adr;
}
/*
* USB Configure Function
* Parameters: cfg: Configure/Deconfigure
* Return Value: None
*/
void USB_Configure (BOOL cfg) {
/* Not needed */
}
/*
* Configure USB Endpoint according to Descriptor
* Parameters: pEPD: Pointer to Endpoint Descriptor
* Return Value: None
*/
void USB_ConfigEP (USB_ENDPOINT_DESCRIPTOR *pEPD) {
DWORD ep_addr;
ep_addr = pEPD->bEndpointAddress;
if (ep_addr & 0x80) {
ep_addr = ((ep_addr & 0x7F) << 1) | EIX_DIR;
} else {
ep_addr = ep_addr << 1;
}
USBEIX = ep_addr;
USBEType = (pEPD->bmAttributes & 0x001F) | 0x0010;
USBEMaxSize = pEPD->wMaxPacketSize & 0x03FF;
}
/*
* Set Direction for USB Control Endpoint
* Parameters: dir: Out (dir == 0), In (dir <> 0)
* Return Value: None
*/
void USB_DirCtrlEP (DWORD dir) {
dir = dir; /* Not needed */
}
/*
* Enable USB Endpoint
* Parameters: EPNum: Endpoint Number
* EPNum.0..3: Address
* EPNum.7: Dir
* Return Value: None
*/
void USB_EnableEP (DWORD EPNum) {
if ( EPNum & 0x80 ) {
USBEIX = ((EPNum&0x7F) << 1)|EIX_DIR; // IN
} else {
USBEIX = (EPNum&0x7F) << 1; // OUT
}
USBEType |= ETYPE_EP_ENAB;
return;
}
/*
* Disable USB Endpoint
* Parameters: EPNum: Endpoint Number
* EPNum.0..3: Address
* EPNum.7: Dir
* Return Value: None
*/
void USB_DisableEP (DWORD EPNum) {
if ( EPNum & 0x80 ) {
USBEIX = ((EPNum&0x7F) << 1)|EIX_DIR; // IN
} else {
USBEIX = (EPNum&0x7F) << 1; // OUT
}
USBEType &= ~ETYPE_EP_ENAB;
return;
}
/*
* Reset USB Endpoint
* Parameters: EPNum: Endpoint Number
* EPNum.0..3: Address
* EPNum.7: Dir
* Return Value: None
*/
void USB_ResetEP (DWORD EPNum) {
return;
}
/*
* Set Stall for USB Endpoint
* Parameters: EPNum: Endpoint Number
* EPNum.0..3: Address
* EPNum.7: Dir
* Return Value: None
*/
void USB_SetStallEP (DWORD EPNum) {
if ( EPNum & 0x80 ) {
USBEIX = ((EPNum&0x7F) << 1)|EIX_DIR; // IN
USBECtrl |= (0x1 << 0);
USB_EndPointHalt |= ((1 << 16) << (EPNum & 0x0F));
} else {
USBEIX = (EPNum&0x7F) << 1; // OUT
USBECtrl |= (0x1 << 0);
USB_EndPointHalt |= (1 << EPNum);
}
return;
}
/*
* Clear Stall for USB Endpoint
* Parameters: EPNum: Endpoint Number
* EPNum.0..3: Address
* EPNum.7: Dir
* Return Value: None
*/
void USB_ClrStallEP (DWORD EPNum) {
if ( EPNum & 0x80 ) {
USBEIX = ((EPNum&0x7F) << 1)|EIX_DIR; // IN
USBECtrl &= ~(0x1 << 0);
USB_EndPointHalt &= ~((1 << 16) << (EPNum & 0x0F));
} else {
USBEIX = (EPNum&0x7F) << 1; // OUT
USBECtrl &= ~(0x1 << 0);
USB_EndPointHalt &= ~(1 << EPNum);
}
return;
}
/*
* Read USB Setup Data on Endpoint 0
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -