From e703803892afa95756e5d65100f0f281c949d618 Mon Sep 17 00:00:00 2001 From: Shubhrajyoti Datta Date: Tue, 30 Jun 2015 11:35:31 +0530 Subject: [PATCH] intc: Create a new version v3.4 This patch creates a new v3.4 of intc driver and deprecates older v3.3. Signed-off-by: Shubhrajyoti Datta --- .../drivers/intc/data/intc.mdd | 73 ++ .../drivers/intc/data/intc.tcl | 685 +++++++++++ .../drivers/intc/data/intc_header.h | 42 + .../drivers/intc/data/intc_tapp.tcl | 206 ++++ .../drivers/intc/examples/index.html | 19 + .../drivers/intc/examples/xintc_example.c | 348 ++++++ .../intc/examples/xintc_low_level_example.c | 302 +++++ .../intc/examples/xintc_tapp_example.c | 250 ++++ .../drivers/intc/src/Makefile | 28 + XilinxProcessorIPLib/drivers/intc/src/xintc.c | 1078 +++++++++++++++++ XilinxProcessorIPLib/drivers/intc/src/xintc.h | 366 ++++++ .../drivers/intc/src/xintc_g.c | 112 ++ .../drivers/intc/src/xintc_i.h | 90 ++ .../drivers/intc/src/xintc_intr.c | 173 +++ .../drivers/intc/src/xintc_l.c | 662 ++++++++++ .../drivers/intc/src/xintc_l.h | 327 +++++ .../drivers/intc/src/xintc_options.c | 146 +++ .../drivers/intc/src/xintc_selftest.c | 252 ++++ 18 files changed, 5159 insertions(+) create mode 100755 XilinxProcessorIPLib/drivers/intc/data/intc.mdd create mode 100755 XilinxProcessorIPLib/drivers/intc/data/intc.tcl create mode 100644 XilinxProcessorIPLib/drivers/intc/data/intc_header.h create mode 100755 XilinxProcessorIPLib/drivers/intc/data/intc_tapp.tcl create mode 100755 XilinxProcessorIPLib/drivers/intc/examples/index.html create mode 100644 XilinxProcessorIPLib/drivers/intc/examples/xintc_example.c create mode 100644 XilinxProcessorIPLib/drivers/intc/examples/xintc_low_level_example.c create mode 100644 XilinxProcessorIPLib/drivers/intc/examples/xintc_tapp_example.c create mode 100644 XilinxProcessorIPLib/drivers/intc/src/Makefile create mode 100644 XilinxProcessorIPLib/drivers/intc/src/xintc.c create mode 100644 XilinxProcessorIPLib/drivers/intc/src/xintc.h create mode 100644 XilinxProcessorIPLib/drivers/intc/src/xintc_g.c create mode 100644 XilinxProcessorIPLib/drivers/intc/src/xintc_i.h create mode 100644 XilinxProcessorIPLib/drivers/intc/src/xintc_intr.c create mode 100644 XilinxProcessorIPLib/drivers/intc/src/xintc_l.c create mode 100644 XilinxProcessorIPLib/drivers/intc/src/xintc_l.h create mode 100644 XilinxProcessorIPLib/drivers/intc/src/xintc_options.c create mode 100644 XilinxProcessorIPLib/drivers/intc/src/xintc_selftest.c diff --git a/XilinxProcessorIPLib/drivers/intc/data/intc.mdd b/XilinxProcessorIPLib/drivers/intc/data/intc.mdd new file mode 100755 index 00000000..03183441 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/intc/data/intc.mdd @@ -0,0 +1,73 @@ +############################################################################### +# +# Copyright (C) 2005 - 2014 Xilinx, Inc. All rights reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# Use of the Software is limited solely to applications: +# (a) running on a Xilinx device, or +# (b) that interact with a Xilinx device through a bus or interconnect. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +# OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# +# Except as contained in this notice, the name of the Xilinx shall not be used +# in advertising or otherwise to promote the sale, use or other dealings in +# this Software without prior written authorization from Xilinx. +# +# MODIFICATION HISTORY: +# +# Ver Who Date Changes +# -------- ------ -------- -------------------------------------------------- +# 3.0 adk 10/12/13 Removed support for dcr_intc intc_core xps_intc +############################################################################## + +## @BEGIN_CHANGELOG EDK_M +## +## 11/18/09 ktn Removed support for opb_intc +## +## @END_CHANGELOG + +## @BEGIN_CHANGELOG EDK_MS3 +## +## 06/16/10 sv Added support for axi_intc +## +## @END_CHANGELOG + + +OPTION psf_version = 2.1; + +BEGIN driver intc + +OPTION DRC = intc_drc; +OPTION supported_peripherals = (axi_intc); +OPTION driver_state = ACTIVE; +OPTION copyfiles = all; +OPTION VERSION = 3.4; +OPTION NAME = intc; +OPTION INTC_TYPE = XIntc; + +BEGIN ARRAY interrupt_handler +PROPERTY desc = "Interrupt Handler"; +PROPERTY size = 1, permit = none; +PROPERTY state = deprecated; +PARAM name = int_handler, default = XIntc_DeviceInterruptHandler, desc = "Interrupt Handler", type = string; +PARAM name = int_port, default = Irq, desc = "Interrupt pin associated with the interrupt handler", permit=none; +PARAM name = int_handler_arg, desc = "Argument type to Handler function", type = enum, values= ("Use baseaddress"=C_BASEADDR, "Use device id"=DEVICE_ID), default = DEVICE_ID ; +END ARRAY + + +END driver diff --git a/XilinxProcessorIPLib/drivers/intc/data/intc.tcl b/XilinxProcessorIPLib/drivers/intc/data/intc.tcl new file mode 100755 index 00000000..3f5c5ad0 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/intc/data/intc.tcl @@ -0,0 +1,685 @@ +############################################################################### +# +# Copyright (C) 2005 - 2014 Xilinx, Inc. All rights reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# Use of the Software is limited solely to applications: +# (a) running on a Xilinx device, or +# (b) that interact with a Xilinx device through a bus or interconnect. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +# OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# +# Except as contained in this notice, the name of the Xilinx shall not be used +# in advertising or otherwise to promote the sale, use or other dealings in +# this Software without prior written authorization from Xilinx. +# +# MODIFICATION HISTORY: +# Ver Who Date Changes +# -------- ------ -------- ------------------------------------ +# 3.0 adk 12/10/13 Updated as per the New Tcl API's +############################################################################## + +## @BEGIN_CHANGELOG +## +## 09/17/07 ecm Removed the PCI specific connections +## Moved to the Linux MLD. +## 10/24/07 rpm Fixed KIND_OF_INTR bug in canonicals and +## also generalized match on external interrupts +## 06/25/09 sdm Updated so that canonical definitions are +## not generated when instance name matches +## canonical name +## 04/27/10 sdm Updated the tcl so that the defintions are generated in +## the xparameters.h to know whether the optional registers +## SIE, CIE and IVR are enabled in the HW - Refer CR 555392 +## 05/24/11 hvm updated tcl to generate vector ids for external interrupts +## CR565336 +## 06/15/11 hvm Updated tcl with bypassing the external interrupt definition +## in xredefine_intc function. CR613925. +## 01/19/12 Updated the intc_define_use_dcr function so that it doesnot +## error out if there is more than one bus interface to the +## intc controller. The new common::version of the AXI_INTC can have two +## bus interfaces to support the fast interrupt for MicroBlaze. +## Updated for the generation of the C_HAS_FAST xparameters +## 08/16/12 bss added generation of C_IVAR_RESET_VALUE xparameters +## +## 01/29/13 bss Added check_cascade and get_intctype to support +## Cascade mode. Modified intc_define_vector_table procedure +## to generate interrupt IDs as 32..63 and 64..95 and so on +## for Slave controllers in Cascade mode +## 01/22/14 bss Modified check_cascade to fix CR#764865 +## 17/02/14 adk Fixed the CR:771287 in intc_define_vector_table +## if number of interrupt ports not equal to total numer of +## interrupts returning immediatly.And in the xredefine_intc +## if there is not interrupt source returining immediately. +## 4/8/14 bss Modified xredefine_intc to handle external interrupt pins +## correctly (CR#799609). +## 11/3/14 adk added generation of C_HAS_ILR parameter to xparameters.h +## (CR#828046). +## +## +## +## @END_CHANGELOG + +############################################################ +# Global interrupt handlers array, default handler routine +############################################################ +array set interrupt_handlers "" +set default_interrupt_handler "XNullHandler" +set cascade 0 +set intrid 0 + +array set source_port_name "" +array set source_name "" +array set source_port_type "" +array set source_driver "" +array set source_interrupt_handler "" +array set source_interrupt_id "" +set total_source_intrs 0 + +############################################################ +# DRC procedure +############################################################ +proc intc_drc {drv_handle} { + +} + + +############################################################ +# "generate" procedure +############################################################ +proc generate {drv_handle} { + + # Generate the following definitions in xparameters.h + # 2. BASEADDR, HIGHADDR, C_NUM_INTR_INPUTS, XPAR_INTC_MAX_NUM_INTR_INPUTS + + set periphs [::hsi::utils::get_common_driver_ips $drv_handle] + set count [llength $periphs] + variable cascade + + if {$count > 1} { + set cascade [check_cascade $drv_handle] + } + + if {$cascade == 0} { + ::hsi::utils::define_max $drv_handle "xparameters.h" "XPAR_INTC_MAX_NUM_INTR_INPUTS" "C_NUM_INTR_INPUTS" + } else { + set maxintrs 0 + foreach periph $periphs { + set intrs [common::get_property CONFIG.C_NUM_INTR_INPUTS $periph] + set maxintrs [expr "$maxintrs + $intrs"] + } + set file_handle [::hsi::utils::open_include_file "xparameters.h"] + puts $file_handle "#define XPAR_INTC_MAX_NUM_INTR_INPUTS $maxintrs" + close $file_handle + } + + foreach periph $periphs { + set fast [::hsi::utils::get_param_value $periph "C_HAS_FAST"] + set nested [::hsi::utils::get_param_value $periph "C_HAS_ILR"] + if {$fast == 1 && $nested == 1} { + puts "ERROR: Internal error: Interrupt Controller Driver has no support for nesting fast interrupts" + } + if {$cascade == 1 && $nested == 1} { + puts "ERROR: Internal error: Interrupt Controller Driver has no support for nesting interrupts in Cascaded mode" + } + } + + ::hsi::utils::define_if_all $drv_handle "xparameters.h" "XIntc" "C_HAS_IPR" "C_HAS_SIE" "C_HAS_CIE" "C_HAS_IVR" "C_HAS_ILR" + ::hsi::utils::define_include_file $drv_handle "xparameters.h" "XIntc" "NUM_INSTANCES" "DEVICE_ID" "C_BASEADDR" "C_HIGHADDR" "C_KIND_OF_INTR" "C_HAS_FAST" "C_IVAR_RESET_VALUE" "C_NUM_INTR_INPUTS" + + + # Define XPAR_SINGLE_DEVICE_ID + + if {$count == 1} { + ::hsi::utils::define_with_names $drv_handle [::hsi::utils::get_common_driver_ips $drv_handle] "xparameters.h" "XPAR_INTC_SINGLE_BASEADDR" "C_BASEADDR" "XPAR_INTC_SINGLE_HIGHADDR" "C_HIGHADDR" "XPAR_INTC_SINGLE_DEVICE_ID" "DEVICE_ID" + } + + + set config_inc [::hsi::utils::open_include_file "xparameters.h"] + + # Generate config table, vector tables + intc_define_config_file $drv_handle $periphs $config_inc + + close $config_inc + + # Generate canonical xparameters + xdefine_canonical_xpars $drv_handle "xparameters.h" "Intc" "DEVICE_ID" "C_BASEADDR" "C_HIGHADDR" "C_KIND_OF_INTR" "C_HAS_FAST" "C_IVAR_RESET_VALUE" "C_NUM_INTR_INPUTS" +} + + +########################################################################## +# Generate Configuration C file xintc_g.c +# This file has the Config Table and vector tables for each intc instance +# as required by Xilinx intc driver +########################################################################## + +proc intc_define_config_file {drv_handle periphs config_inc} { + + variable interrupt_handlers + variable default_interrupt_handler + variable cascade + + # set isr_options to be XIN_SVC_SGL_ISR_OPTION as defined in xintc.h + set isr_options XIN_SVC_SGL_ISR_OPTION + set file_name "xintc_g.c" + set drv_string "XIntc" + set args [list "DEVICE_ID" "C_BASEADDR" "C_KIND_OF_INTR" "C_HAS_FAST" "C_IVAR_RESET_VALUE" "C_NUM_INTR_INPUTS"] + set filename [file join "src" $file_name] + file delete $filename + set config_file [open $filename w] + ::hsi::utils::write_c_header $config_file "Driver configuration" + puts $config_file "#include \"xparameters.h\"" + puts $config_file "#include \"[string tolower $drv_string].h\"" + puts $config_file "\n" + + set tmp_filename [file join "src" "tmpconfig.c"] + set tmp_config_file [open $tmp_filename w] + + puts $tmp_config_file "\n/*" + puts $tmp_config_file "* The configuration table for devices" + puts $tmp_config_file "*/\n" + puts $tmp_config_file [format "%s_Config %s_ConfigTable\[\] =" $drv_string $drv_string] + puts $tmp_config_file "\{" + + set start_comma "" + foreach periph $periphs { + set periph_name [string toupper [get_property NAME $periph ]] + set xpar_periph_name [::hsi::utils::format_xparam_name $periph_name] + + if {$cascade == 1} { + puts $config_inc [format "#define XPAR_%s_%s %d" [string toupper [common::get_property NAME $periph ]] "TYPE" [get_intctype $periph]] + } else { + puts $config_inc [format "#define XPAR_%s_%s %d" [string toupper [common::get_property NAME $periph ]] "TYPE" $cascade] + } + puts $tmp_config_file [format "%s\t\{" $start_comma] + set comma "" + foreach arg $args { + # Check if this is a driver parameter or a peripheral parameter + set value [common::get_property CONFIG.$arg $drv_handle ] + if {[llength $value] == 0} { + puts -nonewline $tmp_config_file [format "%s\t\t%s" $comma [::hsi::utils::get_ip_param_name $periph $arg]] + } else { + puts -nonewline $tmp_config_file [format "%s\t\t%s" $comma [::hsi::utils::get_driver_param_name $drv_string $arg]] + } + set comma ",\n" + } + # add the OPTIONS as an arg to the config table - default OPTIONS value is XIN_SVC_SGL_ISR_OPTION + puts -nonewline $tmp_config_file [format "%s\t\t%s" $comma $isr_options] + puts -nonewline $tmp_config_file ",\n\t\t" + puts -nonewline $tmp_config_file [format "XPAR_%s_%s" [string toupper [common::get_property NAME $periph]] "TYPE"] + + # generate the vector table for this intc instance + intc_define_vector_table $periph $config_inc $tmp_config_file + + puts $config_inc "\n/******************************************************************/\n" + + puts -nonewline $tmp_config_file "\n\t\}" + set start_comma ",\n" + } + puts $tmp_config_file "\n\};" + close $tmp_config_file + + # Write out the extern definitions of handlers... + foreach elem [array names interrupt_handlers] { + puts $config_file [format "extern void %s (void *);" $elem ] + } + + # copy over the tmp_config_file contents to config_file + set tmp_config_file [open $tmp_filename r] + while {![eof $tmp_config_file]} { + gets $tmp_config_file line + puts $config_file $line + } + close $tmp_config_file + file delete -force $tmp_filename + + close $config_file + } + +proc intc_define_vector_table {periph config_inc config_file} { + + variable interrupt_handlers + variable default_interrupt_handler + variable cascade + variable source_port_name + variable source_name + variable source_port_type + variable source_driver + variable source_interrupt_handler + variable source_interrupt_id + variable total_source_intrs + + #update global array of Interrupt sources for this periph + intc_update_source_array $periph + + set periph_name [common::get_property NAME $periph] + set interrupt_pin [hsi::get_pins -of_objects $periph intr] + + # Get pins/ports that are driving the interrupt + lappend source_pins + set source_pins [::hsi::utils::get_source_pins $interrupt_pin] + + set num_intr_inputs [common::get_property CONFIG.C_NUM_INTR_INPUTS $periph] + #calculate the total interrupt sources + + set total_intr_ports [::hsi::utils::get_connected_pin_count $interrupt_pin] + + if {$num_intr_inputs != $total_intr_ports} { + puts "ERROR: Internal error: Num intr inputs $num_intr_inputs not the same as length of ::hsi::utils::get_interrupt_sources [llength $source_pins] hsi_error" + return + } + + #Check if default_interrupt_handler has to have an extern definition + if {[array size interrupt_handlers] < $total_source_intrs } { + intc_add_handler $default_interrupt_handler + } + + puts -nonewline $config_file ",\n\t\t\{" + set comma "\n" + + for {set i 0} {$i < $total_source_intrs} {incr i} { + puts $config_file [format "%s\t\t\t\{" $comma ] + puts $config_file [format "\t\t\t\t%s," $source_interrupt_handler($i) ] + if {[llength $source_name($i)] == 0} { + puts $config_file "\t\t\t\t(void *)XNULL" + } else { + set sname [string toupper $source_name($i)] + set source_xparam_name [::hsi::utils::format_xparam_name $sname] + set pname [string toupper $periph_name] + set periph_xparam_name [::hsi::utils::format_xparam_name $pname] + puts $config_inc [format "#define XPAR_%s_%s_MASK %#08X" $source_xparam_name [string toupper $source_port_name($i)] [expr 1 << $i]] + if {$cascade ==1} { + puts $config_inc [format "#define XPAR_%s_%s_%s_INTR %d" [string toupper $periph_name] [string toupper $source_name($i)] [string toupper $source_port_name($i)] $source_interrupt_id($i)] + } else { + puts $config_inc [format "#define XPAR_%s_%s_%s_INTR %d" [string toupper $periph_name] [string toupper $source_name($i)] [string toupper $source_port_name($i)] $i] + } + if {[string compare -nocase "global" $source_port_type($i) ] != 0 && \ + [string compare $source_interrupt_handler($i) $default_interrupt_handler ] != 0} { + puts $config_file [format "\t\t\t\t(void *) %s" $source_handler_arg($i)] + } else { + puts $config_file "\t\t\t\t(void *) XNULL" + } + } + puts -nonewline $config_file "\t\t\t\}" + set comma ",\n" + } + puts $config_file "\n\t\t\}" +} + +################################################ +# This procedure creates a unique list of +# handlers that needs to have an extern defn. +# in xparameters.h +################################################ +proc intc_add_handler {handler} { + + variable interrupt_handlers + + set interrupt_handlers($handler) 1 +} + + +# +# Given a list of arguments, define each as a canonical constant name, using +# the driver name, in an include file. +# +proc xdefine_canonical_xpars {drv_handle file_name drv_string args} { + + variable cascade + + # Open include file + set file_handle [::hsi::utils::open_include_file $file_name] + + # Get all the peripherals connected to this driver + set periphs [::hsi::utils::get_common_driver_ips $drv_handle] + + # Get the names of all the peripherals connected to this driver + foreach periph $periphs { + set peripheral_name [string toupper [common::get_property NAME $periph]] + lappend peripherals $peripheral_name + } + + # Get possible canonical names for all the peripherals connected to this driver + set device_id 0 + foreach periph $periphs { + set canonical_name [string toupper [format "%s_%s" $drv_string $device_id]] + lappend canonicals $canonical_name + + # Create a list of IDs of the peripherals whose hardware instance name + # doesn't match the canonical name. These IDs can be used later to + # generate canonical definitions + if { [lsearch $peripherals $canonical_name] < 0 } { + lappend indices $device_id + } + incr device_id + } + + set i 0 + foreach periph $periphs { + set periph_name [string toupper [common::get_property NAME $periph]] + + # Generate canonical definitions only for the peripherals whose + # canonical name is not the same as hardware instance name + if { [lsearch $canonicals $periph_name] < 0 } { + puts $file_handle "/* Canonical definitions for peripheral $periph_name */" + set canonical_name [format "%s_%s" $drv_string [lindex $indices $i]] + + foreach arg $args { + set lvalue [::hsi::utils::get_driver_param_name $canonical_name $arg] + + # The commented out rvalue is the name of the instance-specific constant + # set rvalue [::hsi::utils::get_ip_param_name $periph $arg] + + # The rvalue set below is the actual value of the parameter + set rvalue [::hsi::utils::get_param_value $periph $arg] + if {[llength $rvalue] == 0} { + set rvalue 0 + } + set rvalue [::hsi::utils::format_addr_string $rvalue $arg] + + puts $file_handle "#define $lvalue $rvalue" + + } + if {$cascade == 1} { + puts $file_handle "#define [::hsi::utils::get_driver_param_name $canonical_name "INTC_TYPE"] [get_intctype $periph]" + } else { + puts $file_handle "#define [::hsi::utils::get_driver_param_name $canonical_name "INTC_TYPE"] $cascade" + } + puts $file_handle "" + incr i + } + } + + # + # Now redefine the Interrupt ID constants + # + xredefine_intc $drv_handle $file_handle + + puts $file_handle "\n/******************************************************************/\n" + close $file_handle +} + +################################################ +# +# intc redefines +# +################################################ +proc xredefine_intc {drvhandle config_inc} { + variable source_port_name + variable source_name + variable source_port_type + variable source_driver + variable source_interrupt_handler + variable source_interrupt_id + variable total_source_intrs + + + # Next define interrupt IDs for each connected peripheral + + set periphs [::hsi::utils::get_common_driver_ips $drvhandle] + set device_id 0 + set periph_name [string toupper "intc"] + + foreach periph $periphs { + #update global array of Interrupt sources for this periph + intc_update_source_array $periph + + lappend source_list + for {set j 0 } { $j < $total_source_intrs } { incr j} { + lappend source_list $source_name($j) + } + + + # Get the edk based name of peripheral for printing redefines + set periph_ip_name [common::get_property NAME $periph] + + set num_intr_inputs [common::get_property CONFIG.C_NUM_INTR_INPUTS $periph] + for {set i 0} {$i < $num_intr_inputs} {incr i} { + + if {[string compare -nocase $source_name($i) "system"] == 0} { + continue + } + set drv [hsi::get_drivers -filter "HW_INSTANCE==$source_name($i)"] + + if {[llength $source_name($i)] != 0 && [llength $drv] != 0} { + + set instance [xfind_instance $drv $source_name($i)] + set drvname [common::get_property NAME $drv] + + # + # Handle reference cores, which have non-reference driver names + # + if {[string compare -nocase $drvname "touchscreen_ref"] == 0} { + set drvname "touchscreen" + } elseif {[string compare -nocase $drvname "ps2_ref"] == 0} { + set drvname "ps2" + set instance [expr $instance*2] + if {[string match -nocase "*SYS_INTR2" $source_port_name($i)] == 1} { + incr instance + } + } + + # + # Define the interrupt vector IDs in xparameters.h for each core + # that is connected to this intc. + # + set drvname [string toupper $drvname] + + # + # Treat sources with multiple interrupt ports slightly different + # by including the interrupt port name in the canonical constant + # name + # + if { [lcount $source_list $source_name($i)] > 1} { + set port_name [string toupper $source_port_name($i)] + + # + # If there are multiple interrupt ports for axi_ethernet, do not include + # the port name in the canonical name, for the port "INTERRUPT". Other ports + # will have the port name in the canonical name. This is to make sure that + # the canonical name for the port INTERRUPT will remain same irrespective of + # whether the design has a single interrupt port or multiple interrupt ports + # + if {[string compare -nocase $drvname "axiethernet"] == 0} { + if {[string compare -nocase $port_name "INTERRUPT"] == 0} { + set first_part [format "#define XPAR_%s_%s_%s_%s_VEC_ID" $periph_name $device_id $drvname $instance] + } else { + set first_part [format "#define XPAR_%s_%s_%s_%s_%s_VEC_ID" $periph_name $device_id $drvname $instance $port_name] + } + } else { + set first_part [format "#define XPAR_%s_%s_%s_%s_%s_VEC_ID" $periph_name $device_id $drvname $instance $port_name] + } + } else { + set first_part [format "#define XPAR_%s_%s_%s_%s_VEC_ID" $periph_name $device_id $drvname $instance] + } + set second_part [format "XPAR_%s_%s_%s_INTR" [string toupper $periph_ip_name] [string toupper $source_name($i)] [string toupper $source_port_name($i)] ] + + if {[string compare -nocase $drvname "generic"] != 0} { + set first_part_xparam_name [::hsi::utils::format_xparam_name $first_part] + set second_part_xparam_name [::hsi::utils::format_xparam_name $second_part] + puts $config_inc "$first_part_xparam_name $second_part_xparam_name" + } + } + } + incr device_id + } +} + +################################################################### +# +# Get the number of elements in the given list that match the +# given entry. Assume elements are strings. +# +################################################################### +proc lcount {list match_entry} { + + set len [llength $list] + set count 0 + + for {set i 0} {$i < $len} {incr i} { + set entry [lindex $list $i] + if { [string compare -nocase $entry $match_entry] == 0} { + incr count + } + } + + return $count +} + + +################################################################### +# +# Get the HW instance number for a particular device. This will be used to enumerate +# the vector ID defines if more than one interrupt from the core is connected to the +# interrupt controller. +# +################################################################### +proc xfind_instance {drvhandle instname} { + + set instlist [::hsi::utils::get_common_driver_ips $drvhandle] + set i 0 + foreach inst $instlist { + set name [common::get_property NAME $inst] + if {[string compare -nocase $instname $name] == 0} { + return $i + } + incr i + } + set i 0 + return $i +} + +################################################################################### +# +# Checks whether system has Cascade interrupt controllers +# +################################################################################### +proc check_cascade {drv_handle} { + set periphs [::hsi::utils::get_common_driver_ips $drv_handle] + foreach periph $periphs { + set i 0 + set source_pins [::hsi::utils::get_interrupt_sources $periph] + foreach source_pin $source_pins { + set source_pin_name($i) [common::get_property NAME $source_pin] + if { [::hsi::utils::is_external_pin $source_pin] } { + continue + } + set source_periph [hsi::get_cells -of_objects $source_pin ] + set source_type [common::get_property IP_TYPE $source_periph] + if {[string compare -nocase $source_type "INTERRUPT_CNTLR"] == 0} { + return 1 + } + } + } + return 0 +} + +################################################################## +# +# Returns Interrupt controller type +# 1 - primary instance +# 2 - secondary instance +# 3 - last instance +# +################################################################## + +proc get_intctype {periph} { + set iscascade [::hsi::utils::get_param_value $periph "C_EN_CASCADE_MODE"] + set ismaster [::hsi::utils::get_param_value $periph "C_CASCADE_MASTER"] + if {$iscascade == 1 && $ismaster == 1} { + set retval 1 + } elseif {$iscascade == 1 && $ismaster == 0} { + set retval 2 + } elseif {$iscascade == 0 && $ismaster == 0} { + set retval 3 + } else { + error "ERROR: The C_CASCADE_MASTER is allowed to set only when the C_EN_CASCADE_MODE is set to 1" + } + + return $retval +} + +############################################################################### +# this proc traverse all the interrupt source of peripheral and create a array +# will the the details +############################################################################### +proc intc_update_source_array {periph} { + variable default_interrupt_handler + variable source_port_name + variable source_name + variable source_port_type + variable source_driver + variable source_interrupt_handler + variable source_interrupt_id + variable total_source_intrs + + array unset source_port_name + array unset source_name + array unset source_port_type + array unset source_driver + array unset source_interrupt_handler + array unset source_interrupt_id + + lappend source_pins + set source_pins [::hsi::utils::get_interrupt_sources $periph] + puts "source_pins = $source_pins of intc = $periph" + set intr_cnt 0 + foreach source_pin $source_pins { + #default value as per external processor + set t_source_port_name [common::get_property NAME $source_pin] + set t_source_name "system" + set t_ip_name "" + set t_port_type "global" + set t_source_driver "" + set t_source_interrupt_handler $default_interrupt_handler + set t_source_intrrupt_id "-1" + + #if interrupt is coming from IP, update it. + if { [::hsi::utils::is_external_pin $source_pin] == 0} { + set source_periph [hsi::get_cells -of_objects $source_pin] + set t_source_name [common::get_property NAME $source_periph] + set t_ip_name $t_source_name + set t_port_type "local" + set t_source_driver [hsi::get_drivers -filter "HW_INSTANCE==$t_source_name"] + } + set port_intr_id [::hsi::utils::get_interrupt_id $t_ip_name $source_pin] + if { [llength $port_intr_id ] > 1 } { + #this is the case of vector interrupt port + set j 0 + foreach pin_id $port_intr_id { + set source_port_name($intr_cnt) "${t_source_port_name}_$j" + set source_name($intr_cnt) $t_source_name + set source_port_type($intr_cnt) $t_port_type + set source_driver($intr_cnt) $t_source_driver + set source_interrupt_handler($intr_cnt) $t_source_interrupt_handler + set source_interrupt_id($intr_cnt) $pin_id + incr intr_cnt + incr j + } + } else { + set source_port_name($intr_cnt) "${t_source_port_name}" + set source_name($intr_cnt) $t_source_name + set source_port_type($intr_cnt) $t_port_type + set source_driver($intr_cnt) $t_source_driver + set source_interrupt_handler($intr_cnt) $t_source_interrupt_handler + set source_interrupt_id($intr_cnt) $port_intr_id + incr intr_cnt + } + } + set total_source_intrs $intr_cnt +} diff --git a/XilinxProcessorIPLib/drivers/intc/data/intc_header.h b/XilinxProcessorIPLib/drivers/intc/data/intc_header.h new file mode 100644 index 00000000..4a2e393e --- /dev/null +++ b/XilinxProcessorIPLib/drivers/intc/data/intc_header.h @@ -0,0 +1,42 @@ +/****************************************************************************** +* +* Copyright (C) 2012 - 2014 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +#ifndef INTC_HEADER_H /* prevent circular inclusions */ +#define INTC_HEADER_H /* by using protection macros */ + +#include "xil_assert.h" +#include "xil_types.h" +#include "xstatus.h" + +int IntcSelfTestExample(u16 DeviceId); +int IntcInterruptSetup(XIntc *IntcInstancePtr, u16 DeviceId); + +#endif diff --git a/XilinxProcessorIPLib/drivers/intc/data/intc_tapp.tcl b/XilinxProcessorIPLib/drivers/intc/data/intc_tapp.tcl new file mode 100755 index 00000000..5fd38a4d --- /dev/null +++ b/XilinxProcessorIPLib/drivers/intc/data/intc_tapp.tcl @@ -0,0 +1,206 @@ +############################################################################### +# +# Copyright (C) 2004 - 2014 Xilinx, Inc. All rights reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# Use of the Software is limited solely to applications: +# (a) running on a Xilinx device, or +# (b) that interact with a Xilinx device through a bus or interconnect. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +# OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# +# Except as contained in this notice, the name of the Xilinx shall not be used +# in advertising or otherwise to promote the sale, use or other dealings in +# this Software without prior written authorization from Xilinx. +# +# +# MODIFICATION HISTORY: +# Ver Who Date Changes +# -------- ------ -------- ------------------------------------ +# 3.0 adk 12/10/13 Updated as per the New Tcl API's +# 3.1 adk 8/4/14 Fix the CR:783248 Modified the Cascade logic +# in the app tcl +############################################################################## + +## @BEGIN_CHANGELOG EDK_I_SP1 +## +## - Initial Revision +## +## 01/30/13 bss Modified script to skip tests for Slave controllers in Cascade +## mode +## 02/26/13 bss Modified get_intr procedure to support Vivado designs +## +## @END_CHANGELOG + +# Uses $XILINX_EDK/bin/lib/xillib_sw.tcl + +# ----------------------------------------------------------------- +# Software Project Types (swproj): +# 0 : MemoryTest - Calls basic memorytest routines from common driver dir +# 1 : PeripheralTest - Calls any existing polled_example and/or selftest +# ----------------------------------------------------------------- + +# ----------------------------------------------------------------- +# TCL Procedures: +# ----------------------------------------------------------------- + + + + +proc gen_include_files {swproj mhsinst} { + + if {$swproj == 0} { + return "" + } + + if {$swproj == 1} { + set inc_file_lines {xintc.h intc_header.h} + return $inc_file_lines + } +} + +proc gen_src_files {swproj mhsinst} { + if {$swproj == 0} { + return "" + } + if {$swproj == 1} { + set inc_file_lines {examples/xintc_tapp_example.c data/intc_header.h} + return $inc_file_lines + } +} + +proc gen_testfunc_def {swproj mhsinst} { + return "" +} + +proc gen_init_code {swproj mhsinst} { + return "" +} + +proc gen_testfunc_call {swproj mhsinst} { + + if {$swproj == 0} { + return "" + } + +set cascade [check_cascade $mhsinst] +if {$cascade == 1} { + set iscascade [common::get_property CONFIG.C_EN_CASCADE_MODE $mhsinst] + set ismaster [common::get_property CONFIG.C_CASCADE_MASTER $mhsinst] + if {!($iscascade == 1 && $ismaster == 1)} { + return "" + } + } + + set ipname [common::get_property NAME $mhsinst] + set deviceid [::hsi::utils::get_ip_param_name $mhsinst "DEVICE_ID"] + set stdout [common::get_property CONFIG.STDOUT [hsi::get_os]] + if { $stdout == "" || $stdout == "none" } { + set hasStdout 0 + } else { + set hasStdout 1 + } + set intcvar intc + set testfunc_call "" + + if {${hasStdout} == 0} { + + append testfunc_call " + + { + int status; + + status = IntcSelfTestExample(${deviceid}); + + }" + + set ifintr [::hsi::utils::is_ip_interrupting_current_proc $mhsinst] + if {$ifintr != 0} { + append testfunc_call " + + { + int Status; + + Status = IntcInterruptSetup(&${intcvar}, ${deviceid}); + + }" + } + + } else { + + append testfunc_call " + + { + int status; + + print(\"\\r\\n Running IntcSelfTestExample() for ${ipname}...\\r\\n\"); + + status = IntcSelfTestExample(${deviceid}); + + if (status == 0) { + print(\"IntcSelfTestExample PASSED\\r\\n\"); + } + else { + print(\"IntcSelfTestExample FAILED\\r\\n\"); + } + }" + + set ifintr [::hsi::utils::is_ip_interrupting_current_proc $mhsinst] + if {$ifintr != 0} { + + append testfunc_call " + + { + int Status; + + Status = IntcInterruptSetup(&${intcvar}, ${deviceid}); + if (Status == 0) { + print(\"Intc Interrupt Setup PASSED\\r\\n\"); + } + else { + print(\"Intc Interrupt Setup FAILED\\r\\n\"); + } + }" + + } + } + + return $testfunc_call + +} + + +proc check_cascade {mhsinst} { + set periphs [::hsi::utils::get_common_driver_ips $mhsinst] + foreach periph $periphs { + set i 0 + set source_pins [::hsi::utils::get_interrupt_sources $periph] + foreach source_pin $source_pins { + set source_pin_name($i) [common::get_property NAME $source_pin] + if { [::hsi::utils::is_external_pin $source_pin] } { + continue + } + set source_periph [hsi::get_cells -of_objects $source_pin ] + set source_type [common::get_property IP_TYPE $source_periph] + if {[string compare -nocase $source_type "INTERRUPT_CNTLR"] == 0} { + return 1 + } + } + } + return 0 +} diff --git a/XilinxProcessorIPLib/drivers/intc/examples/index.html b/XilinxProcessorIPLib/drivers/intc/examples/index.html new file mode 100755 index 00000000..6b506617 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/intc/examples/index.html @@ -0,0 +1,19 @@ + + + + + +Driver example applications + + + +

