You are on page 1of 82

ECE 699: Lecture 4

Interrupts
AXI GPIO and AXI Timer
Required Reading
The ZYNQ Book Tutorials
Tutorial 2: Next Steps in Zynq SoC Design
ZYBO Reference Manual
Section 13: Basic I/O
LogiCORE IP AXI GPIO Product Specification
LogiCORE IP AXI GPIO v2.0 Product Guide
LogiCORE IP AXI Timer v2.0 Product Guide
Zynq-7000 All Programmable SoC
Technical Reference Manual
Chapter 7: Interrupts
Recommended Reading
The ZYNQ Book
Chapter 10.4: Interrupts

ARM Generic Interrupt Controller Architecture


Specification

Chapter 1: Introduction
Chapter 2: GIC Partitioning
Chapter 3: Interrupt Handling and Prioritization
Chapter 4: Programmers Model
ZYBO Board

Source: ZYBO Reference Manual


ZYBO Board Components

Source: ZYBO Reference Manual


Class Exercise 1:

Modifying a Counter Using


Pushbuttons
Class Exercise 2:

Modifying a Counter Using


AXI Timer
(every N ms)
ZYBO General Purpose Input Output (GPIO)

Source: ZYBO Reference Manual


AXI GPIO Core
Connected to Buttons
AXI Timer Core
Implemented in Programmable Logic
Mapping of an Embedded SoC
Hardware Architecture to Zynq

Source: Xilinx White Paper: Extensible Processing Platform


A Simplified Model of the Zynq Architecture

Source: The Zynq Book


Block Design for Class Exercise 1

btns

leds

DDR
FIXED_IO
Block Design for Class Exercise 1

btns

leds

DDR
FIXED_IO
Block Design for Class Exercise 2

leds

btns

DDR
FIXED_IO
Block Design for Class Exercise 2

leds

btns

DDR
FIXED_IO
Block Diagram of AXI GPIO

enabled only when the


C_INTERRUPT_PRESENT
generic set to 1

IPIC IP Interconnect interface

Source: LogiCORE IP AXI GPIO: Product Specification


Setting GPIO Core Parameters in Vivado

4
GPIO
Core

Source: LogiCORE IP AXI GPIO: Product Specification


Block Diagram of AXI GPIO

enabled only when the


C_INTERRUPT_PRESENT
generic set to 1

IPIC IP Interconnect interface

Source: LogiCORE IP AXI GPIO: Product Specification


AXI Interconnects and Interfaces

Source: The Zynq Book


Constraints File
entity design_int_wrapper is
port (
DDR_addr : inout STD_LOGIC_VECTOR ( 14 downto 0 );
DDR_ba : inout STD_LOGIC_VECTOR ( 2 downto 0 );
DDR_cas_n : inout STD_LOGIC;
DDR_ck_n : inout STD_LOGIC;
DDR_ck_p : inout STD_LOGIC;
DDR_cke : inout STD_LOGIC;
DDR_cs_n : inout STD_LOGIC;
DDR_dm : inout STD_LOGIC_VECTOR ( 3 downto 0 );
DDR_dq : inout STD_LOGIC_VECTOR ( 31 downto 0 );
DDR_dqs_n : inout STD_LOGIC_VECTOR ( 3 downto 0 );
DDR_dqs_p : inout STD_LOGIC_VECTOR ( 3 downto 0 );
DDR_odt : inout STD_LOGIC;
DDR_ras_n : inout STD_LOGIC;
DDR_reset_n : inout STD_LOGIC;
DDR_we_n : inout STD_LOGIC;
FIXED_IO_ddr_vrn : inout STD_LOGIC;
FIXED_IO_ddr_vrp : inout STD_LOGIC;
FIXED_IO_mio : inout STD_LOGIC_VECTOR ( 53 downto 0 );
FIXED_IO_ps_clk : inout STD_LOGIC;
FIXED_IO_ps_porb : inout STD_LOGIC;
FIXED_IO_ps_srstb : inout STD_LOGIC;
leds_tri_o : out STD_LOGIC_VECTOR ( 3 downto 0 );
btns_tri_i : in STD_LOGIC_VECTOR ( 3 downto 0 )
);
end design_int_wrapper;
design_1_i: component design_1
port map (
DDR_addr(14 downto 0) => DDR_addr(14 downto 0),
DDR_ba(2 downto 0) => DDR_ba(2 downto 0),
DDR_cas_n => DDR_cas_n,
DDR_ck_n => DDR_ck_n,
DDR_ck_p => DDR_ck_p,
DDR_cke => DDR_cke,
DDR_cs_n => DDR_cs_n,
DDR_dm(3 downto 0) => DDR_dm(3 downto 0),
DDR_dq(31 downto 0) => DDR_dq(31 downto 0),
DDR_dqs_n(3 downto 0) => DDR_dqs_n(3 downto 0),
DDR_dqs_p(3 downto 0) => DDR_dqs_p(3 downto 0),
DDR_odt => DDR_odt,
DDR_ras_n => DDR_ras_n,
DDR_reset_n => DDR_reset_n,
DDR_we_n => DDR_we_n,
FIXED_IO_ddr_vrn => FIXED_IO_ddr_vrn,
FIXED_IO_ddr_vrp => FIXED_IO_ddr_vrp,
FIXED_IO_mio(53 downto 0) => FIXED_IO_mio(53 downto 0),
FIXED_IO_ps_clk => FIXED_IO_ps_clk,
FIXED_IO_ps_porb => FIXED_IO_ps_porb,
FIXED_IO_ps_srstb => FIXED_IO_ps_srstb,
leds_tri_o(3 downto 0) => leds_tri_o(3 downto 0),
btns_tri_o(3 downto 0) => btns_tri_i(3 downto 0)
);
ZYBO General Purpose Input Output (GPIO)

Source: ZYBO Reference Manual


ZYBO_Master.xdc (1)

##LEDs
##IO_L23P_T3_35
set_property PACKAGE_PIN M14 [get_ports {leds_tri_o[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {leds_tri_o[0]}]

##IO_L23N_T3_35
set_property PACKAGE_PIN M15 [get_ports {leds_tri_o[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {leds_tri_o[1]}]

##IO_0_35
set_property PACKAGE_PIN G14 [get_ports {leds_tri_o[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {leds_tri_o[2]}]

##IO_L3N_T0_DQS_AD1N_35
set_property PACKAGE_PIN D18 [get_ports {leds_tri_o[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {leds_tri_o[3]}]
ZYBO General Purpose Input Output (GPIO)

Source: ZYBO Reference Manual


ZYBO_Master.xdc (3)

##Buttons
##IO_L20N_T3_34
set_property PACKAGE_PIN R18 [get_ports {btn_tri_i[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {btn_tri_i[0]}]

##IO_L24N_T3_34
set_property PACKAGE_PIN P16 [get_ports {btn_tri_i[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {btn_tri_i[1]}]

##IO_L18P_T2_34
set_property PACKAGE_PIN V16 [get_ports {btn_tri_i[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {btn_tri_i[2]}]

##IO_L7P_T1_34
set_property PACKAGE_PIN Y16 [get_ports {btn_tri_i[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {btn_tri_i[3]}]
Interrupts
Block Diagram of AXI GPIO

enabled only when the


C_INTERRUPT_PRESENT
generic set to 1

IPIC IP Interconnect interface

Source: LogiCORE IP AXI GPIO: Product Specification


Global Interrupt Enable, GIER

Source: LogiCORE IP AXI GPIO: Product Specification


Interrupt Enable Registers, IP IER

Source: LogiCORE IP AXI GPIO: Product Specification


Interrupt Status Registers, IP ISR

Status
Status

Source: LogiCORE IP AXI GPIO: Product Specification


Addresses of Interrupt-Related
AXI GPIO Registers

Source: LogiCORE IP AXI GPIO: Product Specification


AXI GPIO Resource Utilization and
Maximum Clock Frequency

Source: LogiCORE IP AXI GPIO: Product Specification


AXI Timer
Functions of a Typical Timer (1)

1. Generating delays - imposing a specific delay


between two points in the program

label 1 instr1
instr2
delay
label2 instrN
Functions of a Typical Timer (2)

2. Output compare - generating signals with the given


timing characteristics
single pulse periodical signal

pulse width period


Functions of a Typical Timer (3)

3. Input capture - measuring the time between signal


edges

start stop
start stop
Block Diagram of AXI Timer

Source: LogiCORE IP AXI Timer: Product Guide


AXI Timer: Modes of Operation

Generate Mode
Capture Mode
Pulse Width Modulation Mode
Cascade Mode
Generate Mode
Counter when enabled begins to count up or down
On transition of carry out, the counter
stops, or
automatically reloads the initial value from the load register,
and continues counting
if enabled, GenerateOut is driven to 1 for one clock cycle
if enabled, the interrupt signal for the timer is driven to 1

Can be used to
Generate repetitive interrupts
One-time pulses
Periodical signals
Capture Mode
The counter can be configured as an up or down counter
The value of the counter is stored in the load register when
the external capture signal is asserted
The TINT flag is also set on detection of the capture event
The Auto Reload/Hold (ARHT) bit controls whether the
capture value is overwritten with a new capture value
before the previous TINT flag is cleared

Can be used to measure


Widths of non-periodical signals
Periods of periodical signals
Intervals between edges of two different signals, etc.
Pulse Width Modulation (PWM) Mode

Two timer/counters are used as a pair to produce an output


signal (PWM0) with a specified frequency and duty factor
Timer 0 sets the period
Timer 1 sets the high time for the PWM0 output

Can be used to generate


Periodical signals with varying period and duty cycle
Cascade Mode

Two timer/counters are cascaded to operate as


a single 64-bit counter/timer
The cascaded counter can work in both generate
and capture modes
TCSR0 acts as the control and status register for the
cascaded counter. TCSR1 is ignored in this mode.

Can be used to
Generate longer delays
Generate signals with larger pulse widths or periods
Measure longer time intervals
Timer/Counter Register, TCR0, TCR1

Source: LogiCORE IP AXI Timer: Product Guide


Load Register, TLR0, TLR1
Control/Status Registers, TCSR0

Source: LogiCORE IP AXI Timer: Product Guide


Control/Status Register 0, TCSR0
Control/Status Registers, TCSR0
Control/Status Register 0, TCSR0
Control/Status Registers, TCSR0

Source: LogiCORE IP AXI Timer: Product Guide


Control/Status Register 0, TCSR0

Source: LogiCORE IP AXI Timer: Product Guide


Control/Status Registers, TCSR0

Source: LogiCORE IP AXI Timer: Product Guide


Control/Status Register 0, TCSR0

Source: LogiCORE IP AXI Timer: Product Guide


Configuration of Zynq Processing System
in Vivado
Configuration of Zynq Processing System
in Vivado
System-Level Interrupt Environment

Source: Zynq-7000 All Programmable SoC Technical Reference Manual


Class Exercise 1:

Modifying a Counter Using


Pushbuttons
C Program (1)

#include "xparameters.h"
#include "xgpio.h"
#include "xscugic.h"
#include "xil_exception.h"
#include "xil_printf.h"

// Parameter definitions
#define INTC_DEVICE_ID XPAR_PS7_SCUGIC_0_DEVICE_ID
#define BTNS_DEVICE_ID XPAR_AXI_GPIO_0_DEVICE_ID
#define LEDS_DEVICE_ID XPAR_AXI_GPIO_1_DEVICE_ID
#define INTC_GPIO_INTERRUPT_ID
XPAR_FABRIC_AXI_GPIO_0_IP2INTC_IRPT_INTR

#define BTN_INT XGPIO_IR_CH1_MASK


C Program (2)

XGpio LEDInst, BTNInst;


XScuGic INTCInst;
static int led_data;
static int btn_value;

//----------------------------------------------------
// PROTOTYPE FUNCTIONS
//----------------------------------------------------
static void BTN_Intr_Handler(void *InstancePtr);
static int InterruptSystemSetup(XScuGic *XScuGicInstancePtr);
static int IntcInitFunction(u16 DeviceId, XGpio *GpioInstancePtr);
C Program (3)
void BTN_Intr_Handler(void *InstancePtr)
{
// Disable GPIO interrupts
XGpio_InterruptDisable(&BTNInst, BTN_INT);
// Ignore additional button presses
if ((XGpio_InterruptGetStatus(&BTNInst) & BTN_INT) !=BTN_INT) {
return;
}
btn_value = XGpio_DiscreteRead(&BTNInst, 1);
// Increment counter based on button value
// Reset if center button pressed
if(btn_value != 8)
led_data = led_data + btn_value;
else
led_data = 0;
XGpio_DiscreteWrite(&LEDInst, 1, led_data);
(void) XGpio_InterruptClear(&BTNInst, BTN_INT);
// Enable GPIO interrupts
XGpio_InterruptEnable(&BTNInst, BTN_INT);
}
C Program (4)
int main (void)
{
int status;
// Initialise LEDs
status = XGpio_Initialize(&LEDInst, LEDS_DEVICE_ID);
if(status != XST_SUCCESS) return XST_FAILURE;
// Initialize Push Buttons
status = XGpio_Initialize(&BTNInst, BTNS_DEVICE_ID);
if(status != XST_SUCCESS) return XST_FAILURE;
// Set LEDs direction to outputs
XGpio_SetDataDirection(&LEDInst, 1, 0x00);
// Set all buttons direction to inputs
XGpio_SetDataDirection(&BTNInst, 1, 0xFF);

// Initialize interrupt controller


status = IntcInitFunction(INTC_DEVICE_ID, &BTNInst);
if(status != XST_SUCCESS) return XST_FAILURE;
while(1);
return 0;
}
C Program (5)

int IntcInitFunction(u16 DeviceId, XGpio *GpioInstancePtr)


{
XScuGic_Config *IntcConfig;
int status;

// Interrupt controller initialization


IntcConfig = XScuGic_LookupConfig(DeviceId);
status = XScuGic_CfgInitialize(&INTCInst, IntcConfig,
IntcConfig->CpuBaseAddress);
if(status != XST_SUCCESS) return XST_FAILURE;

// Call to interrupt setup


status = InterruptSystemSetup(&INTCInst);
if(status != XST_SUCCESS) return XST_FAILURE;
C Program (6)

// Connect GPIO interrupt to handler


status = XScuGic_Connect(&INTCInst, INTC_GPIO_INTERRUPT_ID,
(Xil_ExceptionHandler) BTN_Intr_Handler,
(void *)GpioInstancePtr);

if(status != XST_SUCCESS) return XST_FAILURE;

// Enable GPIO interrupts interrupt


XGpio_InterruptEnable(GpioInstancePtr, 1);
XGpio_InterruptGlobalEnable(GpioInstancePtr);

// Enable GPIO interrupts in the controller


XScuGic_Enable(&INTCInst, INTC_GPIO_INTERRUPT_ID);

return XST_SUCCESS;
}
C Program (7)

int InterruptSystemSetup(XScuGic *XScuGicInstancePtr)


{
// Enable interrupt
XGpio_InterruptEnable(&BTNInst, BTN_INT);
XGpio_InterruptGlobalEnable(&BTNInst);

Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
(Xil_ExceptionHandler) XScuGic_InterruptHandler,
XScuGicInstancePtr);

Xil_ExceptionEnable();

return XST_SUCCESS;

}
Class Exercise 2:

Modifying a Counter Using


AXI Timer
(every N ms)
C Program (1)
#include "xparameters.h"
#include "xgpio.h"
#include "xtmrctr.h"
#include "xscugic.h"
#include "xil_exception.h"
#include "xil_printf.h"

// Parameter definitions
#define INTC_DEVICE_ID XPAR_PS7_SCUGIC_0_DEVICE_ID
#define TMR_DEVICE_ID XPAR_TMRCTR_0_DEVICE_ID
#define BTNS_DEVICE_ID XPAR_AXI_GPIO_0_DEVICE_ID
#define LEDS_DEVICE_ID XPAR_AXI_GPIO_1_DEVICE_ID
#define INTC_GPIO_INTERRUPT_ID
XPAR_FABRIC_AXI_GPIO_0_IP2INTC_IRPT_INTR
#define INTC_TMR_INTERRUPT_ID
XPAR_FABRIC_AXI_TIMER_0_INTERRUPT_INTR

#define BTN_INT XGPIO_IR_CH1_MASK


#define TMR_LOAD 0xF8000000
C Program (2)
XGpio LEDInst, BTNInst;
XScuGic INTCInst;
XTmrCtr TMRInst;
static int led_data;
static int btn_value;
static int tmr_count;

//----------------------------------------------------
// PROTOTYPE FUNCTIONS
//----------------------------------------------------
static void BTN_Intr_Handler(void *InstancePtr);
static void TMR_Intr_Handler(void *InstancePtr);
static int InterruptSystemSetup(XScuGic *XScuGicInstancePtr);
static int IntcInitFunction(u16 DeviceId, XTmrCtr *TmrInstancePtr, XGpio
*GpioInstancePtr);
C Program (3A)
void BTN_Intr_Handler(void *InstancePtr)
{
// Disable GPIO interrupts
XGpio_InterruptDisable(&BTNInst, BTN_INT);
// Ignore additional button presses
if ((XGpio_InterruptGetStatus(&BTNInst) & BTN_INT) !=BTN_INT) {
return;
}
btn_value = XGpio_DiscreteRead(&BTNInst, 1);
// Increment counter based on button value
// Reset if center button pressed
if(btn_value != 8)
led_data = led_data + btn_value;
else
led_data = 0;
XGpio_DiscreteWrite(&LEDInst, 1, led_data);
(void) XGpio_InterruptClear(&BTNInst, BTN_INT);
// Enable GPIO interrupts
XGpio_InterruptEnable(&BTNInst, BTN_INT);
}
C Program (3B)
void TMR_Intr_Handler(void *InstancePtr)
{
if (XTmrCtr_IsExpired(&TMRInst, 0)){
// Once timer has expired 3 times, stop, increment counter
// reset timer and start running again
if(tmr_count == 3){
XTmrCtr_Stop(&TMRInst, 0);
tmr_count = 0;
led_data++;
XGpio_DiscreteWrite(&LEDInst, 1, led_data);
XTmrCtr_Reset(&TMRInst, 0);
XTmrCtr_Start(&TMRInst, 0);

}
else tmr_count++;
}
}
C Program (4A)
int main (void)
{
int status;
// Initialise LEDs
status = XGpio_Initialize(&LEDInst, LEDS_DEVICE_ID);
if(status != XST_SUCCESS) return XST_FAILURE;
// Initialize Push Buttons
status = XGpio_Initialize(&BTNInst, BTNS_DEVICE_ID);
if(status != XST_SUCCESS) return XST_FAILURE;
// Set LEDs direction to outputs
XGpio_SetDataDirection(&LEDInst, 1, 0x00);
// Set all buttons direction to inputs
XGpio_SetDataDirection(&BTNInst, 1, 0xFF);
C Program (4A)

//----------------------------------------------------
// SETUP THE TIMER
//----------------------------------------------------
status = XTmrCtr_Initialize(&TMRInst, TMR_DEVICE_ID);
if(status != XST_SUCCESS)
return XST_FAILURE;
XTmrCtr_SetHandler(&TMRInst, TMR_Intr_Handler, &TMRInst);
XTmrCtr_SetResetValue(&TMRInst, 0, TMR_LOAD);
XTmrCtr_SetOptions(&TMRInst, 0,
XTC_INT_MODE_OPTION | XTC_AUTO_RELOAD_OPTION);
C Program (4C)
// Initialize interrupt controller
status = IntcInitFunction(INTC_DEVICE_ID, &BTNInst);
if(status != XST_SUCCESS) return XST_FAILURE;
while(1);
return 0;
}
C Program (5)

int IntcInitFunction(u16 DeviceId, XTmrCtr *TmrInstancePtr,


XGpio *GpioInstancePtr)
{
XScuGic_Config *IntcConfig;
int status;

// Interrupt controller initialization


IntcConfig = XScuGic_LookupConfig(DeviceId);
status = XScuGic_CfgInitialize(&INTCInst, IntcConfig,
IntcConfig->CpuBaseAddress);
if(status != XST_SUCCESS) return XST_FAILURE;

// Call to interrupt setup


status = InterruptSystemSetup(&INTCInst);
if(status != XST_SUCCESS) return XST_FAILURE;
C Program (6A)

// Connect GPIO interrupt to handler


status = XScuGic_Connect(&INTCInst, INTC_GPIO_INTERRUPT_ID,
(Xil_ExceptionHandler) BTN_Intr_Handler,
(void *)GpioInstancePtr);

if(status != XST_SUCCESS) return XST_FAILURE;

// Connect timer interrupt to handler


status = XScuGic_Connect(&INTCInst, INTC_TMR_INTERRUPT_ID,
(Xil_ExceptionHandler)TMR_Intr_Handler,
(void *)TmrInstancePtr);

if(status != XST_SUCCESS) return XST_FAILURE;


C Program (6B)

// Enable GPIO interrupts interrupt


XGpio_InterruptEnable(GpioInstancePtr, 1);
XGpio_InterruptGlobalEnable(GpioInstancePtr);

// Enable GPIO and timer interrupts in the controller


XScuGic_Enable(&INTCInst, INTC_GPIO_INTERRUPT_ID);

XScuGic_Enable(&INTCInst, INTC_TMR_INTERRUPT_ID);

return XST_SUCCESS;
}
C Program (7)

int InterruptSystemSetup(XScuGic *XScuGicInstancePtr)


{
// Enable interrupt
XGpio_InterruptEnable(&BTNInst, BTN_INT);
XGpio_InterruptGlobalEnable(&BTNInst);

Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
(Xil_ExceptionHandler) XScuGic_InterruptHandler,
XScuGicInstancePtr);

Xil_ExceptionEnable();

return XST_SUCCESS;

}
Board Support Package
Hardware Platform
Specification (1)
Hardware Platform
Specification (2)
Hardware Platform
Specification (3)