cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Adventurer
Adventurer
353 Views
Registered: ‎11-10-2019

PL-PS IRQ0 interrupt signal not detected (irq_handler not executed)

ZCU104 Eval Board, Vivado 2019.1.3, Ubuntu 18.04

I created a simple design and used xaxidma_example_simple_intr.c project to test it. The DMA seem to work fine - I monitored the memory and saw that the transfer was completed and the IOC_Irg bit was set in the status register for both TX and RX. The Interrupt Controller's status registers also are set in response to axi_dma_0_mm2s_introut and axi_dma_0_s2mm_introut triggers from the DMA. The interrupt signal from the controller is also set HI (the LED is lit) - so the HI signal is provided to the pl_ps_irq0 of ZYNQ. There seems to be a software problem that does not react to the external interrupt.

dma.png

I am using the Xilinx example and I assume that the code should work as is, however, after the first DMA transaction the script is stuck on the line, because the interrupt subroutine is not called and the flags are not set:

while (!TxDone && !RxDone && !Error)

Here's how the interrupt is setup:

static int SetupIntrSystem(INTC * IntcInstancePtr,
			   XAxiDma * AxiDmaPtr, u16 TxIntrId, u16 RxIntrId)
{
	int Status;

#ifdef XPAR_INTC_0_DEVICE_ID

	/* Initialize the interrupt controller and connect the ISRs */
	Status = XIntc_Initialize(IntcInstancePtr, INTC_DEVICE_ID);
	if (Status != XST_SUCCESS) {

		xil_printf("Failed init intc\r\n");
		return XST_FAILURE;
	}

	Status = XIntc_Connect(IntcInstancePtr, TxIntrId,
			       (XInterruptHandler) TxIntrHandler, AxiDmaPtr);
	if (Status != XST_SUCCESS) {

		xil_printf("Failed tx connect intc\r\n");
		return XST_FAILURE;
	}

	Status = XIntc_Connect(IntcInstancePtr, RxIntrId,
			       (XInterruptHandler) RxIntrHandler, AxiDmaPtr);
	if (Status != XST_SUCCESS) {

		xil_printf("Failed rx connect intc\r\n");
		return XST_FAILURE;
	}

	/* Start the interrupt controller */
	Status = XIntc_Start(IntcInstancePtr, XIN_REAL_MODE);
	if (Status != XST_SUCCESS) {

		xil_printf("Failed to start intc\r\n");
		return XST_FAILURE;
	}

	XIntc_Enable(IntcInstancePtr, TxIntrId);
	XIntc_Enable(IntcInstancePtr, RxIntrId);

	/* Enable interrupts from the hardware */

	Xil_ExceptionInit();
	Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
			(Xil_ExceptionHandler)INTC_HANDLER,
			(void *)IntcInstancePtr);

	Xil_ExceptionEnable();

What am I missing there? Since I have an external interrupt controller, the portion of the code with XScuGic routines is grayed-out and not used.

UPDATE:

When the PL raises the interrupt on pl_pl_irq0, I read the the GICP2_IRQ_STATUS (LPD_SLCR) Register bit25 is set high which is the bit0 of IRQ0. So, looks like the processor knows that the interrupts was triggered, but does not call the subroutine to clear it.

Is there a Xilinx working example of Hardware + Software design with a AXI interrupt controller that I could test and compare to my design?

0 Kudos
1 Reply
Highlighted
Adventurer
Adventurer
190 Views
Registered: ‎11-10-2019

Re: PL-PS IRQ0 interrupt signal not detected (irq_handler not executed)

UPDATE 2:
When removing AXI Interrupt controller and connecting DMA interrupt signals to pl_ps_irq0 directly, and having interrupts registered with GIC, the design works as expected. So, the problem is probably with the ExceptionHandler which does not properly register the external interrupt controller handler and does not call the 'XIntc_InterruptHandler'.

UPDATE 3:

When using the GIC and AXI IC the design works. That is, having Xil_ExceptionHandler to call XScuGic_InterruptHandler, which in turn would call XIntc_InterruptHandler. Why cann't I get Xil_ExceptionHandler to call the XIntc_InterruptHandler directly? Why is the need for the middleman?

Please, give me something - I ran out of ideas on what could be possibly wrong!

0 Kudos