實驗目的:

1. 瞭解USB基本概念和原理

2.    編程實現USB DEVICE驅動

添加S3C2410USB DEVICE 驅動代碼,實現通過USB下載文件到記憶體中。


#include <stdlib.h>
#include <string.h>
#include "def.h"
#include "option.h"
#include "2410addr.h"
#include "2410lib.h"
#include "2410slib.h"
#include "mmu.h"
#include "profile.h"
#include "memtest.h"

#include "usbmain.h"
#include "usbout.h"
#include "usblib.h"
#include "2410usb.h"
extern U32 srcAddress;
extern U32 targetBlock; // Block number (0 ~ 4095)
extern U32 targetSize; // Total byte size
extern void InputTargetBlock(void);
void Isr_Init(void);
void HaltUndef(void);
void HaltSwi(void);
void HaltPabort(void);
void HaltDabort(void);
void Lcd_Off(void);
void WaitDownload(void);
int Menu(void);

//#define DOWNLOAD_ADDRESS _RAM_STARTADDRESS
volatile U32 downloadAddress=0x30000000;
int timeout=0x300;
int boot=1;
void (*restart)(void)=(void (*)(void))0x0;
void (*run)(void);


volatile unsigned char *downPt;
volatile U32 downloadFileSize;
volatile U16 checkSum;
volatile unsigned int err=0;
volatile U32 totalDmaCount;

volatile int isUsbdSetConfiguration;

int download_run=0;
U32 tempDownloadAddress;
int menuUsed=0;

extern char Image$$RW$$Limit[];
U32 *pMagicNum=(U32 *)Image$$RW$$Limit;
int consoleNum;

void Main(void)
{
char *mode;
int i;
int choice;
U8 key;

#if ADS10
__rt_lib_init(); //for ADS 1.0
#endif

ChangeClockDivider(1,1); // 1:2:4
//ChangeMPllValue(82,2,1); //FCLK=135.0Mhz
ChangeMPllValue(82,1,1); //FCLK=180.0Mhz
//ChangeMPllValue(161,3,1); //FCLK=202.8Mhz

Port_Init();

rGPHCON = rGPHCON&~(0xf<<18)|(0x5<<18);
//To enhance the USB signal quality.
//CLKOUT 0,1=OUTPUT to reduce the power consumption.
MMU_Init();

Isr_Init();
if(*pMagicNum!=0x12345678)
consoleNum=0;
else
consoleNum=1;

Uart_Init(0,115200);
Uart_Select(consoleNum);

rMISCCR=rMISCCR&~(1<<3); // USBD is selected instead of USBH1
rMISCCR=rMISCCR&~(1<<13); // USB port 1 is enabled.

//
// USBD should be initialized first of all.
//
isUsbdSetConfiguration=0;


UsbdMain();

//#if 0
// UsbdMain();
// MMU_Init(); //MMU should be reconfigured or turned off for the debugger,
// //After downloading, MMU should be turned off for the MMU based program,such as WinCE.
//#else
// MMU_EnableICache();
// UsbdMain();
//#endif
Delay(0); //calibrate Delay()

pISR_SWI=(_ISR_STARTADDRESS+0xf0); //for pSOS

Led_Display(0x6);

#if USBDMA
mode="DMA";
#else
mode="Int";
#endif

Uart_Printf("\n\n");
Uart_Printf("+---------------------------------------------+\n");
Uart_Printf("| S3C2410X USB Downloader ver R1.11 SEP/03/02 |\n");
Uart_Printf("+---------------------------------------------+\n");
Uart_Printf("FCLK=%dMHz,%s mode\n",FCLK/1000000,mode);
Uart_Printf("USB: IN_ENDPOINT:1 OUT_ENDPOINT:3\n");
Uart_Printf("FORMAT: <ADDR(DATA):4>+<SIZE(n+10):4>+<DATA:n>+<CS:2>\n");
Uart_Printf("NOTE: 1. Power off/on or press the reset button for 1 sec\n");
Uart_Printf(" in order to get a valid USB device address.\n");
Uart_Printf(" 2. For additional menu, Press any key. \n");
Uart_Printf("\n");

download_run=1; //The default menu is the Download & Run mode.

while(1)
{
//if(menuUsed==1)

choice=Menu();
switch(choice)
{
case 0:
rINTMSK&=~(BIT_USBD);
WaitDownload();
break;
case 1:
rINTMSK&=~(BIT_USBD);
WaitDownload();
break;
case 2:
break;
case 3:
break;
case 4:
rINTMSK&=~(BIT_USBD);
WaitDownload();
K9S1208_Program();
break;
case 5:
// rINTMSK&=~(BIT_USBD);
for(i=0;i<50000;i++)
;
K9S1208_Read();
MMU_DisableDCache();
MMU_DisableICache();
MMU_DisableMMU();
for(i=0;i<50000;i++)
;
rINTMSK=BIT_ALLMSK;
run=(void (*)(void))downloadAddress;
run();
break;
case 6:
rINTMSK&=~(BIT_USBD);
K9S1208_Read();
break;
case 7:
rINTMSK=BIT_ALLMSK;
for(i=0;i<50000;i++)
;
K9S1208_Read();
MMU_DisableDCache();
MMU_DisableICache();
MMU_DisableMMU();
for(i=0;i<50000;i++)
;
rINTMSK=BIT_ALLMSK;

run=(void (*)(void))downloadAddress;
run();


break;
default:
break;
}

}

}



