PSOC 4 USB - buggy behavior

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
KUn_4718781
Level 1
Level 1

Hi,

I have a working (mostly) project that takes text from the PC, one byte at a time, and echoes it back to the PC.  It does this in generic HID, using the 8 byte reports as defined in AN82072.  I have weird behavior though, which I would like to fix.  The device displays the string that it receives to an LCD; the LCD is helpful for testing.  It seems to receive the overwhelming majority of bytes OK.  But on the PC side, the IN side, the text comes back somewhat garbled.  I have largely mitigated this, but I don't understand why it is happening.  I can't reliably create a device with this USB if moving a block around changes it from working to not without rhyme or reason.

#############################################################################

###########

#############################################################################

USB_Start(0,USB_DWR_VDDD_OPERATION);

    #define UnassignedAddress 0

    while(USB_deviceAddress == UnassignedAddress)

    {

        // Wait for device address to be assigned

    }

    while(!(USB_GetConfiguration()));

    for(;;)

    {

        uint8 interruptState;

        interruptState = CyEnterCriticalSection();

        /* Place your application code here. */

        // the primary USB send and receive function

        OUT_COUNT = 0;

        if(USB_IsConfigurationChanged()) //make happen every time

        {

            //USB_GetInterfaceSetting(0); // works without this line???

            USB_LoadEP(IN_ENDPOINT, IN_Data_Buffer, 8);

            USB_ReadOutEP(OUT_ENDPOINT, OUT_Data_Buffer, OUT_COUNT);

            USB_EnableOutEP(OUT_ENDPOINT);

        }

//     //////////////////////////// WHY DOES THIS CHANGE WORK? ///////////////////////////////////////////

// --------------------------------------------------------------------------------------------------------------------------------

// moved the following block down below:

#############################################################################

/*

        if ((USB_GetEPState(IN_ENDPOINT) == USB_IN_BUFFER_EMPTY ) ) //Data to send

        {

            USB_LoadEP(IN_ENDPOINT, NULL, 8);

            //USB_EnableOutEP(OUT_ENDPOINT);

        }

*/

#############################################################################

// --------------------------------------------------------------------------------------------------------------------------------

        if(USB_GetEPState(OUT_ENDPOINT) == USB_OUT_BUFFER_FULL)   /// Data to Receive

        {

            OUT_COUNT = USB_GetEPCount(OUT_ENDPOINT);

            USB_EnableOutEP(OUT_ENDPOINT);

        }

        if (OUT_COUNT != 0)  

        {

            char tempChar = (char)OUT_Data_Buffer[0];

            // this loop resets the OUT line on LCD

            // once it is full and more text has arrived

            if(textOutLength > maxLength)

            {

                textOutLength = 0;

                //LCD_Position(1u,0u);

                // this loop blanks the OUT line on LCD

                // it is 21 elements long, even though the screen is 20

                // b/c I append a \0 when sending the text from PC

                for(int z = 0; z <= 20; z++)

                {

                    textOut = ' ';

                }

                int bob = 0;

            }    

            if (tempChar != 0)

            {

                textOut[textOutLength] = tempChar;

                textOutLength = textOutLength + 1;

                 IN_Data_Buffer[0] = OUT_Data_Buffer[0];

                if(textInLength > maxLength)

                {

                    textInLength = 0;

                    textInIndex = 0;    // should I update this one here???

                    for(int i = 0; i < 20; i++)

                    {

                        textIn = ' ';

                    }

                }

                textIn[textInLength] = IN_Data_Buffer[0];

                textInLength = textInLength + 1;

            }    

        }

// --------------------------------------------------------------------------------------------------------------------------------

// This block was moved down here from the marked area above

        if ((USB_GetEPState(IN_ENDPOINT) == USB_IN_BUFFER_EMPTY ) ) //Data to send

        {

            USB_LoadEP(IN_ENDPOINT, NULL, 8);

            //USB_EnableOutEP(OUT_ENDPOINT);

        }

// --------------------------------------------------------------------------------------------------------------------------------

        CyExitCriticalSection(interruptState);

    }

}

#############################################################################

#############################################################################

#############################################################################

Maybe it is the addition of a delay between the OUT and IN???  But I've tried the old version with small CyDelay(1) (note that the interrupt timing is 100ms, so a 1ms delay shouldn't be consequential) between GetEpState() blocks, to no effect?

0 Likes
2 Replies
Aashita_R
Moderator
Moderator
Moderator
50 likes received 100 solutions authored 250 replies posted

Hi KUn_4718781​,

As per my understanding, you are trying to send the data from host (PC) to the device and display it on LCD, then this data is being sent back to the host where you are able to see the garbled data. Can you please confirm? If this is the case, the below should be flow of firmware, inside the for() loop which should be followed-

1.  Check the number of bytes which are available to be read to OUT_Endpoint.

2.  Reading out the data from the OUT_Endpoint.

3.  Writing the data back to the host.

4.  Enabling the OUT_Endpoint to write the data again.

Therefore, Can you please answer the below queries?  This will help us understand the issue more clearly.

1. Can you please elaborate on what are you exactly trying to do? Why are you using CyEnterCriticalSection() and  CyExitCriticalSection() for the interrupts?

2. What is the endpoint buffer management option, you have selected in the USB descriptor? Are you using Automatic or manual buffer management ?

Please let us know answers to the above queries so that we can help you out the solution.

Best Regards,

Aashita

0 Likes

Hi,

broadly speaking, yes that is the program flow.

I tried the critical section code in case an interrupt was interfering with

the correct operation of the main for() loop.

I have selected automatic DMA. You can see a tweaked version of the

program in my question "PSOC 4 USB - data errors" I have it attached

along with the PC side program

On Thu, Nov 12, 2020 at 12:30 AM AashitaR_11 <community-manager@cypress.com>

0 Likes