UPGRADE YOUR BROWSER

We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Observer kabba
Observer
95 Views
Registered: ‎12-02-2014

Zynq Ultrascale+ MPSoC USB CDC ACM Device Bulk endpoint handler not called

Jump to solution

Hi All

I am very new to USB implementations. I have been trying to create a USB CDC ACM device on our ZCU106 eval kit.

I have found a Zynq 7000 CDC ACM example and have been trying to work from the storage example provided with the XUSBPSU driver code and change it to follow the implementation that I can see have been done in the Zynq 7000 CDC example.

Thus far windows correctly reads the descriptors and sees the device as a CDC device with one interrupt endpoint and bidirectional bulk data endpoint data pipes reported as open by the windows USBview tool.

I can also see that the class requests are correctly handled, meaning set_carrier, set_line_coding and get_line_coding class requests. So a serial terminal connects succesfully to via the COM port.

My Issue is that when I send a byte via the terminal I do not get the BULK endpoint handler to be called on the device. The control endpoint works fine. I can see from a USB protocol analyzer that the terminal is constantly trying to send the same byte indefinately. As far as I know I have done all that needs to be in place for a endpoint to work on the device, configuring, hooking handler functions and Enabling them in the setConfiguration stage.

Initialization code:

s32 Status;
    int bytes;
    u8 text_buffer[256];
    const u8 text_rec[13] = "Received ";
    const u8 text_newline[4] = "\r\n";

    xil_printf("CDC DEVICE START...\r\n");

    /* Initialize the USB driver so that it's ready to use,
     * specify the controller ID that is generated in xparameters.h
     */
    UsbConfigPtr = LookupConfig(USB_DEVICE_ID);
    if (NULL == UsbConfigPtr) {
        return XST_FAILURE;
    }

    CacheInit();

    /* We are passing the physical base address as the third argument
     * because the physical and virtual base address are the same in our
     * example.  For systems that support virtual memory, the third
     * argument needs to be the virtual base address.
     */
    Status = CfgInitialize(&UsbInstance, UsbConfigPtr,
                    UsbConfigPtr->BaseAddress);
    if (XST_SUCCESS != Status) {
        return XST_FAILURE;
    }

    /* hook up chapter9 handler */
    Set_Ch9Handler(UsbInstance.PrivateData, Ch9Handler);

    /* Assign the data to usb driver */
    Set_DrvData(UsbInstance.PrivateData, &storage_data);

    EpConfigure(UsbInstance.PrivateData, 1, USB_EP_DIR_IN,
                USB_EP_TYPE_INTERRUPT);
    EpConfigure(UsbInstance.PrivateData, 2, USB_EP_DIR_OUT,
                USB_EP_TYPE_BULK);
    EpConfigure(UsbInstance.PrivateData, 2, USB_EP_DIR_IN,
                    USB_EP_TYPE_BULK);

    Status = ConfigureDevice(UsbInstance.PrivateData, &Buffer[0], MEMORY_SIZE);
    if (XST_SUCCESS != Status) {
        return XST_FAILURE;
    }

    /*
     * set endpoint handlers
     * BulkOutHandler - to be called when data is received
     * BulkInHandler -  to be called when data is sent
     */


    SetEpHandler(UsbInstance.PrivateData, 0, USB_EP_DIR_OUT,
                    EpCtrlHandler);
    SetEpHandler(UsbInstance.PrivateData, 1, USB_EP_DIR_IN,
                    EpIntrInEpHandler);
    SetEpHandler(UsbInstance.PrivateData, 2, USB_EP_DIR_IN,
                    EpBulkInHandler);
    SetEpHandler(UsbInstance.PrivateData, 2, USB_EP_DIR_OUT,
                    EpBulkOutHandler);

    /* setup interrupts */
    Status = SetupInterruptSystem(UsbInstance.PrivateData, INTC_DEVICE_ID, USB_INT_ID, (void *)&InterruptController);

    if (Status != XST_SUCCESS) {
        return XST_FAILURE;
    }
    /* Start the controller so that Host can see our device */
    Usb_Start(UsbInstance.PrivateData);

 

SetConfigurationApp function:

