cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
edoardo.cerini
Visitor
Visitor
2,666 Views
Registered: ‎05-08-2015

GIC multiple interrupt handling

Jump to solution

Hello everybody

 

I'm trying to deal with the General Interrup Controller, having 2 different interrupts coming from S2MM of AXI DMA, and from an interrupt signal coming from my custom IP (a counter generating an interrupt after counting up to 63, and sending the count data throught AXI stream to DMA, which in turns transfers data to DDR3 of my zc702)

 

What I expect is the GIC will serve my DONE_INTR interrupt (doing a simple action of xil_printf "transcritpion done") and then I expect the GIC will serve the S2MM_INTROUT after the DMA finishes transferring data to DDR ( the routine does some easy tasks like printf, see code below).

 

What happens is the interrupt S2MM_INTROUT is arriving after but too close to DONE_INTR from my IP (See picture below).

And my GIC is able to serve just one interrupt: or S2MM_INTROUT or DONT_INTR, but not both, skipping always one of them, and I don´t know why..

I want to stress that I´m able to serve individually both of them, but or one or the other one (I mean both routines are working fine), but I´m not able to serve both routines in the same programming sequence.

 

ila_introut.jpg

 

I noticed if I set

XScuGic_SetPriorityTriggerType(&INTCInst, XPAR_FABRIC_AXI_DMA_0_S2MM_INTROUT_INTR, 0xA0, 0x3);
XScuGic_SetPriorityTriggerType(&INTCInst, XPAR_FABRIC_AXI_STREAM_COUNTER_0_DONE_INTR_INTR, 0xA0, 0x3);

just the S2MM_INTROUT_INTR  will be served (and the DONE_INTR  gets lost)

 

while if I change the priority of 

XScuGic_SetPriorityTriggerType(&INTCInst, XPAR_FABRIC_AXI_STREAM_COUNTER_0_DONE_INTR_INTR, 0x00, 0x3);

then DONE_INTR will be served and the S2MM_INTROUT_INTR  will get lost.

 

Why am I not able to serve both of them? where is the error in the programming sequence?

 

I attached my code here:

 

 

#include <stdio.h>
#include "platform.h"
#include "xil_printf.h"
#include "ps7_init.h"
#include <xil_io.h>
#include "xscugic.h"
#include "xparameters.h"
#include "xaxidma.h"
//#include "xgpio.h"


XScuGic INTCInst;
static XScuGic_Config *IntcConfig;
u32 global_frame_counter = 0;
static u32 baseDDR= 0x100000;

void InterruptHandlerS2MM ( void ){
	u32 tmpValue;
	tmpValue = Xil_In32 (XPAR_AXI_DMA_0_BASEADDR+0x30);
	xil_printf ( "current value of dmaCR.rs: %d \n\r", tmpValue);

	u32 tmpValue1;
	tmpValue1 = Xil_In32 (XPAR_AXI_DMA_0_BASEADDR+0x34);
	xil_printf ( "current value of dmaSR: %d \n\r", tmpValue1);
	tmpValue1 = tmpValue1 | 0x1000; // Reset interrupt
	Xil_Out32(XPAR_AXI_DMA_0_BASEADDR+0x34, tmpValue1); //write in the SR register
	tmpValue1 = Xil_In32 (XPAR_AXI_DMA_0_BASEADDR+0x34);
	xil_printf ( "current value of dmaSR: %d \n\r", tmpValue1);

	global_frame_counter++;
	if (global_frame_counter >10){
		xil_printf ( "more than 10 interrupts! : %d \n\r", global_frame_counter);
		return;
	}

	xil_printf("-- interrupt s2mm arrived --\r\n");
	xil_printf ( "interupt number : %d \n\r", global_frame_counter);
	xil_printf("-- press any key to continue --\r\n");
	getchar();
}


void InterruptHandlerStreamCounter ( void ){
	XScuGic_Disable(&INTCInst, XPAR_FABRIC_AXI_STREAM_COUNTER_0_DONE_INTR_INTR);

	xil_printf("-- transaction finished --\r\n");

	// Set Start value to 1
	Xil_Out32(XPAR_AXI_GPIO_1_BASEADDR, 0x1 );

	XScuGic_Enable(&INTCInst, XPAR_FABRIC_AXI_STREAM_COUNTER_0_DONE_INTR_INTR);

}
int InterruptSystemSetup(XScuGic *XScuGicInstancePtr)
{
	Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
			(Xil_ExceptionHandler) XScuGic_InterruptHandler,
			XScuGicInstancePtr);

	// Enable interrupts in the ARM
	Xil_ExceptionEnable();

	return XST_SUCCESS;

}