int Menu(void)
{
int i;
U8 key;
menuUsed=1;
while(1)
{
Uart_Printf("\n###### Select Menu ######\n");
Uart_Printf(" [0] Download & Run\n");
Uart_Printf(" [1] Download Only\n");
Uart_Printf(" [2] Test SDRAM \n");
Uart_Printf(" [3] Change The Console UART Ch.\n");
Uart_Printf(" [4] Download to Flash.\n");
Uart_Printf(" [5] Run From Flash\n");
Uart_Printf(" [6] Load From Flash\n");

key=Uart_Getch();

switch(key)
{
case '0':
Uart_Printf("\nDownload&Run is selected.\n\n");
download_run=1;
return 0;
case '1':
Uart_Printf("\nDownload Only is selected.\n");
Uart_Printf("Enter a new temporary download address(0x3...):");
tempDownloadAddress=Uart_GetIntNum();
download_run=0;
Uart_Printf("The temporary download address is 0x%x.\n\n",tempDownloadAddress);
return 1;
case '2':
Uart_Printf("\nMemory Test is selected.\n");
MemoryTest();
//Menu();
return 2;
break;
case '3':
Uart_Printf("\nWhich UART channel do you want to use for the console?[0/1]\n");
if(Uart_Getch()!='1')
{
*pMagicNum=0x0;
Uart_Printf("UART ch.0 will be used for console at next boot.\n");
}
else
{
*pMagicNum=0x12345678;
Uart_Printf("UART ch.1 will be used for console at next boot.\n");
Uart_Printf("UART ch.0 will be used after long power-off.\n");
}
Uart_Printf("System is waiting for a reset. Please, Reboot!!!\n");
while(1);
return 3;
break;
case '4':
Uart_Printf("\nDownload To Flash is selected.\n");
Uart_Printf("Enter a new temporary download address(0x3...):");
tempDownloadAddress=Uart_GetIntNum();
download_run=0;
Uart_Printf("The temporary download address is 0x%x.\n\n",tempDownloadAddress);

Uart_Printf("Input start block number:");
targetBlock=Uart_GetIntNum(); // Block number(0~4095)
Uart_Printf("start block number =%d\n",targetBlock);

// if(targetSize==0)
{
Uart_Printf("Input size(0x4000*n):");
targetSize=Uart_GetIntNum(); // Total byte size
targetSize=targetSize*0x4000;
}
Uart_Printf("size (0x4000*n) =0x%x\n",targetSize);
return 4;
break;
case '5':
Uart_Printf("\nDownload from Flash and run is selected.\n");

Uart_Printf("Enter dst address(0x3...):");
downloadAddress=Uart_GetIntNum();
Uart_Printf("The run address is 0x%x.\n\n",downloadAddress);


Uart_Printf("Input start block number:");
targetBlock=Uart_GetIntNum(); // Block number(0~4095)
Uart_Printf("start block number =%d\n",targetBlock);

// if(targetSize==0)
{
Uart_Printf("Input size(0x4000*n):");
targetSize=Uart_GetIntNum(); // Total byte size
targetSize=targetSize*0x4000;
}
Uart_Printf("size (0x4000*n) =0x%x\n",targetSize);

return 5;
break;
case '6':

Uart_Printf("\nLoad from Flash is selected.\n");

Uart_Printf("Enter dst address(0x3...):");
downloadAddress=Uart_GetIntNum();
Uart_Printf("The run address is 0x%x.\n\n",downloadAddress);


Uart_Printf("Input start block number:");
targetBlock=Uart_GetIntNum(); // Block number(0~4095)
Uart_Printf("start block number =%d\n",targetBlock);

// if(targetSize==0)
{
Uart_Printf("Input size(0x4000*n):");
targetSize=Uart_GetIntNum(); // Total byte size
targetSize=targetSize*0x4000;
}
Uart_Printf("size (0x4000*n) =0x%x\n",targetSize);
return 6;
break;
case '7':

return 7;
break;

default:
break;
}
}

}