Example Applications for the driver intc_v3_2

+
+ +

Copyright � 1995-2014 Xilinx, Inc. All rights reserved.

+ + diff --git a/XilinxProcessorIPLib/drivers/intc/examples/xintc_example.c b/XilinxProcessorIPLib/drivers/intc/examples/xintc_example.c new file mode 100644 index 00000000..db4069e5 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/intc/examples/xintc_example.c @@ -0,0 +1,348 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2014 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/******************************************************************************/ +/** +* +* @file xintc_example.c +* +* This file contains a design example using the Interrupt Controller driver +* (XIntc) and hardware device. Please reference other device driver examples to +* see more examples of how the intc and interrupts can be used by a software +* application. +* +* This example shows the use of the Interrupt Controller both with a PowerPC +* and MicroBlaze processor. +* +* @note +* This example can also be used for Cascade mode interrupt +* controllers by using the interrupt IDs generated in +* xparameters.h. For Cascade mode, Interrupt IDs are generated +* in xparameters.h as shown below: +* +* Master/Primary INTC +* ______ +* | |-0 Secondary INTC +* | |-. ______ +* | |-. | |-32 Last INTC +* | |-. | |-. ______ +* |______|<--31-----| |-. | |-64 +* | |-. | |-. +* |______|<--63------| |-. +* | |-. +* |______|-95 +* +* All driver functions has to be called using +* DeviceId/InstancePtr of Primary/Master Controller only. Driver +* functions takes care of Slave Controllers based on Interrupt +* ID passed. User must not use Interrupt source/ID 31 of Primary +* and Secondary controllers to call driver functions. +* +*
+*
+* MODIFICATION HISTORY:
+* Ver   Who  Date	 Changes
+* ----- ---- -------- ----------------------------------------------------
+* 1.00b jhl  02/13/02 First release
+* 1.00c rpm  11/13/03 Updated to show microblaze and PPC interrupt use and
+*		      to use the common L0/L1 interrupt handler with device ID.
+* 1.00c sv   06/29/05 Minor changes to comply to Doxygen and coding guidelines
+* 2.00a ktn  10/20/09 Updated to use HAL Processor APIs amd minor modifications
+*		      as per coding guidelines.
+* 
+******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xparameters.h" +#include "xstatus.h" +#include "xintc.h" +#include "xil_exception.h" + +/************************** Constant Definitions *****************************/ + +/* + * The following constants map to the XPAR parameters created in the + * xparameters.h file. They are defined here such that a user can easily + * change all the needed parameters in one place. + */ +#define INTC_DEVICE_ID XPAR_INTC_0_DEVICE_ID + +/* + * This is the Interrupt Number of the Device whose Interrupt Output is + * connected to the Input of the Interrupt Controller + */ +#define INTC_DEVICE_INT_ID XPAR_INTC_0_UARTLITE_0_VEC_ID + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + +int IntcExample(u16 DeviceId); + +int SetUpInterruptSystem(XIntc *XIntcInstancePtr); + +void DeviceDriverHandler(void *CallbackRef); + + +/************************** Variable Definitions *****************************/ + +static XIntc InterruptController; /* Instance of the Interrupt Controller */ + +/* + * Create a shared variable to be used by the main thread of processing and + * the interrupt processing + */ +volatile static int InterruptProcessed = FALSE; + +/*****************************************************************************/ +/** +* +* This is the main function for the Interrupt Controller example. +* +* @param None. +* +* @return XST_SUCCESS to indicate success, otherwise XST_FAILURE. +* +* @note None. +* +****************************************************************************/ +int main(void) +{ + int Status; + + /* + * Run the Intc example , specify the Device ID generated in + * xparameters.h + */ + Status = IntcExample(INTC_DEVICE_ID); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + return XST_SUCCESS; + +} + + +/*****************************************************************************/ +/** +* +* This function is an example of how to use the interrupt controller driver +* component (XIntc) and the hardware device. This function is designed to +* work without any hardware devices to cause interrupts. It may not return +* if the interrupt controller is not properly connected to the processor in +* either software or hardware. +* +* This function relies on the fact that the interrupt controller hardware +* has come out of the reset state such that it will allow interrupts to be +* simulated by the software. +* +* @param DeviceId is Device ID of the Interrupt Controller Device, +* typically XPAR__DEVICE_ID value from +* xparameters.h. +* +* @return XST_SUCCESS to indicate success, otherwise XST_FAILURE. +* +* @note None. +* +******************************************************************************/ +int IntcExample(u16 DeviceId) +{ + int Status; + + /* + * Initialize the interrupt controller driver so that it is ready to + * use. + */ + Status = XIntc_Initialize(&InterruptController, DeviceId); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + + /* + * Perform a self-test to ensure that the hardware was built + * correctly. + */ + Status = XIntc_SelfTest(&InterruptController); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + + /* + * Setup the Interrupt System. + */ + Status = SetUpInterruptSystem(&InterruptController); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + + /* + * Simulate the Interrupt. + */ + Status = XIntc_SimulateIntr(&InterruptController, INTC_DEVICE_INT_ID); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + + /* + * Wait for the interrupt to be processed, if the interrupt does not + * occur this loop will wait forever. + */ + while (1) + { + /* + * If the interrupt occurred which is indicated by the global + * variable which is set in the device driver handler, then + * stop waiting. + */ + if (InterruptProcessed) { + break; + } + } + + return XST_SUCCESS; + +} + +/******************************************************************************/ +/** +* +* This function connects the interrupt handler of the interrupt controller to +* the processor. This function is seperate to allow it to be customized for +* each application. Each processor or RTOS may require unique processing to +* connect the interrupt handler. +* +* @param None. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +int SetUpInterruptSystem(XIntc *XIntcInstancePtr) +{ + int Status; + + + /* + * Connect a device driver handler that will be called when an interrupt + * for the device occurs, the device driver handler performs the + * specific interrupt processing for the device. + */ + Status = XIntc_Connect(XIntcInstancePtr, INTC_DEVICE_INT_ID, + (XInterruptHandler)DeviceDriverHandler, + (void *)0); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + + /* + * Start the interrupt controller such that interrupts are enabled for + * all devices that cause interrupts, specify simulation mode so that + * an interrupt can be caused by software rather than a real hardware + * interrupt. + */ + Status = XIntc_Start(XIntcInstancePtr, XIN_SIMULATION_MODE); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + + /* + * Enable the interrupt for the device and then cause (simulate) an + * interrupt so the handlers will be called. + */ + XIntc_Enable(XIntcInstancePtr, INTC_DEVICE_INT_ID); + + /* + * Initialize the exception table. + */ + Xil_ExceptionInit(); + + /* + * Register the interrupt controller handler with the exception table. + */ + Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, + (Xil_ExceptionHandler)XIntc_InterruptHandler, + XIntcInstancePtr); + + /* + * Enable exceptions. + */ + Xil_ExceptionEnable(); + + return XST_SUCCESS; + +} + +/******************************************************************************/ +/** +* +* This function is designed to look like an interrupt handler in a device +* driver. This is typically a 2nd level handler that is called from the +* interrupt controller interrupt handler. This handler would typically +* perform device specific processing such as reading and writing the registers +* of the device to clear the interrupt condition and pass any data to an +* application using the device driver. Many drivers already provide this +* handler and the user is not required to create it. +* +* @param CallbackRef is passed back to the device driver's interrupt +* handler by the XIntc driver. It was given to the XIntc driver +* in the XIntc_Connect() function call. It is typically a pointer +* to the device driver instance variable if using the Xilinx +* Level 1 device drivers. In this example, we do not care about +* the callback reference, so we passed it a 0 when connecting the +* handler to the XIntc driver and we make no use of it here. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void DeviceDriverHandler(void *CallbackRef) +{ + /* + * Indicate the interrupt has been processed using a shared variable. + */ + InterruptProcessed = TRUE; + +} diff --git a/XilinxProcessorIPLib/drivers/intc/examples/xintc_low_level_example.c b/XilinxProcessorIPLib/drivers/intc/examples/xintc_low_level_example.c new file mode 100644 index 00000000..835b1b5a --- /dev/null +++ b/XilinxProcessorIPLib/drivers/intc/examples/xintc_low_level_example.c @@ -0,0 +1,302 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2014 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/******************************************************************************/ +/** +* +* @file xintc_low_level_example.c +* +* This file contains a design example using the low level-0 driver, interface +* of the Interrupt Controller driver. +* +* This example shows the use of the Interrupt Controller both with a PowerPC +* and a MicroBlaze processor. +* +* @note +* This example can also be used for Cascade mode interrupt +* controllers by using the interrupt IDs generated in +* xparameters.h. For Cascade mode, Interrupt IDs are generated +* in xparameters.h as shown below: +* +* Master/Primary INTC +* ______ +* | |-0 Secondary INTC +* | |-. ______ +* | |-. | |-32 Last INTC +* | |-. | |-. ______ +* |______|<--31-----| |-. | |-64 +* | |-. | |-. +* |______|<--63------| |-. +* | |-. +* |______|-95 +* +* All driver functions has to be called using BaseAddress +* of Primary/Master Controller only. Driver functions takes +* care of Slave Controllers based on Interrupt ID passed. +* User must not use Interrupt source/ID 31 of Primary and +* Secondary controllers to call driver functions. +* +* +*
+*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date	 Changes
+* ----- ---- -------- ---------------------------------------------------------
+* 1.00c rpm  12/04/03 First release
+* 1.00c sv   06/29/05 Minor changes to comply to Doxygen and coding guidelines
+* 2.00a ktn  10/20/09 Updated to use HAL Processor APIs and _m is removed from
+*		      all the macro names/definitions. Minor changes done as per
+*		      coding guidelines.
+* 
+******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xparameters.h" +#include "xstatus.h" +#include "xintc_l.h" +#include "xil_exception.h" + +/************************** Constant Definitions *****************************/ + +/* + * The following constants map to the XPAR parameters created in the + * xparameters.h file. They are defined here such that a user can easily + * change all the needed parameters in one place. + */ +#define INTC_BASEADDR XPAR_INTC_0_BASEADDR +#define INTC_DEVICE_ID XPAR_INTC_0_DEVICE_ID +#define INTC_DEVICE_INTR_ID XPAR_INTC_0_UARTLITE_0_VEC_ID +#define INTC_DEVICE_INT_MASK XPAR_RS232_UART_1_INTERRUPT_MASK + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + +int IntcLowLevelExample(u32 IntcBaseAddress); + +void SetupInterruptSystem(); + +void DeviceDriverHandler(void *CallbackRef); + + +/************************** Variable Definitions *****************************/ + +/* + * Create a shared variable to be used by the main thread of processing and + * the interrupt processing + */ +volatile static int InterruptProcessed = FALSE; + +/*****************************************************************************/ +/** +* +* This is the main function for the Interrupt Controller Low Level example. +* +* @param None. +* +* @return XST_SUCCESS to indicate success, otherwise XST_FAILURE. +* +* @note None. +* +******************************************************************************/ +int main(void) +{ + int Status; + + /* + * Run the low level example of Interrupt Controller, specify the Base + * Address generated in xparameters.h. + */ + Status = IntcLowLevelExample(INTC_BASEADDR); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + return XST_SUCCESS; + +} + +/*****************************************************************************/ +/** +* +* This function is an example of how to use the interrupt controller driver +* component (XIntc) and the hardware device. This function is designed to +* work without any hardware devices to cause interrupts. It may not return +* if the interrupt controller is not properly connected to the processor in +* either software or hardware. +* +* This function relies on the fact that the interrupt controller hardware +* has come out of the reset state such that it will allow interrupts to be +* simulated by the software. +* +* @param IntcBaseAddress is Base Address of the the Interrupt Controller +* Device. +* +* @return XST_SUCCESS to indicate success, otherwise XST_FAILURE. +* +* @note None. +* +******************************************************************************/ +int IntcLowLevelExample(u32 IntcBaseAddress) +{ + + /* + * Connect a device driver handler that will be called when an interrupt + * for the device occurs, the device driver handler performs the + * specific interrupt processing for the device. + */ + XIntc_RegisterHandler(IntcBaseAddress, INTC_DEVICE_INTR_ID, + (XInterruptHandler)DeviceDriverHandler, + (void *)0); + + /* + * Enable interrupts for all devices that cause interrupts, and enable + * the INTC master enable bit. + */ + XIntc_EnableIntr(IntcBaseAddress, INTC_DEVICE_INT_MASK); + + + /* + * Set the master enable bit. Note that we do not enable hardware + * interrupts yet since we want to simulate an interrupt from software + * down below. + */ + XIntc_Out32(IntcBaseAddress + XIN_MER_OFFSET, XIN_INT_MASTER_ENABLE_MASK); + + /* + * This step is processor specific, connect the handler for the + * interrupt controller to the interrupt source for the processor. + */ + SetupInterruptSystem(); + + /* + * Cause (simulate) an interrupt so the handler will be called. This is + * done by writing a 1 to the interrupt status bit for the device + * interrupt. + */ + XIntc_Out32(IntcBaseAddress + XIN_ISR_OFFSET, INTC_DEVICE_INT_MASK); + + /* + * Wait for the interrupt to be processed, if the interrupt does not + * occur this loop will wait forever. + */ + while (1) + { + /* + * If the interrupt occurred which is indicated by the global + * variable which is set in the device driver handler, then + * stop waiting. + */ + if (InterruptProcessed) { + break; + } + } + + + return XST_SUCCESS; + +} +/*****************************************************************************/ +/** +* +* This function connects the interrupt handler of the interrupt controller to +* the processor. This function is seperate to allow it to be customized for +* each application. Each processor or RTOS may require unique processing to +* connect the interrupt handler. +* +* @param None. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void SetupInterruptSystem() +{ + /* + * Initialize the exception table. + */ + Xil_ExceptionInit(); + + /* + * Register the interrupt controller handler with the exception table. + */ + Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, + (Xil_ExceptionHandler)XIntc_DeviceInterruptHandler, + INTC_DEVICE_ID); + + /* + * Enable exceptions. + */ + Xil_ExceptionEnable(); + +} + + + +/*****************************************************************************/ +/** +* +* This function is designed to look like an interrupt handler in a device +* driver. This is typically a 2nd level handler that is called from the +* interrupt controller interrupt handler. This handler would typically +* perform device specific processing such as reading and writing the registers +* of the device to clear the interrupt condition and pass any data to an +* application using the device driver. +* +* @param CallbackRef is passed back to the device driver's interrupt +* handler by the XIntc driver. It was given to the XIntc driver +* in the XIntc_Connect() function call. It is typically a pointer +* to the device driver instance variable if using the Xilinx Level +* 1 device drivers. In this example, we do not care about the +* callback reference, so we passed it a 0 when connecting the +* handler to the XIntc driver and we make no use of it here. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void DeviceDriverHandler(void *CallbackRef) +{ + /* + * Indicate the interrupt has been processed using a shared variable. + */ + InterruptProcessed = TRUE; + +} diff --git a/XilinxProcessorIPLib/drivers/intc/examples/xintc_tapp_example.c b/XilinxProcessorIPLib/drivers/intc/examples/xintc_tapp_example.c new file mode 100644 index 00000000..b3937439 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/intc/examples/xintc_tapp_example.c @@ -0,0 +1,250 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2014 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/******************************************************************************/ +/** +* +* @file xintc_tapp_example.c +* +* This file contains a self test example using the Interrupt Controller driver +* (XIntc) and hardware device. Please reference other device driver examples to +* see more examples of how the Intc and interrupts can be used by a software +* application. +* +* This example shows the use of the Interrupt Controller both with a PowerPC405 +* and MicroBlaze processor. +* +* The TestApp Gen utility uses this file to perform the self test and setup +* of Intc for interrupts. +* +* @note +* +* None +* +*
+*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date	 Changes
+* ----- ---- -------- --------------------------------------------------------
+* 1.00a sv   06/29/05  Created for Test App Integration
+* 1.00c sn   05/09/06  Added Interrupt Setup Function
+* 2.00a ktn  10/20/09  Updated to use HAL Processor APIs and minor changes as
+*		       per coding guidelines.
+* 
+******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xparameters.h" +#include "xstatus.h" +#include "xintc.h" +#include "xil_exception.h" + + +/************************** Constant Definitions *****************************/ + +/* + * The following constants map to the XPAR parameters created in the + * xparameters.h file. They are defined here such that a user can easily + * change all the needed parameters in one place. This definition is not + * included if the example is generated from the TestAppGen test tool. + */ +#ifndef TESTAPP_GEN +#define INTC_DEVICE_ID XPAR_INTC_0_DEVICE_ID +#endif + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + +int IntcSelfTestExample(u16 DeviceId); +int IntcInterruptSetup(XIntc *IntcInstancePtr, u16 DeviceId); + +/************************** Variable Definitions *****************************/ + +static XIntc InterruptController; /* Instance of the Interrupt Controller */ + + +/*****************************************************************************/ +/** +* +* This is the main function for the Interrupt Controller example. This +* function is not included if the example is generated from the TestAppGen test +* tool. +* +* @param None. +* +* @return XST_SUCCESS to indicate success, otherwise XST_FAILURE. +* +* @note None. +* +******************************************************************************/ +#ifndef TESTAPP_GEN +int main(void) +{ + int Status; + + /* + * Run the Intc example , specify the Device ID generated in + * xparameters.h. + */ + Status = IntcSelfTestExample(INTC_DEVICE_ID); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + return XST_SUCCESS; + +} +#endif + +/*****************************************************************************/ +/** +* +* This function runs a self-test on the driver/device. This is a destructive +* test. This function is an example of how to use the interrupt controller +* driver component (XIntc) and the hardware device. This function is designed +* to work without any hardware devices to cause interrupts. It may not return +* if the interrupt controller is not properly connected to the processor in +* either software or hardware. +* +* This function relies on the fact that the interrupt controller hardware +* has come out of the reset state such that it will allow interrupts to be +* simulated by the software. +* +* @param DeviceId is device ID of the Interrupt Controller Device, +* typically XPAR__DEVICE_ID value from +* xparameters.h. +* +* @return XST_SUCCESS to indicate success, otherwise XST_FAILURE. +* +* @note None. +* +******************************************************************************/ +int IntcSelfTestExample(u16 DeviceId) +{ + int Status; + + /* + * Initialize the interrupt controller driver so that it is ready to use. + */ + Status = XIntc_Initialize(&InterruptController, DeviceId); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + + /* + * Perform a self-test to ensure that the hardware was built correctly. + */ + Status = XIntc_SelfTest(&InterruptController); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + return XST_SUCCESS; + +} + + +/*****************************************************************************/ +/** +* +* This function is used by the TestAppGen generated application to setup +* the interrupt controller. +* +* @param IntcInstancePtr is the reference to the Interrupt Controller +* instance. +* @param DeviceId is device ID of the Interrupt Controller Device, +* typically XPAR__DEVICE_ID value from +* xparameters.h. +* +* @return XST_SUCCESS to indicate success, otherwise XST_FAILURE. +* +* @note None. +* +******************************************************************************/ +int IntcInterruptSetup(XIntc *IntcInstancePtr, u16 DeviceId) +{ + + int Status; + + /* + * Initialize the interrupt controller driver so that it is + * ready to use. + */ + Status = XIntc_Initialize(IntcInstancePtr, DeviceId); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Perform a self-test to ensure that the hardware was built correctly. + */ + Status = XIntc_SelfTest(IntcInstancePtr); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Initialize the exception table. + */ + Xil_ExceptionInit(); + + /* + * Register the interrupt controller handler with the exception table. + */ + Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, + (Xil_ExceptionHandler)XIntc_DeviceInterruptHandler, + (void*) 0); + + /* + * Enable exceptions. + */ + Xil_ExceptionEnable(); + + /* + * Start the interrupt controller such that interrupts are enabled for + * all devices that cause interrupts. + */ + Status = XIntc_Start(IntcInstancePtr, XIN_REAL_MODE); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + return XST_SUCCESS; + +} diff --git a/XilinxProcessorIPLib/drivers/intc/src/Makefile b/XilinxProcessorIPLib/drivers/intc/src/Makefile new file mode 100644 index 00000000..9dd1eedd --- /dev/null +++ b/XilinxProcessorIPLib/drivers/intc/src/Makefile @@ -0,0 +1,28 @@ +COMPILER= +ARCHIVER= +CP=cp +COMPILER_FLAGS= +EXTRA_COMPILER_FLAGS= +LIB=libxil.a +LEVEL=0 + +RELEASEDIR=../../../lib +INCLUDEDIR=../../../include +INCLUDES=-I./. -I${INCLUDEDIR} + +INCLUDEFILES=*.h +LIBSOURCES=*.c + +OUTS = *.o + +libs: + echo "Compiling intc" + $(COMPILER) $(COMPILER_FLAGS) $(EXTRA_COMPILER_FLAGS) $(INCLUDES) $(LIBSOURCES) + $(ARCHIVER) -r ${RELEASEDIR}/${LIB} ${OUTS} + make clean + +include: + ${CP} $(INCLUDEFILES) $(INCLUDEDIR) + +clean: + rm -rf ${OUTS} diff --git a/XilinxProcessorIPLib/drivers/intc/src/xintc.c b/XilinxProcessorIPLib/drivers/intc/src/xintc.c new file mode 100644 index 00000000..9bf3f9dc --- /dev/null +++ b/XilinxProcessorIPLib/drivers/intc/src/xintc.c @@ -0,0 +1,1078 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2014 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xintc.c +* +* Contains required functions for the XIntc driver for the Xilinx Interrupt +* Controller. See xintc.h for a detailed description of the driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- --------------------------------------------------------
+* 1.00a ecm  08/16/01 First release
+* 1.00b jhl  02/21/02 Repartitioned the driver for smaller files
+* 1.00b jhl  04/24/02 Made LookupConfig global and compressed ack before table
+*                     in the configuration into a bit mask
+* 1.00c rpm  10/17/03 New release. Support the static vector table created
+*                     in the xintc_g.c configuration table.
+* 1.00c rpm  04/23/04 Removed check in XIntc_Connect for a previously connected
+*                     handler. Always overwrite the vector table handler with
+*                     the handler provided as an argument.
+* 1.10c mta  03/21/07 Updated to new coding style
+* 1.11a sv   11/21/07 Updated driver to support access through a DCR bridge
+* 2.00a ktn  10/20/09 Updated to use HAL Processor APIs.
+* 2.04a bss  01/13/12 Added XIntc_ConnectFastHandler API for Fast Interrupt
+*		      and XIntc_SetNormalIntrMode for setting to normal
+*		      interrupt mode.
+* 2.05a bss  08/16/12 Updated to support relocatable vectors in Microblaze,
+*		      updated XIntc_SetNormalIntrMode to use IntVectorAddr
+*		      which is the interrupt vector address
+* 2.06a bss  01/28/13 To support Cascade mode:
+*		      Modified XIntc_Initialize,XIntc_Start,XIntc_Connect
+*		      XIntc_Disconnect,XIntc_Enable,XIntc_Disable,
+*		      XIntc_Acknowledge,XIntc_ConnectFastHandler and
+*		      XIntc_SetNormalIntrMode APIs.
+*		      Added XIntc_InitializeSlaves API.
+* 3.0   bss  01/28/13 Modified to initialize IVAR register with
+*		      XPAR_MICROBLAZE_BASE_VECTORS + 0x10 to fix
+*		      CR#765931
+*
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xintc.h" +#include "xintc_l.h" +#include "xintc_i.h" + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Variable Definitions *****************************/ + +/* + * Array of masks associated with the bit position, improves performance + * in the ISR and acknowledge functions, this table is shared between all + * instances of the driver. XIN_CONTROLLER_MAX_INTRS is the maximum number of + * sources of Interrupt controller + */ +u32 XIntc_BitPosMask[XIN_CONTROLLER_MAX_INTRS]; + +/************************** Function Prototypes ******************************/ + +static void StubHandler(void *CallBackRef); +static void XIntc_InitializeSlaves(XIntc * InstancePtr); + +/*****************************************************************************/ +/** +* +* Initialize a specific interrupt controller instance/driver. The +* initialization entails: +* +* - Initialize fields of the XIntc structure +* - Initial vector table with stub function calls +* - All interrupt sources are disabled +* - Interrupt output is disabled +* +* @param InstancePtr is a pointer to the XIntc instance to be worked on. +* @param DeviceId is the unique id of the device controlled by this XIntc +* instance. Passing in a device id associates the generic XIntc +* instance to a specific device, as chosen by the caller or +* application developer. +* +* @return +* - XST_SUCCESS if initialization was successful +* - XST_DEVICE_IS_STARTED if the device has already been started +* - XST_DEVICE_NOT_FOUND if device configuration information was +* not found for a device with the supplied device ID. +* +* @note In Cascade mode this function calls XIntc_InitializeSlaves to +* initialiaze Slave Interrupt controllers. +* +******************************************************************************/ +int XIntc_Initialize(XIntc * InstancePtr, u16 DeviceId) +{ + u8 Id; + XIntc_Config *CfgPtr; + u32 NextBitMask = 1; + + Xil_AssertNonvoid(InstancePtr != NULL); + + /* + * If the device is started, disallow the initialize and return a status + * indicating it is started. This allows the user to stop the device + * and reinitialize, but prevents a user from inadvertently initializing + */ + if (InstancePtr->IsStarted == XIL_COMPONENT_IS_STARTED) { + return XST_DEVICE_IS_STARTED; + } + + /* + * Lookup the device configuration in the CROM table. Use this + * configuration info down below when initializing this component. + */ + CfgPtr = XIntc_LookupConfig(DeviceId); + if (CfgPtr == NULL) { + return XST_DEVICE_NOT_FOUND; + } + + /* + * Set some default values + */ + InstancePtr->IsReady = 0; + InstancePtr->IsStarted = 0; /* not started */ + InstancePtr->CfgPtr = CfgPtr; + + InstancePtr->CfgPtr->Options = XIN_SVC_SGL_ISR_OPTION; + InstancePtr->CfgPtr->IntcType = CfgPtr->IntcType; + + /* + * Save the base address pointer such that the registers of the + * interrupt can be accessed + */ +#if (XPAR_XINTC_USE_DCR_BRIDGE != 0) + InstancePtr->BaseAddress = ((CfgPtr->BaseAddress >> 2)) & 0xFFF; +#else + InstancePtr->BaseAddress = CfgPtr->BaseAddress; +#endif + + /* + * Initialize all the data needed to perform interrupt processing for + * each interrupt ID up to the maximum used + */ + for (Id = 0; Id < CfgPtr->NumberofIntrs; Id++) { + + /* + * Initalize the handler to point to a stub to handle an + * interrupt which has not been connected to a handler. Only + * initialize it if the handler is 0 or XNullHandler, which + * means it was not initialized statically by the tools/user. + * Set the callback reference to this instance so that + * unhandled interrupts can be tracked. + */ + if ((InstancePtr->CfgPtr->HandlerTable[Id].Handler == 0) || + (InstancePtr->CfgPtr->HandlerTable[Id].Handler == + XNullHandler)) { + InstancePtr->CfgPtr->HandlerTable[Id].Handler = + StubHandler; + } + InstancePtr->CfgPtr->HandlerTable[Id].CallBackRef = InstancePtr; + + /* + * Initialize the bit position mask table such that bit + * positions are lookups only for each interrupt id, with 0 + * being a special case + * (XIntc_BitPosMask[] = { 1, 2, 4, 8, ... }) + */ + XIntc_BitPosMask[Id] = NextBitMask; + NextBitMask *= 2; + } + + /* + * Disable IRQ output signal + * Disable all interrupt sources + * Acknowledge all sources + */ + XIntc_Out32(InstancePtr->BaseAddress + XIN_MER_OFFSET, 0); + XIntc_Out32(InstancePtr->BaseAddress + XIN_IER_OFFSET, 0); + XIntc_Out32(InstancePtr->BaseAddress + XIN_IAR_OFFSET, 0xFFFFFFFF); + + /* + * If the fast Interrupt mode is enabled then set all the + * interrupts as normal mode. + */ + if(InstancePtr->CfgPtr->FastIntr == TRUE) { + XIntc_Out32(InstancePtr->BaseAddress + XIN_IMR_OFFSET, 0); + +#ifdef XPAR_MICROBLAZE_BASE_VECTORS + for (Id = 0; Id < 32 ; Id++) + { + XIntc_Out32(InstancePtr->BaseAddress + XIN_IVAR_OFFSET + + (Id * 4), XPAR_MICROBLAZE_BASE_VECTORS + + 0x10); + } +#else + for (Id = 0; Id < 32 ; Id++) + { + XIntc_Out32(InstancePtr->BaseAddress + XIN_IVAR_OFFSET + + (Id * 4), 0x10); + } +#endif + } + + /* Initialize slaves in Cascade mode*/ + if (InstancePtr->CfgPtr->IntcType != XIN_INTC_NOCASCADE) { + XIntc_InitializeSlaves(InstancePtr); + } + + /* + * Indicate the instance is now ready to use, successfully initialized + */ + InstancePtr->IsReady = XIL_COMPONENT_IS_READY; + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* Starts the interrupt controller by enabling the output from the controller +* to the processor. Interrupts may be generated by the interrupt controller +* after this function is called. +* +* It is necessary for the caller to connect the interrupt handler of this +* component to the proper interrupt source. This function also starts Slave +* controllers in Cascade mode. +* +* @param InstancePtr is a pointer to the XIntc instance to be worked on. +* @param Mode determines if software is allowed to simulate interrupts or +* real interrupts are allowed to occur. Note that these modes are +* mutually exclusive. The interrupt controller hardware resets in +* a mode that allows software to simulate interrupts until this +* mode is exited. It cannot be reentered once it has been exited. +* +* One of the following values should be used for the mode. +* - XIN_SIMULATION_MODE enables simulation of interrupts only +* - XIN_REAL_MODE enables hardware interrupts only +* +* @return +* - XST_SUCCESS if the device was started successfully +* - XST_FAILURE if simulation mode was specified and it could not +* be set because real mode has already been entered. +* +* @note Must be called after XIntc initialization is completed. +* +******************************************************************************/ +int XIntc_Start(XIntc * InstancePtr, u8 Mode) +{ + u32 MasterEnable = XIN_INT_MASTER_ENABLE_MASK; + XIntc_Config *CfgPtr; + int Index; + + /* + * Assert the arguments + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid((Mode == XIN_SIMULATION_MODE) || + (Mode == XIN_REAL_MODE)) + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Check for simulation mode + */ + if (Mode == XIN_SIMULATION_MODE) { + if (MasterEnable & XIN_INT_HARDWARE_ENABLE_MASK) { + return XST_FAILURE; + } + } + else { + MasterEnable |= XIN_INT_HARDWARE_ENABLE_MASK; + } + + /* + * Indicate the instance is ready to be used and is started before we + * enable the device. + */ + InstancePtr->IsStarted = XIL_COMPONENT_IS_STARTED; + + /* Start the Slaves for Cascade Mode */ + if (InstancePtr->CfgPtr->IntcType != XIN_INTC_NOCASCADE) { + for (Index = 1; Index <= XPAR_XINTC_NUM_INSTANCES - 1; Index++) + { + CfgPtr = XIntc_LookupConfig(Index); + XIntc_Out32(CfgPtr->BaseAddress + XIN_MER_OFFSET, + MasterEnable); + } + } + + /* Start the master */ + XIntc_Out32(InstancePtr->BaseAddress + XIN_MER_OFFSET, MasterEnable); + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* Stops the interrupt controller by disabling the output from the controller +* so that no interrupts will be caused by the interrupt controller. +* +* @param InstancePtr is a pointer to the XIntc instance to be worked on. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XIntc_Stop(XIntc * InstancePtr) +{ + /* + * Assert the arguments + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Stop all interrupts from occurring thru the interrupt controller by + * disabling all interrupts in the MER register + */ + XIntc_Out32(InstancePtr->BaseAddress + XIN_MER_OFFSET, 0); + + InstancePtr->IsStarted = 0; +} + +/*****************************************************************************/ +/** +* +* Makes the connection between the Id of the interrupt source and the +* associated handler that is to run when the interrupt is recognized. The +* argument provided in this call as the Callbackref is used as the argument +* for the handler when it is called. In Cascade mode, connects handler to +* Slave controller handler table depending on the interrupt Id. +* +* @param InstancePtr is a pointer to the XIntc instance to be worked on. +* @param Id contains the ID of the interrupt source and should be in the +* range of 0 to XPAR_INTC_MAX_NUM_INTR_INPUTS - 1 with 0 being +* the highest priority interrupt. +* @param Handler to the handler for that interrupt. +* @param CallBackRef is the callback reference, usually the instance +* pointer of the connecting driver. +* +* @return +* +* - XST_SUCCESS if the handler was connected correctly. +* +* @note +* +* WARNING: The handler provided as an argument will overwrite any handler +* that was previously connected. +* +****************************************************************************/ +int XIntc_Connect(XIntc * InstancePtr, u8 Id, + XInterruptHandler Handler, void *CallBackRef) +{ + XIntc_Config *CfgPtr; + /* + * Assert the arguments + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(Id < XPAR_INTC_MAX_NUM_INTR_INPUTS); + Xil_AssertNonvoid(Handler != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* Connect Handlers for Slave controllers in Cascade Mode */ + if (Id > 31) { + + CfgPtr = XIntc_LookupConfig(Id/32); + + CfgPtr->HandlerTable[Id%32].Handler = Handler; + CfgPtr->HandlerTable[Id%32].CallBackRef = CallBackRef; + } + /* Connect Handlers for Master/primary controller */ + else { + /* + * The Id is used as an index into the table to select the + * proper handler + */ + InstancePtr->CfgPtr->HandlerTable[Id].Handler = Handler; + InstancePtr->CfgPtr->HandlerTable[Id].CallBackRef = + CallBackRef; + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* Updates the interrupt table with the Null Handler and NULL arguments at the +* location pointed at by the Id. This effectively disconnects that interrupt +* source from any handler. The interrupt is disabled also. In Cascade mode, +* disconnects handler from Slave controller handler table depending on the +* interrupt Id. +* +* @param InstancePtr is a pointer to the XIntc instance to be worked on. +* @param Id contains the ID of the interrupt source and should be in the +* range of 0 to XPAR_INTC_MAX_NUM_INTR_INPUTS - 1 with 0 being +* the highest priority interrupt. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void XIntc_Disconnect(XIntc * InstancePtr, u8 Id) +{ + u32 CurrentIER; + u32 Mask; + XIntc_Config *CfgPtr; + + /* + * Assert the arguments + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(Id < XPAR_INTC_MAX_NUM_INTR_INPUTS); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Disable the interrupt such that it won't occur while disconnecting + * the handler, only disable the specified interrupt id without + * modifying the other interrupt ids + */ + + /* Disconnect Handlers for Slave controllers in Cascade Mode */ + if (Id > 31) { + + CfgPtr = XIntc_LookupConfig(Id/32); + + CurrentIER = XIntc_In32(CfgPtr->BaseAddress + XIN_IER_OFFSET); + + /* Convert from integer id to bit mask */ + Mask = XIntc_BitPosMask[(Id%32)]; + + XIntc_Out32(CfgPtr->BaseAddress + XIN_IER_OFFSET, + (CurrentIER & ~Mask)); + /* + * Disconnect the handler and connect a stub, the callback + * reference must be set to this instance to allow unhandled + * interrupts to be tracked + */ + CfgPtr->HandlerTable[Id%32].Handler = StubHandler; + CfgPtr->HandlerTable[Id%32].CallBackRef = InstancePtr; + } + /* Disconnect Handlers for Master/primary controller */ + else { + CurrentIER = XIntc_In32(InstancePtr->BaseAddress + + XIN_IER_OFFSET); + + /* Convert from integer id to bit mask */ + Mask = XIntc_BitPosMask[Id]; + + XIntc_Out32(InstancePtr->BaseAddress + XIN_IER_OFFSET, + (CurrentIER & ~Mask)); + InstancePtr->CfgPtr->HandlerTable[Id%32].Handler = + StubHandler; + InstancePtr->CfgPtr->HandlerTable[Id%32].CallBackRef = + InstancePtr; + } + +} + +/*****************************************************************************/ +/** +* +* Enables the interrupt source provided as the argument Id. Any pending +* interrupt condition for the specified Id will occur after this function is +* called. In Cascade mode, enables corresponding interrupt of Slave controllers +* depending on the Id. +* +* @param InstancePtr is a pointer to the XIntc instance to be worked on. +* @param Id contains the ID of the interrupt source and should be in the +* range of 0 to XPAR_INTC_MAX_NUM_INTR_INPUTS - 1 with 0 being +* the highest priority interrupt. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void XIntc_Enable(XIntc * InstancePtr, u8 Id) +{ + u32 CurrentIER; + u32 Mask; + XIntc_Config *CfgPtr; + + /* + * Assert the arguments + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(Id < XPAR_INTC_MAX_NUM_INTR_INPUTS); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + if (Id > 31) { + + /* Enable user required Id in Slave controller */ + CfgPtr = XIntc_LookupConfig(Id/32); + + CurrentIER = XIntc_In32(CfgPtr->BaseAddress + XIN_IER_OFFSET); + + /* Convert from integer id to bit mask */ + Mask = XIntc_BitPosMask[(Id%32)]; + + XIntc_Out32(CfgPtr->BaseAddress + XIN_IER_OFFSET, + (CurrentIER | Mask)); + } + else { + /* + * The Id is used to create the appropriate mask for the + * desired bit position. + */ + Mask = XIntc_BitPosMask[Id]; + + /* + * Enable the selected interrupt source by reading the + * interrupt enable register and then modifying only the + * specified interrupt id enable + */ + CurrentIER = XIntc_In32(InstancePtr->BaseAddress + + XIN_IER_OFFSET); + XIntc_Out32(InstancePtr->BaseAddress + XIN_IER_OFFSET, + (CurrentIER | Mask)); + } +} + +/*****************************************************************************/ +/** +* +* Disables the interrupt source provided as the argument Id such that the +* interrupt controller will not cause interrupts for the specified Id. The +* interrupt controller will continue to hold an interrupt condition for the +* Id, but will not cause an interrupt.In Cascade mode, disables corresponding +* interrupt of Slave controllers depending on the Id. +* +* @param InstancePtr is a pointer to the XIntc instance to be worked on. +* @param Id contains the ID of the interrupt source and should be in the +* range of 0 to XPAR_INTC_MAX_NUM_INTR_INPUTS - 1 with 0 being the +* highest priority interrupt. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void XIntc_Disable(XIntc * InstancePtr, u8 Id) +{ + u32 CurrentIER; + u32 Mask; + XIntc_Config *CfgPtr; + + /* + * Assert the arguments + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(Id < XPAR_INTC_MAX_NUM_INTR_INPUTS); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + if (Id > 31) { + /* Enable user required Id in Slave controller */ + CfgPtr = XIntc_LookupConfig(Id/32); + + CurrentIER = XIntc_In32(CfgPtr->BaseAddress + XIN_IER_OFFSET); + + /* Convert from integer id to bit mask */ + Mask = XIntc_BitPosMask[(Id%32)]; + + XIntc_Out32(CfgPtr->BaseAddress + XIN_IER_OFFSET, + (CurrentIER & ~Mask)); + } else { + /* + * The Id is used to create the appropriate mask for the + * desired bit position. Id currently limited to 0 - 31 + */ + Mask = XIntc_BitPosMask[Id]; + + /* + * Disable the selected interrupt source by reading the + * interrupt enable register and then modifying only the + * specified interrupt id + */ + CurrentIER = XIntc_In32(InstancePtr->BaseAddress + + XIN_IER_OFFSET); + XIntc_Out32(InstancePtr->BaseAddress + XIN_IER_OFFSET, + (CurrentIER & ~Mask)); + } +} + +/*****************************************************************************/ +/** +* +* Acknowledges the interrupt source provided as the argument Id. When the +* interrupt is acknowledged, it causes the interrupt controller to clear its +* interrupt condition.In Cascade mode, acknowledges corresponding interrupt +* source of Slave controllers depending on the Id. +* +* @param InstancePtr is a pointer to the XIntc instance to be worked on. +* @param Id contains the ID of the interrupt source and should be in the +* range of 0 to XPAR_INTC_MAX_NUM_INTR_INPUTS - 1 with 0 being +* the highest priority interrupt. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void XIntc_Acknowledge(XIntc * InstancePtr, u8 Id) +{ + u32 Mask; + XIntc_Config *CfgPtr; + + /* + * Assert the arguments + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(Id < XPAR_INTC_MAX_NUM_INTR_INPUTS); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + if (Id > 31) { + /* Enable user required Id in Slave controller */ + CfgPtr = XIntc_LookupConfig(Id/32); + + /* Convert from integer id to bit mask */ + Mask = XIntc_BitPosMask[(Id%32)]; + + XIntc_Out32(CfgPtr->BaseAddress + XIN_IAR_OFFSET, Mask); + } else { + /* + * The Id is used to create the appropriate mask for the + * desired bit position. + */ + Mask = XIntc_BitPosMask[Id]; + + /* + * Acknowledge the selected interrupt source, no read of the + * acknowledge register is necessary since only the bits set + * in the mask will be affected by the write + */ + XIntc_Out32(InstancePtr->BaseAddress + XIN_IAR_OFFSET, Mask); + } +} + +/*****************************************************************************/ +/** +* +* A stub for the asynchronous callback. The stub is here in case the upper +* layers forget to set the handler. +* +* @param CallBackRef is a pointer to the upper layer callback reference +* +* @return None. +* +* @note None. +* +******************************************************************************/ +static void StubHandler(void *CallBackRef) +{ + /* + * Verify that the inputs are valid + */ + Xil_AssertVoid(CallBackRef != NULL); + + /* + * Indicate another unhandled interrupt for stats + */ + ((XIntc *) CallBackRef)->UnhandledInterrupts++; +} + +/*****************************************************************************/ +/** +* +* Looks up the device configuration based on the unique device ID. A table +* contains the configuration info for each device in the system. +* +* @param DeviceId is the unique identifier for a device. +* +* @return A pointer to the XIntc configuration structure for the specified +* device, or NULL if the device was not found. +* +* @note None. +* +******************************************************************************/ +XIntc_Config *XIntc_LookupConfig(u16 DeviceId) +{ + XIntc_Config *CfgPtr = NULL; + int Index; + + for (Index = 0; Index < XPAR_XINTC_NUM_INSTANCES; Index++) { + if (XIntc_ConfigTable[Index].DeviceId == DeviceId) { + CfgPtr = &XIntc_ConfigTable[Index]; + break; + } + } + + return CfgPtr; +} + +/*****************************************************************************/ +/** +* +* Makes the connection between the Id of the interrupt source and the +* associated handler that is to run when the interrupt is recognized.In Cascade +* mode, connects handler to corresponding Slave controller IVAR register +* depending on the Id and sets all interrupt sources of the Slave controller as +* fast interrupts. +* +* @param InstancePtr is a pointer to the XIntc instance to be worked on. +* @param Id contains the ID of the interrupt source and should be in the +* range of 0 to XPAR_INTC_MAX_NUM_INTR_INPUTS - 1 with 0 being +* the highest priority interrupt. +* @param Handler to the handler for that interrupt. +* +* @return +* - XST_SUCCESS +* +* @note +* Slave controllers in Cascade Mode should have all as Fast +* interrupts or Normal interrupts, mixed interrupts are not +* supported +* +* WARNING: The handler provided as an argument will overwrite any handler +* that was previously connected. +* +****************************************************************************/ +int XIntc_ConnectFastHandler(XIntc *InstancePtr, u8 Id, + XFastInterruptHandler Handler) +{ + u32 Imr; + u32 CurrentIER; + u32 Mask; + XIntc_Config *CfgPtr; + + /* + * Assert the arguments + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(Id < XPAR_INTC_MAX_NUM_INTR_INPUTS); + Xil_AssertNonvoid(Handler != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(InstancePtr->CfgPtr->FastIntr == TRUE); + + + if (Id > 31) { + /* Enable user required Id in Slave controller */ + CfgPtr = XIntc_LookupConfig(Id/32); + + if (CfgPtr->FastIntr != TRUE) { + /*Fast interrupts of slave controller are not enabled*/ + return XST_FAILURE; + } + + /* Get the Enabled Interrupts */ + CurrentIER = XIntc_In32(CfgPtr->BaseAddress + XIN_IER_OFFSET); + + /* Convert from integer id to bit mask */ + Mask = XIntc_BitPosMask[(Id%32)]; + + /* Disable the Interrupt if it was enabled before calling + * this function + */ + if (CurrentIER & Mask) { + XIntc_Disable(InstancePtr, Id); + } + + XIntc_Out32(CfgPtr->BaseAddress + XIN_IVAR_OFFSET + + ((Id%32) * 4), (u32) Handler); + + /* Slave controllers in Cascade Mode should have all as Fast + * interrupts or Normal interrupts, mixed interrupts are not + * supported + */ + XIntc_Out32(CfgPtr->BaseAddress + XIN_IMR_OFFSET, 0xFFFFFFFF); + + /* Enable the Interrupt if it was enabled before calling this + * function + */ + if (CurrentIER & Mask) { + XIntc_Enable(InstancePtr, Id); + } + } + else { + /* Get the Enabled Interrupts */ + CurrentIER = XIntc_In32(InstancePtr->BaseAddress + + XIN_IER_OFFSET); + /* Convert from integer id to bit mask */ + Mask = XIntc_BitPosMask[Id]; + + /* Disable the Interrupt if it was enabled before calling + * this function + */ + if (CurrentIER & Mask) { + XIntc_Disable(InstancePtr, Id); + } + + XIntc_Out32(InstancePtr->BaseAddress + XIN_IVAR_OFFSET + + (Id * 4), (u32) Handler); + + Imr = XIntc_In32(InstancePtr->BaseAddress + XIN_IMR_OFFSET); + XIntc_Out32(InstancePtr->BaseAddress + XIN_IMR_OFFSET, + Imr | Mask); + + /* Enable the Interrupt if it was enabled before + * calling this function + */ + if (CurrentIER & Mask) { + XIntc_Enable(InstancePtr, Id); + } + + } + + return XST_SUCCESS; +} + + +/*****************************************************************************/ +/** +* +* Sets the normal interrupt mode for the specified interrupt in the Interrupt +* Mode Register. In Cascade mode disconnects handler from corresponding Slave +* controller IVAR register depending on the Id and sets all interrupt sources +* of the Slave controller as normal interrupts. +* +* @param InstancePtr is a pointer to the XIntc instance to be worked on. +* @param Id contains the ID of the interrupt source and should be in the +* range of 0 to XPAR_INTC_MAX_NUM_INTR_INPUTS - 1 with 0 being the +* highest priority interrupt. +* +* @return None. +* +* @note +* Slave controllers in Cascade Mode should have all as Fast +* interrupts or Normal interrupts, mixed interrupts are not +* supported +* +****************************************************************************/ +void XIntc_SetNormalIntrMode(XIntc *InstancePtr, u8 Id) +{ + u32 Imr; + u32 CurrentIER; + u32 Mask; + XIntc_Config *CfgPtr; + + /* + * Assert the arguments + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(Id < XPAR_INTC_MAX_NUM_INTR_INPUTS); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(InstancePtr->CfgPtr->FastIntr == TRUE); + + if (Id > 31) { + /* Enable user required Id in Slave controller */ + CfgPtr = XIntc_LookupConfig(Id/32); + + /* Get the Enabled Interrupts */ + CurrentIER = XIntc_In32(CfgPtr->BaseAddress + XIN_IER_OFFSET); + + /* Convert from integer id to bit mask */ + Mask = XIntc_BitPosMask[(Id%32)]; + + /* Disable the Interrupt if it was enabled before calling + * this function + */ + if (CurrentIER & Mask) { + XIntc_Disable(InstancePtr, Id); + } + + /* Slave controllers in Cascade Mode should have all as Fast + * interrupts or Normal interrupts, mixed interrupts are not + * supported + */ + XIntc_Out32(CfgPtr->BaseAddress + XIN_IMR_OFFSET, 0x0); + +#ifdef XPAR_MICROBLAZE_BASE_VECTORS + for (Id = 0; Id < 32 ; Id++) + { + XIntc_Out32(CfgPtr->BaseAddress + XIN_IVAR_OFFSET + + (Id * 4), XPAR_MICROBLAZE_BASE_VECTORS + + 0x10); + } +#else + for (Id = 0; Id < 32 ; Id++) + { + XIntc_Out32(CfgPtr->BaseAddress + XIN_IVAR_OFFSET + + (Id * 4), 0x10); + } +#endif + + /* Enable the Interrupt if it was enabled before calling this + * function + */ + if (CurrentIER & Mask) { + XIntc_Enable(InstancePtr, Id); + } + + } + else { + + /* Get the Enabled Interrupts */ + CurrentIER = XIntc_In32(InstancePtr->BaseAddress + XIN_IER_OFFSET); + Mask = XIntc_BitPosMask[Id];/* Convert from integer id to bit mask */ + + + /* Disable the Interrupt if it was enabled before + * calling this function + */ + if (CurrentIER & Mask) { + XIntc_Disable(InstancePtr, Id); + } + + /* + * Disable the selected interrupt as Fast Interrupt by reading the + * interrupt mode register and then modifying only the + * specified interrupt id + */ + Imr = XIntc_In32(InstancePtr->BaseAddress + XIN_IMR_OFFSET); + XIntc_Out32(InstancePtr->BaseAddress + XIN_IMR_OFFSET, + Imr & ~Mask); + +#ifdef XPAR_MICROBLAZE_BASE_VECTORS + for (Id = 0; Id < 32 ; Id++) + { + XIntc_Out32(InstancePtr->BaseAddress + XIN_IVAR_OFFSET + + (Id * 4), XPAR_MICROBLAZE_BASE_VECTORS + + 0x10); + } +#else + for (Id = 0; Id < 32 ; Id++) + { + XIntc_Out32(InstancePtr->BaseAddress + XIN_IVAR_OFFSET + + (Id * 4), 0x10); + } +#endif + /* Enable the Interrupt if it was enabled before + * calling this function + */ + if (CurrentIER & Mask) { + XIntc_Enable(InstancePtr, Id); + } + } +} + +/*****************************************************************************/ +/** +* +* Initializes Slave controllers in Cascade mode. The initialization entails: +* - Initial vector table with stub function calls +* - All interrupt sources are disabled for last controller. +* - All interrupt sources are disabled except sources to 31 pin of +* primary and secondary controllers +* - Interrupt outputs are disabled +* +* @param InstancePtr is a pointer to the XIntc instance to be worked on. +* +* @return None +* +* @note None. +* +******************************************************************************/ +static void XIntc_InitializeSlaves(XIntc * InstancePtr) +{ + int Index; + u32 Mask; + XIntc_Config *CfgPtr; + int Id; + + Mask = XIntc_BitPosMask[31]; /* Convert from integer id to bit mask */ + + /* Enable interrupt id with 31 for Master + * interrupt controller + */ + XIntc_Out32(InstancePtr->CfgPtr->BaseAddress + XIN_IER_OFFSET, Mask); + + for (Index = 1; Index <= XPAR_XINTC_NUM_INSTANCES - 1; Index++) { + CfgPtr = XIntc_LookupConfig(Index); + + XIntc_Out32(CfgPtr->BaseAddress + XIN_IAR_OFFSET, + 0xFFFFFFFF); + if (CfgPtr->IntcType != XIN_INTC_LAST) { + + /* Enable interrupt ids with 31 for secondary + * interrupt controllers + */ + XIntc_Out32(CfgPtr->BaseAddress + XIN_IER_OFFSET, + Mask); + } else { + XIntc_Out32(CfgPtr->BaseAddress + XIN_IER_OFFSET, 0x0); + } + + /* Disable Interrupt output */ + XIntc_Out32(CfgPtr->BaseAddress + XIN_MER_OFFSET, 0); + + /* Set all interrupts as normal mode if Fast Interrupts + * are enabled + */ + if(CfgPtr->FastIntr == TRUE) { + XIntc_Out32(CfgPtr->BaseAddress + XIN_IMR_OFFSET, 0); + +#ifdef XPAR_MICROBLAZE_BASE_VECTORS + for (Id = 0; Id < 32 ; Id++) + { + XIntc_Out32(CfgPtr->BaseAddress + + XIN_IVAR_OFFSET + (Id * 4), + XPAR_MICROBLAZE_BASE_VECTORS + 0x10); + } +#else + for (Id = 0; Id < 32 ; Id++) + { + XIntc_Out32(CfgPtr->BaseAddress + + XIN_IVAR_OFFSET + (Id * 4), 0x10); + } +#endif + } + + /* + * Initialize all the data needed to perform interrupt + * processing for each interrupt ID up to the maximum used + */ + for (Id = 0; Id < CfgPtr->NumberofIntrs; Id++) { + + /* + * Initalize the handler to point to a stub to handle an + * interrupt which has not been connected to a handler. + * Only initialize it if the handler is 0 or + * XNullHandler, which means it was not initialized + * statically by the tools/user.Set the callback + * reference to this instance so that unhandled + * interrupts can be tracked. + */ + if ((CfgPtr->HandlerTable[Id].Handler == 0) || + (CfgPtr->HandlerTable[Id].Handler == + XNullHandler)) { + CfgPtr->HandlerTable[Id].Handler = StubHandler; + } + CfgPtr->HandlerTable[Id].CallBackRef = InstancePtr; + } + } +} diff --git a/XilinxProcessorIPLib/drivers/intc/src/xintc.h b/XilinxProcessorIPLib/drivers/intc/src/xintc.h new file mode 100644 index 00000000..1947d0a5 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/intc/src/xintc.h @@ -0,0 +1,366 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2014 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xintc.h +* +* The Xilinx interrupt controller driver component. This component supports the +* Xilinx interrupt controller. +* +* The interrupt controller driver uses the idea of priority for the various +* handlers. Priority is an integer within the range of 0 and 31 inclusive with +* 0 being the highest priority interrupt source. +* +* The Xilinx interrupt controller supports the following features: +* +* - specific individual interrupt enabling/disabling +* - specific individual interrupt acknowledging +* - attaching specific callback function to handle interrupt source +* - master enable/disable +* - single callback per interrupt or all pending interrupts handled for +* each interrupt of the processor +* +* The acknowledgement of the interrupt within the interrupt controller is +* selectable, either prior to the device's handler being called or after +* the handler is called. This is necessary to support interrupt signal inputs +* which are either edge or level signals. Edge driven interrupt signals +* require that the interrupt is acknowledged prior to the interrupt being +* serviced in order to prevent the loss of interrupts which are occurring +* extremely close together. A level driven interrupt input signal requires +* the interrupt to acknowledged after servicing the interrupt to ensure that +* the interrupt only generates a single interrupt condition. +* +* Details about connecting the interrupt handler of the driver are contained +* in the source file specific to interrupt processing, xintc_intr.c. +* +* This driver is intended to be RTOS and processor independent. It works with +* physical addresses only. Any needs for dynamic memory management, threads +* or thread mutual exclusion, virtual memory, or cache control must be +* satisfied by the layer above this driver. +* +* Interrupt Vector Tables +* +* The interrupt vector table for each interrupt controller device is declared +* statically in xintc_g.c within the configuration data for each instance. +* The device ID of the interrupt controller device is used by the driver as a +* direct index into the configuration data table - to retrieve the vector table +* for an instance of the interrupt controller. The user should populate the +* vector table with handlers and callbacks at run-time using the XIntc_Connect() +* and XIntc_Disconnect() functions. +* +* Each vector table entry corresponds to a device that can generate an +* interrupt. Each entry contains an interrupt handler function and an argument +* to be passed to the handler when an interrupt occurs. The tools default this +* argument to the base address of the interrupting device. Note that the +* device driver interrupt handlers given in this file do not take a base +* address as an argument, but instead take a pointer to the driver instance. +* This means that although the table is created statically, the user must still +* use XIntc_Connect() when the interrupt handler takes an argument other than +* the base address. This is only to say that the existence of the static vector +* tables should not mislead the user into thinking they no longer need to +* register/connect interrupt handlers with this driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a ecm  08/16/01 First release
+* 1.00a rpm  01/09/02 Removed the AckLocation argument from XIntc_Connect().
+*                     This information is now internal in xintc_g.c.
+* 1.00b jhl  02/13/02 Repartitioned the driver for smaller files
+* 1.00b jhl  04/24/02 Made LookupConfig function global and relocated config
+*                     data type
+* 1.00c rpm  10/17/03 New release. Support the static vector table created
+*                     in the xintc_g.c configuration table. Moved vector
+*                     table and options out of instance structure and into
+*                     the configuration table.
+* 1.10c mta  03/21/07 Updated to new coding style
+* 1.11a sv   11/21/07 Updated driver to support access through a DCR bridge
+* 2.00a ktn  10/20/09 Updated to use HAL Processor APIs and _m is removed from
+*		      all the macro names/definitions.
+* 2.01a sdm  04/27/10 Updated the tcl so that the defintions are generated in
+*		      the xparameters.h to know whether the optional registers
+*		      SIE, CIE and IVR are enabled in the HW - Refer CR 555392.
+*		      This driver doesnot make use of these definitions and does
+*		      not use the optional registers.
+* 2.03a hvm  05/24/11 Updated the tcl to generate vector Ids for external
+*		      interrupts. CR565336
+* 2.04a bss  01/13/12 Added XIntc_ConnectFastHandler API for Fast Interrupt
+*		      and XIntc_SetNormalIntrMode for setting to normal
+*		      interrupt mode.
+* 2.04a asa  03/19/12 Changed the XIntc_Config struct. The order of entries
+*		      declared in the structure now matches with the
+*		      XIntc_ConfigTable generated by the driver tcl.
+* 2.05a bss  08/16/12 Updated to support relocatable vectors in Microblaze,
+*		      added IntVectorAddr to XIntc_Config for this.
+*		      Added XIntc_RegisterFastHandler API to register fast
+*		      interrupt handlers using base address.
+* 2.06a bss  01/28/13 To support Cascade mode:
+* 		      Added XIN_INTC_NOCASCADE,XIN_INTC_PRIMARY,
+*		      XIN_INTC_SECONDARY,XIN_INTC_LAST and
+*		      XIN_CONTROLLER_MAX_INTRS  macros
+*		      Added NumberofIntrs and IntcType fields in XIntc_Config
+*		      structure.
+*		      Modified XIntc_Initialize,XIntc_Start,XIntc_Connect
+*		      XIntc_Disconnect,XIntc_Enable,XIntc_Disable,
+*		      XIntc_Acknowledge,XIntc_ConnectFastHandler and
+*		      XIntc_SetNormalIntrMode APIs.Added XIntc_InitializeSlaves
+*		      API in xintc.c
+*  		      Modified XIntc_DeviceInterruptHandler,
+*  		      XIntc_SetIntrSvcOption,XIntc_RegisterHandler and
+*		      XIntc_RegisterFastHandler APIs.Added XIntc_CascadeHandler
+*		      API in xintc_l.c.
+*		      Modified XIntc_SetOptions API in xintc_options.c.
+*		      Modified XIntc_SimulateIntr API in xintc_selftest.c.
+*		      Modified driver tcl:
+*			to check for Cascade mode and generate XPAR_INTC_TYPE
+*			for each controller.
+*			Generate XPAR_INTC_MAX_NUM_INTR_INPUTS by adding all
+*			interrupt sources of all Controllers in Cascade mode.
+* 2.07a bss  10/18/13 To support Nested interrupts:
+*		      Modified XIntc_DeviceInterruptHandler API.
+*		      Added XIN_ILR_OFFSET macro in xintc_l.h.
+*		      Modified driver tcl to generate HAS_ILR parameter in
+*		      xparameters.h
+* 3.0   bss  01/28/13 Modified xintc.c to initialize IVAR register with
+*		      XPAR_MICROBLAZE_BASE_VECTORS + 0x10 to fix
+*		      CR#765931.
+*		      Modified driver tcl to generate XPAR_AXI_INTC_0_TYPE
+*		      correctly(CR#764865).
+*
+* @note
+*		For Cascade mode, Interrupt IDs are generated in xparameters.h
+*		as shown below:
+*
+*	    Master/Primary INTC
+*		 ______
+*		|      |-0      Secondary INTC
+*		|      |-.         ______
+*		|      |-.        |      |-32        Last INTC
+*		|      |-.        |      |-.          ______
+*		|______|<-31------|      |-.         |      |-64
+*			          |      |-.         |      |-.
+*			          |______|<-63-------|      |-.
+*                                                    |      |-.
+*                                                    |______|-95
+*
+*		All driver functions has to be called using DeviceId/
+*		InstancePtr/BaseAddress of Primary/Master Controller and
+*		Interrupts IDs generated in xparameters.h only.
+*		Driver functions takes care of Slave Controllers based on
+*		Interrupt ID passed. User must not use Interrupt source/ID
+*		31 of Primary and Secondary controllers to call driver
+*		functions.
+*
+*		For nested interrupts, XIntc_DeviceInterruptHandler saves
+*		microblaze r14 register on entry and restores on exit. This is
+*		required since compiler does not support nesting. It enables
+*		Microblaze interrupts after blocking further interrupts from
+*		the current interrupt number and interrupts below current
+*		interrupt proirity by writing to Interrupt Level Register of
+*		INTC on entry. On exit, it disables microblaze interrupts and
+*		restores ILR register default value(0xFFFFFFFF)back. It is
+*		recommended to increase STACK_SIZE in linker script for nested
+*		interrupts.
+* 3.0     adk    12/10/13  Updated as per the New Tcl API's
+* 3.0 	  adk 	 17/02/14  Fixed the CR:771287 Changes are made in the intc
+* 		           driver tcl.
+* 3.1     adk    8/4/14    Fixed the CR:783248 Changes are made in
+*			   the test-app tcl
+* 3.2     bss    4/8/14    Fixed driver tcl to handle external interrupt pins
+*			   correctly (CR#799609).
+* 3.3     adk    11/3/14   added generation of C_HAS_ILR parameter to
+*			   xparameters.h.Changes are made in the driver tcl file
+*			   (CR#828046).
+*
+* 
+* +******************************************************************************/ + +#ifndef XINTC_H /* prevent circular inclusions */ +#define XINTC_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xparameters.h" +#include "xstatus.h" +#include "xintc_l.h" + +/************************** Constant Definitions *****************************/ + +/** + * @name Configuration options + * These options are used in XIntc_SetOptions() to configure the device. + * @{ + */ +/** + *
+ * XIN_SVC_SGL_ISR_OPTION	Service the highest priority pending interrupt
+ *				and then return.
+ * XIN_SVC_ALL_ISRS_OPTION	Service all of the pending interrupts and then
+ *				return.
+ * 
+ */ +#define XIN_SVC_SGL_ISR_OPTION 1UL +#define XIN_SVC_ALL_ISRS_OPTION 2UL +/*@}*/ + +/** + * @name Start modes + * One of these values is passed to XIntc_Start() to start the device. + * @{ + */ +/** Simulation only mode, no hardware interrupts recognized */ +#define XIN_SIMULATION_MODE 0 +/** Real mode, no simulation allowed, hardware interrupts recognized */ +#define XIN_REAL_MODE 1 +/*@}*/ + +/** + * @name Masks to specify Interrupt Controller Mode + * @{ + */ +#define XIN_INTC_NOCASCADE 0 /* Normal - No Cascade Mode */ +#define XIN_INTC_PRIMARY 1 /* Master/Primary controller */ +#define XIN_INTC_SECONDARY 2 /* Secondary Slave Controllers */ +#define XIN_INTC_LAST 3 /* Last Slave Controller */ + +/*@}*/ + +/** + * @name Mask to specify maximum number of interrupt sources per controller + * @{ + */ +#define XIN_CONTROLLER_MAX_INTRS 32 /* Each Controller has 32 + interrupt pins */ +/*@}*/ + +/**************************** Type Definitions *******************************/ + +/** + * This typedef contains configuration information for the device. + */ +typedef struct { + u16 DeviceId; /**< Unique ID of device */ + u32 BaseAddress; /**< Register base address */ + u32 AckBeforeService; /**< Ack location per interrupt */ + int FastIntr; /**< Fast Interrupt enabled */ + u32 IntVectorAddr; /**< Interrupt Vector Address */ + int NumberofIntrs; /**< Number of Interrupt sources */ + u32 Options; /**< Device options */ + int IntcType; /**< Intc type 0 - No Cascade Mode + 1 - primary instance + 2 - secondary instance + 3 - last instance */ + +/** Static vector table of interrupt handlers */ +#if XPAR_INTC_0_INTC_TYPE != XIN_INTC_NOCASCADE + XIntc_VectorTableEntry HandlerTable[XIN_CONTROLLER_MAX_INTRS]; +#else + XIntc_VectorTableEntry HandlerTable[XPAR_INTC_MAX_NUM_INTR_INPUTS]; +#endif + +} XIntc_Config; + +/** + * The XIntc driver instance data. The user is required to allocate a + * variable of this type for every intc device in the system. A pointer + * to a variable of this type is then passed to the driver API functions. + */ +typedef struct { + u32 BaseAddress; /**< Base address of registers */ + u32 IsReady; /**< Device is initialized and ready */ + u32 IsStarted; /**< Device has been started */ + u32 UnhandledInterrupts; /**< Intc Statistics */ + XIntc_Config *CfgPtr; /**< Pointer to instance config entry */ + +} XIntc; + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/* + * Required functions in xintc.c + */ +int XIntc_Initialize(XIntc * InstancePtr, u16 DeviceId); + +int XIntc_Start(XIntc * InstancePtr, u8 Mode); +void XIntc_Stop(XIntc * InstancePtr); + +int XIntc_Connect(XIntc * InstancePtr, u8 Id, + XInterruptHandler Handler, void *CallBackRef); +void XIntc_Disconnect(XIntc * InstancePtr, u8 Id); + +void XIntc_Enable(XIntc * InstancePtr, u8 Id); +void XIntc_Disable(XIntc * InstancePtr, u8 Id); + +void XIntc_Acknowledge(XIntc * InstancePtr, u8 Id); + +XIntc_Config *XIntc_LookupConfig(u16 DeviceId); + +int XIntc_ConnectFastHandler(XIntc *InstancePtr, u8 Id, + XFastInterruptHandler Handler); +void XIntc_SetNormalIntrMode(XIntc *InstancePtr, u8 Id); + +/* + * Interrupt functions in xintr_intr.c + */ +void XIntc_VoidInterruptHandler(void); +void XIntc_InterruptHandler(XIntc * InstancePtr); + +/* + * Options functions in xintc_options.c + */ +int XIntc_SetOptions(XIntc * InstancePtr, u32 Options); +u32 XIntc_GetOptions(XIntc * InstancePtr); + +/* + * Self-test functions in xintc_selftest.c + */ +int XIntc_SelfTest(XIntc * InstancePtr); +int XIntc_SimulateIntr(XIntc * InstancePtr, u8 Id); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ diff --git a/XilinxProcessorIPLib/drivers/intc/src/xintc_g.c b/XilinxProcessorIPLib/drivers/intc/src/xintc_g.c new file mode 100644 index 00000000..8a0c9538 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/intc/src/xintc_g.c @@ -0,0 +1,112 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2014 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xintc_g.c +* +* This file contains a configuration table that specifies the configuration of +* interrupt controller devices in the system. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a rpm  01/09/02 First release
+* 1.00b jhl  02/21/02 Repartitioned the driver for smaller files
+* 1.00b jhl  04/24/02 Compressed the ack table into a bit mask.
+* 1.00c rpm  10/17/03 New release. Support the static vector table created
+*                     in the xintc_g.c configuration table.
+* 1.10c mta  03/21/07 Updated to new coding style
+* 
+* +* @internal +* +* This configuration table contains entries that are modified at runtime +* by the driver. The EDK tools populate the table with default values for the +* vector table and the options flag. These default values can be, and are, +* overwritten at runtime by the driver. This is a deviation from most drivers' +* configuration tables in that most are created statically by the tools and +* are never modified during runtime. Most tables reflect only the hardware +* configuration of the device. This Intc configuration table contains software +* information in addition to hardware configuration. The Intc configuration +* table should be considered an exception to the usage of the configuration +* table rather than the norm. +* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xintc.h" +#include "xparameters.h" + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + + +/************************** Variable Prototypes ******************************/ + +/** + * This table contains configuration information for each intc device + * in the system. The XIntc driver must know when to acknowledge the interrupt. + * The entry which specifies this as a bit mask where each bit corresponds to + * a specific interrupt. A bit set indicates to ack it before servicing it. + * Generally, acknowledge before service is used when the interrupt signal is + * edge-sensitive, and after when the signal is level-sensitive. + * + * Refer to the XIntc_Config data structure in xintc.h for details on how this + * table should be initialized. + */ +XIntc_Config XIntc_ConfigTable[XPAR_XINTC_NUM_INSTANCES] = { + { + XPAR_INTC_0_DEVICE_ID, /* Unique ID of device */ + XPAR_INTC_0_BASEADDR, /* Register base address */ + XPAR_INTC_0_ACK_BEFORE, /* Ack before or after service */ + 0 /* Device options */ + } + , + { + XPAR_INTC_1_DEVICE_ID, /* Unique ID of device */ + XPAR_INTC_1_BASEADDR, /* Register base address */ + XPAR_INTC_1_ACK_BEFORE, /* Ack before or after service */ + 0 /* Device options */ + } +}; diff --git a/XilinxProcessorIPLib/drivers/intc/src/xintc_i.h b/XilinxProcessorIPLib/drivers/intc/src/xintc_i.h new file mode 100644 index 00000000..a9b7d680 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/intc/src/xintc_i.h @@ -0,0 +1,90 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2014 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xintc_i.h +* +* This file contains data which is shared between files and internal to the +* XIntc component. It is intended for internal use only. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00b jhl  02/06/02 First release
+* 1.00b jhl  04/24/02 Moved register definitions to xintc_l.h
+* 1.00c rpm  10/17/03 New release. Removed extern of global, single instance
+*                     pointer.
+* 1.10c mta  03/21/07 Updated to new coding style
+* 2.00a ktn  10/20/09 Updated to use HAL Processor APIs.
+* 
+* +******************************************************************************/ + +#ifndef XINTC_I_H /* prevent circular inclusions */ +#define XINTC_I_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xintc.h" + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + + +/************************** Variable Definitions *****************************/ + +extern u32 XIntc_BitPosMask[]; + +extern XIntc_Config XIntc_ConfigTable[]; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/XilinxProcessorIPLib/drivers/intc/src/xintc_intr.c b/XilinxProcessorIPLib/drivers/intc/src/xintc_intr.c new file mode 100644 index 00000000..3179ba98 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/intc/src/xintc_intr.c @@ -0,0 +1,173 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2014 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xintc_intr.c +* +* This file contains the interrupt processing for the XIntc component which +* is the driver for the Xilinx Interrupt Controller. The interrupt +* processing is partitioned seperately such that users are not required to +* use the provided interrupt processing. This file requires other files of +* the driver to be linked in also. +* +* Two different interrupt handlers are provided for this driver such that the +* user must select the appropriate handler for the application. The first +* interrupt handler, XIntc_VoidInterruptHandler, is provided for systems +* which use only a single interrupt controller or for systems that cannot +* otherwise provide an argument to the XIntc interrupt handler (e.g., the RTOS +* interrupt vector handler may not provide such a facility). The constant +* XPAR_INTC_SINGLE_DEVICE_ID must be defined for this handler to be included in +* the driver. The second interrupt handler, XIntc_InterruptHandler, uses an +* input argument which is an instance pointer to an interrupt controller driver +* such that multiple interrupt controllers can be supported. This handler +* requires the calling function to pass it the appropriate argument, so another +* level of indirection may be required. +* +* Note that both of these handlers are now only provided for backward +* compatibility. The handler defined in xintc_l.c is the recommended handler. +* +* The interrupt processing may be used by connecting one of the interrupt +* handlers to the interrupt system. These handlers do not save and restore +* the processor context but only handle the processing of the Interrupt +* Controller. The two handlers are provided as working examples. The user is +* encouraged to supply their own interrupt handler when performance tuning is +* deemed necessary. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- ---------------------------------------------------------
+* 1.00b jhl  02/13/02 First release
+* 1.00c rpm  10/17/03 New release. Support the static vector table created
+*                     in the xintc_g.c configuration table. Collapse handlers
+*                     to use the XIntc_DeviceInterruptHandler() in xintc_l.c.
+* 1.00c rpm  04/09/04 Added conditional compilation around the old handler
+*                     XIntc_VoidInterruptHandler(). This handler will only be
+*                     include/compiled if XPAR_INTC_SINGLE_DEVICE_ID is defined.
+* 1.10c mta  03/21/07 Updated to new coding style
+* 2.00a ktn  10/20/09 Updated to use HAL Processor APIs.
+*
+* 
+* +* @internal +* +* This driver assumes that the context of the processor has been saved prior to +* the calling of the Interrupt Controller interrupt handler and then restored +* after the handler returns. This requires either the running RTOS to save the +* state of the machine or that a wrapper be used as the destination of the +* interrupt vector to save the state of the processor and restore the state +* after the interrupt handler returns. +* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xparameters.h" +#include "xintc.h" + +/************************** Constant Definitions *****************************/ + + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + + +/************************** Variable Definitions *****************************/ + + +/*****************************************************************************/ +/** +* +* Interrupt handler for the driver used when there can be no argument passed +* to the handler. This function is provided mostly for backward compatibility. +* The user should use XIntc_DeviceInterruptHandler(), defined in xintc_l.c, +* if possible. +* +* The user must connect this function to the interrupt system such that it is +* called whenever the devices which are connected to it cause an interrupt. +* +* @return None. +* +* @note +* +* The constant XPAR_INTC_SINGLE_DEVICE_ID must be defined for this handler +* to be included in the driver compilation. +* +******************************************************************************/ +#ifdef XPAR_INTC_SINGLE_DEVICE_ID +void XIntc_VoidInterruptHandler(void) +{ + /* Use the single instance to call the main interrupt handler */ + XIntc_DeviceInterruptHandler((void *) XPAR_INTC_SINGLE_DEVICE_ID); +} +#endif + +/*****************************************************************************/ +/** +* +* The interrupt handler for the driver. This function is provided mostly for +* backward compatibility. The user should use XIntc_DeviceInterruptHandler(), +* defined in xintc_l.c when possible and pass the device ID of the interrupt +* controller device as its argument. +* +* The user must connect this function to the interrupt system such that it is +* called whenever the devices which are connected to it cause an interrupt. +* +* @param InstancePtr is a pointer to the XIntc instance to be worked on. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XIntc_InterruptHandler(XIntc * InstancePtr) +{ + /* Assert that the pointer to the instance is valid + */ + Xil_AssertVoid(InstancePtr != NULL); + + /* Use the instance's device ID to call the main interrupt handler. + * (the casts are to avoid a compiler warning) + */ + XIntc_DeviceInterruptHandler((void *) + ((u32) (InstancePtr->CfgPtr->DeviceId))); +} diff --git a/XilinxProcessorIPLib/drivers/intc/src/xintc_l.c b/XilinxProcessorIPLib/drivers/intc/src/xintc_l.c new file mode 100644 index 00000000..188f5052 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/intc/src/xintc_l.c @@ -0,0 +1,662 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2014 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xintc_l.c +* +* This file contains low-level driver functions that can be used to access the +* device. The user should refer to the hardware device specification for more +* details of the device operation. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00b jhl  04/24/02 First release
+* 1.00c rpm  10/17/03 New release. Support the static vector table created
+*                     in the xintc_g.c configuration table.
+* 1.00c rpm  04/09/04 Added conditional compilation around the old handler
+*                     XIntc_LowLevelInterruptHandler(). This handler will only
+*                     be include/compiled if XPAR_INTC_SINGLE_DEVICE_ID is
+*                     defined.
+* 1.10c mta  03/21/07 Updated to new coding style
+* 1.10c ecm  07/09/07 Read the ISR after the Acknowledge in the interrupt
+*		      handler to support architectures with posted write bus
+*		      access issues.
+* 2.00a ktn  10/20/09 Updated to use HAL Processor APIs and  _m is removed
+*		      from all the macro definitions.
+* 2.04a bss  01/13/12 Removed the unused Register variable for warnings.
+* 2.05a bss  08/18/12 Added XIntc_RegisterFastHandler API to register fast
+*		      interrupt handlers using base address.
+* 2.06a bss  01/28/13 To support Cascade mode:
+*		      Modified XIntc_DeviceInterruptHandler,
+*		      XIntc_SetIntrSvcOption,XIntc_RegisterHandler and
+*		      XIntc_RegisterFastHandler APIs.
+*		      Added XIntc_CascadeHandler API.
+* 2.07a bss  10/18/13 Modified XIntc_DeviceInterruptHandler to support
+*		      nested interrupts.
+*
+* 
+* +******************************************************************************/ + + +/***************************** Include Files *********************************/ + +#include "xparameters.h" +#include "xil_types.h" +#include "xil_assert.h" +#include "xintc.h" +#include "xintc_i.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + +static XIntc_Config *LookupConfigByBaseAddress(u32 BaseAddress); + +#if XPAR_INTC_0_INTC_TYPE != XIN_INTC_NOCASCADE +static void XIntc_CascadeHandler(void *DeviceId); +#endif + +/************************** Variable Definitions *****************************/ + +/*****************************************************************************/ +/** +* +* This is the interrupt handler for the driver interface provided in this file +* when there can be no argument passed to the handler. In this case, we just +* use the globally defined device ID for the interrupt controller. This function +* is provided mostly for backward compatibility. The user should use +* XIntc_DeviceInterruptHandler() if possible. +* +* This function does not support multiple interrupt controller instances to be +* handled. +* +* The user must connect this function to the interrupt system such that it is +* called whenever the devices which are connected to it cause an interrupt. +* +* @return None. +* +* @note +* +* The constant XPAR_INTC_SINGLE_DEVICE_ID must be defined for this handler +* to be included in the driver compilation. +* +******************************************************************************/ +#ifdef XPAR_INTC_SINGLE_DEVICE_ID +void XIntc_LowLevelInterruptHandler(void) +{ + /* + * A level of indirection here because the interrupt handler used with + * the driver interface given in this file needs to remain void - no + * arguments. So we need the globally defined device ID of THE + * interrupt controller. + */ + XIntc_DeviceInterruptHandler((void *) XPAR_INTC_SINGLE_DEVICE_ID); +} +#endif + +/*****************************************************************************/ +/** +* +* This function is the primary interrupt handler for the driver. It must be +* connected to the interrupt source such that is called when an interrupt of +* the interrupt controller is active. It will resolve which interrupts are +* active and enabled and call the appropriate interrupt handler. It uses +* the AckBeforeService flag in the configuration data to determine when to +* acknowledge the interrupt. Highest priority interrupts are serviced first. +* This function assumes that an interrupt vector table has been previously +* initialized.It does not verify that entries in the table are valid before +* calling an interrupt handler. In Cascade mode this function calls +* XIntc_CascadeHandler to handle interrupts of Master and Slave controllers. +* This functions also handles interrupts nesting by saving and restoring link +* register of Microblaze and Interrupt Level register of interrupt controller +* properly. + +* @param DeviceId is the zero-based device ID defined in xparameters.h +* of the interrupting interrupt controller. It is used as a direct +* index into the configuration data, which contains the vector +* table for the interrupt controller. Note that even though the +* argument is a void pointer, the value is not a pointer but the +* actual device ID. The void pointer type is necessary to meet +* the XInterruptHandler typedef for interrupt handlers. +* +* @return None. +* +* @note For nested interrupts, this function saves microblaze r14 +* register on entry and restores on exit. This is required since +* compiler does not support nesting. This function enables +* Microblaze interrupts after blocking further interrupts +* from the current interrupt number and interrupts below current +* interrupt proirity by writing to Interrupt Level Register of +* INTC on entry. On exit, it disables microblaze interrupts and +* restores ILR register default value(0xFFFFFFFF)back. It is +* recommended to increase STACK_SIZE in linker script for nested +* interrupts. +* +******************************************************************************/ +void XIntc_DeviceInterruptHandler(void *DeviceId) +{ + u32 IntrStatus; + u32 IntrMask = 1; + int IntrNumber; + XIntc_Config *CfgPtr; + u32 Imr; + + /* Get the configuration data using the device ID */ + CfgPtr = &XIntc_ConfigTable[(u32)DeviceId]; + +#if XPAR_INTC_0_INTC_TYPE != XIN_INTC_NOCASCADE + if (CfgPtr->IntcType != XIN_INTC_NOCASCADE) { + XIntc_CascadeHandler(DeviceId); + } + else +#endif + { /* This extra brace is required for compilation in Cascade Mode */ + +#if XPAR_XINTC_HAS_ILR == TRUE +#ifdef __MICROBLAZE__ + volatile u32 R14_register; + /* Save r14 register */ + R14_register = mfgpr(r14); +#endif + volatile u32 ILR_reg; + /* Save ILR register */ + ILR_reg = Xil_In32(CfgPtr->BaseAddress + XIN_ILR_OFFSET); +#endif + /* Get the interrupts that are waiting to be serviced */ + IntrStatus = XIntc_GetIntrStatus(CfgPtr->BaseAddress); + + /* Mask the Fast Interrupts */ + if (CfgPtr->FastIntr == TRUE) { + Imr = XIntc_In32(CfgPtr->BaseAddress + XIN_IMR_OFFSET); + IntrStatus &= ~Imr; + } + + /* Service each interrupt that is active and enabled by + * checking each bit in the register from LSB to MSB which + * corresponds to an interrupt input signal + */ + for (IntrNumber = 0; IntrNumber < CfgPtr->NumberofIntrs; + IntrNumber++) { + if (IntrStatus & 1) { + XIntc_VectorTableEntry *TablePtr; +#if XPAR_XINTC_HAS_ILR == TRUE + /* Write to ILR the current interrupt + * number + */ + Xil_Out32(CfgPtr->BaseAddress + + XIN_ILR_OFFSET, IntrNumber); + + /* Read back ILR to ensure the value + * has been updated and it is safe to + * enable interrupts + */ + + Xil_In32(CfgPtr->BaseAddress + + XIN_ILR_OFFSET); + + /* Enable interrupts */ + Xil_ExceptionEnable(); +#endif + /* If the interrupt has been setup to + * acknowledge it before servicing the + * interrupt, then ack it */ + if (CfgPtr->AckBeforeService & IntrMask) { + XIntc_AckIntr(CfgPtr->BaseAddress, + IntrMask); + } + + /* The interrupt is active and enabled, call + * the interrupt handler that was setup with + * the specified parameter + */ + TablePtr = &(CfgPtr->HandlerTable[IntrNumber]); + TablePtr->Handler(TablePtr->CallBackRef); + + /* If the interrupt has been setup to + * acknowledge it after it has been serviced + * then ack it + */ + if ((CfgPtr->AckBeforeService & + IntrMask) == 0) { + XIntc_AckIntr(CfgPtr->BaseAddress, + IntrMask); + } + +#if XPAR_XINTC_HAS_ILR == TRUE + /* Disable interrupts */ + Xil_ExceptionDisable(); + /* Restore ILR */ + Xil_Out32(CfgPtr->BaseAddress + XIN_ILR_OFFSET, + ILR_reg); +#endif + /* + * Read the ISR again to handle architectures + * with posted write bus access issues. + */ + XIntc_GetIntrStatus(CfgPtr->BaseAddress); + + /* + * If only the highest priority interrupt is to + * be serviced, exit loop and return after + * servicing + * the interrupt + */ + if (CfgPtr->Options == XIN_SVC_SGL_ISR_OPTION) { + +#if XPAR_XINTC_HAS_ILR == TRUE +#ifdef __MICROBLAZE__ + /* Restore r14 */ + mtgpr(r14, R14_register); +#endif +#endif + return; + } + } + + /* Move to the next interrupt to check */ + IntrMask <<= 1; + IntrStatus >>= 1; + + /* If there are no other bits set indicating that all + * interrupts have been serviced, then exit the loop + */ + if (IntrStatus == 0) { + break; + } + } +#if XPAR_XINTC_HAS_ILR == TRUE +#ifdef __MICROBLAZE__ + /* Restore r14 */ + mtgpr(r14, R14_register); +#endif +#endif + } +} + +/*****************************************************************************/ +/** +* +* Set the interrupt service option, which can configure the driver so that it +* services only a single interrupt at a time when an interrupt occurs, or +* services all pending interrupts when an interrupt occurs. The default +* behavior when using the driver interface given in xintc.h file is to service +* only a single interrupt, whereas the default behavior when using the driver +* interface given in this file is to service all outstanding interrupts when an +* interrupt occurs. In Cascade mode same Option is set to Slave controllers. +* +* @param BaseAddress is the unique identifier for a device. +* @param Option is XIN_SVC_SGL_ISR_OPTION if you want only a single +* interrupt serviced when an interrupt occurs, or +* XIN_SVC_ALL_ISRS_OPTION if you want all pending interrupts +* serviced when an interrupt occurs. +* +* @return None. +* +* @note +* +* Note that this function has no effect if the input base address is invalid. +* +******************************************************************************/ +void XIntc_SetIntrSvcOption(u32 BaseAddress, int Option) +{ + XIntc_Config *CfgPtr; + + CfgPtr = LookupConfigByBaseAddress(BaseAddress); + if (CfgPtr != NULL) { + CfgPtr->Options = Option; + /* If Cascade mode set the option for all Slaves */ + if (CfgPtr->IntcType != XIN_INTC_NOCASCADE) { + int Index; + for (Index = 1; Index <= XPAR_XINTC_NUM_INSTANCES - 1; + Index++) { + CfgPtr = XIntc_LookupConfig(Index); + CfgPtr->Options = Option; + } + } + } +} + +/*****************************************************************************/ +/** +* +* Register a handler function for a specific interrupt ID. The vector table +* of the interrupt controller is updated, overwriting any previous handler. +* The handler function will be called when an interrupt occurs for the given +* interrupt ID. +* +* This function can also be used to remove a handler from the vector table +* by passing in the XIntc_DefaultHandler() as the handler and NULL as the +* callback reference. +* In Cascade mode Interrupt Id is used to set Handler for corresponding Slave +* Controller +* +* @param BaseAddress is the base address of the interrupt controller +* whose vector table will be modified. +* @param InterruptId is the interrupt ID to be associated with the input +* handler. +* @param Handler is the function pointer that will be added to +* the vector table for the given interrupt ID. +* @param CallBackRef is the argument that will be passed to the new +* handler function when it is called. This is user-specific. +* +* @return None. +* +* @note +* +* Note that this function has no effect if the input base address is invalid. +* +******************************************************************************/ +void XIntc_RegisterHandler(u32 BaseAddress, int InterruptId, + XInterruptHandler Handler, void *CallBackRef) +{ + XIntc_Config *CfgPtr; + + CfgPtr = LookupConfigByBaseAddress(BaseAddress); + + if (CfgPtr != NULL) { + + if (InterruptId > 31) { + CfgPtr = XIntc_LookupConfig(InterruptId/32); + CfgPtr->HandlerTable[InterruptId%32].Handler = Handler; + CfgPtr->HandlerTable[InterruptId%32].CallBackRef = + CallBackRef; + } + else { + CfgPtr->HandlerTable[InterruptId].Handler = Handler; + CfgPtr->HandlerTable[InterruptId].CallBackRef = + CallBackRef; + } + } +} + + +/*****************************************************************************/ +/** +* +* Looks up the device configuration based on the base address of the device. +* A table contains the configuration info for each device in the system. +* +* @param BaseAddress is the unique identifier for a device. +* +* @return +* +* A pointer to the configuration structure for the specified device, or +* NULL if the device was not found. +* +* @note None. +* +******************************************************************************/ +static XIntc_Config *LookupConfigByBaseAddress(u32 BaseAddress) +{ + XIntc_Config *CfgPtr = NULL; + int Index; + + for (Index = 0; Index < XPAR_XINTC_NUM_INSTANCES; Index++) { + if (XIntc_ConfigTable[Index].BaseAddress == BaseAddress) { + CfgPtr = &XIntc_ConfigTable[Index]; + break; + } + } + + return CfgPtr; +} + +/*****************************************************************************/ +/** +* +* Register a fast handler function for a specific interrupt ID. The handler +* function will be called when an interrupt occurs for the given interrupt ID. +* In Cascade mode Interrupt Id is used to set Handler for corresponding Slave +* Controller +* +* @param BaseAddress is the base address of the interrupt controller +* whose vector table will be modified. +* @param InterruptId is the interrupt ID to be associated with the input +* handler. +* @param FastHandler is the function pointer that will be called when +* interrupt occurs +* +* @return None. +* +* @note +* +* Note that this function has no effect if the input base address is invalid. +* +******************************************************************************/ +void XIntc_RegisterFastHandler(u32 BaseAddress, u8 Id, + XFastInterruptHandler FastHandler) +{ + u32 CurrentIER; + u32 Mask; + u32 Imr; + XIntc_Config *CfgPtr; + + + if (Id > 31) { + /* Enable user required Id in Slave controller */ + CfgPtr = XIntc_LookupConfig(Id/32); + + /* Get the Enabled Interrupts */ + CurrentIER = XIntc_In32(CfgPtr->BaseAddress + XIN_IER_OFFSET); + + /* Convert from integer id to bit mask */ + Mask = XIntc_BitPosMask[(Id%32)]; + + /* Disable the Interrupt if it was enabled before calling + * this function + */ + if (CurrentIER & Mask) { + XIntc_Out32(CfgPtr->BaseAddress + XIN_IER_OFFSET, + (CurrentIER & ~Mask)); + } + + XIntc_Out32(CfgPtr->BaseAddress + XIN_IVAR_OFFSET + + ((Id%32) * 4), (u32) FastHandler); + + /* Slave controllers in Cascade Mode should have all as Fast + * interrupts or Normal interrupts, mixed interrupts are not + * supported + */ + XIntc_Out32(CfgPtr->BaseAddress + XIN_IMR_OFFSET, 0xFFFFFFFF); + + /* Enable the Interrupt if it was enabled before calling this + * function + */ + if (CurrentIER & Mask) { + XIntc_Out32(CfgPtr->BaseAddress + XIN_IER_OFFSET, + (CurrentIER | Mask)); + } + } + else { + + CurrentIER = XIntc_In32(BaseAddress + XIN_IER_OFFSET); + + /* Convert from integer id to bit mask */ + Mask = XIntc_BitPosMask[Id]; + + if (CurrentIER & Mask) { + /* Disable Interrupt if it was enabled */ + CurrentIER = XIntc_In32(BaseAddress + XIN_IER_OFFSET); + XIntc_Out32(BaseAddress + XIN_IER_OFFSET, + (CurrentIER & ~Mask)); + } + + XIntc_Out32(BaseAddress + XIN_IVAR_OFFSET + (Id * 4), + (u32) FastHandler); + + Imr = XIntc_In32(BaseAddress + XIN_IMR_OFFSET); + XIntc_Out32(BaseAddress + XIN_IMR_OFFSET, Imr | Mask); + + + /* Enable Interrupt if it was enabled before calling + * this function + */ + if (CurrentIER & Mask) { + CurrentIER = XIntc_In32(BaseAddress + XIN_IER_OFFSET); + XIntc_Out32(BaseAddress + XIN_IER_OFFSET, + (CurrentIER | Mask)); + } + } +} + +#if XPAR_INTC_0_INTC_TYPE != XIN_INTC_NOCASCADE +/*****************************************************************************/ +/** +* +* This function is called by primary interrupt handler for the driver to handle +* all Controllers in Cascade mode.It will resolve which interrupts are active +* and enabled and call the appropriate interrupt handler. It uses the +* AckBeforeService flag in the configuration data to determine when to +* acknowledge the interrupt. Highest priority interrupts are serviced first. +* This function assumes that an interrupt vector table has been previously +* initialized. It does not verify that entries in the table are valid before +* calling an interrupt handler.This function calls itself recursively to handle +* all interrupt controllers. +* +* @param DeviceId is the zero-based device ID defined in xparameters.h +* of the interrupting interrupt controller. It is used as a direct +* index into the configuration data, which contains the vector +* table for the interrupt controller. +* +* @return None. +* +* @note +* +******************************************************************************/ +static void XIntc_CascadeHandler(void *DeviceId) +{ + u32 IntrStatus; + u32 IntrMask = 1; + int IntrNumber; + u32 Imr; + XIntc_Config *CfgPtr; + static int Id = 0; + + /* Get the configuration data using the device ID */ + CfgPtr = &XIntc_ConfigTable[(u32)DeviceId]; + + /* Get the interrupts that are waiting to be serviced */ + IntrStatus = XIntc_GetIntrStatus(CfgPtr->BaseAddress); + + /* Mask the Fast Interrupts */ + if (CfgPtr->FastIntr == TRUE) { + Imr = XIntc_In32(CfgPtr->BaseAddress + XIN_IMR_OFFSET); + IntrStatus &= ~Imr; + } + + /* Service each interrupt that is active and enabled by + * checking each bit in the register from LSB to MSB which + * corresponds to an interrupt input signal + */ + for (IntrNumber = 0; IntrNumber < CfgPtr->NumberofIntrs; IntrNumber++) { + if (IntrStatus & 1) { + XIntc_VectorTableEntry *TablePtr; + + /* In Cascade mode call this function recursively + * for interrupt id 31 and until interrupts of last + * instance/controller are handled + */ + if ((IntrNumber == 31) && + (CfgPtr->IntcType != XIN_INTC_LAST) && + (CfgPtr->IntcType != XIN_INTC_NOCASCADE)) { + XIntc_CascadeHandler((void *)++Id); + Id--; + } + + /* If the interrupt has been setup to + * acknowledge it before servicing the + * interrupt, then ack it */ + if (CfgPtr->AckBeforeService & IntrMask) { + XIntc_AckIntr(CfgPtr->BaseAddress, IntrMask); + } + + /* Handler of 31 interrupt Id has to be called only + * for Last controller in cascade Mode + */ + if (!((IntrNumber == 31) && + (CfgPtr->IntcType != XIN_INTC_LAST) && + (CfgPtr->IntcType != XIN_INTC_NOCASCADE))) { + + /* The interrupt is active and enabled, call + * the interrupt handler that was setup with + * the specified parameter + */ + TablePtr = &(CfgPtr->HandlerTable[IntrNumber]); + TablePtr->Handler(TablePtr->CallBackRef); + } + /* If the interrupt has been setup to acknowledge it + * after it has been serviced then ack it + */ + if ((CfgPtr->AckBeforeService & IntrMask) == 0) { + XIntc_AckIntr(CfgPtr->BaseAddress, IntrMask); + } + + /* + * Read the ISR again to handle architectures with + * posted write bus access issues. + */ + XIntc_GetIntrStatus(CfgPtr->BaseAddress); + + /* + * If only the highest priority interrupt is to be + * serviced, exit loop and return after servicing + * the interrupt + */ + if (CfgPtr->Options == XIN_SVC_SGL_ISR_OPTION) { + return; + } + } + + /* Move to the next interrupt to check */ + IntrMask <<= 1; + IntrStatus >>= 1; + + /* If there are no other bits set indicating that all interrupts + * have been serviced, then exit the loop + */ + if (IntrStatus == 0) { + break; + } + } +} +#endif diff --git a/XilinxProcessorIPLib/drivers/intc/src/xintc_l.h b/XilinxProcessorIPLib/drivers/intc/src/xintc_l.h new file mode 100644 index 00000000..03af4a8c --- /dev/null +++ b/XilinxProcessorIPLib/drivers/intc/src/xintc_l.h @@ -0,0 +1,327 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2014 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xintc_l.h +* +* This header file contains identifiers and low-level driver functions (or +* macros) that can be used to access the device. The user should refer to the +* hardware device specification for more details of the device operation. +* +* +* Note that users of the driver interface given in this file can register +* an interrupt handler dynamically (at run-time) using the +* XIntc_RegisterHandler() function. +* User of the driver interface given in xintc.h should still use +* XIntc_Connect(), as always. +* Also see the discussion of the interrupt vector tables in xintc.h. +* +* There are currently two interrupt handlers specified in this interface. +* +* - XIntc_LowLevelInterruptHandler() is a handler without any arguments that +* is used in cases where there is a single interrupt controller device in +* the system and the handler cannot be passed an argument. This function is +* provided mostly for backward compatibility. +* +* - XIntc_DeviceInterruptHandler() is a handler that takes a device ID as an +* argument, indicating which interrupt controller device in the system is +* causing the interrupt - thereby supporting multiple interrupt controllers. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------------
+* 1.00b jhl  04/24/02 First release
+* 1.00c rpm  10/17/03 New release. Support the static vector table created
+*                     in the xintc_g.c configuration table.
+* 1.10c mta  03/21/07 Updated to new coding style
+* 1.11a sv   11/21/07 Updated driver to support access through a DCR bridge
+* 2.00a ktn  10/20/09 Updated to use HAL Processor APIs. _m is removed from all
+*		      the macro definitions.
+* 2.04a bss  01/13/12 Updated for adding defines for IMR and IVAR for
+*                     the FAST Interrupt
+* 2.05a bss  08/18/12 Added XIntc_RegisterFastHandler API to register fast
+*		      interrupt handlers using base address.
+* 2.07a bss  10/18/13 Added XIN_ILR_OFFSET macro for nested interrupts.
+*
+* 
+* +******************************************************************************/ + +#ifndef XINTC_L_H /* prevent circular inclusions */ +#define XINTC_L_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xparameters.h" +#include "xil_io.h" + +/* + * XPAR_XINTC_USE_DCR_BRIDGE has to be set to 1 if the Intc device will be + * accessed through a DCR bus connected to a bridge. + */ +#define XPAR_XINTC_USE_DCR_BRIDGE 0 + +#if ((XPAR_XINTC_USE_DCR != 0) || (XPAR_XINTC_USE_DCR_BRIDGE != 0)) +#include "xio_dcr.h" +#endif + +/************************** Constant Definitions *****************************/ + +/* define the offsets from the base address for all the registers of the + * interrupt controller, some registers may be optional in the hardware device + */ +#if ((XPAR_XINTC_USE_DCR != 0) || (XPAR_XINTC_USE_DCR_BRIDGE != 0)) + +#define XIN_ISR_OFFSET 0 /* Interrupt Status Register */ +#define XIN_IPR_OFFSET 1 /* Interrupt Pending Register */ +#define XIN_IER_OFFSET 2 /* Interrupt Enable Register */ +#define XIN_IAR_OFFSET 3 /* Interrupt Acknowledge Register */ +#define XIN_SIE_OFFSET 4 /* Set Interrupt Enable Register */ +#define XIN_CIE_OFFSET 5 /* Clear Interrupt Enable Register */ +#define XIN_IVR_OFFSET 6 /* Interrupt Vector Register */ +#define XIN_MER_OFFSET 7 /* Master Enable Register */ +#define XIN_IMR_OFFSET 8 /* Interrupt Mode Register , this is present + * only for Fast Interrupt */ +#define XIN_IVAR_OFFSET 64 /* Interrupt Vector Address Register + * Interrupt 0 Offest, this is present + * only for Fast Interrupt */ + +#else /* ((XPAR_XINTC_USE_DCR != 0) || (XPAR_XINTC_USE_DCR_BRIDGE != 0)) */ + +#define XIN_ISR_OFFSET 0 /* Interrupt Status Register */ +#define XIN_IPR_OFFSET 4 /* Interrupt Pending Register */ +#define XIN_IER_OFFSET 8 /* Interrupt Enable Register */ +#define XIN_IAR_OFFSET 12 /* Interrupt Acknowledge Register */ +#define XIN_SIE_OFFSET 16 /* Set Interrupt Enable Register */ +#define XIN_CIE_OFFSET 20 /* Clear Interrupt Enable Register */ +#define XIN_IVR_OFFSET 24 /* Interrupt Vector Register */ +#define XIN_MER_OFFSET 28 /* Master Enable Register */ +#define XIN_IMR_OFFSET 32 /* Interrupt Mode Register , this is present + * only for Fast Interrupt */ +#define XIN_ILR_OFFSET 36 /* Interrupt level register */ +#define XIN_IVAR_OFFSET 0x100 /* Interrupt Vector Address Register + * Interrupt 0 Offest, this is present + * only for Fast Interrupt */ + + + +#endif /* ((XPAR_XINTC_USE_DCR != 0) || (XPAR_XINTC_USE_DCR_BRIDGE != 0)) */ + +/* Bit definitions for the bits of the MER register */ + +#define XIN_INT_MASTER_ENABLE_MASK 0x1UL +#define XIN_INT_HARDWARE_ENABLE_MASK 0x2UL /* once set cannot be cleared */ + +/**************************** Type Definitions *******************************/ + +/* The following data type defines each entry in an interrupt vector table. + * The callback reference is the base address of the interrupting device + * for the driver interface given in this file and an instance pointer for the + * driver interface given in xintc.h file. + */ +typedef struct { + XInterruptHandler Handler; + void *CallBackRef; +} XIntc_VectorTableEntry; + +typedef void (*XFastInterruptHandler) (void); + +/***************** Macros (Inline Functions) Definitions *********************/ + +/* + * Define the appropriate I/O access method to memory mapped I/O or DCR. + */ +#if ((XPAR_XINTC_USE_DCR != 0) || (XPAR_XINTC_USE_DCR_BRIDGE != 0)) + +#define XIntc_In32 XIo_DcrIn +#define XIntc_Out32 XIo_DcrOut + +#else + +#define XIntc_In32 Xil_In32 +#define XIntc_Out32 Xil_Out32 + +#endif + +/****************************************************************************/ +/** +* +* Enable all interrupts in the Master Enable register of the interrupt +* controller. The interrupt controller defaults to all interrupts disabled +* from reset such that this macro must be used to enable interrupts. +* +* @param BaseAddress is the base address of the device. +* +* @return None. +* +* @note C-style signature: +* void XIntc_MasterEnable(u32 BaseAddress); +* +*****************************************************************************/ +#define XIntc_MasterEnable(BaseAddress) \ + XIntc_Out32((BaseAddress) + XIN_MER_OFFSET, \ + XIN_INT_MASTER_ENABLE_MASK | XIN_INT_HARDWARE_ENABLE_MASK) + +/****************************************************************************/ +/** +* +* Disable all interrupts in the Master Enable register of the interrupt +* controller. +* +* @param BaseAddress is the base address of the device. +* +* @return None. +* +* @note C-style signature: +* void XIntc_MasterDisable(u32 BaseAddress); +* +*****************************************************************************/ +#define XIntc_MasterDisable(BaseAddress) \ + XIntc_Out32((BaseAddress) + XIN_MER_OFFSET, 0) + +/****************************************************************************/ +/** +* +* Enable specific interrupt(s) in the interrupt controller. +* +* @param BaseAddress is the base address of the device +* @param EnableMask is the 32-bit value to write to the enable register. +* Each bit of the mask corresponds to an interrupt input signal +* that is connected to the interrupt controller (INT0 = LSB). +* Only the bits which are set in the mask will enable interrupts. +* +* @return None. +* +* @note C-style signature: +* void XIntc_EnableIntr(u32 BaseAddress, u32 EnableMask); +* +*****************************************************************************/ +#define XIntc_EnableIntr(BaseAddress, EnableMask) \ + XIntc_Out32((BaseAddress) + XIN_IER_OFFSET, (EnableMask)) + +/****************************************************************************/ +/** +* +* Disable specific interrupt(s) in the interrupt controller. +* +* @param BaseAddress is the base address of the device +* @param DisableMask is the 32-bit value to write to the enable register. +* Each bit of the mask corresponds to an interrupt input signal +* that is connected to the interrupt controller (INT0 = LSB). +* Only the bits which are set in the mask will disable interrupts. +* +* @return None. +* +* @note C-style signature: +* void XIntc_DisableIntr(u32 BaseAddress, u32 DisableMask); +* +*****************************************************************************/ +#define XIntc_DisableIntr(BaseAddress, DisableMask) \ + XIntc_Out32((BaseAddress) + XIN_IER_OFFSET, ~(DisableMask)) + +/****************************************************************************/ +/** +* +* Acknowledge specific interrupt(s) in the interrupt controller. +* +* @param BaseAddress is the base address of the device +* @param AckMask is the 32-bit value to write to the acknowledge +* register. Each bit of the mask corresponds to an interrupt input +* signal that is connected to the interrupt controller (INT0 = +* LSB). Only the bits which are set in the mask will acknowledge +* interrupts. +* +* @return None. +* +* @note C-style signature: +* void XIntc_AckIntr(u32 BaseAddress, u32 AckMask); +* +*****************************************************************************/ +#define XIntc_AckIntr(BaseAddress, AckMask) \ + XIntc_Out32((BaseAddress) + XIN_IAR_OFFSET, (AckMask)) + +/****************************************************************************/ +/** +* +* Get the interrupt status from the interrupt controller which indicates +* which interrupts are active and enabled. +* +* @param BaseAddress is the base address of the device +* +* @return The 32-bit contents of the interrupt status register. Each bit +* corresponds to an interrupt input signal that is connected to +* the interrupt controller (INT0 = LSB). Bits which are set +* indicate an active interrupt which is also enabled. +* +* @note C-style signature: +* u32 XIntc_GetIntrStatus(u32 BaseAddress); +* +*****************************************************************************/ +#define XIntc_GetIntrStatus(BaseAddress) \ + (XIntc_In32((BaseAddress) + XIN_ISR_OFFSET) & \ + XIntc_In32((BaseAddress) + XIN_IER_OFFSET)) + +/************************** Function Prototypes ******************************/ + +/* + * Interrupt controller handlers, to be connected to processor exception + * handling code. + */ +void XIntc_LowLevelInterruptHandler(void); +void XIntc_DeviceInterruptHandler(void *DeviceId); + +/* Various configuration functions */ +void XIntc_SetIntrSvcOption(u32 BaseAddress, int Option); + +void XIntc_RegisterHandler(u32 BaseAddress, int InterruptId, + XInterruptHandler Handler, void *CallBackRef); + +void XIntc_RegisterFastHandler(u32 BaseAddress, u8 Id, + XFastInterruptHandler FastHandler); + +/************************** Variable Definitions *****************************/ + + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ diff --git a/XilinxProcessorIPLib/drivers/intc/src/xintc_options.c b/XilinxProcessorIPLib/drivers/intc/src/xintc_options.c new file mode 100644 index 00000000..893795c5 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/intc/src/xintc_options.c @@ -0,0 +1,146 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2014 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xintc_options.c +* +* Contains option functions for the XIntc driver. These functions allow the +* user to configure an instance of the XIntc driver. This file requires other +* files of the component to be linked in also. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------------
+* 1.00b jhl  02/21/02 First release
+* 1.00c rpm  10/17/03 New release. Support the relocation of the options flag
+*                     from the instance structure to the xintc_g.c
+*                     configuration table.
+* 1.10c mta  03/21/07 Updated to new coding style
+* 2.00a ktn  10/20/09 Updated to use HAL Processor APIs
+* 2.06a bss  01/28/13 To support Cascade mode:
+*		      Modified XIntc_SetOptions API.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xintc.h" + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + + +/************************** Variable Definitions *****************************/ + + +/*****************************************************************************/ +/** +* +* Set the options for the interrupt controller driver. In Cascade mode same +* Option is set to Slave controllers. +* +* @param InstancePtr is a pointer to the XIntc instance to be worked on. +* @param Options to be set. The available options are described in +* xintc.h. +* +* @return +* - XST_SUCCESS if the options were set successfully +* - XST_INVALID_PARAM if the specified option was not valid +* +* @note None. +* +****************************************************************************/ +int XIntc_SetOptions(XIntc * InstancePtr, u32 Options) +{ + XIntc_Config *CfgPtr; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Make sure option request is valid + */ + if ((Options == XIN_SVC_SGL_ISR_OPTION) || + (Options == XIN_SVC_ALL_ISRS_OPTION)) { + InstancePtr->CfgPtr->Options = Options; + /* If Cascade mode set the option for all Slaves */ + if (InstancePtr->CfgPtr->IntcType != XIN_INTC_NOCASCADE) { + int Index; + for (Index = 1; Index <= XPAR_XINTC_NUM_INSTANCES - 1; + Index++) { + CfgPtr = XIntc_LookupConfig(Index); + CfgPtr->Options = Options; + } + } + return XST_SUCCESS; + } + else { + return XST_INVALID_PARAM; + } +} + +/*****************************************************************************/ +/** +* +* Return the currently set options. +* +* @param InstancePtr is a pointer to the XIntc instance to be worked on. +* +* @return The currently set options. The options are described in xintc.h. +* +* @note None. +* +****************************************************************************/ +u32 XIntc_GetOptions(XIntc * InstancePtr) +{ + /* + * Assert the arguments + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + return InstancePtr->CfgPtr->Options; +} diff --git a/XilinxProcessorIPLib/drivers/intc/src/xintc_selftest.c b/XilinxProcessorIPLib/drivers/intc/src/xintc_selftest.c new file mode 100644 index 00000000..4a713119 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/intc/src/xintc_selftest.c @@ -0,0 +1,252 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2014 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xintc_selftest.c +* +* Contains diagnostic self-test functions for the XIntc component. This file +* requires other files of the component to be linked in also. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00b jhl  02/21/02 First release
+* 1.10c mta  03/21/07 Updated to new coding style
+* 2.00a ktn  10/20/09 Updated to use HAL Processor APIs
+* 2.04a bss  01/16/12 Removed CurrentMIE variable and reading of the
+*                     MER register to remove warnings
+* 2.06a bss  01/28/13 To support Cascade mode:
+*		      Modified XIntc_SimulateIntr API.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xintc.h" +#include "xintc_i.h" + +/************************** Constant Definitions *****************************/ + +#define XIN_TEST_MASK 1 + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + + +/************************** Variable Definitions *****************************/ + + +/*****************************************************************************/ +/** +* +* Run a self-test on the driver/device. This is a destructive test. +* +* This involves forcing interrupts into the controller and verifying that they +* are recognized and can be acknowledged. This test will not succeed if the +* interrupt controller has been started in real mode such that interrupts +* cannot be forced. +* +* @param InstancePtr is a pointer to the XIntc instance to be worked on. +* +* @return +* - XST_SUCCESS if self-test is successful. +* - XST_INTC_FAIL_SELFTEST if the Interrupt controller fails the +* self-test. It will fail the self test if the device has +* previously been started in real mode. +* +* @note None. +* +******************************************************************************/ +int XIntc_SelfTest(XIntc * InstancePtr) +{ + u32 CurrentISR; + u32 Temp; + + /* + * Assert the arguments + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + + /* + * Acknowledge all pending interrupts by reading the interrupt status + * register and writing the value to the acknowledge register + */ + Temp = XIntc_In32(InstancePtr->BaseAddress + XIN_ISR_OFFSET); + + XIntc_Out32(InstancePtr->BaseAddress + XIN_IAR_OFFSET, Temp); + + /* + * Verify that there are no interrupts by reading the interrupt status + */ + CurrentISR = XIntc_In32(InstancePtr->BaseAddress + XIN_ISR_OFFSET); + + /* + * ISR should be zero after all interrupts are acknowledged + */ + if (CurrentISR != 0) { + return XST_INTC_FAIL_SELFTEST; + } + + /* + * Set a bit in the ISR which simulates an interrupt + */ + XIntc_Out32(InstancePtr->BaseAddress + XIN_ISR_OFFSET, XIN_TEST_MASK); + + /* + * Verify that it was set + */ + CurrentISR = XIntc_In32(InstancePtr->BaseAddress + XIN_ISR_OFFSET); + + if (CurrentISR != XIN_TEST_MASK) { + return XST_INTC_FAIL_SELFTEST; + } + + /* + * Acknowledge the interrupt + */ + XIntc_Out32(InstancePtr->BaseAddress + XIN_IAR_OFFSET, XIN_TEST_MASK); + + /* + * Read back the ISR to verify that the interrupt is gone + */ + CurrentISR = XIntc_In32(InstancePtr->BaseAddress + XIN_ISR_OFFSET); + + if (CurrentISR != 0) { + return XST_INTC_FAIL_SELFTEST; + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* Allows software to simulate an interrupt in the interrupt controller. This +* function will only be successful when the interrupt controller has been +* started in simulation mode. Once it has been started in real mode, +* interrupts cannot be simulated. A simulated interrupt allows the interrupt +* controller to be tested without any device to drive an interrupt input +* signal into it. In Cascade mode writes to ISR of appropraite Slave +* controller depending on Id. +* +* @param InstancePtr is a pointer to the XIntc instance to be worked on. +* @param Id is the interrupt ID for which to simulate an interrupt. +* +* @return +* - XST_SUCCESS if successful +* - XST_FAILURE if the interrupt could not be +* simulated because the interrupt controller is or +* has previously been in real mode. +* +* @note None. +* +******************************************************************************/ +int XIntc_SimulateIntr(XIntc * InstancePtr, u8 Id) +{ + u32 Mask; + u32 MasterEnable; + XIntc_Config *CfgPtr; + int Index; + int DeviceId; + + /* + * Assert the arguments + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(Id < XPAR_INTC_MAX_NUM_INTR_INPUTS); + + + /* Get the contents of the master enable register and determine if + * hardware interrupts have already been enabled, if so, this is a write + * once bit such that simulation can't be done at this point because + * the ISR register is no longer writable by software + */ + MasterEnable = XIntc_In32(InstancePtr->BaseAddress + XIN_MER_OFFSET); + if (MasterEnable & XIN_INT_HARDWARE_ENABLE_MASK) { + return XST_FAILURE; + } + + + if (Id > 31) { + + DeviceId = Id/32; + + CfgPtr = XIntc_LookupConfig(Id/32); + Mask = XIntc_BitPosMask[Id%32]; + XIntc_Out32(CfgPtr->BaseAddress + XIN_ISR_OFFSET, Mask); + + /* Generate interrupt for 31 by writing to Interrupt Status + * register of parent controllers. Primary controller ISR + * will be written last in the loop + */ + Mask = XIntc_BitPosMask[31]; + for (Index = DeviceId - 1; Index >= 0; Index--) + { + CfgPtr = XIntc_LookupConfig(Index); + + XIntc_Out32(CfgPtr->BaseAddress + XIN_ISR_OFFSET, + Mask); + } + } + else { + /* + * The Id is used to create the appropriate mask for the + * desired bit position. + */ + Mask = XIntc_BitPosMask[Id]; + + /* + * Enable the selected interrupt source by reading the interrupt + * enable register and then modifying only the specified + * interrupt id enable + */ + XIntc_Out32(InstancePtr->BaseAddress + XIN_ISR_OFFSET, Mask); + + } + /* indicate the interrupt was successfully simulated */ + + return XST_SUCCESS; +}