Showing results for 
Show  only  | Search instead for 
Did you mean: 

More About MicroZed Interrupts: Adam Taylor’s MicroZed Chronicles Part 13

Xilinx Employee
Xilinx Employee
0 8 334K

By Adam Taylor


Having looked at interrupts and the different interrupt types available on the Zynq All Programmable SoC in my previous post (MicroZed Interrupts: Adam Taylor’s MicroZed Chronicles Part 12), this blog post focuses on using a Shared Peripheral Interrupt GPIO interrupt.


To implement this interrupt structure correctly, we will need to write two functions:



  • Interrupt service routine (ISR) – defines the actions that occur when the interrupt occurs.
  • Interrupt Set Up – Configures the interrupts. This routine sets up and enables a GPIO interrupt. It will be generic for all interrupts within the system to aid code reuse.



Thankfully the standalone board support package (BSP) contains a number of functions that greatly ease this task. You’ll find these functions within the following header files:



  • Xparameters.h – defines processor device IDs
  • XGPIOS.h – drivers for GPIO configuration and use
  • Xscugic.h – drivers for GIC (General Interrupt Controller) configuration and use
  • Xil_exception.h – exception functions for the ARM Cortex-A9 processor



Just as before, when we wrote code to communicate with the Zynq SoC’s XADC (MicroZed XADC Software: Adam Taylor’s MicroZed Chronicles Part 8), we need to know the hardware ID parameters for the on-chip devices we wish to use. For this example, those devices are the GIC and GPIO. These parameters are provided mostly within the BSP header file xparameters.h with the exception of the interrupt ID, which is provided by xparameters_ps.h. There is no need to declare this header file within your source code; it is included by the xparameters.h file.







To set up the interrupt, we need two static global variables and the interrupt ID defined above


static XScuGic Intc;        // Interrupt Controller Driver

static XGpioPs Gpio;     //GPIO Device


To set up the interrupts, we initialize the exceptions, configure and initialize the GIC, and then connect the GIC to the interrupt handling hardware. The functions needed to do this are provided within the Xil_exception.h and Xscugic.h files.


When it comes to configuring the GPIO to function as an interrupt source, we can configure either an entire I/O bank or an individual pin using functions provided within xgpiops.h. For example:



void XGpioPs_IntrEnable(XGpioPs *InstancePtr, u8 Bank, u32 Mask);


void XGpioPs_IntrEnablePin(XGpioPs *InstancePtr, int Pin);



We also need to configure the interrupt correctly: edge triggered or level triggered and which edge or level? We configure the interrupt using this function:



void XGpioPs_SetIntrTypePin(XGpioPs *InstancePtr, int Pin, u8 IrqType);



Where the IrqType is defined by one of the five definitions within the xgpiops.h file:



#define XGPIOPS_IRQ_TYPE_EDGE_RISING 0      /**< Interrupt on Rising edge */

#define XGPIOPS_IRQ_TYPE_EDGE_FALLING 1   /**< Interrupt Falling edge */

#define XGPIOPS_IRQ_TYPE_EDGE_BOTH 2        /**< Interrupt on both edges */

#define XGPIOPS_IRQ_TYPE_LEVEL_HIGH 3        /**< Interrupt on high level */

#define XGPIOPS_IRQ_TYPE_LEVEL_LOW 4         /**< Interrupt on low level */


Note that we can configure edge-triggered interrupts to be either rising- or falling-edge interrupts or we can have the interrupt trigger on both rising and falling edges.


If you decide to enable an entire I/O bank, you’ll need to know which bank is associated with the pin or pins you wish to use for interrupts. The Zynq SoC supports a maximum of 118 GPIO pins. For the configuration in this example, all of the MIO (54 pins) are being used as GPIO along with the EMIO (64 pins), broken into four banks with each bank containing 32 pins.


The interrupt set-up function will also define the ISR, which will be called when an interrupt occurs. We use this function:



XGpioPs_SetCallbackHandler(Gpio, (void *)Gpio, IntrHandler);



Having written the interrupt set-up code, our next step will be to write the actual ISR that will be called when an interrupt occurs. An ISR can be as simple or as complicated as the application requires. For this example, the ISR will perform the same task as in the previous polled I/O example: it will toggle the status of the led on and off each time the button is pressed. The ISR will also print out to the console a message when it is run.


Note: Code for a suitably modified version of helloworld.c that uses interrupts is attached to this blog. The original helloworld.c code using polled I/O appeared in: MicroZed XADC Software: Adam Taylor’s MicroZed Chronicles Part 8




Please see the previous entries in this MicroZed series by Adam Taylor:


MicroZed Interrupts: Adam Taylor’s MicroZed Chronicles Part 12


Using the MicroZed Button for Input: Adam Taylor’s MicroZed Chronicles Part 11


Driving the Zynq SoC's GPIO: Adam Taylor’s MicroZed Chronicles Part 10


Meet the Zynq MIO: Adam Taylor’s MicroZed Chronicles Part 9


MicroZed XADC Software: Adam Taylor’s MicroZed Chronicles Part 8


Getting the XADC Running on the MicroZed: Adam Taylor’s MicroZed Chronicles Part 7


A Boot Loader for MicroZed. Adam Taylor’s MicroZed Chronicles, Part 6 


Figuring out the MicroZed Boot Loader – Adam Taylor’s MicroZed Chronicles, Part 5


Running your programs on the MicroZed – Adam Taylor’s MicroZed Chronicles, Part 4


Zynq and MicroZed say “Hello World”-- Adam Taylor’s MicroZed Chronicles, Part 3


Adam Taylor’s MicroZed Chronicles: Setting the SW Scene


Bringing up the Avnet MicroZed with Vivado




Tags (1)