You are here

FX2 - EP0OUT acts as if 2x buffered | Cypress Semiconductor

FX2 - EP0OUT acts as if 2x buffered

Summary: 8 Replies, Latest post by Gayathri on 11 Jul 2012 12:33 AM PDT
Verified Answers: 0
Last post
Log in to post new comments.
onichikun's picture
User
5 posts

 Hey everyone,

I am working on a design where I  send a vendor command, which then takes the data from my vendor command and performs single writes to my GPIF (to set some address registers.) I have run into an issue, however, where the EP0OUT buffer seems to contain data from the last transfer I perform. The first EP0OUT buffer is always invalid as well. I have veried that the data transferd is always the last data I sent by watching the bus with an LSA.

Here is the code I am using for my vendor command (I am sorry if I make register name mistakes, the code is not infront of me at the moment.)

....

case VR_Set_Address:

while( !(GPIFTRIG&0x80)); //wait for GPIF idle

for(i=0; i< SETUPDAT[6]; ++i) {

SYNCDELAY; //suggested from a similar forum post

XGPIFSGLDATH = EP0BUF[i++];

 

SYNCDELAY; //suggested from a similar forum post

 

XGPIFSGLDATLX = EP0BUF[i]; //trigger GPIF

while( !(GPIFTRIG&0x80)); //wait for GPIF idle 

}

EP0BCH = 0;

EP0BCL = 0;

EP0CS |= bmHSNAK;

 break;

 

I thought there may be an issue with the EP0 being armed, so I added EP0BCL = 0; to my TD_Init() code, but still no luck. 

 

Thank you for your time.

Robert

 

 

aasi's picture
Cypress Employee
1166 posts

The dataphase takes little time to happen and you're most probably accessing the buffer before that happens. Use

 

while(EP0CS & bmEPBUSY);

 

to wait for the arrival of the data, this should fix your issue.

Regards,

Anand

onichikun's picture
User
5 posts

Thanks for the response. I finally got time to work on this..

So I implemented your suggested change, and I am still getting the same result. Note that if I dont read from the EP0 Buf and I hardcode values, everything is correct... so it defininately appears to be an issue with the EP0 buffer.

My exact code is:

TD_Init:

    // set the CPU clock to 48 MHz
    CPUCS = ((CPUCS & ~bmCLKSPD) | bmCLKSPD1);

    EP1OUTCFG = 0xA0; //EP1OUT, bulk, OUT, 64 bytes, single buffered
    SYNCDELAY;
    EP1INCFG = 0xA0; //EP1IN, bulk, IN, 64 bytes, single buffered
    SYNCDELAY;

    EP2CFG = 0xA2; // EP2OUT, bulk, size 512, 2x buffered
    SYNCDELAY;

    EP4CFG = 0x00; // EP4 not valid
    SYNCDELAY;

    EP6CFG = 0xE2; // EP6IN, bulk, size 512, 2x buffered
    SYNCDELAY;

    EP8CFG = 0x00; // EP8 not valid
    SYNCDELAY;

    EP2FIFOCFG = 0x01; // manual mode, disable PKTEND zero length send, word ops
    SYNCDELAY;
    EP6FIFOCFG = 0x01; // manual mode, disable PKTEND zero length send, word ops
    SYNCDELAY;
    FIFORESET = 0x80; // set NAKALL bit to NAK all transfers from host
    SYNCDELAY;
    FIFORESET = 0x02; // reset EP2 FIFO
    SYNCDELAY;
    FIFORESET = 0x06; // reset EP6 FIFO
    SYNCDELAY;
    FIFORESET = 0x00; // clear NAKALL bit to resume normal operation
    SYNCDELAY;

    // Arm endpoint with # bytes to transfer
    // out endpoints do not come up armed
    // since EP2OUT is quad buffered we must write dummy byte counts four times
    EP0BCL = 0; 
    SYNCDELAY;
    EP2BCL = 0x80; // arm EP2OUT by writing byte count w/skip.
    SYNCDELAY;
    EP2BCL = 0x80;
    SYNCDELAY;
    EP2BCL = 0x80;
    SYNCDELAY;
    EP2BCL = 0x80;
    SYNCDELAY;
    GpifInit (); // initialize GPIF registers   
    OEA |= 0x03;

