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
Modifying a Counter Using Class Exercise 1: Modifying a Counter Using Pushbuttons
Modifying a Counter Using 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
Implemented in Programmable Logic 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 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) 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
Modifying a Counter Using 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); // 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); 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);
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; }
Modifying a Counter Using 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); // 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);
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);
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)