书接上回
下面这段代码不解释,但我把注释翻译一下:
下面部分用来对描述符表重新定位,固件框架使用SUDPTRH and SUDPTRL自动响应描述符的SETUP请求。这两个寄存器只能处理EZ-USB内部RAM的地址,所以,如果描述符存在于片外RAM,则他们必须被复制到片内RAM(16K)。
// 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;
}
第一个&是取值符号,取设备描述符的地址;第二个&是按位与运算符。
我没有看懂是怎么判断the descriptor table in external RAM (> 16Kbytes)
Enable USB interrupt (INT2)
EZUSB_IRQ_ENABLE(); // Enable USB interrupt (INT2)
#define EZUSB_IRQ_ENABLE() EUSB = 1
sfr EIE = 0xE8; // EIE Bit Values differ from Reg320
/* EIE */
sbit EUSB = 0xE8+0;
sbit EI2C = 0xE8+1;
sbit EIEX4 = 0xE8+2;
sbit EIEX5 = 0xE8+3;
sbit EIEX6 = 0xE8+4;
Enable Wake-up interrupt
EZUSB_ENABLE_RSMIRQ(); // Wake-up interrupt
#define EZUSB_ENABLE_RSMIRQ() (EICON |= 0x20) // Enable Resume Interrupt (EPFI_)
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
其中,函数EZUSB_Discon(TRUE)源自库函数,源代码为,(这里先不做解释):
void EZUSB_Discon(BOOL renum)
{
if(renum) // If renumerate (i.e. 8051 will handle SETUP commands)
USBCS |= (bmDISCON | bmRENUM); // disconnect from USB and set the renumerate bit
else
USBCS |= bmDISCON; // just disconnect from USB
EZUSB_Delay(1500); // Wait 1500 ms
USBIRQ = 0xff; // Clear any pending USB interrupt requests. They're for our old life.
EPIRQ = 0xff;
EZUSB_IRQ_CLEAR();
USBCS &=~bmDISCON; // reconnect USB
}
唉,下面的也不是很懂!!
// 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;
硬着头皮往下看主循环;
// Poll User Device
TD_Poll();
// Check for pending SETUP
if(GotSUD)
{
SetupCommand(); // Implement setup command
GotSUD = FALSE; // Clear SETUP flag
}
函数TD_Poll()在前面已经说过了。
GotSUD出现在SUDAV的中断服务程序里:
// Setup Data Available Interrupt Handler
void ISR_Sudav(void) interrupt 0
{
GotSUD = TRUE; // Set flag
EZUSB_IRQ_CLEAR();
USBIRQ = bmSUDAV; // Clear SUDAV IRQ
}