阅读:4947回复:0
CY7C68013A工作在BULK Auto-IN模式下,总是出现错误数据--附代码
我用的是CY7C68013A,FPGA向68013A源源不断的写数据,因为数据源是不间断的,所以当主机来不及接收数据的情况下,要求中断传输。EP2设置成Auto In模式,在TD_poll函数中主要用到两个中断服务函数,EP1OUTBUF主要是主机发指令给68013A,通知它开始工作;另处,EP2FIFO Full Flag中断服务程序:当EP2FIFO Full Flag有效时,表明EP2FIFo已经占满,这时可以肯定是主机来不及接收数据,所以我在这里设置EP2非法,目的是中止传输。下面附代码,请各位帮我看看。谢谢!!
#pragma NOIV // Do not generate interrupt vectors //----------------------------------------------------------------------------- // File: FX2_to_extsyncFIFO.c // Contents: Hooks required to implement FX2 GPIF to external sync. FIFO // interface using CY4265-15AC // // Copyright (c) 2003 Cypress Semiconductor, Inc. All rights reserved //----------------------------------------------------------------------------- #include "fx2.h" #include "fx2regs.h" #include "fx2sdly.h" // SYNCDELAY macro, see Section 15.14 of FX2 Tech. // Ref. Manual for usage details. #define EXTFIFONOTFULL GPIFREADYSTAT & bmBIT1 #define EXTFIFONOTEMPTY GPIFREADYSTAT & bmBIT0 extern BOOL GotSUD; //Received setup data flag extern BOOL Sleep; extern BOOL Rwuen; extern BOOL Selfpwr; BYTE Configuration; //Current configuration BYTE AlternateSetting; //Alternate settings extern BOOL in_enable; //Flag enable IN transfers BOOL enum_high_speed = FALSE; //Flag to let firmware know FX2 enumerated at high speed extern const char xdata FlowStates[36]; //----------------------------------------------------------------------------- // Task Dispatcher hooks // The following hooks are called by the task dispatcher. //----------------------------------------------------------------------------- void Setup_FLOWSTATE_Read ( void ); //void GpifInit (); void TD_Init(void) //Called once at startup { //Set the CPU clock to 48MHz CPUCS = ((CPUCS & ~bmCLKSPD) | bmCLKSPD1); //FIFO interface //**********************************************// SYNCDELAY; IFCONFIG=0x13;//IFCONFIG.7 selects between internal and external sources: 0 = external, 1 = internal. //IFCONFIG.6 selects between the 30- and 48-MHz internal clock: 0 = 30 MHz, 1 = 48 MHz. //IFCONFIG.5 is the output enable for the internal clock source: 0 = disable, 1 = enable. //IFCONFIG.4 inverts the polarity of the interface clock (whether it’s internal or external): 0 = normal,1 = inverted. //IFCONFIG.3 = 1 asynchronous mode; IFCONFIG.3 = 0 synchronous mode //IFCFG1 IFCFG0 // 0 0 Ports // 0 1 Reserved // 1 0 GPIF Interface (internal master) // 1 1 Slave FIFO Interface (external master) //REVCTL //**********************************************// SYNCDELAY; REVCTL=0x01; //SET REVCTL.0=0 & REVCTL.1=1 //USB Domain of the FIFO //***********************************************************// SYNCDELAY; //EP1OUTCFG, EP1INCFG EP1OUTCFG=0xA0; // Bit7 bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0 SYNCDELAY; // VALID 0 TYPE1 TYPE0 0 0 0 0 EP1INCFG=0xA0; //TYPE[1:0], 00,01=VALID; 10=BULK; 11=INTERRUPT; SYNCDELAY; //EPxCFG where x=2,4,6,8 EP2CFG = 0xE8; // Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0 SYNCDELAY; // VALID DIR TYPE1 TYPE0 SIZE 0 BUF1 BUF0 EP4CFG = 0x00; //DIR:0=OUT; 1=IN. SYNCDELAY; //TYPE[1:0], 00=Invalid, 01=ISOCHRONOUS, 10=BULK, 11=INTERRUPT EP6CFG = 0x00; //SIZE: 0=512 bytes, 1=1024 bytes. SYNCDELAY; //BUF[1:0], 00=Quad, 01=Invalid, 10=Double, 11=Triple. EP8CFG = 0x00; //Reset FIFOs //***********************************************************// SYNCDELAY; FIFORESET = 0x80; //Write 0x80 to this register to NAK all transfers from the host, then write 0x02, 0x04, 0x06, or 0x08 SYNCDELAY; //to reset an individual FIFO (i.e., to restore endpoint FIFO flags and byte counts to their default FIFORESET = 0x02; //states), then write 0x00 to restore normal operation. SYNCDELAY; FIFORESET = 0x00; //Peripheral Domain side of FIFO //**********************************************************// SYNCDELAY; EP2FIFOCFG = 0x09; // Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0 // 0 INFM1 OEP1 AUTOOUT AUTOIN ZEROLENIN 0 WORDWIDE //INFM1==1, The FIFO falgs for that endpoint become valid one sample earlier than when the FULL condition occurs. only to IN endpoints and operating synchronously. //OEP1==1, The FIFO for that endpoint become valid one sample earlier than when the EMPTY condition occurs. applies only to OUT endpoints and operating aschrously. //WORDWIDE applies when IFCFG=11 or 10. //*******************************************************// //FLAGA,FLAGB,FLAGC,FLAGD SYNCDELAY; PINFLAGSAB=0x00; //FLAGx3 FLAGx2 FLAGx1 FLAGx0 Pin Function SYNCDELAY; // 0 0 0 0 FLAGA=PF, FLAGB=FF, FLAGC=EF, FLAGD=EP2PF. PINFLAGSCD=0x40; // 0 0 0 1 Reserved // 0 0 1 0 Reserved // 0 0 1 1 Reserved // 0 1 0 0 EP2 PF // 0 1 0 1 EP4 PF // 0 1 1 0 EP6 PF // 0 1 1 1 EP8 PF // 1 0 0 0 EP2 EF // 1 0 0 1 EP4 EF // 1 0 1 0 EP6 EF // 1 0 1 1 EP8 EF // 1 1 0 0 EP2 FF // 1 1 0 1 EP4 FF // 1 1 1 0 EP6 FF // 1 1 1 1 EP8 FF //*******************************************************// SYNCDELAY; FIFOPINPOLAR=0x3F; // Bit5 (PKTEND) 0:active low; 1:active high // Bit4 (SLOE) 0:active low; 1:active high // Bit3 (SLRD) 0:active low; 1:active high // Bit2 (SLWR) 0:active low; 1:active high // Bit1 (Empty Flag) 0:active low; 1:active high // Bit0 (Full Flag) 0:active low; 1:active high //*******************************************************// SYNCDELAY; // Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0 EP2FIFOPFH=0x81; // DECIS PKTSTAT IN:PKTS[2] IN:PKTS[1] IN:PKTS[0] 0 PFC9 PFC8 SYNCDELAY; // OUT:PFC12 OUT:PFC11 OUT:PFC10 0 EP2FIFOPFL=0x00; // For OUT packets, DECIS=0 (or 1):PF is asserted when the number is less/equal (or greater/equal) the threshold. // For IN packets, PKTSTAT=1, The threshold is stored in PFC9:0, PKTSTAT=0, the threshold is stored in PKTS2:0 and PFC9:0 //*******************************************************// SYNCDELAY; PORTACFG=0x00; // Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0 //FLAGD SLCS 0 0 0 0 INT1 INT0 //FLAGD=1 when IFCFG[1:0]=11 configures PA7 as FLAGD. //SLCS=1 when IFCFG[1:0]=11 configures PA7 as S\L\C\S\. //INT[1:0] configures PA[1:0] as INT1 and INT0 pins. //*******************************************************// SYNCDELAY; OEA|=0x88; //Output Enable (Port A) PORTA.7: Enable PORTA.3:Enable SYNCDELAY; IOA=0x88; //PORTA.3=1 reset and suspend the FPGA. //******************************************************// SYNCDELAY; IE|=0x80; // IE.7 IE.6 IE.5 IE.4 IE.3 IE.2 IE.1 IE.0 // EA Serial_1 Timer_2 Serial_0 Timer_1 External_1 Timer_0 External_0 //*************************EIE******************************// SYNCDELAY; // Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0 EIE|=0x05; // EX6 EX5 EX4 EI2C EUSB //*****************Enable selected interrupts**************** USBIE |= bmSUDAV | bmSUTOK | bmSUSP | bmURES | bmHSGRANT; //Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0 // 0 EP0ACK HSGRANT URES SUSP SUTOK SOF SUDAV //**************************IP******************************// IP=0x05; //Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0 // 1 Serial_1 Timer_2 Serial_0 Timer_1 INT1 Timer_0 INT0 //=1:high priority, =0:low priority //*************************EIP******************************// EIP=0x01; //Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0 // 1 1 1 INT6 INT5 INT4/GPIF/FIFO I2CINT PUSB //=1: high priority, =0: low priority //*************************Endpoint Interrupt Enable********// SYNCDELAY; // Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0 EPIE|=0x08; // EP8 EP6 EP4 EP2 EP1OUT EP1IN EP0OUT EPOIN //****************EP2 Slave FIFO Flag Interrupt Enable******// EP2FIFOIE=0x01; // Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0 // 0 0 0 0 EDGEPF PF EF FF //EDGE=0 (or 1), the interrupt fires on the rising (falling) edge of the programmable flag //*************************TCON*****************************// SYNCDELAY; // Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0 TCON=0x05; // TF1 TR1 TF0 TR0 IE1 IT1 IE0 IT0 //TCON.2(IT1) - INT1 is detected on falling edge when IT1 = 1; INT1 is detected as a low level when IT1 = 0. //TCON.0(IT0) - INT0 is detected on falling edge when IT0 = 1; INT0 is detected as a low level when IT0 = 0. //ARM EP1OUT SYNCDELAY; EP1OUTBC=0; //Set the BUSY bit in EP1OUTCS by writing any value to EP1OUTBC, arm the endpoint for EP1OUT transfer. //The BUSY bit in EP1OUTCS, BUSY=1 means the SIE owns the buffer, //BUSY=0 means that the firmware may read from or write the buffer. //At power-on (or whenever a 0-to-1 transition occurs on the RESET pin), the BUSY //bit is set to 0, //Firware arms the endpoint for OUT transfers by writing any value to the //byte count register EP1OUTBC, which automatically sets BUSY=1. //BUSY is automatically cleared to 0 after the FX2 verifies the OUT data for //accuracy and ACKs the transfer. //A 1-to-0 BUSY transition asserts the EP1OUT interrupt request, signaling //new EP1OUT data is availabe. //在重启或者复位后,BUSY自动置0; //在固件给EP1OUTBC写入一数值后,BUSY自动设置为1,准备EP1OUT传输 //在FX2验证数据无误并且ACK此对话后,BUSY自动清零 //BUSY位的1-0变化,会产生EP1OUT中断请求。 SYNCDELAY; in_enable=FALSE; } void TD_Poll(void) { } BOOL TD_Suspend(void) // Called before the device goes into suspend mode { return(TRUE); } BOOL TD_Resume(void) // Called after the device resumes { return(TRUE); } //----------------------------------------------------------------------------- // Device Request hooks // The following hooks are called by the end point 0 device request parser. //----------------------------------------------------------------------------- BOOL DR_GetDescriptor(void) { return(TRUE); } BOOL DR_SetConfiguration(void) // Called when a Set Configuration command is received { if( EZUSB_HIGHSPEED( ) ) { // FX2 enumerated at high speed SYNCDELAY; // EP2AUTOINLENH = 0x02; // 0x02,set AUTOIN commit length to 512 bytes SYNCDELAY; // EP2AUTOINLENL = 0x00; SYNCDELAY; enum_high_speed = TRUE; } else { // FX2 enumerated at full speed SYNCDELAY; EP2AUTOINLENH = 0x00; // set AUTOIN commit length to 64 bytes SYNCDELAY; EP2AUTOINLENL = 0x40; SYNCDELAY; enum_high_speed = FALSE; } Configuration = SETUPDAT[2]; return(TRUE); // Handled by user code } BOOL DR_GetConfiguration(void) // Called when a Get Configuration command is received { EP0BUF[0] = Configuration; EP0BCH = 0; EP0BCL = 1; return(TRUE); // Handled by user code } BOOL DR_SetInterface(void) // Called when a Set Interface command is received { AlternateSetting = SETUPDAT[2]; return(TRUE); // Handled by user code } BOOL DR_GetInterface(void) // Called when a Set Interface command is received { EP0BUF[0] = AlternateSetting; EP0BCH = 0; EP0BCL = 1; return(TRUE); // Handled by user code } BOOL DR_GetStatus(void) { return(TRUE); } BOOL DR_ClearFeature(void) { return(TRUE); } BOOL DR_SetFeature(void) { return(TRUE); } #define VX_B1 0xB1 // reset the external FIFO BOOL DR_VendorCmnd(void) { switch (SETUPDAT[1]) { case VX_B1: { //start FPGA OEA=0xfc; //1111 1100 // 1:turn on output buffer ; 0: turn off SYNCDELAY; IOA&=0xf7; *EP0BUF=VX_B1; EP0BCH=0; EP0BCL=1; EP0CS |= bmHSNAK; break; } default: return(TRUE); } return(FALSE); } //----------------------------------------------------------------------------- // USB Interrupt Handlers // The following functions are called by the USB interrupt jump table. //----------------------------------------------------------------------------- // Setup Data Available Interrupt Handler void ISR_Sudav(void) interrupt 0 { GotSUD = TRUE; // Set flag EZUSB_IRQ_CLEAR(); USBIRQ = bmSUDAV; // Clear SUDAV IRQ } // Setup Token Interrupt Handler void ISR_Sutok(void) interrupt 0 { EZUSB_IRQ_CLEAR(); USBIRQ = bmSUTOK; // Clear SUTOK IRQ } void ISR_Sof(void) interrupt 0 { EZUSB_IRQ_CLEAR(); USBIRQ = bmSOF; // Clear SOF IRQ } void ISR_Ures(void) interrupt 0 { // whenever we get a USB reset, we should revert to full speed mode pConfigDscr = pFullSpeedConfigDscr; ((CONFIGDSCR xdata *) pConfigDscr)->type = CONFIG_DSCR; pOtherConfigDscr = pHighSpeedConfigDscr; ((CONFIGDSCR xdata *) pOtherConfigDscr)->type = OTHERSPEED_DSCR; EZUSB_IRQ_CLEAR(); USBIRQ = bmURES; // Clear URES IRQ } void ISR_Susp(void) interrupt 0 { Sleep = TRUE; EZUSB_IRQ_CLEAR(); USBIRQ = bmSUSP; } void ISR_Highspeed(void) interrupt 0 { if (EZUSB_HIGHSPEED()) { pConfigDscr = pHighSpeedConfigDscr; ((CONFIGDSCR xdata *) pConfigDscr)->type = CONFIG_DSCR; pOtherConfigDscr = pFullSpeedConfigDscr; ((CONFIGDSCR xdata *) pOtherConfigDscr)->type = OTHERSPEED_DSCR; } EZUSB_IRQ_CLEAR(); USBIRQ = bmHSGRANT; } void ISR_Ep0ack(void) interrupt 0 { } void ISR_Stub(void) interrupt 0 { } void ISR_Ep0in(void) interrupt 0 { } void ISR_Ep0out(void) interrupt 0 { } void ISR_Ep1in(void) interrupt 0 { } void ISR_Ep1out(void) interrupt 0 { //the interrupt asserts when the host supplies a packet to the endpoint.(EP1-OUT has USB data) if(in_enable==FALSE) { //if in_enable==false, this is the first EP1OUT transfer, so enable EP2 IN transfer in_enable=TRUE; SYNCDELAY; // EP2CS &=0xFE; //Clear EP2 STALL bit. SYNCDELAY; IOA=0x80; //PORTA.3=0 release the FPGA. //Reset EP2 FIFO SYNCDELAY; FIFORESET = 0x80; //Write 0x80 to this register to NAK all transfers from the host, then write 0x02, 0x04, 0x06, or 0x08 SYNCDELAY; //to reset an individual FIFO (i.e., to restore endpoint FIFO flags and byte counts to their default FIFORESET = 0x02; //states), then write 0x00 to restore normal operation. SYNCDELAY; FIFORESET = 0x00; } while(EP24FIFOFLGS&0x04) { //waiting untill EP2FIFO Programable Flag is disasserted! (when it is idle for EP2 transfer) ; } EP1INBUF[0]=0x55; SYNCDELAY; EP1INBUF[1]=0xAA; SYNCDELAY; EP1INBC=2; //Arm EP1INBUF for IN-Transfer //The BUSY bit in EP1INCS //BUSY=1,means that the SIE "ownn" the buffer, so firmwave should not write (or read) the buffer. //BUSY=0,means that the firmwave may write data into (or read from) the buffer. //A 1-to-0 BUSY transition asserts the EP1IN interrupt request, signaling that the EP1IN buffer is //free and ready to loaded with new data. //The firmwave schedules an IN transfer by loading up to 64 bytes of data into EP1INBUF, //then writing the byte count register EP1INBC with the number of bytes loaded. //Writing the byte coun-register automatically sets BUSY=1. //After the FX2 subsequently receives an IN token, sends the data, and successfully receives //an ACK from the host, BUSY is automatically cleared to 0 to indicate that the buffer is ready //to accept more data. //After power-on, or whether a 0-to-1 transition occurs on the RESET pin, the BUSY bit is set to 0 SYNCDELAY; SYNCDELAY; EP1OUTBC=0; //Set the BUSY bit in EP1OUTCS by writing any value to EP1OUTBC; Arm the endpoint for EP1OUT transfer. SYNCDELAY; EZUSB_IRQ_CLEAR(); EPIRQ=0x08; //Clear the EP1out-USB IRQ bit by writing 1 to Bit-3. 0000 1000 } void ISR_Ep2inout(void) interrupt 0 { } void ISR_Ep4inout(void) interrupt 0 { } void ISR_Ep6inout(void) interrupt 0 { } void ISR_Ep8inout(void) interrupt 0 { } void ISR_Ibn(void) interrupt 0 { } void ISR_Ep0pingnak(void) interrupt 0 { } void ISR_Ep1pingnak(void) interrupt 0 { } void ISR_Ep2pingnak(void) interrupt 0 { } void ISR_Ep4pingnak(void) interrupt 0 { } void ISR_Ep6pingnak(void) interrupt 0 { } void ISR_Ep8pingnak(void) interrupt 0 { } void ISR_Errorlimit(void) interrupt 0 { } void ISR_Ep2piderror(void) interrupt 0 { } void ISR_Ep4piderror(void) interrupt 0 { } void ISR_Ep6piderror(void) interrupt 0 { } void ISR_Ep8piderror(void) interrupt 0 { } void ISR_Ep2pflag(void) interrupt 0 { } void ISR_Ep4pflag(void) interrupt 0 { } void ISR_Ep6pflag(void) interrupt 0 { } void ISR_Ep8pflag(void) interrupt 0 { } void ISR_Ep2eflag(void) interrupt 0 { } void ISR_Ep4eflag(void) interrupt 0 { } void ISR_Ep6eflag(void) interrupt 0 { } void ISR_Ep8eflag(void) interrupt 0 { } void ISR_Ep2fflag(void) interrupt 0 { //if EP2FIFOBUF is full, the error occurs! in_enable=FALSE; SYNCDELAY; IOA=0x88; //PORTA.3=1 reset and suspend the FPGA. // SYNCDELAY; // EP2CS |=0x01; //Stall EP2. SYNCDELAY; //EPxCFG where x=2,4,6,8 EP2CFG = 0x68; // Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0 // VALID DIR TYPE1 TYPE0 SIZE 0 BUF1 BUF0 //DIR:0=OUT; 1=IN. //TYPE[1:0], 00=Invalid, 01=ISOCHRONOUS, 10=BULK, 11=INTERRUPT //SIZE: 0=512 bytes, 1=1024 bytes. //BUF[1:0], 00=Quad, 01=Invalid, 10=Double, 11=Triple. SYNCDELAY; EXIF &=0xBF; //clear FIFO main interrupt request flag. SYNCDELAY; EP2FIFOIRQ=0x01; //**********EP2 Slave FIFO Flag Interrupt Request********* // Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0 // 0 0 0 0 0 PF Empty-Flag Full-Flag } void ISR_Ep4fflag(void) interrupt 0 { } void ISR_Ep6fflag(void) interrupt 0 { } void ISR_Ep8fflag(void) interrupt 0 { } void ISR_GpifComplete(void) interrupt 0 { } void ISR_GpifWaveform(void) interrupt 0 { } void Setup_FLOWSTATE_Read ( void ) { FLOWSTATE = FlowStates[18]; // 1000 0010b - FSE=1, FS[2:0]=002 SYNCDELAY; FLOWEQ0CTL = FlowStates[20]; // CTL0 = 0 when flow condition equals zero (data flows) SYNCDELAY; FLOWEQ1CTL = FlowStates[21]; // CTL0 = 1 when flow condition equals one (data does not flow) SYNCDELAY; } |
|