Trouble on CY8C24493-24LTXI and BL_USBFS USB Bus Reset

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

cross mob
JeFe_286036
Level 3
Level 3

I have implemented a composite bootloadable USBFS device consisting of 2 interfaces.

Interface 1 implements a HID 'boot protocol' keyboard

Interface 2 implements a HID 'report protocol' wheel mouse and multimedia keys

I have been able to successfully hot-plug the device into a working Linux or Windows OS and it works flawlessly.

The same device though, when connected with some machines, will simply freeze when it is at the BIOS setup screen or the UEFI boot screen

I have narrowed the problem down to the USB bus reset that does not seem to happen.  On some hosts, unplugging and re-plugging in the device seems to get it to comply.

The vector _BL_USBFS_RESET_ISR never seems to trigger.  I have confirmed this by implementing visual aids on the Reset_ISR.  The aid should trigger if the ISR is triggered, else the aid should show an enumeration.  Neither of these 2 happens.

The only way out of this freeze is to either hard reset the controller or recycle power.

Question : Does anyone have some clue as to how to ensure that the PSOC1 does not freeze when a USB bus reset comes its way ?  Any suggestions gratefully accepted.

void main(void)
{
    M8C_EnableGInt;                      //Enable Global Interrupts
    BL_USBFS_Start(0, USB_5V_OPERATION); //Start USB Operation using device 0
    InitUsb();
    Red_Data_ADDR = 0x00;
    Intensity = 0;
    while(1)     // Main loop 
    {
        if (!UsbState)
        {
            if (BL_USBFS_bGetConfiguration())
            {
                UsbState=USBENUM;
                Tred =Intensity=2; Color=0;
            }
        }
        else
        {
            Task_Kbd();
        }
    }             // End While
}
This is a snippet of the contents of Task_Kbd
    // if the USB_KBD_ENDPOINT has been acked, send more data
    if (isbit(RptStatus,RS_Kbd))                              // there is data to send, this flag is set
    {
        if (!(UsbState & KBEP))                                    // if the EndPoint has not been written to as yet, this will be 0
        {
            BL_USBFS_LoadInEP(USB_KBD_ENDPOINT, (BYTE *)&keyboard_report, sizeof(keyboard_report), USB_TOGGLE);
            UsbState |= KBEP;
        }
        else
        {
            if (BL_USBFS_bGetEPAckState(USB_KBD_ENDPOINT))           // if the endpoint is acknowledged, write to it again
            {
                // send KBD report on EP1
                BL_USBFS_LoadInEP(USB_KBD_ENDPOINT, (BYTE *)&keyboard_report, sizeof(keyboard_report), USB_TOGGLE);
                bitclr(RptStatus,RS_Kbd);                          // and clear the flag
            }
        }
    }
    // if MM endpoint is open, send its data
    if (!(UsbState & MMEP))                                           // in case only the boot keyboard is working, this part will evaluate to 0
    {                                                                                 // it will send a packet but never get ack'ed and never send again to EP2
        BL_USBFS_LoadInEP(USB_MM_ENDPOINT, (BYTE*)&mouse_report, sizeof(mouse_report), USB_TOGGLE);
        UsbState |= MMEP;
    }
    else
    {
        // NAK, go back
        if (!BL_USBFS_bGetEPAckState(USB_MM_ENDPOINT)) return;
        
        // send mouse report
        if (isbit(RptStatus,RS_Mouse))
        {
            BL_USBFS_LoadInEP(USB_MM_ENDPOINT, (BYTE*)&mouse_report, sizeof(mouse_report), USB_TOGGLE);
            bitclr(RptStatus,RS_Mouse);
            return;
        }
    }
        

Regards

Jerson

0 Likes
4 Replies
JeFe_286036
Level 3
Level 3

Just in case you are wondering - here's some additional info

What if I use just one interface for boot keyboard?  Does it still freeze?  -  Yes it does.

Again, the reason for the freeze is a USB bus reset.  This can be confirmed by forcing a  USB reset to the device

/* usbreset -- send a USB port reset to a USB device

https://askubuntu.com/questions/645/how-do-you-reset-a-usb-device-from-the-command-line#661

run the following commands in terminal:

    Compile the program:

    $ cc usbreset.c -o usbreset

    Get the Bus and Device ID of the USB device you want to reset:

    $ lsusb

  Bus 002 Device 003: ID 0fe9:9010 DVICO

    Make our compiled program executable:

    $ chmod +x usbreset

    Execute the program with sudo privilege; make necessary substitution for <Bus> and <Device> ids as found by running the lsusb command:

    $ sudo ./usbreset /dev/bus/usb/002/003

*/

#include <stdio.h>

#include <unistd.h>

#include <fcntl.h>

#include <errno.h>

#include <sys/ioctl.h>

#include <linux/usbdevice_fs.h>

int main(int argc, char **argv)

{

    const char *filename;

    int fd;

    int rc;

    if (argc != 2) {

        fprintf(stderr, "Usage: usbreset device-filename\n");

        return 1;

    }

    filename = argv[1];

    fd = open(filename, O_WRONLY);

    if (fd < 0) {

        perror("Error opening output file");

        return 1;

    }

    printf("Resetting USB device %s\n", filename);

    rc = ioctl(fd, USBDEVFS_RESET, 0);

    if (rc < 0) {

        perror("Error in ioctl");

        return 1;

    }

    printf("Reset successful\n");

    close(fd);

    return 0;

}

0 Likes

Another important update.

The precise location seems to be the call to BL_USBFS_bGetConfiguration()

After a bus reset, this function does not show configured again (return value = 0)

What could be the cause for this?

Regards

Jerson

0 Likes

The problem was fixed by commenting out line 1510 in the std_dev.asm file

Attached screenshot shows the offending line.

I would say this problem is solved here, but, I need to modify the template code so that a Build (F6) does not undo the change.

Regards

Jerson

USB_bus_reset_soln.GIF

0 Likes

Hello Jerson,

There are two approaches.

The first is to lock the User Module from the Workspace Explorer, by right clicking on the BootLdrUSBFS User Module, and then selecting "Lock". This way, PSoC Designer will not regenerate the code for this User Module.

The second is to change the template code for this BootLdrUSBFS. You can find this under "Installation Folder/PSoC Designer/5.4/Common/CypressSemiDeviceEditor/Data/Stdum/BootLdrUSBFS". Usually the installation folder is "C:\Program Files\Cypress".

Sampath

0 Likes