void WaitDownload(void)
{
U32 i;
U32 j;
U16 cs;
U32 temp;
U16 dnCS;
int first=1;
float time;
U8 tempMem[16];
U8 key;

checkSum=0;
downloadAddress=(U32)tempMem; //_RAM_STARTADDRESS;
downPt=(unsigned char *)downloadAddress;
//This address is used for receiving first 8 byte.
downloadFileSize=0;

#if 0
MMU_DisableICache();
//For multi-ICE.
//If ICache is not turned-off, debugging is started with ICache-on.
#endif

/*******************************/
/* Test program download */
/*******************************/
j=0;

if(isUsbdSetConfiguration==0)
{
Uart_Printf("USB host is not connected yet.\n");
return;

}
while(downloadFileSize==0)
;
#if 0
while(downloadFileSize==0)
{
if(first==1 && isUsbdSetConfiguration!=0)
{
Uart_Printf("USB host is connected. Waiting a download.\n");
first=0;
}

if(j%0x50000==0)Led_Display(0x6);
if(j%0x50000==0x28000)Led_Display(0x9);
j++;

key=Uart_GetKey();
if(key!=0)
{
Menu();
first=1; //To display the message,"USB host ...."
}

}
#endif
Timer_InitEx();
Timer_StartEx();

#if USBDMA

rINTMSK&=~(BIT_DMA2);

ClearEp3OutPktReady();
// indicate the first packit is processed.
// has been delayed for DMA2 cofiguration.

if(downloadFileSize>EP3_PKT_SIZE)
{
if(downloadFileSize<=(0x80000))
{
ConfigEp3DmaMode(downloadAddress+EP3_PKT_SIZE-8,downloadFileSize-EP3_PKT_SIZE);
//wait until DMA reload occurs.
while((rDSTAT2&0xfffff)==0);

//will not be used.
rDIDST2=(downloadAddress+downloadFileSize-EP3_PKT_SIZE);
rDIDSTC2=(0<<1)|(0<<0);
rDCON2=rDCON2&~(0xfffff)|(0);
}
else
{
ConfigEp3DmaMode(downloadAddress+EP3_PKT_SIZE-8,0x80000-EP3_PKT_SIZE);
//wait until DMA reload occurs.
while((rDSTAT2&0xfffff)==0);

if(downloadFileSize>(0x80000*2))//for 1st autoreload
{
rDIDST2=(downloadAddress+0x80000-8); //for 1st autoreload.
rDIDSTC2=(0<<1)|(0<<0);
rDCON2=rDCON2&~(0xfffff)|(0x80000);

while(rEP3_DMA_TTC<0xfffff)
{
rEP3_DMA_TTC_L=0xff;
rEP3_DMA_TTC_M=0xff;
rEP3_DMA_TTC_H=0xf;
}
}
else
{
rDIDST2=(downloadAddress+0x80000-8); //for 1st autoreload.
rDIDSTC2=(0<<1)|(0<<0);
rDCON2=rDCON2&~(0xfffff)|(downloadFileSize-0x80000);

while(rEP3_DMA_TTC<0xfffff)
{
rEP3_DMA_TTC_L=0xff;
rEP3_DMA_TTC_M=0xff;
rEP3_DMA_TTC_H=0xf;
}
}
}
totalDmaCount=0;
}
else
{
totalDmaCount=downloadFileSize;
}
#endif

Uart_Printf("\nNow, Downloading [ADDRESS:%xh,TOTAL:%d]\n",
downloadAddress,downloadFileSize);
Uart_Printf("RECEIVED FILE SIZE:%8d",0);

#if USBDMA
j=0x10000;

while(1)
{
if( (rDCDST2-(U32)downloadAddress+8)>=j)
{
Uart_Printf("\b\b\b\b\b\b\b\b%8d",j);
j+=0x10000;
}
if(totalDmaCount>=downloadFileSize)break;
}

#else
j=0x10000;

while(((U32)downPt-downloadAddress)<(downloadFileSize-8))
{
if( ((U32)downPt-downloadAddress)>=j)
{
Uart_Printf("\b\b\b\b\b\b\b\b%8d",j);
j+=0x10000;
}
}
#endif
// time=Timer_StopEx();
Uart_Printf("\b\b\b\b\b\b\b\b%8d",downloadFileSize);
// Uart_Printf("(%5.1fKB/S,%3.1fS)\n",(float)(downloadFileSize/time/1000.),time);

#if USBDMA
/*******************************/
/* Verify check sum */
/*******************************/

Uart_Printf("Now, Checksum calculation\n");

cs=0;
i=(downloadAddress);
j=(downloadAddress+downloadFileSize-10)&0xfffffffc;
while(i<j)
{
temp=*((U32 *)i);
i+=4;
cs+=(U16)(temp&0xff);
cs+=(U16)((temp&0xff00)>>8);
cs+=(U16)((temp&0xff0000)>>16);
cs+=(U16)((temp&0xff000000)>>24);
}

i=(downloadAddress+downloadFileSize-10)&0xfffffffc;
j=(downloadAddress+downloadFileSize-10);
while(i<j)
{
cs+=*((U8 *)i++);
}

checkSum=cs;
#else
//checkSum was calculated including dnCS. So, dnCS should be subtracted.
checkSum=checkSum - *((unsigned char *)(downloadAddress+downloadFileSize-8-2))
- *( (unsigned char *)(downloadAddress+downloadFileSize-8-1) );
#endif

dnCS=*((unsigned char *)(downloadAddress+downloadFileSize-8-2))+
(*( (unsigned char *)(downloadAddress+downloadFileSize-8-1) )<<8);

if(checkSum!=dnCS)
{
Uart_Printf("Checksum Error!!! MEM:%x DN:%x\n",checkSum,dnCS);
return;
}

Uart_Printf("Download O.K.\n\n");
Uart_TxEmpty(consoleNum);


if(download_run==1)
{
MMU_DisableDCache();
MMU_DisableICache();
MMU_DisableMMU();

rINTMSK=BIT_ALLMSK;
run=(void (*)(void))downloadAddress;
run();
}
}




