📄 usb.c
字号:
#include <string.h>
#include "def.h"
#include "at4x0f.h"
#include "debug.h"
#include "usbotg.h"
#include "nand.h"
#include "loader.h"
#include "vendormsg.h"
//#include "bspname.h"
#define BSP_NAME "AT4X0BD"
#define CONFIG_DESC_LENGTH 0x3c
extern TOC* g_pTOC;
static unsigned char DESCRIPTOR_TABLE[78] = {0x12,0x01,0x10,0x01,0xff,0xff,0xff,0x08,
0x52,0x32,0x04,0x00,0x01,0x01,0x00,0x00,
0x00,0x01,
0x09,0x02,0x3c,0x00,0x01,0x01,0x00,0xc0,0x00,//Config Descriptor
0x09,0x04,0x00,0x00,0x06,0xff,0xff,0xff,0x00,//Interface Descriptor - Alternate setting 0
0x07,0x05,0x81,0x02,0x10,0x00,0x00,
0x07,0x05,0x01,0x02,0x10,0x00,0x00,
0x07,0x05,0x82,0x02,0x40,0x00,0x00,
0x07,0x05,0x02,0x02,0x40,0x00,0x00,
0x07,0x05,0x83,0x02,0x40,0x00,0x00,
0x07,0x05,0x03,0x02,0x40,0x00,0x00};
// MPS FORMAT XBSA YBSA BS
static USB_ENDPOINT ep_table[NUM_EPS*2] = {{8, CTL_TYPE, 0, 0, 0x07}, //EP0 out
{8, CTL_TYPE, 0, 0, 0x07}, //EP0 in
{16, BLK_TYPE, 0x08, 0x18, 0x0f}, //EP1 out
{16, BLK_TYPE, 0x28, 0x38, 0x0f}, //EP1 in
{64, BLK_TYPE, 0x48, 0x88, 0x3f}, //EP2 out
{64, BLK_TYPE, 0xc8, 0x108, 0x3f}, //EP2 in
{64, BLK_TYPE, 0x00, 0x40, 0x3f}, //EP3 out
{64, BLK_TYPE, 0x00, 0x40, 0x3f}}; //EP3 in
USB_INTERRUPT usb_int;
TASK_CTRL usb_task;
USB_PARAMETER usb_para;
void USB_Reset(void);
void USB_Run(void);
void USB_ConfigEps(void);
void USB_ResetState(void);
void vendor_command(void);
void bulk_in_ep1(void);
void bulk_out_ep1(void);
void bulk_in_ep2(void);
#ifndef USING_USB_DMA_MODE
void bulk_out_ep2(void);
#endif // USING_USB_DMA_MODE
unsigned char SetupPacket[8];
#define BMREQUEST_TYPE_V SetupPacket[0]
#define BREQUEST_V SetupPacket[1]
#define WVALUE_LO_V SetupPacket[2]
#define WVALUE_HI_V SetupPacket[3]
#define WINDEX_LO_V SetupPacket[4]
#define WINDEX_HI_V SetupPacket[5]
#define WLENGTH_LO_V SetupPacket[6]
#define WLENGTH_HI_V SetupPacket[7]
unsigned char iDevAddr;
unsigned char g_bEp0End;
unsigned int bDeviceConfigured;
unsigned int bAddrAssigned;
unsigned int bSetAddress;
unsigned int bTransferOver;
unsigned int bWaitForXmit;
int bStatusStage;
unsigned short iNeededLen;
unsigned char iXferedLen;
unsigned char * pEp0Data;
uchar * pCurImgCache = (uchar *)SDRAM_IMG_CACHE_START;
ulong g_iCurImgLength = 16384;
ulong iCurImgTransfered = 0;
uchar * pDbgMsg = NULL;
int bWriteImage = 0;
int bWriteToc = 0;
int bChangeCS = 0;
int iValue;
extern int g_iDevStatus;
extern char g_dbgMsg[64];
int bNeedZeroPkt = 0;
int bInstRcvd = 0;
extern DWORD g_nCurImg;
extern DWORD g_nNandCS;
extern int g_bTransportChange;
#ifdef USING_USB_DMA_MODE
void OTG_FuncDmaCfg(int epnum, DWORD dwSMSA)
{
if (USBOTG_FUNC_IS_EP_READY(USB_EP_ADDR(epnum, EP_OUT_DIR)))
{
USBOTG_FUNC_CLR_EP_READY(USB_EP_ADDR(epnum, EP_OUT_DIR));
}
USBOTG_FUNC_SET_EP_XFER_LEN(epnum, EP_OUT_DIR, 64);
USBOTG_FUNC_SET_EP_SMSA(USB_EP_ADDR(epnum, EP_OUT_DIR), dwSMSA);
USBOTG_FUNC_EP_EN_DMA (USB_EP_ADDR(epnum, EP_OUT_DIR));
USBOTG_FUNC_SET_EP_READY(USB_EP_ADDR(epnum, EP_OUT_DIR));
}
#endif //USING_USB_DMA_MODE
void OTG_FuncCommonInit()
{
USBOTG_TOP_SET_FUNC_MODE(); // OTG port forced as function
USBOTG_MNP_PULSE_ADDR = TL_NONE_SET;
USBOTG_TOP_INT_EN(TL_FUNCTION_INT);// Enable Function Interrupts
// Bit2=FunctionEnable
USBOTG_TL_CLK_CTRL_ADDR |= TL_FUNC_CLOCK_ON;
USBOTG_FC_SYS_INT_EN_ADDR = (FC_RESET_DETECT_INT | FC_DONE_REG_INT);
USBOTG_FC_DONE_REG_EN_ADDR = (1 << (NUM_EPS*2)) -1; // enable all Done Interrupts
// program the device model for short frame also
USBOTG_MNP_CTRL_ADDR |= 0x800;
}
void USB_Init(void)
{
volatile unsigned int io_i;
unsigned int uiReg;
PWR_CLOCK_ENABLE(PWRCLK_USB_EN | PWRCLK_PCI_EN);
INT_RISC_MASK |= INT_MASK_USB;
{
PWR_PLL2_CONFIG = 0x00004220; // pll2 192MHz
for(io_i=1;io_i<=1000;io_i++);
// set usb clock ratio to pll2:usb_clk=4:1
uiReg = PWR_CLK_RATIO;
uiReg &= ~0xf0000;
uiReg |= 0x40000;
PWR_CLK_RATIO = uiReg;
// set usb clock source to pll2
uiReg = PWR_CLK_SWITCH;
uiReg &= ~0x0c;
uiReg |= 0x08;
PWR_CLK_SWITCH = uiReg;
for(io_i=1;io_i<=10000;io_i++);
}
USB_Reset();
}
void USB_Reset(void)
{
RESET_DECLARE(RESET_SR_USB_RST);
RESET_CLEAR(RESET_SR_USB_RST);
OTG_FuncCommonInit();
USB_ConfigEps();
USBOTG_FC_IMM_INT_ADDR = 0xffffffff;
USB_ResetState();
#ifdef USING_USB_DMA_MODE
OTG_FuncDmaCfg(2, (DWORD)SDRAM_IMG_CACHE_START);
#endif // USING_USB_DMA_MODE
g_iDevStatus = ATLAS_DEV_STATUS_UNINITED_NBOOT;
}
void USB_ConfigEps(void)
{
int i;
for (i = 0; i < NUM_EPS * 2; ++i) {
USBOTG_FUNC_INIT_EP (i >> 1,
(i & 1) ? EP_IN_DIR : EP_OUT_DIR,
ep_table[i].mps,
ep_table[i].format,
ep_table[i].xbsa,
ep_table[i].ybsa,
ep_table[i].bs);
}
USBOTG_FUNC_SET_EP_XFER_LEN(1, EP_IN_DIR, 16);
USBOTG_FUNC_SET_EP_XFER_LEN(1, EP_OUT_DIR, 16);
USBOTG_FUNC_SET_EP_XFER_LEN(2, EP_IN_DIR, 64);
USBOTG_FUNC_SET_EP_XFER_LEN(2, EP_OUT_DIR, 64);
}
void USB_ResetState(void)
{
bDeviceConfigured = 0;
bAddrAssigned = 0;
bSetAddress = 0;
bTransferOver = 1;
bWaitForXmit = 0;
memset(&usb_int, 0, sizeof(USB_INTERRUPT));
}
void USB_Process(void)
{
while(1)
{
if (usb_int.intr)
{
INT_RISC_MASK &= ~INT_MASK_USB;
USB_Run();
usb_int.intr = 0;
INT_RISC_MASK |= INT_MASK_USB;
}
if( g_iDevStatus != ATLAS_DEV_STATUS_INITING_NBOOT &&
g_iDevStatus != ATLAS_DEV_STATUS_SENDING_MSG_NBOOT )
return;
}
}
void Set_Configuration(void)
{
// Check whether bmrequest type is for device.
if( (BMREQUEST_TYPE_V != 0) || (WLENGTH_LO_V != 0) ||
(WLENGTH_HI_V != 0) || (WINDEX_LO_V != 0) || (WINDEX_HI_V != 0))
{
USBOTG_FUNC_STALL_EP(USB_EP_ADDR(0, EP_OUT_DIR));
return;
}
// Check whether the device in configured state.
if((bDeviceConfigured != 0) && (bAddrAssigned == 0))
{
USBOTG_FUNC_STALL_EP(USB_EP_ADDR(0, EP_OUT_DIR));
return;
}
switch(WVALUE_LO_V)
{
case 0x01:
bDeviceConfigured = 1;
g_iDevStatus = ATLAS_DEV_STATUS_IDLE_NBOOT;
break;
case 0x00:
bDeviceConfigured = 0;
break;
default:
USBOTG_FUNC_STALL_EP(USB_EP_ADDR(0, EP_OUT_DIR));
break;
}
}
void Set_Address(void)
{
// Check whether the device is in configured state. If yes, the device behavior
// for this request is unspecified.
if(bDeviceConfigured != 0)
goto set_addr_stall;
// Check whether bmrequest type is for device.
if((BMREQUEST_TYPE_V != 0) || (WLENGTH_LO_V != 0) || (WLENGTH_HI_V != 0) || (WINDEX_LO_V != 0) || (WINDEX_HI_V != 0))
goto set_addr_stall;
// Get the wValue low byte for processing. The device address should not exceed 127 .
// Because only 7-bits are provided for address field for USB device address.
// if address value exceeds 127 then we should consider as unsupported request.
if(WVALUE_LO_V == 0 && WVALUE_HI_V == 0)
goto set_addr_stall;
// Currently store the address assigned by the host in a variable and only
// after the status stage write the address in the Register.
iDevAddr = WVALUE_LO_V;
// USBOTG_FC_DEV_ADDRESS_ADDR = WVALUE_LO_V;
bAddrAssigned = 1;
bSetAddress = 1;
g_iDevStatus = ATLAS_DEV_STATUS_INITING_NBOOT;
return;
set_addr_stall:
USBOTG_FUNC_STALL_EP(USB_EP_ADDR(0, EP_OUT_DIR));
return;
}
void send_ep0_data()
{
unsigned short curLength;
WORD *pwBuf = (WORD *)&pEp0Data[iXferedLen];
curLength = iNeededLen - iXferedLen;
if(curLength > 8)
curLength = 8;
USBOTG_FUNC_PREPARE_EP(0, EP_IN_DIR);
USBOTG_FUNC_SET_EP_XFER_LEN(0, EP_IN_DIR, curLength);
*(volatile DWORD *)(USBOTG_DATA_BASE + 0) = (pwBuf [1] << 16) | pwBuf [0];
*(volatile DWORD *)(USBOTG_DATA_BASE + 4) = (pwBuf [3] << 16) | pwBuf [2];
USBOTG_FUNC_SET_XBUF(USB_EP_ADDR(0, EP_IN_DIR));
USBOTG_FUNC_SET_EP_READY(USB_EP_ADDR(0, EP_IN_DIR));
iXferedLen += curLength;
if ((iXferedLen == iNeededLen) && (iNeededLen % 8) || (curLength == 0))
{
bTransferOver = 1;
}
//Set a flag here, the next EP0 recieve will not be handled until the current xmit is finished.
bWaitForXmit = 1;
bStatusStage = 1;
}
void Get_Descriptor(void)
{
unsigned short length;
length = WLENGTH_HI_V << 8;
length = length | WLENGTH_LO_V;
// compare wlength value with the actual device
// descriptor length.If greater,then initialise
// Total numer of bytes with actual descriptor
// length otherwise with wlength value and
// for remaining bytes respond with stall on EP0.
switch(WVALUE_HI_V)
{
case 0x01:
if(length <= 0x12)
iNeededLen = length;
else
iNeededLen = 0x12;
pEp0Data = (unsigned char*)DESCRIPTOR_TABLE;
break;
case 0x02:
if(length <= CONFIG_DESC_LENGTH)
iNeededLen = length;
else
iNeededLen = CONFIG_DESC_LENGTH;
pEp0Data = (unsigned char*)DESCRIPTOR_TABLE + 0x12;
break;
default:
USBOTG_FUNC_STALL_EP(USB_EP_ADDR(0, EP_OUT_DIR));
return;
}
iXferedLen = 0;
bTransferOver = 0;
send_ep0_data();
return;
}
void device_command(void)
{
switch (BREQUEST_V)
{
case USB_SET_ADDR:
Set_Address();
break;
case USB_GET_DESCRIPTOR:
Get_Descriptor();
break;
case USB_SET_CONFIG:
Set_Configuration();
break;
case USB_GET_STATUS:
break;
default:
USBOTG_FUNC_STALL_EP(USB_EP_ADDR(0, EP_OUT_DIR));
break;
}
}
void process_setup_packet(void)
{
// upon setup, the host will always expect a DATA1 packet
USBOTG_FUNC_SET_EP_PID1(0, EP_IN_DIR);
if ((WLENGTH_LO_V == 0) && (WLENGTH_HI_V == 0))
{
//clear last config.
USBOTG_FUNC_PREPARE_EP(0, EP_IN_DIR);
USBOTG_FUNC_SET_EP_XFER_LEN(0, EP_IN_DIR, 0);
USBOTG_FUNC_SET_XBUF(USB_EP_ADDR(0, EP_IN_DIR));
USBOTG_FUNC_SET_EP_READY(USB_EP_ADDR(0, EP_IN_DIR));
bStatusStage = 1;
}
if((BMREQUEST_TYPE_V & 0x60) == 0)
{
switch(BMREQUEST_TYPE_V & 0x03)
{
case 0x00:
device_command();
break;
default:
USBOTG_FUNC_STALL_EP(USB_EP_ADDR(0, EP_OUT_DIR));
break;
}
}
else
{
if((BMREQUEST_TYPE_V & 0x60) == 0x40)
{
vendor_command();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -