在文档《DvkUsersGuide.pdf》里有main函数的描述:
源码如下:
// Task dispatcher
void main(void)
{
DWORD i;
WORD offset;
DWORD DevDescrLen;
DWORD j=0;
WORD IntDescrAddr;
WORD ExtDescrAddr;
// Initialize Global States
Sleep = FALSE; // Disable sleep mode
Rwuen = FALSE; // Disable remote wakeup
Selfpwr = FALSE; // Disable self powered
GotSUD = FALSE; // Clear "Got setup data" flag
// Initialize user device
TD_Init();
// The following section of code is used to relocate the descriptor table.
// The frameworks uses SUDPTRH and SUDPTRL to automate the SETUP requests
// for descriptors. These registers only work with memory locations
// in the EZ-USB internal RAM. Therefore, if the descriptors are located
// in external RAM, they must be copied to in internal RAM.
// The descriptor table is relocated by the frameworks ONLY if it is found
// to be located in external memory.
pDeviceDscr = (WORD)&DeviceDscr;
pDeviceQualDscr = (WORD)&DeviceQualDscr;
pHighSpeedConfigDscr = (WORD)&HighSpeedConfigDscr;
pFullSpeedConfigDscr = (WORD)&FullSpeedConfigDscr;
pStringDscr = (WORD)&StringDscr;
// Is the descriptor table in external RAM (> 16Kbytes)? If yes,
// then relocate.
// Note that this code only checks if the descriptors START in
// external RAM. It will not work if the descriptor table spans
// internal and external RAM.
if ((WORD)&DeviceDscr & 0xC000)
{
// first, relocate the descriptors
IntDescrAddr = INTERNAL_DSCR_ADDR;
ExtDescrAddr = (WORD)&DeviceDscr;
DevDescrLen = (WORD)&UserDscr - (WORD)&DeviceDscr + 2;
for (i = 0; i < DevDescrLen; i++)
*((BYTE xdata *)IntDescrAddr+i) = *((BYTE xdata *)ExtDescrAddr+i);
// update all of the descriptor pointers
pDeviceDscr = IntDescrAddr;
offset = (WORD)&DeviceDscr - INTERNAL_DSCR_ADDR;
pDeviceQualDscr -= offset;
pConfigDscr -= offset;
pOtherConfigDscr -= offset;
pHighSpeedConfigDscr -= offset;
pFullSpeedConfigDscr -= offset;
pStringDscr -= offset;
}
EZUSB_IRQ_ENABLE(); // Enable USB interrupt (INT2)
EZUSB_ENABLE_RSMIRQ(); // Wake-up interrupt
INTSETUP |= (bmAV2EN | bmAV4EN); // Enable INT 2 & 4 autovectoring
USBIE |= bmSUDAV | bmSUTOK | bmSUSP | bmURES | bmHSGRANT; // Enable selected interrupts
EA = 1; // Enable 8051 interrupts
#ifndef NO_RENUM
// Renumerate if necessary. Do this by checking the renum bit. If it
// is already set, there is no need to renumerate. The renum bit will
// already be set if this firmware was loaded from an eeprom.
if(!(USBCS & bmRENUM))
{
EZUSB_Discon(TRUE); // renumerate
}
#endif
// unconditionally re-connect. If we loaded from eeprom we are
// disconnected and need to connect. If we just renumerated this
// is not necessary but doesn't hurt anything
USBCS &=~bmDISCON;
CKCON = (CKCON&(~bmSTRETCH)) | FW_STRETCH_VALUE; // Set stretch
// clear the Sleep flag.
Sleep = FALSE;
// Task Dispatcher
while(TRUE) // Main Loop
{
// Poll User Device
TD_Poll();
// Check for pending SETUP
if(GotSUD)
{
SetupCommand(); // Implement setup command
GotSUD = FALSE; // Clear SETUP flag
}
// check for and handle suspend.
// NOTE: Idle mode stops the processor clock. There are only two
// ways out of idle mode, the WAKEUP pin, and detection of the USB
// resume state on the USB bus. The timers will stop and the
// processor will not wake up on any other interrupts.
if (Sleep)
{
if(TD_Suspend())
{
Sleep = FALSE; // Clear the "go to sleep" flag. Do it here to prevent any race condition between wakeup and the next sleep.
do
{
EZUSB_Susp(); // Place processor in idle mode.
}
while(!Rwuen && EZUSB_EXTWAKEUP());
// above. Must continue to go back into suspend if the host has disabled remote wakeup
// *and* the wakeup was caused by the external wakeup pin.
// 8051 activity will resume here due to USB bus or Wakeup# pin activity.
EZUSB_Resume(); // If source is the Wakeup# pin, signal the host to Resume.
TD_Resume();
}
}
}
}
以下代码用于初始化全局状态变量:
// Initialize Global States
Sleep = FALSE; // Disable sleep mode
Rwuen = FALSE; // Disable remote wakeup
Selfpwr = FALSE; // Disable self powered
GotSUD = FALSE; // Clear "Got setup data" flag
//-----------------------------------------------------------------------------
// Global Variables
//-----------------------------------------------------------------------------
volatile BOOL GotSUD;
BOOL Rwuen;
BOOL Selfpwr;
volatile BOOL Sleep; // Sleep mode enable flag
还是不懂,变量是怎样跟相关功能连接起来的!!!
函数TD_Init()用于初始化用户设备:
void TD_Init(void) // Called once at startup
{
BREAKPT &= ~bmBPEN;
Rwuen = TRUE; // 使能远程唤醒
CPUCS=((CPUCS & ~bmCLKSPD) | bmCLKSPD1); //USB时钟频率
IFCONFIG |=0x40;
EP1OUTCFG = 0xA0;
EP1INCFG = 0xA0;
SYNCDELAY;
EP2CFG = 0xA2;
SYNCDELAY;
EP4CFG = 0xA0;
SYNCDELAY;
EP6CFG = 0xE2;
SYNCDELAY;
EP8CFG = 0xE0;
// 由于缺省的端点是双重因此需要写两次
SYNCDELAY;
EP2BCL = 0x80; //写EP2OUT比特两次
SYNCDELAY;
EP2BCL = 0x80;
SYNCDELAY;
EP4BCL = 0x80; //写EP4OUT比特两次
SYNCDELAY;
EP4BCL = 0x80;
//使能双自动指针
AUTOPTRSETUP |= 0x01;
}
文档里这样说道:
只说是,用于全局的状态变量和设备的初始化,需在ReNumeration 和 the Task Dispatcher开始之前调用。并未说明这样初始化的依据。
在另一份文档里,发现这样初始化是为了使用端点2、4、6、8进行批量的数据发送和接收:
那么,我就只能采用笨方法逐句地看TD_Init()这个函数了。
1、禁用 Breakpoint
BREAKPT &= ~bmBPEN;
首先找到了变量BREAKPT的声明:
EXTERN xdata volatile BYTE BREAKPT _AT_ 0xE605; // Breakpoint
其在文档里的表述:
#define bmBPEN bmBIT1
2、
Rwuen = TRUE; // 使能远程唤醒
3、选择CPU的时钟速度:48MHZ
CPUCS=((CPUCS & ~bmCLKSPD) | bmCLKSPD1); //USB时钟频率
文档中关于CPUCS的描述;
#define bmCLKSPD (bmBIT4 | bmBIT3)
#define bmCLKSPD1 bmBIT4
5、选择内部FIFO and GPIF时钟频率为48MHZ
IFCONFIG |=0x40;
6、使能EP1OUT和EP1IN,端点类型为批量传输
EP1OUTCFG = 0xA0;
EP1INCFG = 0xA0;
7、同步延时
SYNCDELAY;
8、
EP2CFG = 0xA2;
SYNCDELAY;
EP4CFG = 0xA0;
SYNCDELAY;
EP6CFG = 0xE2;
SYNCDELAY;
EP8CFG = 0xE0;
9、设置EP2和EP4的“ maximum buffer sizes”
// 由于缺省的端点是双重因此需要写两次
SYNCDELAY;
EP2BCL = 0x80; //写EP2OUT比特两次
SYNCDELAY;
EP2BCL = 0x80;
SYNCDELAY;
EP4BCL = 0x80; //写EP4OUT比特两次
SYNCDELAY;
EP4BCL = 0x80;
我也没搞懂,这个是啥意思!!!
10、使能双自动指针
//使能双自动指针
AUTOPTRSETUP |= 0x01;