s32 Usb_SetConfigurationApp(struct Usb_DevData *InstancePtr,
                                 SetupPacket *SetupData)
{
    s32 RetVal;
    u16 MaxPktSize;
    u8 tempBuf[512];

#ifdef CDC_CH9_DEBUG
    xil_printf("INFO: Set application Configuration function called. \r\n");
#endif

    if(InstancePtr->Speed == USB_SPEED_SUPER) {
        MaxPktSize = 1024;
    } else {
        MaxPktSize = 512;
    }

    /* When we run CV test suite application in Windows, need to
     * add SET_CONFIGURATION command with value 0/1 to pass test suite
     */
    if ((SetupData->wValue && 0xff) ==  1) {
        /* SET_CONFIGURATION with value 1 */
#ifdef CDC_CH9_DEBUG
    xil_printf("INFO: Set application Configuration wValue 1 \r\n");
#endif
        /* Endpoint enables - not needed for Control EP */

        RetVal = EpEnable(InstancePtr->PrivateData, 1, USB_EP_DIR_IN,
                MaxPktSize, USB_EP_TYPE_INTERRUPT);
        if (RetVal != XST_SUCCESS) {
            xil_printf("failed to enable BULK IN Ep\r\n");
            return XST_FAILURE;
        }
        RetVal = EpEnable(InstancePtr->PrivateData, 2, USB_EP_DIR_IN,
                MaxPktSize, USB_EP_TYPE_BULK);
        if (RetVal != XST_SUCCESS) {
            xil_printf("failed to enable BULK OUT Ep\r\n");
            return XST_FAILURE;
        }
        RetVal = EpEnable(InstancePtr->PrivateData, 2, USB_EP_DIR_OUT,
                MaxPktSize, USB_EP_TYPE_BULK);
        if (RetVal != XST_SUCCESS) {
            xil_printf("failed to enable BULK OUT Ep\r\n");
            return XST_FAILURE;
        }

        SetConfigDone(InstancePtr->PrivateData, 1U);


#ifdef CDC_CH9_DEBUG
    xil_printf("INFO: Set Endpoints Enabled complete. \r\n");
#endif
        
    } else {
#ifdef CDC_CH9_DEBUG
    xil_printf("INFO: Set Endpoints Enabled configuration not called, this is bad. \r\n");
#endif
//    }
//    else {
        /* SET_CONFIGURATION with value 0 */
#ifdef CDC_CH9_DEBUG
    xil_printf("INFO: Set application Configuration wValue 0 \r\n");
#endif
        /* Endpoint disables - not needed for Control EP */
        RetVal = EpDisable(InstancePtr->PrivateData, 1, USB_EP_DIR_IN);
        if (RetVal != XST_SUCCESS) {
            xil_printf("failed to disable INTR IN Ep\r\n");
            return XST_FAILURE;
        }

        RetVal = EpDisable(InstancePtr->PrivateData, 2, USB_EP_DIR_OUT);
        if (RetVal != XST_SUCCESS) {
            xil_printf("failed to disable BULK OUT Ep\r\n");
            return XST_FAILURE;
        }
        /* Endpoint disables - not needed for Control EP */
        RetVal = EpDisable(InstancePtr->PrivateData, 2, USB_EP_DIR_IN);
        if (RetVal != XST_SUCCESS) {
            xil_printf("failed to disable BULK IN Ep\r\n");
            return XST_FAILURE;
        }

        SetConfigDone(InstancePtr->PrivateData, 0U);
    }

#ifdef CDC_CH9_DEBUG
    xil_printf("INFO: Set application Configuration function done. \r\n");
#endif

    return XST_SUCCESS;
}

 

 

I do not see any other code in the storage example that sets up endpoints. I have added checks for IsEpStalled but it always reports that the BULK endpoints are not stalled. I feel like I am missing some knowledge on what needs to happen for the driver code to call the endpoint handlers. I see in the Zynq7000 driver code they used a EpPrime function in the setConfiguration function, but I do not see a similar action in the XUSBPSU storage example.

Is there anyone that can point a newbie into the right direction to debug such endpoint inactivity?

Thanks in advance!

0 Kudos
1 Solution

Accepted Solutions
Observer kabba
Observer
44 Views
Registered: ‎12-02-2014

Re: Zynq Ultrascale+ MPSoC USB CDC ACM Device Bulk endpoint handler not called

Jump to solution

I can see now that my understanding of the endpoint data transfer was wrong. I Imagined that any data coming in from the PC to a BULK endpoint would trigger the handler being called. But it seems I have to initially call the EpBufferRec function for an expected amount of bytes (I started this in the SetConfigurationApp function that is called via USB standard requests from the PC. Then each time the handler is triggered for this data being received I make sure that the handler reissues the EpBufferRec function to be ready for any following data incoming.

My confusion came in with the previous Zynq7000 XUSBPS driver there was a EpPrime function to prepare the endpoint for incoming data seperate from the actual data receive function. It seems it works a bit differently now in the MPSoC USB3.0 controller driver.

Hope this helps any other newbies to embedded software and USB like I am.

0 Kudos
1 Reply
Observer kabba
Observer
45 Views
Registered: ‎12-02-2014

Re: Zynq Ultrascale+ MPSoC USB CDC ACM Device Bulk endpoint handler not called

Jump to solution

I can see now that my understanding of the endpoint data transfer was wrong. I Imagined that any data coming in from the PC to a BULK endpoint would trigger the handler being called. But it seems I have to initially call the EpBufferRec function for an expected amount of bytes (I started this in the SetConfigurationApp function that is called via USB standard requests from the PC. Then each time the handler is triggered for this data being received I make sure that the handler reissues the EpBufferRec function to be ready for any following data incoming.

My confusion came in with the previous Zynq7000 XUSBPS driver there was a EpPrime function to prepare the endpoint for incoming data seperate from the actual data receive function. It seems it works a bit differently now in the MPSoC USB3.0 controller driver.

Hope this helps any other newbies to embedded software and USB like I am.

0 Kudos