Vendor Command:

    case VR_SET_ADDRESS:
            while(!(GPIFTRIG & 0x80)); //While GPIF is busy

            IOA |= 0x2; //Set address enable bit

            for(i=0; i<SETUPDAT[6]; ++i) {
                while(EP0CS & bmEPBUSY);
                SYNCDELAY;
                XGPIFSGLDATH = EP0BUF[i++];
                SYNCDELAY;
                XGPIFSGLDATLX = EP0BUF[i];
                  while(!(GPIFTRIG & 0x80)); //While GPIF is busy
            }
            IOA ^= 0x2; //Disable address bit

            EP0BCH = 0;
            EP0BCL = 0; // Arm endpoint with # bytes to transfer
            EP0CS |= bmHSNAK; // Acknowledge handshake phase of device request
        break;

 

Thank you again!

onichikun's picture
User
5 posts

I apologize for the double post --

I have everything working, except for the fact that I have to write the address vendor command twice to set my address register appropriately.

After a lot of experiements, even if I delay for an entire ms using EZUSB_Delay(1) before reading from EP0BUF,  I still get the same results. The first transfer is always incorrect, and the data on the bus after that is ALWAYS the last data I transfered. The SETUPDAT however is always correct.

EP0BUF shouldnt be double buffered, correct? Is there some setting I need for EP0? Is there any problem with using the data from EP0 to set the GPIF data registers for the single transfer? Really not sure where to go from here.

 

onichikun's picture
User
5 posts

Little change here, I am dealing with an FX2LP not just an FX2. 

gaya's picture
Cypress Employee
578 posts

 Hi,

 

Glad that you posted the solution. It might be of use to someone!!!

 

Regards,

Gayathri

travis01234's picture
User
1 post

I had similar problems but solved it a different way.

Regards,
Travis
 

/* Called once at startup */
void TD_Init(void)
{
    /* ..your start-up code.. */

    EPIE |= bmBIT1; // Enable EP0-OUT Endpoint interrupt
}

void ISR_Ep0out(void) interrupt 0 {

    BYTE ep0Count = EP0BCL;

    /* Store EP0OUT data. */
    while(ep0Count) {
        ep0Count--;
        g_StreamDat[ep0Count]=EP0BUF[ep0Count];
    }

    /* Stage next batch of bytes. */
    EP0BCH = 0;
    EP0BCL = 0;
    EP0CS |= bmHSNAK;

    /* Clear EP0IF. */
    EZUSB_IRQ_CLEAR();
    EPIRQ = bmBIT1;
}

BOOL DR_VendorCmnd(void)
{
    BYTE length, pos;

     if (!SETUPDAT[6] || (SETUPDAT[6] > sizeof(g_StreamDat)) || ((SETUPDAT[0] & 0x41) != 0x41)) return(FALSE);

    if (SETUPDAT[1] == SC_GET_STREAM_DATA && (SETUPDAT[0] & 0x80)) {

        // Device -> Host
        for(pos = 0; pos < length; pos++) EP0BUF[pos]=g_StreamDat[pos];
        EP0BCH = 0;
        EP0BCL = SETUPDAT[6];

        return(TRUE);
    } else if (SETUPDAT[1] == SC_SET_STREAM_DATA) {

        // Host -> Device
        EP0BCH = 0;
        EP0BCL = SETUPDAT[6];
        return(TRUE);
    }
    return(FALSE);
}

 

 

gaya's picture
Cypress Employee
578 posts

  Cool. Good that you posted it !!!

onichikun's picture
User
5 posts

Follow up solution :

So just if anyone is running into the same problem, it looks like I made a very stupid oversight with setting the byte counter registers for EP0, which is why the data was never being flushed into the EP0BUF!

 

case VR_SET_ADDRESS:

            //FIX

           EP0BCH = 0;

           EP0BCL = 4;

           //END FIX

           while(EP0CS & bmBUSY); //Wait for EP0BC bytes to enter the FIFO
            while(!(GPIFTRIG & 0x80)); //While GPIF is busy

            IOA |= 0x2; //Set address enable bit

            for(i=0; i                 while(EP0CS & bmEPBUSY);
                SYNCDELAY;
                XGPIFSGLDATH = EP0BUF[i++];
                SYNCDELAY;
                XGPIFSGLDATLX = EP0BUF[i];
                  while(!(GPIFTRIG & 0x80)); //While GPIF is busy
            }
            IOA ^= 0x2; //Disable address bit

            EP0BCH = 0;
            EP0BCL = 0; // Arm endpoint with # bytes to transfer
            EP0CS |= bmHSNAK; // Acknowledge handshake phase of device request
        break;

Log in to post new comments.