EZ-USB固件框架的追踪研读之main函数3

来源:互联网 发布:win bash linux桌面 编辑:程序博客网 时间:2024/05/29 16:21
书接上回

  下面这段代码不解释,但我把注释翻译一下:
  下面部分用来对描述符表重新定位,固件框架使用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 autovectoringUSBIE |= bmSUDAV | bmSUTOK | bmSUSP | bmURES | bmHSGRANT;   // Enable selected interruptsEA = 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 DeviceTD_Poll();// Check for pending SETUPif(GotSUD){   SetupCommand();          // Implement setup command   GotSUD = FALSE;          // Clear SETUP flag}

  函数TD_Poll()在前面已经说过了。

  GotSUD出现在SUDAV的中断服务程序里:

// Setup Data Available Interrupt Handlervoid ISR_Sudav(void) interrupt 0{   GotSUD = TRUE;            // Set flag   EZUSB_IRQ_CLEAR();   USBIRQ = bmSUDAV;         // Clear SUDAV IRQ}

这里写图片描述

这里写图片描述

1 0
原创粉丝点击