官方手冊中給出了bulkloop參考例程,此例程是PC從端口2發送出數據,然后從端口6接收到數據,那么根據這個思想,可以進行修改,使得PC機接收到的數據不是從EP2發送過來的,而是從外部邏輯,比如FPGA處送來的數據。那么如何進行修改呢?
//=============================================
void TD_Init(void) // Called once at startup
{
BYTE dum; // For the LEDS
CPUCS = ((CPUCS & ~bmCLKSPD) | bmCLKSPD1) ; // 48 MHz CPU clock
// Turn off all 4 LEDS
dum = D2OFF;
dum = D3OFF;
dum = D4OFF;
dum = D5OFF;
// EP2CFG & EP6CFG configure our two endpoints, EP2-OUT and EP6-IN
// b7: Valid
// b6: DIR (0=OUT, 1=IN)
// b[5:4] Type (01=ISO, 10=BULK, 11=INT)
// b3: Size (0=512, 1=1024 bytes)
// b2: 0
// b[1:0] Buffering (00=quad, 10=double, 11=triple)
//
EP2CFG = 0xA2; // Valid, BULK-OUT, 512 byte buffer, double-buffered
SYNCDELAY; // Some regs take longer to update, see TRM Section 15.14.
EP6CFG = 0xE2; // Valid, BULK-IN, 512 byte buffer, double-buffered
SYNCDELAY;
// OUT endpoints do not come up armed
// Since the endpoint is double buffered we must write dummy byte counts twice
EP2BCL = 0x80; // arm EP2OUT by writing byte count w/skip.
SYNCDELAY;
EP2BCL = 0x80; // again
SYNCDELAY;
// enable dual autopointer feature
AUTOPTRSETUP |= 0x01;
USBIE |= bmSOF; // Enable the SOF IRQ to serve as LED timers
EPIE = bmEP6IRQ | bmEP2IRQ; // Enable EP6 and EP2 Interrupts to turn on transfer LEDS
}
//=============================================
void TD_Poll(void) // Called repeatedly while the device is idle
{
WORD i;
WORD count;
// BYTE dummy_LED2; // ***For the LED
BYTE waiting_inpkts;
#ifdef ENABLE_7_SEG_DISPLAY
if(start_7_seg_display)
{
// update 7-seg readout with number of IN packets waiting for transfer to the host
waiting_inpkts = (EP6CS & 0xF0)>>4;
EZUSB_WriteI2C(LED_ADDR, 0x01, &(Digit[waiting_inpkts]));
EZUSB_WaitForEEPROMWrite(LED_ADDR);
}
#endif
// Transfer EP6-OUT buffer to EP2-IN buffer when there is a packet in one of the EP6-OUT buffers, AND
// there is an available EP2-IN buffer. The FIFO status flags update after full packets are transferred.
// Therefore EP2-OUT "Not Empty" means a packet is available, and "EP6-IN "Not Full" means there is an
// available buffer. Using the flags this way handles any packet size and takes multiple buffering
// into account.
if(!(EP2468STAT & bmEP2EMPTY)) // Is EP2-OUT buffer not empty (has at least one packet)?
{
if(!(EP2468STAT & bmEP6FULL)) // YES: Is EP6-IN buffer not full (room for at least 1 pkt)?
{
APTR1H = MSB( &EP2FIFOBUF );
APTR1L = LSB( &EP2FIFOBUF );
AUTOPTRH2 = MSB( &EP6FIFOBUF );
AUTOPTRL2 = LSB( &EP6FIFOBUF );
count = (EP2BCH << 8) + EP2BCL;
// loop EP2OUT buffer data to EP6IN
for( i = 0; i < count; i++ )
{
EXTAUTODAT2 = EXTAUTODAT1; // Autopointers make block transfers easy...
}
EP6BCH = EP2BCH; // Send the same number of bytes as received
SYNCDELAY;
EP6BCL = EP2BCL; // arm EP6IN
SYNCDELAY;
EP2BCL = 0x80; // arm EP2OUT
}
}
}
上面程序是bulkloop中的TD_POLL()中的程序,此代碼執行的就是EP6從EP2中取出數據,再發送到PC機,之前也有提及到,在TD_POLL()中的程序是供用戶控制外部設備使用,那么將TD_POLL()中的所有代碼去除掉,就不會執行從EP2數據發送到EP6數據中了。
上述還有一個地方需要注意,若是定義某個端點為輸出,那么在初始化時需要進行2次初始化,如下:
對於 攝像頭 ----》 FPGA -----》USB架構,那么將USB定義為slave FIFO模式,相關初始化參數如下:
void TD_Init(void) // Called once at startup { // set the CPU clock to 48MHz, Default 12MHz(Page 333) //CPUCS = 0x02; //12MHZ CLKOUT ENALBE //CPUCS = 0x0a; //24MHZ CLKOUT ENALBE CPUCS = 0x12; //48MHZ CLKOUT ENALBE,時鍾不反向,CLKOUT PIN驅動,有時鍾輸出; SYNCDELAY; //Interface Configure(Page 334) IFCONFIG =0x03; //選擇為外部時鍾,且時鍾頻率為30MHz,且為同步slaveFIFO模式,輸入IFCLK(5~48MHz)(0000_0011) //IFCONFIG =0x0B;//選擇為外部時鍾,且為異步slaveFIFO模式,不需要IFCLK SYNCDELAY; //Configure REVCTL for Chip Revision Control(Page 344) REVCTL = 0x03; //Cypress highly recommends setting both bits to 1 SYNCDELAY; Rwuen = TRUE; // Enable remote-wakeup //-------------------------------------------------------- //Set FIFO端點0-3狀態: EP2CFG、EP4CFG、EP6CFG、EP8CFG(只用到EP2CFG,選擇512B/1024B,輸入) EP1OUTCFG = 0xA0; // default values(Page 346) SYNCDELAY; EP1INCFG = 0xA0; // default values(Page 346) SYNCDELAY; EP2CFG = 0xE0; // enabled, quad buffered, 512B, IN, bulk fifo, 4 buffer(Page 347) // EP2CFG = 0xE8; // enabled, quad buffered, 1024B, IN, bulk fifo, 4 buffer SYNCDELAY; EP4CFG = 0x60; // disabled... SYNCDELAY; EP6CFG = 0x60; // disabled... SYNCDELAY; EP8CFG = 0x60; // disabled... SYNCDELAY; //-------------------------------------------------------- //Configure the EPxFIFOCFG(Page 349) EP2FIFOCFG = 0x08; // autoin, 8 Bit Wide // EP2FIFOCFG = 0x09; // autoin, 16 Bit Wide SYNCDELAY; EP4FIFOCFG = 0x00; // no-autoOUT, bytewide SYNCDELAY; EP6FIFOCFG = 0x00; // no-autoOUT, bytewide SYNCDELAY; EP8FIFOCFG = 0x00; // no-autoOUT, bytewide SYNCDELAY; //-------------------------------------------------------- //Configure PIN Polarity PORTACFG |= 0x40; //IFCOG[1:0] = 11(Slave FIFO Mode), Set PORTACFG[6] to USE PA7-SLCS (Page 375) SYNCDELAY; FIFOPINPOLAR = 0x04; //BIT[5:0] = {PKTEND, SLOE, SLRD, SLWR, EMPTY, FULL} //Set SLWR High Valid; PKTEND,SLOE,SLRD EMPTY, FULL Low Active(Page 342) SYNCDELAY; //-------------------------------------------------------- //設置為Autoin時的自動傳輸包大小(Page 351) SYNCDELAY; EP2AUTOINLENH = 0x02; // EZ-USB automatically commits data in 512-byte chunks // EP2AUTOINLENH = 0x04; // EZ-USB automatically commits data in 1024-byte chunks SYNCDELAY; EP2AUTOINLENL = 0x00; SYNCDELAY; //Set Autopointer, enable dual autopointer(Page 328) AUTOPTRSETUP |= 0x01; //FLAGA - User-Programmable Level; FLAGB - FIFO Full, FLAGC - FIFO Empty: (L: Valid)(Page 338) PINFLAGSAB = 0x00;//0x8a; SYNCDELAY; PINFLAGSCD = 0x00;//0x08; SYNCDELAY; //復位FIFO,先復位端點,再清空端點(Page 340) SYNCDELAY; FIFORESET = 0x80;// activate NAK-ALL to avoid race conditions SYNCDELAY; FIFORESET = 0x02;// reset, FIFO 2 SYNCDELAY; FIFORESET = 0x04;// reset, FIFO 4 SYNCDELAY; FIFORESET = 0x06;// reset, FIFO 6 SYNCDELAY; FIFORESET = 0x08;// reset, FIFO 8 SYNCDELAY; FIFORESET = 0x00;// deactivate NAK-AL SYNCDELAY;

