📄 lpc24xx_usb.c
字号:
/*************************************************************************
*
* Used with ICCARM and AARM.
*
* (c) Copyright IAR Systems 2007
*
* File name : LPC24xx_usb.c
* Description : usb module (HAL)
*
* History :
* 1. Date : January 7, 2007
* Author : Stanimir Bonev
* Description : Create
*
* $Revision: 18137 $
**************************************************************************/
#define HAL_USB_GLOBAL
#include "LPC24xx_usb.h"
// Single/Double buffered EP flags
static const Boolean UsbEpDoubleBuffType[] =
{
FALSE, // OUT 0
FALSE, // IN 0
FALSE, // OUT 1
FALSE, // IN 1
TRUE, // OUT 2
TRUE, // IN 2
TRUE, // OUT 3
TRUE, // IN 3
FALSE, // OUT 4
FALSE, // IN 4
TRUE, // OUT 5
TRUE, // IN 5
TRUE, // OUT 6
TRUE, // IN 6
FALSE, // OUT 7
FALSE, // IN 7
TRUE, // OUT 8
TRUE, // IN 8
TRUE, // OUT 9
TRUE, // IN 9
FALSE, // OUT 10
FALSE, // IN 10
TRUE, // OUT 11
TRUE, // IN 11
TRUE, // OUT 12
TRUE, // IN 12
FALSE, // OUT 13
FALSE, // IN 13
TRUE, // OUT 14
TRUE, // IN 14
TRUE, // OUT 15
TRUE, // IN 15
};
static UserFunc_t UsbUserFun [UsbLastEvent] =
{
// EP 0 Out
NULL,
// EP 0 In
NULL,
// EP 1 Out
NULL,
// EP 1 In
NULL,
// EP 2 Out
NULL,
// EP 2 Int
NULL,
// EP 3 Out
NULL,
// EP 3 In
NULL,
// EP 4 Out
NULL,
// EP 4 In
NULL,
// EP 5 Out
NULL,
// EP 5 In
NULL,
// EP 6 Out
NULL,
// EP 6 In
NULL,
// EP 7 Out
NULL,
// EP 7 In
NULL,
// EP 8 Out
NULL,
// EP 8 In
NULL,
// EP 9 Out
NULL,
// EP 9 In
NULL,
// EP 10 Out
NULL,
// EP 10 In
NULL,
// EP 11 Out
NULL,
// EP 11 In
NULL,
// EP 12 Out
NULL,
// EP 12 In
NULL,
// EP 13 Out
NULL,
// EP 13 In
NULL,
// EP 14 Out
NULL,
// EP 14 In
NULL,
// EP 15 Out
NULL,
// EP 15 In
NULL,
// UsbClassEp0OutPacket
NULL,
// UsbVendorEp0OutPacket
NULL,
// UsbUserSofEvent
NULL,
// UsbUserClass
NULL,
// UsbUserVendor
NULL,
// UsbUserGetDescriptor
NULL,
// UsbUserConfigure
NULL,
// UsbUserReset
NULL,
// UsbUserConnect
NULL,
// UsbUserSuspend
NULL,
// UsbUserEpStall
NULL,
// UsbUserEpUnStall
NULL,
// UsbUserErrorEvent
NULL,
};
static volatile UsbDevStat_t USB_DevStatus;
static EpInfo_t EpInfo[ENP_MAX_NUMB];
static UsbEpCtrl_t UsbEp0Ctrl;
static UsbSetupPacket_t UsbEp0SetupPacket;
#pragma data_alignment=4
static Int8U EpCtrlDataBuf[Ep0MaxSize];
static UsbDevCtrl_t UsbDevCtrl = {{UsbDevStatusUnknow,UsbDevStatusNoSuspend},0,0,0,0};
static CommUserFpnt_t UsbCoreT9Fun;
volatile Int32U EpPriority;
#include "usb_common.c"
/*************************************************************************
* Function Name: USB_Cmd
* Parameters: Int16U Command, Int8U Data
*
* Return: Int32U - command result
*
* Description: Implement commands transmit to USB Engine
*
*************************************************************************/
static
Int32U USB_Cmd (Int16U Command, Int8U Data)
{
Int32U save, tmp = 0;
// Disable interrupt and save current state of the interrupt flags
save = __get_interrupt_state();
__disable_interrupt();
USBDEVINTCLR = bmUSB_CommDataFullInterrupt | bmUSB_CommRegEmptyInterrupt;
// Load command in USB engine
USBCMDCODE = ((Command&0xFF) << 16) + USB_CMD_WR;
// Wait until command is accepted
while ((USBDEVINTST & bmUSB_CommRegEmptyInterrupt) == 0);
// clear Command reg. empty interrupt
USBDEVINTCLR = bmUSB_CommRegEmptyInterrupt;
// determinate next phase of the command
switch (Command)
{
case CMD_USB_SET_ADDRESS:
case CMD_USB_CFG_DEV:
case CMD_USB_SET_MODE:
case CMD_USB_SET_DEV_STAT:
USBCMDCODE = (Data << 16) + USB_DATA_WR;
while ((USBDEVINTST & bmUSB_CommRegEmptyInterrupt) == 0);
break;
case CMD_USB_RD_FRAME_NUMB:
case CMD_USB_RD_TEST_REG:
USBCMDCODE = (Command << 16) + USB_DATA_RD;
while ((USBDEVINTST & bmUSB_CommDataFullInterrupt) == 0);
USBDEVINTCLR = bmUSB_CommDataFullInterrupt;
tmp = USBCMDDATA;
USBCMDCODE = (Command << 16) + USB_DATA_RD;
while ((USBDEVINTST & bmUSB_CommDataFullInterrupt) == 0);
tmp |= USBCMDDATA << 8;
break;
case CMD_USB_GET_DEV_STAT:
case CMD_USB_GET_ERROR:
case CMD_USB_RD_ERROR_STAT:
case CMD_USB_CLR_BUF:
USBCMDCODE = (Command << 16) + USB_DATA_RD;
while ((USBDEVINTST & bmUSB_CommDataFullInterrupt) == 0);
tmp = USBCMDDATA;
break;
default:
switch (Command & 0x1E0)
{
case CMD_USB_SEL_EP:
case CMD_USB_SEL_CLR_INT_EP:
USBCMDCODE = (Command << 16) + USB_DATA_RD;
while ((USBDEVINTST & bmUSB_CommDataFullInterrupt) == 0);
tmp = USBCMDDATA;
break;
case CMD_USB_SET_EP_STAT:
USBCMDCODE = (Data << 16) + USB_DATA_WR;
while ((USBDEVINTST & bmUSB_CommRegEmptyInterrupt) == 0);
break;
}
break;
}
// restore the interrupt flags
__set_interrupt_state(save);
return(tmp);
}
/*************************************************************************
* Function Name: USB_EpIntrClr
* Parameters: USB_Endpoint_t EndPoint
*
* Return: Int8U
*
* Description: Clear the EP interrupt flag and return the current EP status
*
*************************************************************************/
static
Int8U USB_EpIntrClr(USB_Endpoint_t EndPoint)
{
volatile Int32U TO = 100;
// Disable interrupt and save current state of the interrupt flags
Int32U save = __get_interrupt_state();
__disable_interrupt();
USBDEVINTCLR = bmUSB_CommDataFullInterrupt;
USBEPINTCLR = 1 << EndPoint;
while ((USBDEVINTST & bmUSB_CommDataFullInterrupt) == 0)
{
if(!--TO)
{
break;
}
}
__set_interrupt_state(save);
return(USBCMDDATA);
}
/*************************************************************************
* Function Name: USB_Init
* Parameters: Int32U IntrSlot,
*
* Return: none
*
* Description: Init USB
*
*************************************************************************/
void USB_Init(Int32U IntrSlot, CommUserFpnt_t UserCoreConfigure)
{
// Init variables
UsbEp0Ctrl.EpStatus.Status = UsbSetupPhase;
UsbCoreT9Fun = NULL;
USB_UserFuncRegistering(UserCoreConfigure,UsbUserConfigure);
EpPriority = 0;
// Turn on USB
PCONP_bit.PCUSB = 1;
#ifdef USB1_ERRATA
// Errata 2006 Nov 16
// USB_NEED_CLK is always asserted
// Introduction:The USB_NEED_CLK signal is used to facilitate going into and
// waking up from chip Power Down mode. USB_NEED_CLK is asserted if any of the
// bits of the USBClkSt register are asserted.
// Problem:The USB_NEED_CLK bit of the USBIntSt register (located at 0xE01F C1C0)
// is always asserted, preventing the chip from entering Power Down mode when
// the USBWAKE bit is set in the INTWAKE register (located at 0xE01F C144).
// Workaround:After setting the PCUSB bit in PCONP (located at 0xE01F C0C4),
// write 0x1 to address 0xFFE0C008. The USB_NEED_CLK signal will now function correct
if(RSIR_bit.POR == 1)
{
RSIR_bit.POR = 1;
*(volatile unsigned int *)0xFFE0C008 = 1;
}
#endif // USB1_ERRATA
// Init USB engine clk freq - 48MHz
// 1/3 Fpll - 48 MHz
USBCLKCFG = USB_CLK_DIV-1;
USBCLKCTRL = (1<<1) | // Device clk enable
(1<<3) | // Port select clk enable
(1<<2) | // I2C clk enable
(1<<4); // AHB clk enable
while((USBCLKST & ((1<<1) | (1<<3) | (1<<4))) != ((1<<1) | (1<<3) | (1<<4)));
// USB IO assign
#if (USB_PORT_SEL==1)
// Assign P0.29 to U1+, P0.30 to U1-
PINSEL1_bit.P0_29 = 1;
PINSEL1_bit.P0_30 = 1;
// Enable Link LED, Connect, Vbus sense
// and disable Pull Up/Down resistor of the Vbus pin
PINSEL3_bit.P1_18 = 1;
// Init OTG I2C
PINSEL3_bit.P1_28 = 1;
PINSEL3_bit.P1_29 = 1;
// USB Port select
USBPORTSEL_bit.PORTSEL = 0;
USBCLKCTRL = (1<<1) | // Device clk enable
(1<<2) | // I2C clk enable
(1<<4); // AHB clk enable
#else
// Assign P0.31 to U2+
PINSEL1_bit.P0_31 = 1;
// Enable Link LED, Connect, Vbus sense
// and disable Pull Up/Down resistor of the Vbus pin
PINSEL0_bit.P0_13 = 1;
#ifdef USB3_ERRATA
FIO0DIR_bit.P1_30 = 0;
PINSEL3_bit.P1_30 = 0;
#else
PINSEL3_bit.P1_30 = 2;
#endif // USB3_ERRATA
PINMODE3_bit.P1_30 = 3;
// USB Port select
USBPORTSEL_bit.PORTSEL = 3;
USBCLKCTRL = (1<<1) | // Device clk enable
(1<<4); // AHB clk enable
#endif // (USB_PORT_SEL==1)
// Disable USB interrupts
USBINTS_bit.EN_USB_INTS = 0;
// Clear all interrupts flags
USBEPINTCLR = USBDEVINTCLR = 0xFFFFFFFF;
// USB interrupt enable
VIC_SetVectoredIRQ(USB_ISR,IntrSlot,VIC_USB);
VICINTENABLE |= (1<<VIC_USB);
// Disconnect device
USB_ConnectRes(FALSE);
// Set address 0
USB_SetDefAdd();
// Init controls endpoints
USB_HwReset();
// Init Device status
UsbSetDevState(UsbDevStatusUnknow);
// Enable USB interrupts
USBINTS_bit.EN_USB_INTS = 1;
// Init Device state var
USB_DevStatus.Data = USB_Cmd(CMD_USB_GET_DEV_STAT,0);
}
/*************************************************************************
* Function Name: USB_HwReset
* Parameters: none
*
* Return: none
*
* Description: Reset Usb engine
*
*************************************************************************/
static
void USB_HwReset (void)
{
// Disable all endpoint interrupts
USBEPINTEN = 0;
// Clear all EP interrupts flags
USBEPINTCLR = 0xFFFFFFFF;
// Clear EP_SLOW, EP_FAST, FRAME interrupts flags
USBDEVINTCLR = 0x7;
// All endpoints interrupts are routed to LOW_PRIORITY interrupt
EpPriority = USBEPINTPRI = 0;
// USB_Configure
USB_Configure(FALSE);
// Control EP Init
USB_UserFuncRegistering((UserFunc_t)UsbCtrlEp,UsbEp0Out);
USB_UserFuncRegistering((UserFunc_t)UsbCtrlEp,UsbEp0In);
USB_RealizeEp(CTRL_ENP_OUT,0,Ep0MaxSize,TRUE);
#if USB_DMA > 0
// Enable End_of_Transfer_Interrupt and
// System_Error_Interrupt USB DMA interrupts
USB_DmaReset(DMA_INT_ENABLE_MASK);
#else
// Disable the DMA operation
USBEPDMADIS = 0xFFFFFFFF;
#endif
// Assign high priority interrupt line
USBDEVINTPRI = (USB_HIGH_PRIORITY_EVENT > 0)?
((USB_HIGH_PRIORITY_EP > 0)?bmUSB_HP_FastEp:bmUSB_HP_Frame):
0;
// Enable Device interrupts
USBDEVINTEN = bmUSB_SlowInterrupt | bmUSB_DevStatusInterrupt |
(USB_SOF_EVENT ? bmUSB_FrameInterrupt : 0) |
(USB_ERROR_EVENT ? bmUSB_ErrorInterrupt : 0) |
((USB_FAST_EP || USB_HIGH_PRIORITY_EP)? bmUSB_FastInterrupt : 0);
}
/*************************************************************************
* Function Name: USB_RealizeEp
* Parameters: USB_Endpoint_t EndPoint, Boolean FastIntr,
* Int32U MaxPacketSize, Boolean IntrEna
*
* Return: USB_ErrorCodes_t
*
* Description: Enable or disable endpoint
*
*************************************************************************/
USB_ErrorCodes_t USB_RealizeEp(USB_Endpoint_t EndPoint, Boolean FastIntr,
Int32U MaxPacketSize, Boolean IntrEna)
{
Int32U Mask = (1 << EndPoint);
assert(!(((USB_FAST_EP == 0) && (USB_HIGH_PRIORITY_EP == 0)) && FastIntr));
if (MaxPacketSize)
{
// Realize both directions of control EP
if((EndPoint == CTRL_ENP_OUT) || (EndPoint == CTRL_ENP_IN))
{
// Output dir
Mask = 1;
EndPoint = CTRL_ENP_OUT;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -