ece699 lecture 4 single 64-bit counter/timer • the cascaded counter can work in both generate and...
TRANSCRIPT
Interrupts AXI GPIO and AXI Timer
ECE 699: Lecture 4
Required Reading
• Tutorial 2: Next Steps in Zynq SoC Design The ZYNQ Book Tutorials
• Section 13: Basic I/O ZYBO Reference Manual
LogiCORE IP AXI GPIO Product Specification
LogiCORE IP AXI GPIO v2.0 Product Guide
LogiCORE IP AXI Timer v2.0 Product Guide
• Chapter 7: Interrupts
Zynq-7000 All Programmable SoC – Technical Reference Manual
Recommended Reading
• Chapter 10.4: Interrupts The ZYNQ Book
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
btns
leds
DDR FIXED_IO
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
btns
leds
DDR FIXED_IO
Block Design for Class Exercise 2
Block Diagram of AXI GPIO
IPIC – IP Interconnect interface
enabled only when the C_INTERRUPT_PRESENT generic set to 1
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
IPIC – IP Interconnect interface
enabled only when the C_INTERRUPT_PRESENT generic set to 1
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
##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_Master.xdc (1)
ZYBO General Purpose Input Output (GPIO)
Source: ZYBO Reference Manual
##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]}]
ZYBO_Master.xdc (3)
Interrupts
Block Diagram of AXI GPIO
IPIC – IP Interconnect interface
enabled only when the C_INTERRUPT_PRESENT generic set to 1
Source: LogiCORE IP AXI GPIO: Product Specification
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
AXI Timer
1. Generating delays - imposing a specific delay between two points in the program
label 1
label2
instr1 instr2
instrN
delay
Functions of a Typical Timer (1)
2. Output compare - generating signals with the given timing characteristics
pulse width
single pulse periodical signal
period
Functions of a Typical Timer (2)
3. Input capture - measuring the time between signal edges
start stop start stop
Functions of a Typical Timer (3)
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
#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 (1)
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 (2)
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 (3)
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 (4)
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 (5)
// 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 (6)
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; }
C Program (7)
Class Exercise 2:
Modifying a Counter Using AXI Timer
(every N ms)
#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 (1)
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 (2)
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 (3A)
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 (3B)
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 (4A)
// Initialize interrupt controller status = IntcInitFunction(INTC_DEVICE_ID, &BTNInst); if(status != XST_SUCCESS) return XST_FAILURE; while(1); return 0; }
C Program (4C)
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 (5)
// 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 (6A)
// 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 (6B)
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; }
C Program (7)
Board Support Package
Hardware Platform Specification (1)
Hardware Platform Specification (2)
Hardware Platform Specification (3)