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: 
226 Views
Registered: ‎04-24-2019

Zynq-7000 Interrupt management - Problem

Hi everyone,
I'm trying to build a simple system on the Digilent Zybo board which lights up a LED when the Switch below is turned on. I want to do this by calling an interrupt service routine on the Zynq processor after a 0-1 event on one of the switches.
This is the hardware design that I realized by using Vivado 2018.3 :
design_Zynq_LedSwt_page-0001.jpgHardware designSchermata del 2019-04-24 20-50-26.pngEnabling Interrupts from PL to PS
I'm using the SPI (Shared Peripheral Interrupts) to transmit the edge-triggered interrupt to the GIC. (I've already enabled this interface by editing the Zynq configuration).
Also, this is the program that I've written in SDK:

#include <stdio.h>
#include <stdlib.h>
#include "xil_io.h"
#include "xil_exception.h"
#include "xparameters.h"
#include "xil_cache.h"
#include "xil_printf.h"
#include "xil_types.h"
#include "xscugic.h"

#define GIC_ID XPAR_SCUGIC_0_DEVICE_ID
#define DEV_ID XPAR_FABRIC_MYLEDSWITCH_0_IRQ_INTR

#define LED_SWITCH_BASEADDR 0x43C00000
#define CNT_LED    0
#define STS_SWT    1
#define STS_LED    2
#define LED_SWITCH_INTRADDR 0x43C10000
#define INT_GLB_EN 0
#define INT_LOC_EN 1
#define INT_ACK    3

int init_GIC_Driver(XScuGic *GicDriver,u16 Gic_ID);
int setupInterruptSystem(XScuGic *GicDriver,u32 Device_ID,Xil_InterruptHandler ServiceRoutine);
void LedSwitchHandler(void* CallbackRef);

static int counter = 0;

int main(void)
{
	XScuGic GicDriver;
	unsigned int* LedSwitch_Intr_ptr = (unsigned int*)LED_SWITCH_INTRADDR;

	if(init_GIC_Driver(&GicDriver,GIC_ID)!=XST_SUCCESS)
		return XST_FAILURE;

	XScuGic_SetPriorityTriggerType(&GicDriver,DEV_ID,8,0b11);
	XScuGic_InterruptMaptoCpu(&GicDriver,0,DEV_ID);

	if(setupInterruptSystem(&GicDriver,DEV_ID,LedSwitchHandler)!=XST_SUCCESS)
		return XST_FAILURE;

	LedSwitch_Intr_ptr[INT_GLB_EN] = 0x1;
	LedSwitch_Intr_ptr[INT_LOC_EN] = 0xF;

	while(counter<4);

	return 0;
}

int init_GIC_Driver(XScuGic *GicDriver,u16 Gic_ID)
{
	int status = 0;

	if(GicDriver == NULL)
		return XST_FAILURE;

	GicDriver->Config = XScuGic_LookupConfig(Gic_ID);
	if(GicDriver->Config == NULL)
		return XST_FAILURE;

	status = XScuGic_CfgInitialize(GicDriver,GicDriver->Config,
			GicDriver->Config->CpuBaseAddress);
	if(status != XST_SUCCESS)
		return XST_FAILURE;

	status = XScuGic_SelfTest(GicDriver);
	if(status != XST_SUCCESS)
		return XST_FAILURE;

	return XST_SUCCESS;
}

int setupInterruptSystem(XScuGic *GicDriver,u32 Device_ID,Xil_InterruptHandler ServiceRoutine)
{
	int status = 0;

	Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,(Xil_ExceptionHandler) XScuGic_InterruptHandler,
				GicDriver);
	Xil_ExceptionEnable();

	status = XScuGic_Connect(GicDriver,Device_ID,ServiceRoutine,(void*)GicDriver);
	if(status != XST_SUCCESS)
		return XST_FAILURE;

	XScuGic_Enable(GicDriver,Device_ID);

	return XST_SUCCESS;
}

void LedSwitchHandler(void* CallbackRef)
{
	unsigned int* LedSwitch_ptr = (unsigned int*)LED_SWITCH_BASEADDR;
	unsigned int* LedSwitch_Intr_ptr = (unsigned int*)LED_SWITCH_INTRADDR;

	LedSwitch_ptr[CNT_LED] = LedSwitch_ptr[STS_SWT];
	LedSwitch_Intr_ptr[INT_ACK] = LedSwitch_ptr[STS_LED];

	counter++;
}


When I try to execute the code above I face the following problem:
after the routine was executed for the first time the program doesn't return to the interrupted main but it starts another execution of the interrupt service routine and so on forever until I turned off the switch.
It is like the sensitivity of the interrupt is on the level of the switch signal instead of the edge.

Thanks :)

Tags (1)
0 Kudos
5 Replies
Observer ryandunn19
Observer
216 Views
Registered: ‎06-05-2018

Re: Zynq-7000 Interrupt management - Problem

"It is like the sensitivity of the interrupt is on the level of the switch signal instead of the edge."

You are right. The SPI's can be high-level active or rising-edge sensitive (refer to ug585 section 7.2.3). The configuration is determined by the ICDICFR3 register (ug585 pages 1495-1497). The reset value is 0x55555555, which means that bits 27:26 (for ID 61) are 01, meaning high-level active. 

0 Kudos
196 Views
Registered: ‎04-24-2019

Re: Zynq-7000 Interrupt management - Problem

You are definitely right but I I have already configured that by using this function :

XScuGic_SetPriorityTriggerType(&GicDriver,DEV_ID,8,0b11);

As the scugic manual said, the third and the fourth argument specify the priority and the sensitivity of the interrupt. 

Also, 0b11 is the trigger value needed for rising-edge sensitivity.

0 Kudos
Observer ryandunn19
Observer
191 Views
Registered: ‎06-05-2018

Re: Zynq-7000 Interrupt management - Problem

Ah, I didn't notice that. My apologies. Have you tried reading from the ICDICFR3 register (0xF8F01C0C) afterwards to verify that it is being set correctly?

0 Kudos
177 Views
Registered: ‎04-24-2019

Re: Zynq-7000 Interrupt management - Problem

I will try. Thank you!

0 Kudos
Highlighted
154 Views
Registered: ‎04-24-2019

Re: Zynq-7000 Interrupt management - Problem

After the function the register ICDICFR3 holds the value 0x5d555555 which is correct.

0 Kudos