void Isr_Init(void)
{
pISR_UNDEF=(unsigned)HaltUndef;
pISR_SWI =(unsigned)HaltSwi;
pISR_PABORT=(unsigned)HaltPabort;
pISR_DABORT=(unsigned)HaltDabort;
rINTMOD=0x0; // All=IRQ mode
rINTMSK=BIT_ALLMSK; // All interrupt is masked.

//pISR_URXD0=(unsigned)Uart0_RxInt;
//rINTMSK=~(BIT_URXD0); //enable UART0 RX Default value=0xffffffff

#if 1
pISR_USBD =(unsigned)IsrUsbd;
pISR_DMA2 =(unsigned)IsrDma2;
#else
pISR_IRQ =(unsigned)IsrUsbd;
//Why doesn't it receive the big file if use this. (???)
//It always stops when 327680 bytes are received.
#endif
ClearPending(BIT_DMA2);
ClearPending(BIT_USBD);
//rINTMSK&=~(BIT_USBD);

//pISR_FIQ,pISR_IRQ must be initialized
}


void HaltUndef(void)
{
Uart_Printf("Undefined instruction exception!!!\n");
while(1);
}

void HaltSwi(void)
{
Uart_Printf("SWI exception!!!\n");
while(1);
}

void HaltPabort(void)
{
Uart_Printf("Pabort exception!!!\n");
while(1);
}

void HaltDabort(void)
{
Uart_Printf("Dabort exception!!!\n");
while(1);
}