int IntcInitFunction(u16 DeviceId){

	int status;
	///////////////////////////////////////////////////////////////////////
	//initialize the interrupt controller driver so that it is ready to use

IntcConfig = XScuGic_LookupConfig(DeviceId); if ( NULL == IntcConfig ) { return XST_FAILURE; } // Initialise the GIC using the config information status = XScuGic_CfgInitialize(&INTCInst, IntcConfig, IntcConfig->CpuBaseAddress); if (status != XST_SUCCESS){ return XST_FAILURE; } ////////////////////////////////////////// // Setup the Interrupt SysteM // Call to interrupt setup status = InterruptSystemSetup(&INTCInst); if (status != XST_SUCCESS) return XST_FAILURE; XScuGic_SetPriorityTriggerType(&INTCInst, XPAR_FABRIC_AXI_DMA_0_S2MM_INTROUT_INTR, 0xA0, 0x3); XScuGic_SetPriorityTriggerType(&INTCInst, XPAR_FABRIC_AXI_STREAM_COUNTER_0_DONE_INTR_INTR, 0xA0, 0x3); ////////////////////////////////////////// //connect here the different interrupts status = XScuGic_Connect(&INTCInst, XPAR_FABRIC_AXI_DMA_0_S2MM_INTROUT_INTR, (Xil_ExceptionHandler) InterruptHandlerS2MM, NULL); if (status != XST_SUCCESS){ return XST_FAILURE; } status = XScuGic_Connect(&INTCInst, XPAR_FABRIC_AXI_STREAM_COUNTER_0_DONE_INTR_INTR, (Xil_ExceptionHandler) InterruptHandlerStreamCounter, NULL); if (status != XST_SUCCESS){ return XST_FAILURE; }

// Enable interrupts in the controller XScuGic_Enable(&INTCInst, XPAR_FABRIC_AXI_DMA_0_S2MM_INTROUT_INTR); XScuGic_Enable(&INTCInst, XPAR_FABRIC_AXI_STREAM_COUNTER_0_DONE_INTR_INTR); return XST_SUCCESS; } int main() { //int Status; init_platform(); u32 tmpValue; //enable the pl ps7_post_config(); xil_printf("\r\n--- Entering main() --- \r\n"); xil_printf("initializing axi dma ... \n\r"); int status; status = IntcInitFunction(XPAR_PS7_SCUGIC_0_DEVICE_ID); if (status != XST_SUCCESS) return XST_FAILURE; //disable the cache, check later why Xil_DCacheDisable(); // Set MaxCounter Gpio direction to outputs Xil_Out32(XPAR_AXI_GPIO_0_BASEADDR+0x04, 0x00000000 ); // Set Start Gpio direction to outputs Xil_Out32(XPAR_AXI_GPIO_1_BASEADDR+0x04, 0x00000000 ); // Set MaxCounter value Xil_Out32(XPAR_AXI_GPIO_0_BASEADDR, 0x0000003F ); // Set Start value to 1 Xil_Out32(XPAR_AXI_GPIO_1_BASEADDR, 0x1 ); // Set Start value to 0 Xil_Out32(XPAR_AXI_GPIO_1_BASEADDR, 0x0 ); // set up for S2MM tmpValue=Xil_In32 (XPAR_AXI_DMA_0_BASEADDR+0x30); //DMA S2MM_DMACR.RS=1; tmpValue=tmpValue|0x01; Xil_Out32 (XPAR_AXI_DMA_0_BASEADDR+0x30, tmpValue); tmpValue=Xil_In32 (XPAR_AXI_DMA_0_BASEADDR+0x30); tmpValue=tmpValue & ~(0x00005000); // disable interrupt Xil_Out32 (XPAR_AXI_DMA_0_BASEADDR+0x30, tmpValue); tmpValue=Xil_In32 (XPAR_AXI_DMA_0_BASEADDR+0x30); tmpValue=tmpValue|0x5000; // enable interrupt Xil_Out32 (XPAR_AXI_DMA_0_BASEADDR+0x30, tmpValue); //initialize writing channel //writing the address from wich we want to write in the 0x00 +48h register Xil_Out32(XPAR_AXI_DMA_0_BASEADDR+0x48, baseDDR); //writing the length in the 0x00 +58h register 4 bytes Xil_Out32(XPAR_AXI_DMA_0_BASEADDR+0x58, 256); sleep(5); return 0; }

Thanks in advance

 

Edoardo

 

Tags (3)
1 Solution

Accepted Solutions
edoardo.cerini
Visitor
Visitor
3,195 Views
Registered: ‎05-08-2015

the problem was another one.

I was writing in this location: 

baseDDR= 0x100000

so I was overwriting the info about the .elf file loaded on the dd3 and everything was blocked. I thought the program was finished but actually it was interrupted.

 

thanks anyway!

View solution in original post

0 Kudos
2 Replies
ericv
Scholar
Scholar
2,638 Views
Registered: ‎04-13-2015

@edoardo.cerini

 

is the GIC set-up to use edge trigger on these 2 interrupt sources?

If not it is level sensitive.

With level, if the 2nd interrupt signal goes down before the end of the 1st interrupt you'll lose that 2nd interrupt request. 

0 Kudos
edoardo.cerini
Visitor
Visitor
3,196 Views
Registered: ‎05-08-2015

the problem was another one.

I was writing in this location: 

baseDDR= 0x100000

so I was overwriting the info about the .elf file loaded on the dd3 and everything was blocked. I thought the program was finished but actually it was interrupted.

 

thanks anyway!

View solution in original post

0 Kudos