cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Visitor
Visitor
219 Views
Registered: ‎12-10-2019

Zynq: Not receiving USB interrupts in Host mode?

I'm working on a host-mode USB driver for the USB controller in the Zynq-series chipset, and I've gotten to the point where I have a bunch of the hardware up and running, and I can see port status changes and such when I continually poll the registers while connecting and removing devices. However, I seem to be unable to get any USB-related interrupts to actually fire and invoke the interrupt handler I've installed via XScuGic.

I may be misunderstanding the TRM here, but from what I've read it seems that if I enable the various interrupt bits in the XUSBPS_IER_OFFSET (USBINTR) register, then I should be receiving the XPAR_XUSBPS_0_INTR (53) interrupt, at which point my handler could inspect the USBSTS register to see which interrupt was fired.

While polling the XUSBPS_PORTSCR1_OFFSET (PORTSC1) register, and attaching and removing the device I'm attempting to work with, I successfully see the register change to denote that a device has been attached and at what speed it operates, or that the device has been removed and the port is no longer connected. However, despite me enabling every single USB interrupt, I never get an interrupt fired to denote the change.

The following code is how I'm attempting to enable the USB interrupt handler:

/* Install an interrupt handler for USB-related interrupts */
{
	int Status;
	XScuGic_Config *IntcConfig;

IntcConfig = XScuGic_LookupConfig(XPAR_SCUGIC_SINGLE_DEVICE_ID); Status = XScuGic_CfgInitialize(&ScuGicInstance, IntcConfig, IntcConfig->CpuBaseAddress); if (Status != XST_SUCCESS) xil_printf("XScuGic_CfgInitialize failed\n"); Status = XScuGic_SelfTest(&ScuGicInstance); if (Status != XST_SUCCESS) xil_printf("XScuGic_SelfTest failed!\n"); Status = XScuGic_Connect(&ScuGicInstance, XPAR_XUSBPS_0_INTR, (Xil_ExceptionHandler)UsbInterruptHandler, NULL); if (Status != XST_SUCCESS) xil_printf("XScuGic_Connect failed!\n"); XScuGic_Enable(&ScuGicInstance, XPAR_XUSBPS_0_INTR);
Xil_ExceptionInit(); Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, (Xil_ExceptionHandler)XScuGic_InterruptHandler, &ScuGicInstance); Xil_ExceptionEnable(); }

My UsbInterruptHandler is never called, despite me performing actions that I believe should trigger it.

Please excuse the use of my own code and bit defines in the following, but here's how I've set up the usbintr register. With this setup, I would expect to get an interrupt every time I connect or disconnect a device (the port change interrupt), but I'm seeing nothing. I have previously tested that the GIC is working, by registering for an interrupt number and then triggering that interrupt from software, at which point my interrupt handler was called as expected. I just don't understand why the USB host controller is not doing the same!

writel(&usb_ctrl.ehci.hcor->usbintr, EHCI_HCOR_USB_INT_USBINT | EHCI_HCOR_USB_INT_USBERRINT | EHCI_HCOR_USB_INT_PORTCHG_DETECT | EHCI_HCOR_USB_INT_FRAMELIST_ROLLOVER | EHCI_HCOR_USB_INT_HOSTSYS_ERR | EHCI_HCOR_USB_INT_ASYNC_ADVANCE);

Am I misunderstanding how the USB interrupts are supposed to work? Have I possibly neglected to configure some part of the host controller hardware? Most of the implementation I have thusfar is taken from how the u-boot linux drivers work, and as I mentioned I can successfully see the port status register changing as I attach and remove devices from it.

Thanks!

0 Kudos