spi: Add new version 4.1 and deprecate 4.0

Added new driver version spi_v4_1 and deprecate spi_v4_0

Signed-off-by: Subbaraya Sundeep Bhatta <sbhatta@xilinx.com>
Acked-by: Kedareswara rao Appana <appanad@xilinx.com>
This commit is contained in:
Subbaraya Sundeep Bhatta 2014-08-07 15:02:47 +05:30 committed by Jagannadha Sutradharudu Teki
parent ecd70612c1
commit 10d10f8c2e
29 changed files with 11675 additions and 0 deletions

View file

@ -0,0 +1,60 @@
###############################################################################
#
# 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
# -------- ------ -------- --------------------------------------------------
# 4.0 adk 10/12/13 Removed support for xps_spi xps_insystem_flash
##############################################################################
## @BEGIN_CHANGELOG EDK_M
##
## 11/27/09 ktn Removed support for opb_spi
##
## @END_CHANGELOG
## @BEGIN_CHANGELOG EDK_MS3
##
## 06/16/10 sv Added support for axi_spi
##
## @END_CHANGELOG
OPTION psf_version = 2.1;
BEGIN driver spi
OPTION supported_peripherals = (axi_spi axi_quad_spi);
OPTION driver_state = ACTIVE;
OPTION copyfiles = all;
OPTION VERSION = 4.1;
OPTION NAME = spi;
END driver

View file

@ -0,0 +1,348 @@
###############################################################################
#
# 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.03a sdm 08/11/10 Added C_SPI_MODE parameter to config structure
# 3.04a bss 03/21/12 Added C_TYPE_OF_AXI4_INTERFACE, C_AXI4_BASEADDR and
# C_XIP_MODE to config structure.
# Modified such that based on C_XIP_MODE and
# C_TYPE_OF_AXI4_INTERFACE parameters C_BASEADDR will
# be updated with the value of C_AXI4_BASEADDR.
# Modified such that C_FIFO_EXIST will be updated based
# on C_FIFO_DEPTH for compatability of driver
# 3.06a adk 07/08/13 Added C_USE_STARTUP parameter to the config structure
# 4.0 adk 12/10/13 Updated as per the New Tcl API's
#
##############################################################################
#uses "xillib.tcl"
set periph_config_params_spi 0
set periph_ninstances_spi 0
proc init_periph_config_struct_spi { deviceid } {
global periph_config_params_spi
set periph_config_params_spi($deviceid) [list]
}
proc add_field_to_periph_config_struct_spi { deviceid fieldval } {
global periph_config_params_spi
lappend periph_config_params_spi($deviceid) $fieldval
}
proc get_periph_config_struct_fields_spi { deviceid } {
global periph_config_params_spi
return $periph_config_params_spi($deviceid)
}
proc xdefine_axispi_include_file {drv_handle file_name drv_string} {
global periph_ninstances
# Open include file
set file_handle [::hsm::utils::open_include_file $file_name]
# Get all peripherals connected to this driver
set periphs [::hsm::utils::get_common_driver_ips $drv_handle]
# Handle NUM_INSTANCES
set periph_ninstances 0
puts $file_handle "/* Definitions for driver [string toupper [get_property NAME $drv_handle]] */"
foreach periph $periphs {
init_periph_config_struct_spi $periph_ninstances
incr periph_ninstances 1
}
puts $file_handle "\#define [::hsm::utils::get_driver_param_name $drv_string NUM_INSTANCES] $periph_ninstances"
# Now print all useful parameters for all peripherals
set device_id 0
foreach periph $periphs {
puts $file_handle ""
xdefine_axispi_params_instance $file_handle $periph $device_id
xdefine_axispi_params_canonical $file_handle $periph $device_id
incr device_id
puts $file_handle "\n"
}
puts $file_handle "\n/******************************************************************/\n"
close $file_handle
}
proc xdefine_axispi_params_instance {file_handle periph device_id} {
set ip [get_cells $periph]
set xip_mode_value [get_property CONFIG.C_XIP_MODE $ip]
if {[llength $xip_mode_value] == 0} {
set xip_mode_value 0
}
set axi_type_value [get_property CONFIG.C_TYPE_OF_AXI4_INTERFACE $periph]
if {[llength $axi_type_value] == 0} {
set axi_type_value 0
}
set axi4_baseaddr_value [get_property CONFIG.C_S_AXI4_BASEADDR $periph]
if {[llength $axi4_baseaddr_value] == 0} {
set axi4_baseaddr_value 0
}
set axi4_highaddr_value [get_property CONFIG.C_S_AXI4_HIGHADDR $periph]
if {[llength $axi4_highaddr_value] == 0} {
set axi4_highaddr_value 0
}
puts $file_handle "/* Definitions for peripheral [string toupper [get_property NAME $periph]] */"
puts $file_handle "\#define [::hsm::utils::get_driver_param_name $periph "DEVICE_ID"] $device_id"
if {$xip_mode_value == 0} {
if {$axi_type_value == 0} {
puts $file_handle "\#define [::hsm::utils::get_driver_param_name $periph "BASEADDR"] [get_property CONFIG.C_BASEADDR $periph]"
puts $file_handle "\#define [::hsm::utils::get_driver_param_name $periph HIGHADDR] [get_property CONFIG.C_HIGHADDR $periph]"
} else {
puts $file_handle "\#define [::hsm::utils::get_driver_param_name $periph "BASEADDR"] $axi4_baseaddr_value"
puts $file_handle "\#define [::hsm::utils::get_driver_param_name $periph HIGHADDR] $axi4_highaddr_value"
}
} else {
puts $file_handle "\#define [::hsm::utils::get_driver_param_name $periph "BASEADDR"] [get_property CONFIG.C_BASEADDR $periph]"
puts $file_handle "\#define [::hsm::utils::get_driver_param_name $periph HIGHADDR] [get_property CONFIG.C_HIGHADDR $periph]"
}
set value [get_property CONFIG.C_FIFO_EXIST $periph]
if {[llength $value] == 0} {
set value1 [get_property CONFIG.C_FIFO_DEPTH $periph]
if {[llength $value1] == 0} {
set value1 0
} else {
set value1 [get_property CONFIG.C_FIFO_DEPTH $periph]
puts $file_handle "\#define [::hsm::utils::get_driver_param_name $periph "FIFO_DEPTH"] $value1"
if {$value1 == 0} {
set value1 0
} else {
set value1 1
}
}
} else {
set value1 $value
}
puts $file_handle "\#define [::hsm::utils::get_driver_param_name $periph "FIFO_EXIST"] $value1"
set value [get_property CONFIG.C_SPI_SLAVE_ONLY $periph]
if {[llength $value] == 0} {
set value 0
}
puts $file_handle "\#define [::hsm::utils::get_driver_param_name $periph "SPI_SLAVE_ONLY"] $value"
set value [get_property CONFIG.C_NUM_SS_BITS $periph]
if {[llength $value] == 0} {
set value 0
}
puts $file_handle "\#define [::hsm::utils::get_driver_param_name $periph "NUM_SS_BITS"] $value"
set value [get_property CONFIG.C_NUM_TRANSFER_BITS $periph]
if {[llength $value] == 0} {
set value 0
}
puts $file_handle "\#define [::hsm::utils::get_driver_param_name $periph "NUM_TRANSFER_BITS"] $value"
set value [get_property CONFIG.C_SPI_MODE $periph]
if {[llength $value] == 0} {
set value 0
}
puts $file_handle "\#define [::hsm::utils::get_driver_param_name $periph "SPI_MODE"] $value"
puts $file_handle "\#define [::hsm::utils::get_driver_param_name $periph "TYPE_OF_AXI4_INTERFACE"] $axi_type_value"
puts $file_handle "\#define [::hsm::utils::get_driver_param_name $periph "AXI4_BASEADDR"] $axi4_baseaddr_value"
puts $file_handle "\#define [::hsm::utils::get_driver_param_name $periph "AXI4_HIGHADDR"] $axi4_highaddr_value"
puts $file_handle "\#define [::hsm::utils::get_driver_param_name $periph "XIP_MODE"] $xip_mode_value"
}
proc xdefine_axispi_params_canonical {file_handle periph device_id} {
set xip_mode_value [get_property CONFIG.C_XIP_MODE $periph]
if {[llength $xip_mode_value] == 0} {
set xip_mode_value 0
}
set axi_type_value [get_property CONFIG.C_TYPE_OF_AXI4_INTERFACE $periph]
if {[llength $axi_type_value] == 0} {
set axi_type_value 0
}
set axi4_baseaddr_value [get_property CONFIG.C_S_AXI4_BASEADDR $periph]
if {[llength $axi4_baseaddr_value] == 0} {
set axi4_baseaddr_value 0
}
set axi4_highaddr_value [get_property CONFIG.C_S_AXI4_HIGHADDR $periph]
if {[llength $axi4_highaddr_value] == 0} {
set axi4_highaddr_value 0
}
set use_startup_value [get_property CONFIG.C_USE_STARTUP $periph]
if {[llength $use_startup_value] == 0} {
set use_startup_value 0
}
puts $file_handle "\n/* Canonical definitions for peripheral [string toupper [get_property NAME $periph]] */"
set canonical_tag [string toupper [format "XPAR_SPI_%d" $device_id]]
# Handle device ID
set canonical_name [format "%s_DEVICE_ID" $canonical_tag]
puts $file_handle "\#define $canonical_name $device_id"
add_field_to_periph_config_struct_spi $device_id $canonical_name
if {$xip_mode_value == 0} {
if {$axi_type_value == 0} {
set canonical_name [format "%s_BASEADDR" $canonical_tag]
puts $file_handle "\#define $canonical_name [get_property CONFIG.C_BASEADDR $periph]"
add_field_to_periph_config_struct_spi $device_id $canonical_name
set canonical_name [format "%s_HIGHADDR" $canonical_tag]
puts $file_handle "\#define $canonical_name [get_property CONFIG.C_HIGHADDR $periph]"
} else {
set canonical_name [format "%s_BASEADDR" $canonical_tag]
puts $file_handle "\#define $canonical_name $axi4_baseaddr_value"
add_field_to_periph_config_struct_spi $device_id $canonical_name
set canonical_name [format "%s_HIGHADDR" $canonical_tag]
puts $file_handle "\#define $canonical_name $axi4_highaddr_value"
}
} else {
set canonical_name [format "%s_BASEADDR" $canonical_tag]
puts $file_handle "\#define $canonical_name [get_property CONFIG.C_BASEADDR $periph]"
add_field_to_periph_config_struct_spi $device_id $canonical_name
set canonical_name [format "%s_HIGHADDR" $canonical_tag]
puts $file_handle "\#define $canonical_name [get_property CONFIG.C_HIGHADDR $periph]"
}
set canonical_name [format "%s_FIFO_EXIST" $canonical_tag]
set value [get_property CONFIG.C_FIFO_EXIST $periph]
if {[llength $value] == 0} {
set value1 [get_property CONFIG.C_FIFO_DEPTH $periph]
if {[llength $value1] == 0} {
set value1 0
} else {
set canonical_name1 [format "%s_FIFO_DEPTH" $canonical_tag]
puts $file_handle "\#define $canonical_name1 $value1"
if {$value1 == 0} {
set value1 0
} else {
set value1 1
}
}
} else {
set value1 $value
}
puts $file_handle "\#define $canonical_name $value1"
add_field_to_periph_config_struct_spi $device_id $canonical_name
set canonical_name [format "%s_SPI_SLAVE_ONLY" $canonical_tag]
set value [get_property CONFIG.C_SPI_SLAVE_ONLY $periph]
if {[llength $value] == 0} {
set value 0
}
puts $file_handle "\#define $canonical_name $value"
add_field_to_periph_config_struct_spi $device_id $canonical_name
set canonical_name [format "%s_NUM_SS_BITS" $canonical_tag]
set value [get_property CONFIG.C_NUM_SS_BITS $periph]
if {[llength $value] == 0} {
set value 0
}
puts $file_handle "\#define $canonical_name $value"
add_field_to_periph_config_struct_spi $device_id $canonical_name
set canonical_name [format "%s_NUM_TRANSFER_BITS" $canonical_tag]
set value [get_property CONFIG.C_NUM_TRANSFER_BITS $periph]
if {[llength $value] == 0} {
set value 0
}
puts $file_handle "\#define $canonical_name $value"
add_field_to_periph_config_struct_spi $device_id $canonical_name
set canonical_name [format "%s_SPI_MODE" $canonical_tag]
set value [get_property CONFIG.C_SPI_MODE $periph]
if {[llength $value] == 0} {
set value 0
}
puts $file_handle "\#define $canonical_name $value"
add_field_to_periph_config_struct_spi $device_id $canonical_name
set canonical_name [format "%s_TYPE_OF_AXI4_INTERFACE" $canonical_tag]
puts $file_handle "\#define $canonical_name $axi_type_value"
add_field_to_periph_config_struct_spi $device_id $canonical_name
set canonical_name [format "%s_AXI4_BASEADDR" $canonical_tag]
puts $file_handle "\#define $canonical_name $axi4_baseaddr_value"
add_field_to_periph_config_struct_spi $device_id $canonical_name
set canonical_name [format "%s_AXI4_HIGHADDR" $canonical_tag]
puts $file_handle "\#define $canonical_name $axi4_highaddr_value"
set canonical_name [format "%s_XIP_MODE" $canonical_tag]
puts $file_handle "\#define $canonical_name $xip_mode_value"
add_field_to_periph_config_struct_spi $device_id $canonical_name
set canonical_name [format "%s_USE_STARTUP" $canonical_tag]
puts $file_handle "\#define $canonical_name $use_startup_value"
add_field_to_periph_config_struct_spi $device_id $canonical_name
}
proc xdefine_axispi_config_file {file_name drv_string} {
global periph_ninstances
set filename [file join "src" $file_name]
file delete $filename
set config_file [open $filename w]
::hsm::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/*"
puts $config_file "* The configuration table for devices"
puts $config_file "*/\n"
puts $config_file [format "%s_Config %s_ConfigTable\[\] =" $drv_string $drv_string]
puts $config_file "\{"
set start_comma ""
for {set i 0} {$i < $periph_ninstances} {incr i} {
puts $config_file [format "%s\t\{" $start_comma]
set comma ""
foreach field [get_periph_config_struct_fields_spi $i] {
puts -nonewline $config_file [format "%s\t\t%s" $comma $field]
set comma ",\n"
}
puts -nonewline $config_file "\n\t\}"
set start_comma ",\n"
}
puts $config_file "\n\};\n"
close $config_file
}
proc generate {drv_handle} {
xdefine_axispi_include_file $drv_handle "xparameters.h" "XSpi"
xdefine_axispi_config_file "xspi_g.c" "XSpi"
}

View file

@ -0,0 +1,42 @@
/******************************************************************************
*
* Copyright (C) 2007 - 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 SPI_HEADER_H /* prevent circular inclusions */
#define SPI_HEADER_H /* by using protection macros */
#include "xil_types.h"
#include "xil_assert.h"
#include "xstatus.h"
int SpiSelfTestExample(u16 DeviceId);
#endif

View file

@ -0,0 +1,53 @@
/******************************************************************************
*
* Copyright (C) 2008 - 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 SPI_INTR_HEADER_H /* prevent circular inclusions */
#define SPI_INTR_HEADER_H /* by using protection macros */
#include "xil_types.h"
#include "xil_assert.h"
#include "xstatus.h"
#ifdef XPAR_INTC_0_DEVICE_ID
int SpiIntrExample(XIntc *IntcInstancePtr, \
XSpi *SpiInstancePtr, \
u16 SpiDeviceId, \
u16 SpiIntrId);
#else
int SpiIntrExample(XScuGic *IntcInstancePtr, \
XSpi *SpiInstancePtr, \
u16 SpiDeviceId, \
u16 SpiIntrId);
#endif
#endif

View file

@ -0,0 +1,236 @@
###############################################################################
#
# 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
# -------- ------ -------- ------------------------------------
# 4.0 adk 12/10/13 Updated as per the New Tcl API's
##############################################################################
## @BEGIN_CHANGELOG EDK_L_SP4
##
## - Removed the checking of the parametr C_INTERRUPT_PRESENT as
## this is not present in the core
##
## @END_CHANGELOG
## @BEGIN_CHANGELOG EDK_Im_SP2
##
## - Added Interrupt support
##
## @END_CHANGELOG
## @BEGIN_CHANGELOG EDK_I
##
## - include header files
##
## @END_CHANGELOG
## @BEGIN_CHANGELOG EDK_H
##
## - Added support for generation of multiple applications.
## All TCL procedures are now required to have a software
## project type as its first argument
##
## @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 spi_intr [::hsm::utils::is_ip_interrupting_current_proc $mhsinst]
if { ${spi_intr} == 1} {
set inc_file_lines {xspi.h spi_header.h spi_intr_header.h}
} else {
set inc_file_lines {xspi.h spi_header.h}
}
return $inc_file_lines
}
}
proc gen_src_files {swproj mhsinst} {
if {$swproj == 0} {
return ""
}
if {$swproj == 1} {
set spi_intr [::hsm::utils::is_ip_interrupting_current_proc $mhsinst]
if { ${spi_intr} == 1} {
set inc_file_lines {examples/xspi_selftest_example.c examples/xspi_intr_example.c data/spi_header.h data/spi_intr_header.h}
} else {
set inc_file_lines {examples/xspi_selftest_example.c data/spi_header.h}
}
return $inc_file_lines
}
}
proc gen_testfunc_def {swproj mhsinst} {
return ""
}
proc gen_init_code {swproj mhsinst} {
if {$swproj == 0} {
return ""
}
if {$swproj == 1} {
set spi_intr [::hsm::utils::is_ip_interrupting_current_proc $mhsinst]
set ipname [get_property NAME $mhsinst]
if { ${spi_intr} == 1} {
set decl " static XSpi ${ipname}_Spi;"
set inc_file_lines $decl
return $inc_file_lines
} else {
return ""
}
}
}
proc gen_testfunc_call {swproj mhsinst} {
if {$swproj == 0} {
return ""
}
set ipname [get_property NAME $mhsinst]
set deviceid [::hsm::utils::get_ip_param_name $mhsinst "DEVICE_ID"]
set stdout [get_property CONFIG.STDOUT [get_os]]
if { $stdout == "" || $stdout == "none" } {
set hasStdout 0
} else {
set hasStdout 1
}
set spi_intr [::hsm::utils::is_ip_interrupting_current_proc $mhsinst]
if { ${spi_intr} == 1} {
set intr_pin_name [get_pins -of_objects [get_cells $ipname] -filter "TYPE==INTERRUPT"]
set intcname [::hsm::utils::get_connected_intr_cntrl $ipname $intr_pin_name]
set intcvar intc
set proc [get_property IP_NAME [get_cells [get_sw_processor]]]
}
set testfunc_call ""
if {${hasStdout} == 0} {
append testfunc_call "
{
XStatus status;
status = SpiSelfTestExample(${deviceid});
}"
if { ${spi_intr} == 1} {
if {
$proc == "microblaze"
} then {
set intr_id "XPAR_${intcname}_${ipname}_${intr_pin_name}_INTR"
} else {
set intr_id "XPAR_FABRIC_${ipname}_${intr_pin_name}_INTR"
}
set intr_id [string toupper $intr_id]
append testfunc_call "
{
XStatus Status;
Status = SpiIntrExample(&${intcvar}, &${ipname}_Spi, \\
${deviceid}, \\
${intr_id});
}"
}
} else {
append testfunc_call "
{
XStatus status;
print(\"\\r\\n Runnning SpiSelfTestExample() for ${ipname}...\\r\\n\");
status = SpiSelfTestExample(${deviceid});
if (status == 0) {
print(\"SpiSelfTestExample PASSED\\r\\n\");
}
else {
print(\"SpiSelfTestExample FAILED\\r\\n\");
}
}"
if { ${spi_intr} == 1} {
if {
$proc == "microblaze"
} then {
set intr_id "XPAR_${intcname}_${ipname}_${intr_pin_name}_INTR"
} else {
set intr_id "XPAR_FABRIC_${ipname}_${intr_pin_name}_INTR"
}
set intr_id [string toupper $intr_id]
append testfunc_call "
{
XStatus Status;
print(\"\\r\\n Running Interrupt Test for ${ipname}...\\r\\n\");
Status = SpiIntrExample(&${intcvar}, &${ipname}_Spi, \\
${deviceid}, \\
${intr_id});
if (Status == 0) {
print(\"Spi Interrupt Test PASSED\\r\\n\");
}
else {
print(\"Spi Interrupt Test FAILED\\r\\n\");
}
}"
}
}
return $testfunc_call
}

View file

@ -0,0 +1,27 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<html>
<head>
<meta http-equiv="Content-Language" content="en-us">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Driver example applications</title>
<link rel="stylesheet" type="text/css" href="../help.css">
</head>
<body bgcolor="#FFFFFF">
<h1> Example Applications for the driver spi_v4_0</h1>
<HR>
<ul>
<li>xspi_atmel_flash_example.c <a href="xspi_atmel_flash_example.c">(source)</a> </li>
<li>xspi_eeprom_example.c <a href="xspi_eeprom_example.c">(source)</a> </li>
<li>xspi_intel_flash_example.c <a href="xspi_intel_flash_example.c">(source)</a> </li>
<li>xspi_intr_example.c <a href="xspi_intr_example.c">(source)</a> </li>
<li>xspi_low_level_example.c <a href="xspi_low_level_example.c">(source)</a> </li>
<li>xspi_polled_example.c <a href="xspi_polled_example.c">(source)</a> </li>
<li>xspi_selftest_example.c <a href="xspi_selftest_example.c">(source)</a> </li>
<li>xspi_slave_intr_example.c <a href="xspi_slave_intr_example.c">(source)</a> </li>
<li>xspi_slave_polled_example.c <a href="xspi_slave_polled_example.c">(source)</a> </li>
<li>xspi_stm_flash_example.c <a href="xspi_stm_flash_example.c">(source)</a> </li>
<li>xspi_winbond_flash_quad_example.c <a href="xspi_winbond_flash_quad_example.c">(source)</a> </li>
</ul>
<p><font face="Times New Roman" color="#800000">Copyright <20> 1995-2014 Xilinx, Inc. All rights reserved.</font></p>
</body>
</html>

View file

@ -0,0 +1,692 @@
/******************************************************************************
*
* Copyright (C) 2008 - 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 xspi_atmel_flash_example.c
*
* This file contains a design example using the SPI driver (XSpi) and
* hardware device with an Atmel Serial Flash Device (AT45XX series).
* This example erases the Page, writes to the Page, reads back from the Page and
* compares the data.
*
* This example works for an Atmel AT45DB161D. The bytes per page
* (ATMEL_PAGE_SIZE) in this device is 528 bytes for default addressing mode and
* 512 bytes in Power-of-2 addressing mode.
* For further details of device refer to the Atmel Datasheet of AT45DB161D
* device.
*
* The ATMEL_PAGE_SIZE constant need to be updated by the user according to the
* Device used.
*
* The ATMEL_FLASH_TEST_ADDRESS constant need to be updated by the user according
* to the serial flash device used, there is no error checking done in the
* example for the address specified by the user.
*
* This example also works with the In-System Flash(ISF) in the S3AN devices.
* The ATMEL_PAGE_SIZE and ATMEL_FLASH_TEST_ADDRESS need to be defined properly
* based on the device used. For further details of the ISF refer to the
* Spartan-3AN FPGA In-System Flash User Guide (UG333).
*
* This example assumes that the underlying processor is MicroBlaze and default
* addressing mode is used in the Flash Device.
*
* @note
*
* None.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- -------- -----------------------------------------------
* 1.00a sdn 02/26/08 First release
* 1.00a sdn 07/02/08 Changed the initialization so that the SPI
* Master works in Spi Mode 3 as the In-System Flash
* works only in Spi Mode 3
* 3.00a ktn 10/22/09 Converted all register accesses to 32 bit access.
* Updated to use the HAL APIs/macros. Replaced call to
* XSpi_Initialize API with XSpi_LookupConfig and
* XSpi_CfgInitialize.
* </pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "xparameters.h" /* EDK generated parameters */
#include "xintc.h" /* Interrupt controller device driver */
#include "xspi.h" /* SPI device driver */
#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 SPI_DEVICE_ID XPAR_SPI_0_DEVICE_ID
#define INTC_DEVICE_ID XPAR_INTC_0_DEVICE_ID
#define SPI_INTR_ID XPAR_INTC_0_SPI_0_VEC_ID
/*
* The following constant defines the slave select signal that is used to
* to select the Flash device on the SPI bus, this signal is typically
* connected to the chip select of the device.
*/
#define ATMEL_SPI_SELECT 0x01
/*
* Definition of the commands
*/
#define ATMEL_COMMAND_READ 0x03 /* Read command */
#define ATMEL_COMMAND_WRITE 0x82 /* Write command */
#define ATMEL_COMMAND_STATUSREG_READ 0xD7 /* Status Register Read command */
#define ATMEL_COMMAND_PAGE_ERASE 0x81 /* Erase command */
/*
* The following definition specify the EXTRA bytes in the command
* transactions. This count includes Command byte, address bytes and any
* don't care bytes needed.
*/
#define ATMEL_READ_WRITE_EXTRA_BYTES 0x4 /* Read/Write extra bytes */
#define ATMEL_PAGE_ERASE_BYTES 0x4 /* Page erase extra bytes */
#define ATMEL_STATUS_READ_BYTES 0x2 /* Status read bytes count */
/*
* The following constants define the offsets for command and data.
* Note that the read data offset is not the same as the write data
* because the SPI driver is designed to allow full duplex transfers
* such that the number of bytes received is the number sent and received.
*/
#define ATMEL_COMMAND_OFFSET 0
#define ATMEL_ADDRESS_BYTE1_OFFSET 1
#define ATMEL_ADDRESS_BYTE2_OFFSET 2
#define ATMEL_ADDRESS_BYTE3_OFFSET 3
/*
* The following definitions specify the status register bit definitions.
*/
#define ATMEL_FLASH_SR_IS_READY_MASK 0x80
#define ATMEL_PAGE_SIZE 264 /* Page Size */
/*
* Address of the page to perform Erase, Write and Read operations.
*/
#define ATMEL_FLASH_TEST_ADDRESS 0x259800
/*
* Byte offset value written to Flash. This needs to redefined for writing
* different patterns of data to the Flash device.
*/
#define ATMEL_TEST_BYTE 0x10 /* Test value written to Flash */
#define ATMEL_DUMMYBYTE 0xFF
#define ATMEL_INITBYTE 0x00
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
static int SetupInterruptSystem(XSpi *SpiPtr);
void SpiHandler(void *CallBackRef, u32 StatusEvent, unsigned int ByteCount);
int SpiAtmelFlashRead(XSpi *SpiPtr, u32 Address, u16 ByteCount);
int SpiAtmelFlashWrite(XSpi *SpiPtr, u32 Address, u16 ByteCount);
int SpiAtmelFlashPageErase(XSpi *SpiPtr, u32 Address);
static int SpiAtmelFlashWaitForFlashNotBusy(XSpi *SpiPtr);
/************************** Variable Definitions *****************************/
/*
* The instances to support the device drivers are global such that they
* are initialized to zero each time the program runs. They could be local
* but should at least be static so they are zeroed.
*/
static XIntc InterruptController;
static XSpi Spi;
/*
* The following variables are shared between non-interrupt processing and
* interrupt processing such that they must be global.
*/
volatile static int TransferInProgress;
/*
* The following variable tracks any errors that occur during interrupt
* processing.
*/
int ErrorCount;
/*
* Buffers used during read and write transactions.
*/
u8 ReadBuffer[ATMEL_PAGE_SIZE + ATMEL_READ_WRITE_EXTRA_BYTES];
u8 WriteBuffer[ATMEL_PAGE_SIZE + ATMEL_READ_WRITE_EXTRA_BYTES];
/************************** Function Definitions ******************************/
/*****************************************************************************/
/**
*
* Main function to execute the Atmel Flash example.
*
* @param None
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note None
*
******************************************************************************/
int main()
{
int Status;
u32 Index;
u32 Address;
XSpi_Config *ConfigPtr; /* Pointer to Configuration data */
/*
* Initialize the SPI driver so that it is ready to use.
*/
ConfigPtr = XSpi_LookupConfig(SPI_DEVICE_ID);
if (ConfigPtr == NULL) {
return XST_DEVICE_NOT_FOUND;
}
Status = XSpi_CfgInitialize(&Spi, ConfigPtr,
ConfigPtr->BaseAddress);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Connect the SPI driver to the interrupt subsystem such that
* interrupts can occur. This function is application specific.
*/
Status = SetupInterruptSystem(&Spi);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Setup the handler for the SPI that will be called from the interrupt
* context when an SPI status occurs, specify a pointer to the SPI
* driver instance as the callback reference so the handler is able to
* access the instance data.
*/
XSpi_SetStatusHandler(&Spi, &Spi, (XSpi_StatusHandler)SpiHandler);
/*
* Set the SPI device as a master and in manual slave select mode such
* that the slave select signal does not toggle for every byte of a
* transfer, this must be done before the slave select is set.
*/
Status = XSpi_SetOptions(&Spi, XSP_MASTER_OPTION |
XSP_MANUAL_SSELECT_OPTION |
XSP_CLK_PHASE_1_OPTION |
XSP_CLK_ACTIVE_LOW_OPTION);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Select the slave on the SPI bus so that the Atmel Flash device can be
* read and written using the SPI bus.
*/
Status = XSpi_SetSlaveSelect(&Spi, ATMEL_SPI_SELECT);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Start the SPI driver so that interrupts and the device are enabled.
*/
XSpi_Start(&Spi);
/*
* Specify the address in the flash device for the Erase/Write/Read
* operations.
*/
Address = ATMEL_FLASH_TEST_ADDRESS;
/*
* Erase the Page.
*/
Status = SpiAtmelFlashPageErase(&Spi, Address);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the current Erase command is executed in the Flash
* and the Flash is ready for the next command.
*/
Status = SpiAtmelFlashWaitForFlashNotBusy(&Spi);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Write the data to the Page.
*/
Status = SpiAtmelFlashWrite(&Spi, Address, ATMEL_PAGE_SIZE);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the current Write command is executed in the Flash
* and the Flash is ready for the next command.
*/
Status = SpiAtmelFlashWaitForFlashNotBusy(&Spi);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Read the data from the Page.
*/
Status = SpiAtmelFlashRead(&Spi, Address, ATMEL_PAGE_SIZE);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the current Write command is executed in the Flash
* and the Flash is ready for the next command.
*/
Status = SpiAtmelFlashWaitForFlashNotBusy(&Spi);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Compare the data read with what is written.
*/
for(Index = ATMEL_READ_WRITE_EXTRA_BYTES; Index < (ATMEL_PAGE_SIZE +
ATMEL_READ_WRITE_EXTRA_BYTES); Index++) {
if(ReadBuffer[Index] != (u8)(Index + ATMEL_TEST_BYTE)) {
return XST_FAILURE;
}
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function reads data from the Atmel Flash device connected to the SPI
* interface.
*
* @param SpiPtr is a pointer to the SPI driver component to use.
* @param Addr is the address from which the data is to be read from
* the Flash.
* @param ByteCount is the number of bytes to read.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note None.
*
******************************************************************************/
int SpiAtmelFlashRead(XSpi *SpiPtr, u32 Address, u16 ByteCount)
{
u16 Index;
/*
* Setup the read command with the specified address and data for the
* Atmel Flash.
*/
WriteBuffer[ATMEL_COMMAND_OFFSET] = ATMEL_COMMAND_READ;
WriteBuffer[ATMEL_ADDRESS_BYTE1_OFFSET] = (u8) (Address >> 16);
WriteBuffer[ATMEL_ADDRESS_BYTE2_OFFSET] = (u8) (Address >> 8);
WriteBuffer[ATMEL_ADDRESS_BYTE3_OFFSET] = (u8) Address;
/*
* Prepare the write buffer. Fill in some dummy data.
*/
for(Index = 4; Index < (ByteCount + ATMEL_READ_WRITE_EXTRA_BYTES);
Index++) {
WriteBuffer[Index] = ATMEL_DUMMYBYTE;
}
/*
* Prepare the Read Buffer. Fill in some initialization data into the
* the buffer.
*/
for(Index = 0; Index < (ByteCount +
ATMEL_READ_WRITE_EXTRA_BYTES); Index++) {
ReadBuffer[Index] = ATMEL_INITBYTE;
}
/*
* Send the read command to the Atmel Flash to read the specified number
* of bytes.
*/
TransferInProgress = TRUE;
XSpi_Transfer(SpiPtr, WriteBuffer, ReadBuffer,
ByteCount + ATMEL_READ_WRITE_EXTRA_BYTES);
/*
* Wait till the Transfer is complete and check if there are any errors
* in the transaction.
*/
while (TransferInProgress);
if(ErrorCount != 0) {
ErrorCount = 0;
return XST_FAILURE;
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function writes to the Atmel Flash device connected to the SPI interface.
*
* @param SpiPtr is a pointer to the SPI driver component to use.
* @param Address is the address to which the data is written.
* @param ByteCount contains the number of bytes to write.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note None.
*
******************************************************************************/
int SpiAtmelFlashWrite(XSpi *SpiPtr, u32 Address, u16 ByteCount)
{
u16 Index;
/*
* Setup the write command with the specified address, and data to be
* written to the flash.
*/
WriteBuffer[ATMEL_COMMAND_OFFSET] = ATMEL_COMMAND_WRITE;
WriteBuffer[ATMEL_ADDRESS_BYTE1_OFFSET] = (u8) (Address >> 16);
WriteBuffer[ATMEL_ADDRESS_BYTE2_OFFSET] = (u8) (Address >> 8);
WriteBuffer[ATMEL_ADDRESS_BYTE3_OFFSET] = (u8) (Address);
/*
* Prepare the write buffer. Fill in the data that is to be written into
* the Flash.
*/
for(Index = 4; Index < (ByteCount + ATMEL_READ_WRITE_EXTRA_BYTES);
Index++) {
WriteBuffer[Index] = (u8)(ATMEL_TEST_BYTE + Index);
}
/*
* Send the write command, address, and data to the Flash.
* No receive buffer is specified since there is nothing to receive.
*/
TransferInProgress = TRUE;
XSpi_Transfer(SpiPtr, WriteBuffer, NULL,
ByteCount + ATMEL_READ_WRITE_EXTRA_BYTES)
;
/*
* Wait till the Transfer is complete and check if there are any errors
* in the transaction.
*/
while (TransferInProgress);
if(ErrorCount != 0) {
ErrorCount = 0;
return XST_FAILURE;
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function erases the contents of the specified Page in the Flash.
*
* @param SpiPtr is a pointer to the SPI driver component to use.
* @param Address contains the address of the page to be erased.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note None.
*
******************************************************************************/
int SpiAtmelFlashPageErase(XSpi *SpiPtr, u32 Address) {
/*
* Prepare the Write Buffer.
*/
WriteBuffer[ATMEL_COMMAND_OFFSET] = ATMEL_COMMAND_PAGE_ERASE;
WriteBuffer[ATMEL_ADDRESS_BYTE1_OFFSET] = (u8) (Address >> 16);
WriteBuffer[ATMEL_ADDRESS_BYTE2_OFFSET] = (u8) (Address >> 8);
WriteBuffer[ATMEL_ADDRESS_BYTE3_OFFSET] = ATMEL_DUMMYBYTE;
/*
* Send the Erase command and address to the flash.
* No receive buffer is specified since there is nothing to
* receive.
*/
TransferInProgress = TRUE;
XSpi_Transfer(SpiPtr, WriteBuffer, NULL, ATMEL_PAGE_ERASE_BYTES);
/*
* Wait till the Transfer is complete and check if there are any errors
* in the transaction.
*/
while (TransferInProgress);
if(ErrorCount != 0) {
ErrorCount = 0;
return XST_FAILURE;
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function waits till the flash is ready to accept next command.
*
* @param SpiPtr is a pointer to the SPI driver component to use.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note None.
*
******************************************************************************/
static int SpiAtmelFlashWaitForFlashNotBusy(XSpi *SpiPtr)
{
u8 StatusReg;
/*
* Prepare the Write Buffer.
*/
WriteBuffer[ATMEL_COMMAND_OFFSET] = ATMEL_COMMAND_STATUSREG_READ;
WriteBuffer[ATMEL_ADDRESS_BYTE1_OFFSET] = ATMEL_DUMMYBYTE;
/*
* Prepare the Read Buffer.
*/
ReadBuffer[0] = ATMEL_INITBYTE;
ReadBuffer[1] = ATMEL_INITBYTE;
while(1) {
/*
* Transmit the data.
*/
TransferInProgress = TRUE;
XSpi_Transfer(&Spi, WriteBuffer, ReadBuffer,
ATMEL_STATUS_READ_BYTES);
/*
* Wait for the transmission to be complete and
* check if there are any errors in the transaction.
*/
while (TransferInProgress);
if(ErrorCount != 0) {
ErrorCount = 0;
return XST_FAILURE;
}
StatusReg = ReadBuffer[1];
if ((StatusReg & ATMEL_FLASH_SR_IS_READY_MASK))
break;
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function is the handler which performs processing for the SPI driver.
* It is called from an interrupt context such that the amount of processing
* performed should be minimized. It is called when a transfer of SPI data
* completes or an error occurs.
*
* This handler provides an example of how to handle SPI interrupts and
* is application specific.
*
* @param CallBackRef is the upper layer callback reference passed back
* when the callback function is invoked.
* @param StatusEvent is the event that just occurred.
* @param ByteCount is the number of bytes transferred up until the event
* occurred.
*
* @return None.
*
* @note None.
*
******************************************************************************/
void SpiHandler(void *CallBackRef, u32 StatusEvent, unsigned int ByteCount)
{
/*
* Indicate the transfer on the SPI bus is no longer in progress
* regardless of the status event.
*/
TransferInProgress = FALSE;
/*
* If the event was not transfer done, then track it as an error.
*/
if (StatusEvent != XST_SPI_TRANSFER_DONE) {
ErrorCount++;
}
}
/*****************************************************************************/
/**
*
* This function setups the interrupt system such that interrupts can occur
* for the Spi device. This function is application specific since the actual
* system may or may not have an interrupt controller. The Spi device could be
* directly connected to a processor without an interrupt controller. The
* user should modify this function to fit the application.
*
* @param SpiPtr is a pointer to the instance of the Spi device.
*
* @return XST_SUCCESS if successful, otherwise XST_FAILURE.
*
* @note None
*
******************************************************************************/
static int SetupInterruptSystem(XSpi *SpiPtr)
{
int Status;
/*
* Initialize the interrupt controller driver so that
* it's ready to use, specify the device ID that is generated in
* xparameters.h
*/
Status = XIntc_Initialize(&InterruptController, INTC_DEVICE_ID);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* 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(&InterruptController,
SPI_INTR_ID,
(XInterruptHandler)XSpi_InterruptHandler,
(void *)SpiPtr);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Start the interrupt controller such that interrupts are enabled for
* all devices that cause interrupts, specific real mode so that
* the SPI can cause interrupts thru the interrupt controller.
*/
Status = XIntc_Start(&InterruptController, XIN_REAL_MODE);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Enable the interrupt for the SPI.
*/
XIntc_Enable(&InterruptController, SPI_INTR_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,
&InterruptController);
/*
* Enable non-critical exceptions.
*/
Xil_ExceptionEnable();
return XST_SUCCESS;
}

View file

@ -0,0 +1,589 @@
/******************************************************************************
*
* Copyright (C) 2001 - 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 xspi_eeprom_example.c
*
*
* This file contains a design example using the SPI driver (XSpi) and
* hardware device with a serial EEPROM device. The hardware which this
* example runs on must have a serial EEPROM (Microchip 25XX320 or 25XX160)
* for it to run. This example has been tested with the SPI EEPROM on the ML410
* platform for PPC processor.
*
* @note
*
* None.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- -------- -----------------------------------------------
* 1.00b jhl 02/27/01 First release
* 1.00c jhl 08/15/03 Fixed bugs (local instances and large buffers are now
* moved to globals)
* 1.11a sv 9/10/07 Minor changes to comply to Doxygen and coding guidelines
* 3.00a ktn 10/28/09 Converted all register accesses to 32 bit access.
* Updated to use the HAL APIs/macros. Replaced call to
* XSpi_Initialize API with XSpi_LookupConfig and
* XSpi_CfgInitialize.
*</pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "xparameters.h" /* EDK generated parameters */
#include "xspi.h" /* SPI device driver */
#include "xintc.h" /* Interrupt controller device driver */
#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 SPI_DEVICE_ID XPAR_SPI_0_DEVICE_ID
#define INTC_DEVICE_ID XPAR_INTC_0_DEVICE_ID
#define SPI_INTR_ID XPAR_INTC_0_SPI_0_VEC_ID
/*
* The following constants define the commands which may be sent to the EEPROM
* device.
*/
#define WRITE_STATUS_CMD 1
#define WRITE_CMD 2
#define READ_CMD 3
#define WRITE_DISABLE_CMD 4
#define READ_STATUS_CMD 5
#define WRITE_ENABLE_CMD 6
/*
* The following constants define the offsets within a EepromBuffer data
* type for each kind of data. Note that the read data offset is not the
* same as the write data because the SPI driver is designed to allow full
* duplex transfers such that the number of bytes received is the number
* sent and received.
*/
#define COMMAND_OFFSET 0 /* EEPROM instruction */
#define ADDRESS_MSB_OFFSET 1 /* MSB of address to read or write */
#define ADDRESS_LSB_OFFSET 2 /* LSB of address to read or write */
#define DATA_OFFSET 3
#define WRITE_DATA_OFFSET 3 /* Start of data to write to the EEPROM */
#define READ_DATA_OFFSET 6 /* Start of data read from the EEPROM */
/*
* The following constants specify the extra bytes which are sent to the
* EEPROM on the SPI interface, that are not data, but control information
* which includes the command and address
*/
#define OVERHEAD_SIZE 3
/*
* The following constants specify the page size and number of pages for the
* EEPROM. The page size specifies a max number of bytes that can be written
* to the EEPROM with a single transfer using the SPI driver.
*/
#define PAGE_SIZE 16
#define PAGE_COUNT 128
/*
* The following constants specify the max amount of data and the size of the
* the buffer required to hold the data and overhead to transfer the data to
* and from the EEPROM.
*/
#define MAX_DATA PAGE_COUNT * PAGE_SIZE
#define BUFFER_SIZE MAX_DATA + READ_DATA_OFFSET
/*
* The following constant defines the slave select signal that is used to
* to select the EEPROM device on the SPI bus, this signal is typically
* connected to the chip select of the device
*/
#define SEEPROM_SPI_SELECT 0x01
/**************************** Type Definitions *******************************/
/*
* The following data type is used to send and receive data to the serial
* EEPROM device connected to the SPI interface. It is an array of bytes
* rather than a structure for portability avoiding packing issues. The
* application must setup the data to be written in this buffer and retrieve
* the data read from it.
*/
typedef u8 EepromBuffer[BUFFER_SIZE];
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
static int SetupInterruptSystem(XSpi *SpiPtr);
void SpiHandler(void *CallBackRef, u32 StatusEvent, unsigned int ByteCount);
void EepromRead(XSpi *SpiPtr, u16 Address, int ByteCount, EepromBuffer Buffer);
void EepromWrite(XSpi *SpiPtr, u16 Address, u8 ByteCount, EepromBuffer Buffer);
/************************** Variable Definitions *****************************/
/*
* The instances to support the device drivers are global such that the
* are initialized to zero each time the program runs. They could be local
* but should at least be static so they are zeroed.
*/
XIntc InterruptController;
XSpi Spi;
/*
* The following variables are shared between non-interrupt processing and
* interrupt processing such that they must be global.
*/
volatile int TransferInProgress;
/*
* The following variable tracks any errors that occur during interrupt
* processing
*/
int Error;
/*
* The following variable allows a test value to be added to the values that
* are written to the EEPROM such that unique values can be generated to
* guarantee the writes to the EEPROM were successful
*/
int Test;
/*
* The following variables are used to read and write to the eeprom and they
* are global to avoid having large buffers on the stack
*/
EepromBuffer ReadBuffer;
EepromBuffer WriteBuffer;
/*****************************************************************************
*
* The purpose of this function is to illustrate how to use the XSpi
* device driver. This test writes and reads data from a Microchip serial EEPROM.
* This part must be present in the hardware to use this example.
*
* @param None
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note
*
* This function calls functions which contain loops that may be infinite
* if interrupts are not working such that it may not return. If the device
* slave select is not correct and the device is not responding on bus it will
* read a status of 0xFF for the status register as the bus is pulled up.
*
*****************************************************************************/
int main()
{
int Status;
u8 *BufferPtr;
u8 UniqueValue;
int Count;
int Page;
XSpi_Config *ConfigPtr; /* Pointer to Configuration data */
/*
* Initialize the SPI driver so that it is ready to use.
*/
ConfigPtr = XSpi_LookupConfig(SPI_DEVICE_ID);
if (ConfigPtr == NULL) {
return XST_DEVICE_NOT_FOUND;
}
Status = XSpi_CfgInitialize(&Spi, ConfigPtr,
ConfigPtr->BaseAddress);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Connect the SPI driver to the interrupt subsystem such that
* interrupts can occur. This function is application specific.
*/
Status = SetupInterruptSystem(&Spi);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Setup the handler for the SPI that will be called from the interrupt
* context when an SPI status occurs, specify a pointer to the SPI
* driver instance as the callback reference so the handler is able to
* access the instance data
*/
XSpi_SetStatusHandler(&Spi, &Spi, (XSpi_StatusHandler)SpiHandler);
/*
* Set the SPI device as a master and in manual slave select mode such
* that the slave select signal does not toggle for every byte of a
* transfer, this must be done before the slave select is set
*/
Status = XSpi_SetOptions(&Spi, XSP_MASTER_OPTION |
XSP_MANUAL_SSELECT_OPTION);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Select the slave on the SPI bus, the EEPROM device so that it can be
* read and written using the SPI bus
*/
Status = XSpi_SetSlaveSelect(&Spi, SEEPROM_SPI_SELECT);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Start the SPI driver so that interrupts and the device are enabled
*/
XSpi_Start(&Spi);
/*
* Initialize the write buffer for a pattern to write to the EEPROM
* and the read buffer to zero so it can be verified after the read, the
* test value that is added to the unique value allows the value to be
* changed in a debug environment to guarantee
*/
for (UniqueValue = 10, Count = 0; Count < MAX_DATA;
Count++, UniqueValue++) {
WriteBuffer[WRITE_DATA_OFFSET + Count] =
(u8)(UniqueValue + Test);
ReadBuffer[READ_DATA_OFFSET + Count] = 0;
}
/*
* Write the data in the write buffer to the serial EEPROM a page at a
* time
*/
for (Page = 0; Page < PAGE_COUNT; Page++) {
EepromWrite(&Spi, Page * PAGE_SIZE, PAGE_SIZE,
&WriteBuffer[Page * PAGE_SIZE]);
}
/*
* Read the contents of the entire EEPROM from address 0, since this
* function reads the entire EEPROM it will take some amount of time to
* complete
*/
EepromRead(&Spi, 0, MAX_DATA, ReadBuffer);
/*
* Setup a pointer to the start of the data that was read into the read
* buffer and verify the data read is the data that was written
*/
BufferPtr = &ReadBuffer[READ_DATA_OFFSET];
for (UniqueValue = 10, Count = 0; Count < MAX_DATA;
Count++, UniqueValue++) {
if (BufferPtr[Count] != (u8)(UniqueValue + Test)) {
return XST_FAILURE;
}
}
return XST_SUCCESS;
}
/******************************************************************************
*
* This function is the handler which performs processing for the SPI driver.
* It is called from an interrupt context such that the amount of processing
* performed should be minimized. It is called when a transfer of SPI data
* completes or an error occurs.
*
* This handler provides an example of how to handle SPI interrupts
* but is application specific.
*
*
* @param CallBackRef is a reference passed to the handler.
* @param StatusEvent is the status of the SPI .
* @param ByteCount is the number of bytes transferred.
*
* @return None
*
* @note None.
*
******************************************************************************/
void SpiHandler(void *CallBackRef, u32 StatusEvent, unsigned int ByteCount)
{
/*
* Indicate the transfer on the SPI bus is no longer in progress
* regardless of the status event
*/
TransferInProgress = FALSE;
/*
* If the event was not transfer done, then track it as an error
*/
if (StatusEvent != XST_SPI_TRANSFER_DONE) {
Error++;
}
}
/******************************************************************************
*
* This function reads from the Microchip serial EEPROM connected to the
* SPI interface.
*
* @param SpiPtr is a pointer to the SPI driver component to use.
* @param Address contains the address to read data from in the EEPROM.
* @param ByteCount contains the number of bytes to read.
* @param Buffer is a buffer to read the data into.
*
* @return None.
*
* @note None.
*
******************************************************************************/
void EepromRead(XSpi *SpiPtr, u16 Address, int ByteCount, EepromBuffer Buffer)
{
/*
* Setup the write command with the specified address and data for the
* EEPROM
*/
Buffer[COMMAND_OFFSET] = READ_CMD;
Buffer[ADDRESS_MSB_OFFSET] = (u8)((Address & 0xFF00) >> 8);
Buffer[ADDRESS_LSB_OFFSET] = (u8)(Address & 0x00FF);
/*
* Send the read command to the EEPROM to read the specified number
* of bytes from the EEPROM, send the read command and address and
* receive the specified number of bytes of data in the data buffer
*/
TransferInProgress = TRUE;
XSpi_Transfer(SpiPtr, Buffer, &Buffer[DATA_OFFSET],
ByteCount + OVERHEAD_SIZE);
/*
* Wait for the transfer on the SPI bus to be complete before proceeding
*/
while (TransferInProgress);
}
/******************************************************************************
*
*
* This function writes to the Microchip serial EEPROM connected to the
* SPI interface. This function is not designed to be a driver to handle all
* the conditions of the EEPROM device. The EEPROM contains a 32 byte write
* buffer which can be filled and then a write is automatically performed by
* the device. All the data put into the buffer must be in the same page of
* the device with page boundaries being on 32 byte boundaries.
*
* @param SpiPtr is a pointer to the SPI driver component to use.
* @param Address contains the address to write data to in the EEPROM.
* @param ByteCount contains the number of bytes to write.
* @param Buffer is a buffer of data to write from.
*
* @return None.
*
* @note None.
*
******************************************************************************/
void EepromWrite(XSpi *SpiPtr, u16 Address, u8 ByteCount, EepromBuffer Buffer)
{
u8 WriteEnableCmd = { WRITE_ENABLE_CMD };
u8 ReadStatusCmd[] = { READ_STATUS_CMD, 0 }; /* must send 2 bytes */
u8 EepromStatus[2];
int DelayCount = 0;
/*
* Send the write enable command to the SEEPOM so that it can be
* written to, this needs to be sent as a seperate transfer before
* the write
*/
TransferInProgress = TRUE;
XSpi_Transfer(SpiPtr, &WriteEnableCmd, NULL, sizeof(WriteEnableCmd));
/*
* Wait for the transfer on the SPI bus to be complete before proceeding
*/
while (TransferInProgress);
/*
* Setup the write command with the specified address and data for the
* EEPROM
*/
Buffer[COMMAND_OFFSET] = WRITE_CMD;
Buffer[ADDRESS_MSB_OFFSET] = (u8)((Address & 0xFF00) >> 8);
Buffer[ADDRESS_LSB_OFFSET] = (u8)(Address & 0x00FF);
/*
* Send the write command, address, and data to the EEPROM to be
* written, no receive buffer is specified since there is nothing to
* receive
*/
TransferInProgress = TRUE;
XSpi_Transfer(SpiPtr, Buffer, NULL, ByteCount + OVERHEAD_SIZE);
while (TransferInProgress);
/*
* Wait for a bit of time to allow the programming to occur as reading
* the status while programming causes it to fail because of noisy power
* on the board containing the EEPROM, this loop does not need to be
* very long but is longer to hopefully work for a faster processor
*/
while (DelayCount++ < 10000) {
}
/*
* Wait for the write command to the EEPROM to be completed, it takes
* some time for the data to be written
*/
while (1) {
/*
* Poll the status register of the device to determine when it
* completes by sending a read status command and receiving the
* status byte
*/
TransferInProgress = TRUE;
XSpi_Transfer(SpiPtr, ReadStatusCmd, EepromStatus,
sizeof(ReadStatusCmd));
/*
* Wait for the transfer on the SPI bus to be complete before
* proceeding
*/
while (TransferInProgress);
/*
* If the status indicates the write is done, the stop waiting,
* if a value of 0xFF in the status byte is read from the
* device and this loop never exits, the device slave select is
* possibly incorrect such that the device status is not being
* read
*/
if ((EepromStatus[1] & 0x03) == 0) {
break;
}
}
}
/****************************************************************************
*
*
* This function setups the interrupt system such that interrupts can occur
* for the SPI driver. This function is application specific since the actual
* system may or may not have an interrupt controller. The SPI device could
* be directly connected to a processor without an interrupt controller. The
* user should modify this function to fit the application.
*
* @param SpiPtr contains a pointer to the instance of the XSpi component
* which is going to be connected to the interrupt controller.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note None.
*
****************************************************************************/
static int SetupInterruptSystem(XSpi *SpiPtr)
{
int Status;
/*
* Initialize the interrupt controller driver so that
* it's ready to use, specify the device ID that is generated in
* xparameters.h
*/
Status = XIntc_Initialize(&InterruptController, INTC_DEVICE_ID);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* 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(&InterruptController,
SPI_INTR_ID,
(XInterruptHandler)XSpi_InterruptHandler,
(void *)SpiPtr);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Start the interrupt controller such that interrupts are enabled for
* all devices that cause interrupts, specific real mode so that
* the SPI can cause interrupts thru the interrupt controller.
*/
Status = XIntc_Start(&InterruptController, XIN_REAL_MODE);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Enable the interrupt for the Spi device
*/
XIntc_Enable(&InterruptController, SPI_INTR_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,
&InterruptController);
/*
* Enable non-critical exceptions
*/
Xil_ExceptionEnable();
return XST_SUCCESS;
}

View file

@ -0,0 +1,911 @@
/******************************************************************************
*
* Copyright (C) 2008 - 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 xspi_intel_flash_example.c
*
* This file contains a design example using the SPI driver (XSpi) and hardware
* device with an Intel Serial Flash Memory (S33) in the interrupt mode.
* This example erases a sector, writes to a Page within the sector, reads back
* from that Page and compares the data.
*
* The example works with an Intel Serial Flash Memory (S33). The number of bytes
* per page in this device is 256. For further details about the device refer to
* the Intel Serial Flash Memory (S33) Data sheet
*
* This example assumes that the underlying processor is MicroBlaze.
*
* @note
*
* None.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- -------- -----------------------------------------------
* 1.00a sd 02/26/08 First release
* 3.00a ktn 10/22/09 Converted all register accesses to 32 bit access.
* Updated to use the HAL APIs/macros. Replaced call to
* XSpi_Initialize API with XSpi_LookupConfig and
* XSpi_CfgInitialize.
* </pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "xparameters.h" /* EDK generated parameters */
#include "xintc.h" /* Interrupt controller device driver */
#include "xspi.h" /* SPI device driver */
#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 SPI_DEVICE_ID XPAR_SPI_0_DEVICE_ID
#define INTC_DEVICE_ID XPAR_INTC_0_DEVICE_ID
#define SPI_INTR_ID XPAR_INTC_0_SPI_0_VEC_ID
/*
* The following constant defines the slave select signal that is used to
* to select the Flash device on the SPI bus, this signal is typically
* connected to the chip select of the device.
*/
#define INTEL_SPI_SELECT 0x01
/*
* Definitions of the commands shown in this example.
*/
#define INTEL_COMMAND_RANDOM_READ 0x03 /* Random read command */
#define INTEL_COMMAND_PAGEPROGRAM_WRITE 0x02 /* Page Program command */
#define INTEL_COMMAND_WRITE_ENABLE 0x06 /* Write Enable command */
#define INTEL_COMMAND_SECTOR_ERASE 0xD8 /* Sector Erase command */
#define INTEL_COMMAND_BULK_ERASE 0xC7 /* Bulk Erase command */
#define INTEL_COMMAND_STATUSREG_READ 0x05 /* Status read command */
#define INTEL_COMMAND_STATUSREG_WRITE 0x01 /* Status write command */
/*
* This definitions specify the EXTRA bytes for each of the command
* transactions. This count includes command byte, address bytes and any
* don't care bytes needed.
*/
#define INTEL_READ_WRITE_EXTRA_BYTES 4 /* Read/Write extra bytes */
#define INTEL_WRITE_ENABLE_BYTES 1 /* Write Enable bytes */
#define INTEL_SECTOR_ERASE_BYTES 4 /* Sector erase extra bytes */
#define INTEL_BULK_ERASE_BYTES 1 /* Bulk erase extra bytes */
#define INTEL_STATUS_READ_BYTES 2 /* Status read bytes count */
#define INTEL_STATUS_WRITE_BYTES 2 /* Status write bytes count */
/*
* Flash not busy mask in the status register of the flash device.
*/
#define INTEL_FLASH_SR_IS_READY_MASK 0x01 /* Ready mask */
/*
* Sector protection disable mask in the status register for all the sectors of
* the flash device.
*/
#define INTEL_DISABLE_PROTECTION_ALL 0x00
/*
* Number of bytes per page in the flash device.
*/
#define INTEL_FLASH_PAGE_SIZE 256
/*
* Address of the page to perform Erase, Write and Read operations.
*/
#define INTEL_FLASH_TEST_ADDRESS 0x00
/*
* Byte offset value written to Flash. This needs to redefined for writing
* different patterns of data to the Flash device.
*/
#define INTEL_FLASH_TEST_BYTE 0x20
/*
* Byte Positions.
*/
#define BYTE1 0 /* Byte 1 position */
#define BYTE2 1 /* Byte 2 position */
#define BYTE3 2 /* Byte 3 position */
#define BYTE4 3 /* Byte 4 position */
#define BYTE5 4 /* Byte 5 position */
#define INTEL_DUMMYBYTE 0xFF /* Dummy byte */
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
int SpiIntelFlashWriteEnable(XSpi *SpiPtr);
int SpiIntelFlashWrite(XSpi *SpiPtr, u32 Addr, u32 ByteCount);
int SpiIntelFlashRead(XSpi *SpiPtr, u32 Addr, u32 ByteCount);
int SpiIntelFlashBulkErase(XSpi *SpiPtr);
int SpiIntelFlashSectorErase(XSpi *SpiPtr, u32 Addr);
int SpiIntelFlashGetStatus(XSpi *SpiPtr);
int SpiIntelFlashWriteStatus(XSpi *SpiPtr, u8 StatusRegister);
static int SpiIntelFlashWaitForFlashNotBusy(void);
void SpiHandler(void *CallBackRef, u32 StatusEvent, unsigned int ByteCount);
static int SetupInterruptSystem(XSpi *SpiPtr);
/************************** Variable Definitions *****************************/
/*
* The instances to support the device drivers are global such that they
* are initialized to zero each time the program runs. They could be local
* but should at least be static so they are zeroed.
*/
static XIntc InterruptController;
static XSpi Spi;
/*
* The following variables are shared between non-interrupt processing and
* interrupt processing such that they must be global.
*/
volatile static int TransferInProgress;
/*
* The following variable tracks any errors that occur during interrupt
* processing.
*/
int ErrorCount;
/*
* Buffers used during read and write transactions.
*/
u8 ReadBuffer[INTEL_FLASH_PAGE_SIZE + INTEL_READ_WRITE_EXTRA_BYTES];
u8 WriteBuffer[INTEL_FLASH_PAGE_SIZE + INTEL_READ_WRITE_EXTRA_BYTES];
/************************** Function Definitions ******************************/
/*****************************************************************************/
/**
*
* Main function to execute the Flash example.
*
* @param None
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note None
*
******************************************************************************/
int main()
{
int Status;
u32 Index;
u32 Address;
XSpi_Config *ConfigPtr; /* Pointer to Configuration data */
/*
* Initialize the SPI driver so that it is ready to use.
*/
ConfigPtr = XSpi_LookupConfig(SPI_DEVICE_ID);
if (ConfigPtr == NULL) {
return XST_DEVICE_NOT_FOUND;
}
Status = XSpi_CfgInitialize(&Spi, ConfigPtr,
ConfigPtr->BaseAddress);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Connect the SPI driver to the interrupt subsystem such that
* interrupts can occur. This function is application specific.
*/
Status = SetupInterruptSystem(&Spi);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Setup the handler for the SPI that will be called from the interrupt
* context when an SPI status occurs, specify a pointer to the SPI
* driver instance as the callback reference so the handler is able to
* access the instance data.
*/
XSpi_SetStatusHandler(&Spi, &Spi, (XSpi_StatusHandler)SpiHandler);
/*
* Set the SPI device as a master and in manual slave select mode such
* that the slave select signal does not toggle for every byte of a
* transfer, this must be done before the slave select is set.
*/
Status = XSpi_SetOptions(&Spi, XSP_MASTER_OPTION |
XSP_MANUAL_SSELECT_OPTION);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Select the Intel Serial Flash device, so that it can be
* read and written using the SPI bus.
*/
Status = XSpi_SetSlaveSelect(&Spi, INTEL_SPI_SELECT);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Start the SPI driver so that interrupts and the device are enabled.
*/
XSpi_Start(&Spi);
/*
* Perform the Write Enable operation.
*/
Status = SpiIntelFlashWriteEnable(&Spi);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = SpiIntelFlashWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Disable the sector protection
*/
Status = SpiIntelFlashWriteStatus(&Spi, INTEL_DISABLE_PROTECTION_ALL);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = SpiIntelFlashWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Specify the address in the flash device for the Erase/Write/Read
* operations.
*/
Address = INTEL_FLASH_TEST_ADDRESS;
/*
* Perform the Write Enable operation.
*/
Status = SpiIntelFlashWriteEnable(&Spi);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = SpiIntelFlashWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Perform the Sector Erase operation.
*/
Status = SpiIntelFlashSectorErase(&Spi, Address);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = SpiIntelFlashWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Perform the Write Enable operation.
*/
Status = SpiIntelFlashWriteEnable(&Spi);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = SpiIntelFlashWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Write the data to the Page.
* Perform the Write operation.
*/
Status = SpiIntelFlashWrite(&Spi, Address, INTEL_FLASH_PAGE_SIZE);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = SpiIntelFlashWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Clear the read Buffer.
*/
for(Index = 0; Index < INTEL_FLASH_PAGE_SIZE +
INTEL_READ_WRITE_EXTRA_BYTES; Index++) {
ReadBuffer[Index] = 0x0;
}
/*
* Read the data from the Page.
*/
Status = SpiIntelFlashRead(&Spi, Address, INTEL_FLASH_PAGE_SIZE);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Compare the data read against the data that was Written.
*/
for(Index = 0; Index < INTEL_FLASH_PAGE_SIZE; Index++) {
if(ReadBuffer[Index + INTEL_READ_WRITE_EXTRA_BYTES] !=
(u8)(Index + INTEL_FLASH_TEST_BYTE)) {
return XST_FAILURE;
}
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function enables writes to the Intel Serial Flash memory.
*
* @param SpiPtr is a pointer to the instance of the Spi device.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note None.
*
******************************************************************************/
int SpiIntelFlashWriteEnable(XSpi *SpiPtr)
{
int Status;
/*
* Prepare the WriteBuffer.
*/
WriteBuffer[BYTE1] = INTEL_COMMAND_WRITE_ENABLE;
/*
* Initiate the Transfer.
*/
TransferInProgress = TRUE;
Status = XSpi_Transfer(SpiPtr, WriteBuffer, NULL,
INTEL_WRITE_ENABLE_BYTES);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check if there are any errors
* in the transaction..
*/
while(TransferInProgress);
if(ErrorCount != 0) {
ErrorCount = 0;
return XST_FAILURE;
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function writes the data to the specified locations in the Intel Serial
* Flash memory.
*
* @param SpiPtr is a pointer to the instance of the Spi device.
* @param Addr is the address in the Buffer, where to write the data.
* @param ByteCount is the number of bytes to be written.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note A minimum of one byte and a maximum of one Page can be written
* using this API.
*
******************************************************************************/
int SpiIntelFlashWrite(XSpi *SpiPtr, u32 Addr, u32 ByteCount)
{
u32 Index;
int Status;
/*
* Prepare the WriteBuffer.
*/
WriteBuffer[BYTE1] = INTEL_COMMAND_PAGEPROGRAM_WRITE;
WriteBuffer[BYTE2] = (u8) (Addr >> 16);
WriteBuffer[BYTE3] = (u8) (Addr >> 8);
WriteBuffer[BYTE4] = (u8) Addr;
/*
* Fill in the TEST data that is to be written into the STM Serial Flash
* device.
*/
for(Index = 4; Index < ByteCount + INTEL_READ_WRITE_EXTRA_BYTES;
Index++) {
WriteBuffer[Index] = (u8)((Index - 4) + INTEL_FLASH_TEST_BYTE);
}
/*
* Initiate the Transfer.
*/
TransferInProgress = TRUE;
Status = XSpi_Transfer(SpiPtr, WriteBuffer, NULL,
(ByteCount + INTEL_READ_WRITE_EXTRA_BYTES));
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check if there are any errors
* in the transaction..
*/
while(TransferInProgress);
if(ErrorCount != 0) {
ErrorCount = 0;
return XST_FAILURE;
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function reads the data from the Intel Serial Flash Memory
*
* @param SpiPtr is a pointer to the instance of the Spi device.
* @param Addr is the starting address in the Flash Memory from which the
* data is to be read.
* @param ByteCount is the number of bytes to be read.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note None.
*
******************************************************************************/
int SpiIntelFlashRead(XSpi *SpiPtr, u32 Addr, u32 ByteCount)
{
int Status;
/*
* Prepare the WriteBuffer.
*/
WriteBuffer[BYTE1] = INTEL_COMMAND_RANDOM_READ;
WriteBuffer[BYTE2] = (u8) (Addr >> 16);
WriteBuffer[BYTE3] = (u8) (Addr >> 8);
WriteBuffer[BYTE4] = (u8) Addr;
/*
* Initiate the Transfer.
*/
TransferInProgress = TRUE;
Status = XSpi_Transfer( SpiPtr, WriteBuffer, ReadBuffer,
(ByteCount + INTEL_READ_WRITE_EXTRA_BYTES));
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check if there are any errors
* in the transaction..
*/
while(TransferInProgress);
if(ErrorCount != 0) {
ErrorCount = 0;
return XST_FAILURE;
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function erases the entire contents of the Intel Serial Flash.
*
* @param SpiPtr is a pointer to the instance of the Spi device.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note The erased bytes will read as 0xFF.
*
******************************************************************************/
int SpiIntelFlashBulkErase(XSpi *SpiPtr)
{
int Status;
/*
* Prepare the WriteBuffer.
*/
WriteBuffer[BYTE1] = INTEL_COMMAND_BULK_ERASE;
/*
* Initiate the Transfer.
*/
TransferInProgress = TRUE;
Status = XSpi_Transfer(SpiPtr, WriteBuffer, NULL,
INTEL_BULK_ERASE_BYTES);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check if there are any errors
* in the transaction..
*/
while(TransferInProgress);
if(ErrorCount != 0) {
ErrorCount = 0;
return XST_FAILURE;
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function erases the contents of the specified Sector in the Intel Serial
* Flash.
*
* @param SpiPtr is a pointer to the instance of the Spi device.
* @param Addr is the address within a sector of the Buffer, which is to
* be erased.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note The erased bytes will read as 0xFF.
*
******************************************************************************/
int SpiIntelFlashSectorErase(XSpi *SpiPtr, u32 Addr)
{
int Status;
/*
* Prepare the WriteBuffer.
*/
WriteBuffer[BYTE1] = INTEL_COMMAND_SECTOR_ERASE;
WriteBuffer[BYTE2] = (u8) (Addr >> 16);
WriteBuffer[BYTE3] = (u8) (Addr >> 8);
WriteBuffer[BYTE4] = (u8) (Addr);
/*
* Initiate the Transfer.
*/
TransferInProgress = TRUE;
Status = XSpi_Transfer(SpiPtr, WriteBuffer, NULL,
INTEL_SECTOR_ERASE_BYTES);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check if there are any errors
* in the transaction.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
ErrorCount = 0;
return XST_FAILURE;
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function reads the Status register of the Intel Serial Flash.
*
* @param SpiPtr is a pointer to the instance of the Spi device.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note The status register content is stored at the second byte pointed
* by the ReadBuffer.
*
******************************************************************************/
int SpiIntelFlashGetStatus(XSpi *SpiPtr)
{
int Status;
/*
* Prepare the Write Buffer.
*/
WriteBuffer[BYTE1] = INTEL_COMMAND_STATUSREG_READ;
/*
* Initiate the Transfer.
*/
TransferInProgress = TRUE;
Status = XSpi_Transfer(SpiPtr, WriteBuffer, ReadBuffer,
INTEL_STATUS_READ_BYTES);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check if there are any errors
* in the transaction.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
ErrorCount = 0;
return XST_FAILURE;
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function writes to the Status register of the Intel Flash.
*
* @param SpiPtr is a pointer to the instance of the Spi device.
* @param StatusRegister is the value to be written to the status register
* of the flash device.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note The status register content is stored at the second byte pointed
* by the ReadPtr.
*
******************************************************************************/
int SpiIntelFlashWriteStatus(XSpi *SpiPtr, u8 StatusRegister)
{
int Status;
/*
* Prepare the Write Buffer.
*/
WriteBuffer[BYTE1] = INTEL_COMMAND_STATUSREG_WRITE;
WriteBuffer[BYTE2] = StatusRegister;
/*
* Initiate the Transfer.
*/
TransferInProgress = TRUE;
Status = XSpi_Transfer(SpiPtr, WriteBuffer, NULL,
INTEL_STATUS_WRITE_BYTES);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check if there are any errors
* in the transaction..
*/
while(TransferInProgress);
if(ErrorCount != 0) {
ErrorCount = 0;
return XST_FAILURE;
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function waits till the Intel Serial Flash is ready to accept next
* command.
*
* @param None
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note This function reads the status register of the Buffer and waits
*. till the WIP bit of the status register becomes 0.
*
******************************************************************************/
int SpiIntelFlashWaitForFlashNotBusy(void)
{
int Status;
u8 StatusReg;
while(1) {
/*
* Get the Status Register.
*/
Status = SpiIntelFlashGetStatus(&Spi);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Check if the flash is ready to accept the next command.
* If so break.
*/
StatusReg = ReadBuffer[1];
if((StatusReg & INTEL_FLASH_SR_IS_READY_MASK) == 0) {
break;
}
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function is the handler which performs processing for the SPI driver.
* It is called from an interrupt context such that the amount of processing
* performed should be minimized. It is called when a transfer of SPI data
* completes or an error occurs.
*
* This handler provides an example of how to handle SPI interrupts and
* is application specific.
*
* @param CallBackRef is the upper layer callback reference passed back
* when the callback function is invoked.
* @param StatusEvent is the event that just occurred.
* @param ByteCount is the number of bytes transferred up until the event
* occurred.
*
* @return None.
*
* @note None.
*
******************************************************************************/
void SpiHandler(void *CallBackRef, u32 StatusEvent, unsigned int ByteCount)
{
/*
* Indicate the transfer on the SPI bus is no longer in progress
* regardless of the status event.
*/
TransferInProgress = FALSE;
/*
* If the event was not transfer done, then track it as an error.
*/
if (StatusEvent != XST_SPI_TRANSFER_DONE) {
ErrorCount++;
}
}
/*****************************************************************************/
/**
*
* This function setups the interrupt system such that interrupts can occur
* for the Spi device. This function is application specific since the actual
* system may or may not have an interrupt controller. The Spi device could be
* directly connected to a processor without an interrupt controller. The
* user should modify this function to fit the application.
*
* @param SpiPtr is a pointer to the instance of the Spi device.
*
* @return XST_SUCCESS if successful, otherwise XST_FAILURE.
*
* @note None
*
******************************************************************************/
static int SetupInterruptSystem(XSpi *SpiPtr)
{
int Status;
/*
* Initialize the interrupt controller driver so that
* it's ready to use, specify the device ID that is generated in
* xparameters.h
*/
Status = XIntc_Initialize(&InterruptController, INTC_DEVICE_ID);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* 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(&InterruptController,
SPI_INTR_ID,
(XInterruptHandler)XSpi_InterruptHandler,
(void *)SpiPtr);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Start the interrupt controller such that interrupts are enabled for
* all devices that cause interrupts, specific real mode so that
* the SPI can cause interrupts thru the interrupt controller.
*/
Status = XIntc_Start(&InterruptController, XIN_REAL_MODE);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Enable the interrupt for the SPI.
*/
XIntc_Enable(&InterruptController, SPI_INTR_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,
&InterruptController);
/*
* Enable non-critical exceptions
*/
Xil_ExceptionEnable();
return XST_SUCCESS;
}

View file

@ -0,0 +1,522 @@
/******************************************************************************
*
* Copyright (C) 2006 - 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 xspi_intr_example.c
*
*
* This file contains a design example using the Spi driver (XSpi) and the Spi
* device using the interrupt mode.
*
* This example works with a PPC/MicroBlaze processor.
*
* @note
*
* None.
*
*<pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- -------- ---------------------------------------------------------
* 1.01a sv 05/29/06 First release for Test App Integration
* for Interrupt examples
* 1.11a sdm 03/03/08 Minor changes to comply to Doxygen and coding guidelines
* 3.00a ktn 10/22/09 Converted all register accesses to 32 bit access.
* Updated to use the HAL APIs/macros. Replaced call to
* XSpi_Initialize API with XSpi_LookupConfig and
* XSpi_CfgInitialize.
* 3.02a sdm 05/04/11 Updated to run the loopback test only in standard spi
* mode.
*</pre>
******************************************************************************/
/***************************** Include Files *********************************/
#include "xparameters.h" /* XPAR parameters */
#include "xspi.h" /* SPI device driver */
#include "xil_exception.h"
#ifdef XPAR_INTC_0_DEVICE_ID
#include "xintc.h"
#else
#include "xscugic.h"
#endif
/************************** 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.
*/
#ifndef TESTAPP_GEN
#define SPI_DEVICE_ID XPAR_SPI_0_DEVICE_ID
#define INTC_DEVICE_ID XPAR_INTC_0_DEVICE_ID
#define SPI_IRPT_INTR XPAR_INTC_0_SPI_0_VEC_ID
#endif
#ifdef XPAR_INTC_0_DEVICE_ID
#define INTC XIntc
#define INTC_HANDLER XIntc_InterruptHandler
#else
#define INTC XScuGic
#define INTC_HANDLER XScuGic_InterruptHandler
#endif
/*
* This is the size of the buffer to be transmitted/received in this example.
*/
#define BUFFER_SIZE 12
/**************************** Type Definitions *******************************/
/*
* The following data type is used to send and receive data on the SPI
* interface.
*/
typedef u8 DataBuffer[BUFFER_SIZE];
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
int SpiIntrExample(INTC *IntcInstancePtr, XSpi *SpiInstancePtr,
u16 SpiDeviceId, u16
SpiIntrId);
void SpiIntrHandler(void *CallBackRef, u32 StatusEvent, u32 ByteCount);
static int SpiSetupIntrSystem(INTC *IntcInstancePtr, XSpi *SpiInstancePtr,
u16 SpiIntrId);
static void SpiDisableIntrSystem(INTC *IntcInstancePtr, u16 SpiIntrId);
/************************** Variable Definitions *****************************/
/*
* The instances to support the device drivers are global such that the
* are initialized to zero each time the program runs.
*/
#ifndef TESTAPP_GEN
static INTC Intc; /* The instance of the Interrupt Controller */
static XSpi SpiInstance; /* The instance of the SPI device */
#endif
/*
* The following variables are shared between non-interrupt processing and
* interrupt processing such that they must be global.
*/
volatile int TransferInProgress;
/*
* The following variable tracks any errors that occur during interrupt
* processing
*/
int Error;
/*
* The following variables are used to read and write to the Spi device, they
* are global to avoid having large buffers on the stack.
*/
u8 ReadBuffer[BUFFER_SIZE];
u8 WriteBuffer[BUFFER_SIZE];
/*****************************************************************************/
/**
*
* Main function to call the Spi interrupt example.
*
* @param None
*
* @return XST_SUCCESS if successful, otherwise XST_FAILURE.
*
* @note None
*
******************************************************************************/
#ifndef TESTAPP_GEN
int main(void)
{
int Status;
/*
* Run the Spi Interrupt example.
*/
Status = SpiIntrExample(&IntcInstance,
&SpiInstance,
SPI_DEVICE_ID,
SPI_IRPT_INTR);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
return XST_SUCCESS;
}
#endif
/*****************************************************************************/
/**
*
* This function does a minimal test on the Spi device and driver as a
* design example. The purpose of this function is to illustrate how to use
* the XSpi component using the interrupt mode.
*
* This function sends data and expects to receive the same data.
*
*
* @param IntcInstancePtr is a pointer to the instance of the INTC
* component.
* @param SpiInstancePtr is a pointer to the instance of Spi component.
* @param SpiDeviceId is the Device ID of the Spi Device and is the
* XPAR_<SPI_instance>_DEVICE_ID value from xparameters.h.
* @param SpiIntrId is the interrupt Id and is typically
* XPAR_<INTC_instance>_<SPI_instance>_VEC_ID value from
* xparameters.h .
*
* @return XST_SUCCESS if successful, otherwise XST_FAILURE.
*
* @note
*
* This function contains an infinite loop such that if interrupts are not
* working it may never return.
*
******************************************************************************/
int SpiIntrExample(INTC *IntcInstancePtr, XSpi *SpiInstancePtr,
u16 SpiDeviceId, u16 SpiIntrId)
{
int Status;
u32 Count;
u8 Test;
XSpi_Config *ConfigPtr; /* Pointer to Configuration data */
/*
* Initialize the SPI driver so that it is ready to use.
*/
ConfigPtr = XSpi_LookupConfig(SpiDeviceId);
if (ConfigPtr == NULL) {
return XST_DEVICE_NOT_FOUND;
}
Status = XSpi_CfgInitialize(SpiInstancePtr, ConfigPtr,
ConfigPtr->BaseAddress);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Perform a self-test to ensure that the hardware was built correctly.
*/
Status = XSpi_SelfTest(SpiInstancePtr);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Run loopback test only in case of standard SPI mode.
*/
if (SpiInstancePtr->SpiMode != XSP_STANDARD_MODE) {
return XST_SUCCESS;
}
/*
* Connect the Spi device to the interrupt subsystem such that
* interrupts can occur. This function is application specific.
*/
Status = SpiSetupIntrSystem(IntcInstancePtr,
SpiInstancePtr,
SpiIntrId);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Setup the handler for the SPI that will be called from the interrupt
* context when an SPI status occurs, specify a pointer to the SPI
* driver instance as the callback reference so the handler is able to
* access the instance data.
*/
XSpi_SetStatusHandler(SpiInstancePtr, SpiInstancePtr,
(XSpi_StatusHandler) SpiIntrHandler);
/*
* Set the Spi device as a master and in loopback mode.
*/
Status = XSpi_SetOptions(SpiInstancePtr, XSP_MASTER_OPTION |
XSP_LOOPBACK_OPTION);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Start the SPI driver so that interrupts and the device are enabled.
*/
XSpi_Start(SpiInstancePtr);
/*
* Initialize the write buffer with pattern to write, initialize the
* read buffer to zero so it can be verified after the read, the
* Test value that is added to the unique value allows the value to be
* changed in a debug environment.
*/
Test = 0x10;
for (Count = 0; Count < BUFFER_SIZE; Count++) {
WriteBuffer[Count] = (u8)(Count + Test);
ReadBuffer[Count] = 0;
}
/*
* Transmit the data.
*/
TransferInProgress = TRUE;
XSpi_Transfer(SpiInstancePtr, WriteBuffer, ReadBuffer, BUFFER_SIZE);
/*
* Wait for the transmission to be complete.
*/
while (TransferInProgress);
/*
* Disable the Spi interrupt.
*/
SpiDisableIntrSystem(IntcInstancePtr, SpiIntrId);
/*
* Compare the data received with the data that was transmitted.
*/
for (Count = 0; Count < BUFFER_SIZE; Count++) {
if (WriteBuffer[Count] != ReadBuffer[Count]) {
return XST_FAILURE;
}
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function is the handler which performs processing for the SPI driver.
* It is called from an interrupt context such that the amount of processing
* performed should be minimized. It is called when a transfer of SPI data
* completes or an error occurs.
*
* This handler provides an example of how to handle SPI interrupts and
* is application specific.
*
* @param CallBackRef is the upper layer callback reference passed back
* when the callback function is invoked.
* @param StatusEvent is the event that just occurred.
* @param ByteCount is the number of bytes transferred up until the event
* occurred.
*
* @return None.
*
* @note None.
*
******************************************************************************/
void SpiIntrHandler(void *CallBackRef, u32 StatusEvent, u32 ByteCount)
{
/*
* Indicate the transfer on the SPI bus is no longer in progress
* regardless of the status event.
*/
TransferInProgress = FALSE;
/*
* If the event was not transfer done, then track it as an error.
*/
if (StatusEvent != XST_SPI_TRANSFER_DONE) {
Error++;
}
}
/*****************************************************************************/
/**
*
* This function setups the interrupt system such that interrupts can occur
* for the Spi device. This function is application specific since the actual
* system may or may not have an interrupt controller. The Spi device could be
* directly connected to a processor without an interrupt controller. The
* user should modify this function to fit the application.
*
* @param IntcInstancePtr is a pointer to the instance of the Intc device.
* @param SpiInstancePtr is a pointer to the instance of the Spi device.
* @param SpiIntrId is the interrupt Id and is typically
* XPAR_<INTC_instance>_<SPI_instance>_VEC_ID value from
* xparameters.h
*
* @return XST_SUCCESS if successful, otherwise XST_FAILURE.
*
* @note None
*
******************************************************************************/
static int SpiSetupIntrSystem(INTC *IntcInstancePtr, XSpi *SpiInstancePtr,
u16 SpiIntrId)
{
int Status;
#ifdef XPAR_INTC_0_DEVICE_ID
#ifndef TESTAPP_GEN
/*
* Initialize the interrupt controller driver so that it is ready to
* use.
*/
Status = XIntc_Initialize(IntcInstancePtr, INTC_DEVICE_ID);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
#endif
/*
* 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(IntcInstancePtr, SpiIntrId,
(XInterruptHandler) XSpi_InterruptHandler,
(void *)SpiInstancePtr);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
#ifndef TESTAPP_GEN
/*
* Start the interrupt controller such that interrupts are enabled for
* all devices that cause interrupts, specific real mode so that
* the SPI can cause interrupts through the interrupt controller.
*/
Status = XIntc_Start(IntcInstancePtr, XIN_REAL_MODE);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
#endif
/*
* Enable the interrupt for the SPI device.
*/
XIntc_Enable(IntcInstancePtr, SpiIntrId);
#else
XScuGic_Config *IntcConfig;
/*
* Initialize the interrupt controller driver so that it is ready to
* use.
*/
#ifndef TESTAPP_GEN
IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);
if (NULL == IntcConfig) {
return XST_FAILURE;
}
Status = XScuGic_CfgInitialize(IntcInstancePtr, IntcConfig,
IntcConfig->CpuBaseAddress);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
#endif
XScuGic_SetPriorityTriggerType(IntcInstancePtr, SpiIntrId, 0xA0, 0x3);
/*
* Connect the device driver handler that will be called when an
* interrupt for the device occurs, the handler defined above performs
* the specific interrupt processing for the device.
*/
Status = XScuGic_Connect(IntcInstancePtr, SpiIntrId,
(Xil_InterruptHandler)XSpi_InterruptHandler,
SpiInstancePtr);
if (Status != XST_SUCCESS) {
return Status;
}
XScuGic_Enable(IntcInstancePtr, SpiIntrId);
#endif
#ifndef TESTAPP_GEN
/* Enable interrupts from the hardware */
Xil_ExceptionInit();
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
(Xil_ExceptionHandler)INTC_HANDLER,
(void *)IntcInstancePtr);
Xil_ExceptionEnable();
#endif /* TESTAPP_GEN */
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function disables the interrupts that occur for the Spi device.
*
* @param IntcInstancePtr is the pointer to the instance of the INTC
* component.
* @param SpiIntrId is the interrupt Id and is typically
* XPAR_<INTC_instance>_<SPI_instance>_VEC_ID value from
* xparameters.h
*
* @return None
*
* @note None
*
******************************************************************************/
static void SpiDisableIntrSystem(INTC *IntcInstancePtr, u16 SpiIntrId)
{
/*
* Disconnect and disable the interrupt for the Spi device.
*/
#ifdef XPAR_INTC_0_DEVICE_ID
/* Disconnect the interrupts for the Master complete and error */
XIntc_Disconnect(IntcInstancePtr, SpiIntrId);
#else
XScuGic_Disconnect(IntcInstancePtr, SpiIntrId);
#endif
}

View file

@ -0,0 +1,222 @@
/******************************************************************************
*
* 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 xspi_low_level_example.c
*
* This file contains a design example using the low-level driver of the
* SPI driver (XSpi). These macros are found in xspi_l.h. A simple loopback
* test is done within an SPI device in polled mode. This example works only with
* 8-bit wide data transfers.
*
* @note
* This example works only with 8-bit wide data transfers in standard SPI mode.
* This example will not work if the axi_qspi device is confiured in dual/quad
* modes.
*
* To make this example work for 16 bit transfers change u8 Buffer[BUFFER_SIZE]
* to u16 Buffer[BUFFER_SIZE]. The SPI Core should aslo be configured for 16 bit
* access during the build time.
*
* To make this example work for 32 bit transfers change u8 Buffer[BUFFER_SIZE]
* to u32 Buffer[BUFFER_SIZE]. The SPI Core should aslo be configured for 32 bit
* access during the build time.
*
*
*<pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- -------- ----------------------------------------------------------
* 1.00b rpm 04/24/02 First release
* 1.00b jhl 09/10/02 Added code to ensure it works with a fast processor.
* 1.00b sv 05/16/05 Minor changes to comply to Doxygen and coding guidelines
* 3.00a ktn 10/28/09 Converted all register accesses to 32 bit access.
* 3.02a sdm 05/04/11 Added a note about dual/quad modes in axi_qspi.
*
*</pre>
*******************************************************************************/
/***************************** Include Files **********************************/
#include "xparameters.h"
#include "xstatus.h"
#include "xspi_l.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 SPI_BASEADDR XPAR_SPI_0_BASEADDR
/**************************** Type Definitions ********************************/
/***************** Macros (Inline Functions) Definitions **********************/
/************************** Function Prototypes *******************************/
int XSpi_LowLevelExample(u32 BaseAddress);
/************************** Variable Definitions ******************************/
/*
* This is the size of the buffer to be transmitted/received in this example.
*/
#define BUFFER_SIZE 32
/*
* The buffer used for Transmission/Reception of the SPI test data
*/
u16 Buffer[BUFFER_SIZE];
/******************************************************************************/
/**
* This function is the main function of the SPI Low Level example.
*
* @param None
*
* @return XST_SUCCESS to indicate success, else XST_FAILURE to indicate
* Failure.
*
* @note None
*
*******************************************************************************/
int main(void)
{
int Status;
/*
* Run the example, specify the Base Address that is generated in
* xparameters.h
*/
Status = XSpi_LowLevelExample(SPI_BASEADDR);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
return XST_SUCCESS;
}
/******************************************************************************/
/**
*
* This function does a simple loopback test within an SPI device.
*
* @param BaseAddress is the BaseAddress of the SPI device
*
* @return XST_SUCCESS if successful, XST_FAILURE if unsuccessful
*
* @note None
*
*******************************************************************************/
int XSpi_LowLevelExample(u32 BaseAddress)
{
u32 Control;
int NumBytesSent = 0;
int NumBytesRcvd = 0;
u32 Count;
/*
* Set up the device in loopback mode and enable master mode.
*/
Control = XSpi_ReadReg(BaseAddress, XSP_CR_OFFSET);
Control |= (XSP_CR_LOOPBACK_MASK | XSP_CR_MASTER_MODE_MASK);
XSpi_WriteReg(BaseAddress, XSP_CR_OFFSET, Control);
/*
* Initialize the buffer with some data.
*/
for (Count = 0; Count < BUFFER_SIZE; Count++) {
Buffer[Count] = Count;
}
/*
* Fill up the transmitter with data, assuming the receiver can hold
* the same amount of data.
*/
while ((XSpi_ReadReg(BaseAddress, XSP_SR_OFFSET) &
XSP_SR_TX_FULL_MASK) == 0) {
XSpi_WriteReg((BaseAddress), XSP_DTR_OFFSET,
Buffer[NumBytesSent++]);
}
/*
* Enable the device.
*/
Control = XSpi_ReadReg(BaseAddress, XSP_CR_OFFSET);
Control |= XSP_CR_ENABLE_MASK;
Control &= ~XSP_CR_TRANS_INHIBIT_MASK;
XSpi_WriteReg(BaseAddress, XSP_CR_OFFSET, Control);
/*
* Initialize the buffer with zeroes so that it can be used to receive
* data.
*/
for (Count = 0; Count < BUFFER_SIZE; Count++) {
Buffer[Count] = 0x0;
}
/*
* Wait for the transmit FIFO to transition to empty before checking
* the receive FIFO, this prevents a fast processor from seeing the
* receive FIFO as empty
*/
while (!(XSpi_ReadReg(BaseAddress, XSP_SR_OFFSET) &
XSP_SR_TX_EMPTY_MASK));
/*
* Transmitter is full, now receive the data just looped back until
* the receiver is empty.
*/
while ((XSpi_ReadReg(BaseAddress, XSP_SR_OFFSET) &
XSP_SR_RX_EMPTY_MASK) == 0) {
Buffer[NumBytesRcvd++] = XSpi_ReadReg((BaseAddress),
XSP_DRR_OFFSET);
}
/*
* If no data was sent or the data that was sent was not received,
* then return an error
*/
if ((NumBytesSent != NumBytesRcvd) || (NumBytesSent == 0)) {
return XST_FAILURE;
}
return XST_SUCCESS;
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,250 @@
/******************************************************************************
*
* Copyright (C) 2008 - 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 xspi_polled_example.c
*
*
* This file contains a design example using the Spi driver (XSpi) and the Spi
* device using the polled mode.
*
* To put the driver in polled mode the Global Interrupt must be disabled after
* the Spi is Initialized and Spi driver is started.
*
* This example works with a PPC/MicroBlaze processor.
*
* @note
*
* None.
*
*<pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- -------- ---------------------------------------------------------
* 1.00a sdm 03/03/08 First Release
* 3.00a ktn 10/28/09 Converted all register accesses to 32 bit access.
* Updated to use the HAL APIs/macros. Replaced call to
* XSpi_Initialize API with XSpi_LookupConfig and
* XSpi_CfgInitialize.
* 3.02a sdm 05/04/11 Updated to run the loopback test only in standard spi
* mode.
*</pre>
******************************************************************************/
/***************************** Include Files *********************************/
#include "xparameters.h" /* XPAR parameters */
#include "xspi.h" /* SPI device driver */
#include "xspi_l.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 SPI_DEVICE_ID XPAR_SPI_0_DEVICE_ID
/*
* This is the size of the buffer to be transmitted/received in this example.
*/
#define BUFFER_SIZE 12
/**************************** Type Definitions *******************************/
/*
* The following data type is used to send and receive data on the SPI
* interface.
*/
typedef u8 DataBuffer[BUFFER_SIZE];
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
int SpiPolledExample(XSpi *SpiInstancePtr, u16 SpiDeviceId);
/************************** Variable Definitions *****************************/
/*
* The instances to support the device drivers are global such that the
* are initialized to zero each time the program runs.
*/
static XSpi SpiInstance; /* The instance of the SPI device */
/*
* The following variables are used to read and write to the Spi device, they
* are global to avoid having large buffers on the stack.
*/
u8 ReadBuffer[BUFFER_SIZE];
u8 WriteBuffer[BUFFER_SIZE];
/*****************************************************************************/
/**
*
* Main function to call the Spi Polled example.
*
* @param None
*
* @return XST_SUCCESS if successful, otherwise XST_FAILURE.
*
* @note None
*
******************************************************************************/
int main(void)
{
int Status;
/*
* Run the Spi Polled example.
*/
Status = SpiPolledExample(&SpiInstance, SPI_DEVICE_ID);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function does a minimal test on the Spi device and driver as a
* design example. The purpose of this function is to illustrate how to use
* the XSpi component using the polled mode.
*
* This function sends data and expects to receive the same data.
*
*
* @param SpiInstancePtr is a pointer to the instance of Spi component.
* @param SpiDeviceId is the Device ID of the Spi Device and is the
* XPAR_<SPI_instance>_DEVICE_ID value from xparameters.h.
*
* @return XST_SUCCESS if successful, otherwise XST_FAILURE.
*
* @note
*
* This function contains an infinite loop such that if the Spi device is not
* working it may never return.
*
******************************************************************************/
int SpiPolledExample(XSpi *SpiInstancePtr, u16 SpiDeviceId)
{
int Status;
u32 Count;
u8 Test;
XSpi_Config *ConfigPtr; /* Pointer to Configuration data */
/*
* Initialize the SPI driver so that it is ready to use.
*/
ConfigPtr = XSpi_LookupConfig(SpiDeviceId);
if (ConfigPtr == NULL) {
return XST_DEVICE_NOT_FOUND;
}
Status = XSpi_CfgInitialize(SpiInstancePtr, ConfigPtr,
ConfigPtr->BaseAddress);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Perform a self-test to ensure that the hardware was built correctly.
*/
Status = XSpi_SelfTest(SpiInstancePtr);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Run loopback test only in case of standard SPI mode.
*/
if (SpiInstancePtr->SpiMode != XSP_STANDARD_MODE) {
return XST_SUCCESS;
}
/*
* Set the Spi device as a master and in loopback mode.
*/
Status = XSpi_SetOptions(SpiInstancePtr, XSP_MASTER_OPTION |
XSP_LOOPBACK_OPTION);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Start the SPI driver so that the device is enabled.
*/
XSpi_Start(SpiInstancePtr);
/*
* Disable Global interrupt to use polled mode operation
*/
XSpi_IntrGlobalDisable(SpiInstancePtr);
/*
* Initialize the write buffer with pattern to write, initialize the
* read buffer to zero so it can be verified after the read, the
* Test value that is added to the unique value allows the value to be
* changed in a debug environment.
*/
Test = 0x10;
for (Count = 0; Count < BUFFER_SIZE; Count++) {
WriteBuffer[Count] = (u8)(Count + Test);
ReadBuffer[Count] = 0;
}
/*
* Transmit the data.
*/
XSpi_Transfer(SpiInstancePtr, WriteBuffer, ReadBuffer, BUFFER_SIZE);
/*
* Compare the data received with the data that was transmitted.
*/
for (Count = 0; Count < BUFFER_SIZE; Count++) {
if (WriteBuffer[Count] != ReadBuffer[Count]) {
return XST_FAILURE;
}
}
return XST_SUCCESS;
}

View file

@ -0,0 +1,164 @@
/******************************************************************************
*
* Copyright (C) 2008 - 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 xspi_selftest_example.c
*
* This file contains a example for using the SPI Hardware and driver.
*
* @note
*
* None
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- -------- -----------------------------------------------
* 1.00a sv 05/16/05 Initial release for TestApp integration.
* 1.11a sdm 03/03/08 Minor changes to comply to coding guidelines
* 3.00a ktn 10/28/09 Converted all register accesses to 32 bit access.
* Updated to use the HAL APIs/macros. Replaced call to
* XSpi_Initialize API with XSpi_LookupConfig and
* XSpi_CfgInitialize.
* </pre>
*
*******************************************************************************/
/***************************** Include Files **********************************/
#include "xparameters.h"
#include "xspi.h"
#include "xspi_l.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 SPI_DEVICE_ID XPAR_SPI_0_DEVICE_ID
/**************************** Type Definitions ********************************/
/***************** Macros (Inline Functions) Definitions **********************/
/************************** Function Prototypes *******************************/
int SpiSelfTestExample(u16 DeviceId);
/************************** Variable Definitions ******************************/
XSpi Spi; /* The instance of the SPI device */
/******************************************************************************/
/**
* Main function to call the example. This function is not included if the
* example is generated from the TestAppGen test tool.
*
* @param None
*
* @return XST_SUCCESS if successful, XST_FAILURE if unsuccessful
*
* @note None
*
*******************************************************************************/
#ifndef TESTAPP_GEN
int main(void)
{
int Status;
/*
* Call the example , specify the device ID that is generated in
* xparameters.h
*/
Status = SpiSelfTestExample(SPI_DEVICE_ID);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
return XST_SUCCESS;
}
#endif
/*****************************************************************************/
/**
*
* This function does a selftest and loopback test on the SPI device and
* XSpi driver as an example. The purpose of this function is to illustrate
* how to use the XSpi component.
*
*
* @param DeviceId is the XPAR_<SPI_instance>_DEVICE_ID value from
* xparameters.h
*
* @return XST_SUCCESS if successful, XST_FAILURE if unsuccessful
*
* @note None
*
****************************************************************************/
int SpiSelfTestExample(u16 DeviceId)
{
int Status;
XSpi_Config *ConfigPtr; /* Pointer to Configuration data */
/*
* Initialize the SPI driver so that it is ready to use.
*/
ConfigPtr = XSpi_LookupConfig(DeviceId);
if (ConfigPtr == NULL) {
return XST_DEVICE_NOT_FOUND;
}
Status = XSpi_CfgInitialize(&Spi, ConfigPtr,
ConfigPtr->BaseAddress);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Perform a self-test to ensure that the hardware was built correctly
*/
Status = XSpi_SelfTest(&Spi);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
return XST_SUCCESS;
}

View file

@ -0,0 +1,399 @@
/******************************************************************************
*
* Copyright (C) 2008 - 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 xspi_slave_intr_example.c
*
*
* This file contains a design example using the Spi driver (XSpi) and the Spi
* device as a Slave, in interrupt mode.
*
* This example fills the Spi Tx buffer with the number of data bytes it expects
* to receive from the master and then Spi device waits for an external master to
* initiate the transfer. When the master initiates the transfer, the Spi device
* receives data from the master and simultaneously sends the data in Tx buffer
* to the master. Once the transfer is complete, a transfer complete interrupt is
* generated and this example prints the data received from the master. The
* number of bytes to be received by the Spi slave is defined by the constant
* BUFFER_SIZE in this file.
*
* The external SPI devices that are present on the Xilinx boards don't support
* the Master functionality. This example has been tested with Aardvark I2C/SPI
* Host Adapter, an off board external SPI Master device and the Xilinx SPI
* device configured as a Slave. This example has been tested for byte-wide SPI
* transfers.
*
* @note
*
* This example assumes that there is a STDIO device in the system.
*
*<pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- -------- ---------------------------------------------------------
* 1.00a psk 09/05/08 First Release
* 3.00a ktn 10/22/09 Converted all register accesses to 32 bit access.
* Updated to use the HAL APIs/macros. Replaced call to
* XSpi_Initialize API with XSpi_LookupConfig and
* XSpi_CfgInitialize.
* 3.01a sdm 04/23/10 Enabled DTR Half_empty interrupt so that Tx FIFO is
* not empty during a transfer in slave mode.
*
*</pre>
******************************************************************************/
/***************************** Include Files *********************************/
#include "xparameters.h" /* XPAR parameters */
#include "xspi.h" /* SPI device driver */
#include "xintc.h" /* Interrupt controller devive driver */
#include "stdio.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 SPI_DEVICE_ID XPAR_SPI_0_DEVICE_ID
#define INTC_DEVICE_ID XPAR_INTC_0_DEVICE_ID
#define SPI_IRPT_INTR XPAR_INTC_0_SPI_0_VEC_ID
/*
* This is the size of the buffer to be transmitted/received in this example.
*/
#define BUFFER_SIZE 32
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
static int SpiSlaveIntrExample(XSpi *SpiInstancePtr, u16 SpiDeviceId);
static int SetupInterruptSystem(XSpi *SpiInstance);
static void SpiHandler(void *CallBackRef, u32 StatusEvent,
unsigned int ByteCount);
/************************** Variable Definitions *****************************/
/*
* The instances to support the device drivers are global such that they are
* initialized to zero each time the program runs. They could be local but
* should at least be static so that they are zeroed.
*/
static XSpi SpiInstance; /* Instance of the SPI device */
static XIntc IntcInstance; /* Instance of the Interrupt controller device */
/*
* The following variables are used to read/write from the Spi device, these
* are global to avoid having large buffers on the stack.
*/
u8 ReadBuffer[BUFFER_SIZE];
u8 WriteBuffer[BUFFER_SIZE];
/*
* The following variable allows a test value to be added to the values that
* are sent in reflection to the Master transmission such that unique values can
* be generated to guarantee the transfer from Slave to Master is successful.
*/
int Test;
/*
* The following variables are shared between non-interrupt processing and
* interrupt processing such that they must be global.
*/
static volatile int TransferInProgress;
/*****************************************************************************/
/**
*
* Main function to call the Spi Slave example in interrupt mode.
*
* @param None
*
* @return XST_SUCCESS if successful, otherwise XST_FAILURE.
*
* @note None
*
******************************************************************************/
int main(void)
{
int Status;
/*
* Run the Spi Slave interrupt example.
*/
Status = SpiSlaveIntrExample(&SpiInstance, SPI_DEVICE_ID);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function does a minimal test on the Spi device and driver as a design
* example. The purpose of this function is to illustrate the device slave
* functionality in interrupt mode. This function receives data from a master and
* prints the received data.
*
* @param SpiInstancePtr is a pointer to the instance of Spi component.
* @param SpiDeviceId is the Device ID of the Spi Device and is the
* XPAR_<SPI_instance>_DEVICE_ID value from xparameters.h.
*
* @return XST_SUCCESS if successful, otherwise XST_FAILURE.
*
* @note This function contains an infinite loop such that if the Spi
* device doesn't receive any data or if the interrupts are not
* working, it may never return.
*
******************************************************************************/
static int SpiSlaveIntrExample(XSpi *SpiInstancePtr, u16 SpiDeviceId)
{
XSpi_Config *ConfigPtr;
int Status;
u32 Count;
xil_printf("\r\nEntering the Spi Slave Interrupt Example.\r\n");
xil_printf("Waiting for data from SPI master\r\n");
/*
* Initialize the SPI driver so that it's ready to use, specify the
* device ID that is generated in xparameters.h.
*/
ConfigPtr = XSpi_LookupConfig(SpiDeviceId);
if (ConfigPtr == NULL) {
return XST_FAILURE;
}
Status = XSpi_CfgInitialize(SpiInstancePtr, ConfigPtr,
ConfigPtr->BaseAddress);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Connect the SPI driver to the interrupt subsystem such that
* interrupts can occur. This function is application specific.
*/
Status = SetupInterruptSystem(SpiInstancePtr);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Setup the handler for the SPI that will be called from the interrupt
* context when an SPI status occurs, specify a pointer to the SPI
* driver instance as the callback reference so the handler is able to
* access the instance data.
*/
XSpi_SetStatusHandler(SpiInstancePtr,SpiInstancePtr,(XSpi_StatusHandler)
SpiHandler);
/*
* The SPI device is a slave by default and the clock phase and polarity
* have to be set according to its master. In this example, CPOL is set
* to active low and CPHA is set to 1.
*/
Status = XSpi_SetOptions(SpiInstancePtr, XSP_CLK_PHASE_1_OPTION |
XSP_CLK_ACTIVE_LOW_OPTION);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Start the SPI driver so that the device is enabled.
*/
XSpi_Start(SpiInstancePtr);
/*
* Enable the DTR half-empty interrupt while transfering more than
* FIFO_DEPTH number of bytes in slave mode, so that the Tx FIFO
* is never empty during a transfer. If the Tx FIFO is empty during
* a transfer, it results in master receiving invalid data.
*/
XSpi_IntrEnable(SpiInstancePtr, XSP_INTR_TX_HALF_EMPTY_MASK);
/*
* Initialize the write buffer with pattern to write, initialize the
* read buffer to zero so it can be verified after the read.
*/
Test = 0x50;
for (Count = 0; Count < BUFFER_SIZE; Count++) {
WriteBuffer[Count] = (u8)(Count + Test);
ReadBuffer[Count] = 0;
}
/*
* Transmit data as a slave, when the master starts sending data.
*/
TransferInProgress = TRUE;
Status = XSpi_Transfer(SpiInstancePtr, WriteBuffer, ReadBuffer,
BUFFER_SIZE);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the transfer is complete.
*/
while (TransferInProgress == TRUE);
/*
* Print all the data received from the master.
*/
xil_printf("\r\nReceived data is:\r\n");
for (Count = 0; Count < BUFFER_SIZE; Count++) {
xil_printf("0x%x \r\n", ReadBuffer[Count]);
}
xil_printf("\r\nExiting the Spi Slave Interrupt Example.\r\n");
return XST_SUCCESS;
}
/****************************************************************************/
/**
*
* This function setups the interrupt system such that interrupts can occur
* for the SPI driver. This function is application specific since the actual
* system may or may not have an interrupt controller. The SPI device could
* be directly connected to a processor without an interrupt controller. The
* user should modify this function to fit the application.
*
* @param SpiInstance contains a pointer to the instance of the XSpi
* component which is going to be connected to the interrupt
* controller.
*
* @return XST_SUCCESS if successful, else XST_FAILURE.
*
* @note None.
*
****************************************************************************/
static int SetupInterruptSystem(XSpi *SpiInstance)
{
int Status;
/*
* Initialize the interrupt controller driver so that it's ready to use,
* specify the device ID that is generated in "xparameters.h".
*/
Status = XIntc_Initialize(&IntcInstance, INTC_DEVICE_ID);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* 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(&IntcInstance,
SPI_IRPT_INTR,
(XInterruptHandler)XSpi_InterruptHandler,
(void *)SpiInstance);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Start the interrupt controller such that interrupts are enabled for
* all devices that cause interrupts, specific real mode so that the SPI
* can cause interrupts through the interrupt controller.
*/
Status = XIntc_Start(&IntcInstance, XIN_REAL_MODE);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Enable the interrupt for the Spi device.
*/
XIntc_Enable(&IntcInstance, SPI_IRPT_INTR);
/*
* 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,
&IntcInstance);
/*
* Enable non-critical exceptions.
*/
Xil_ExceptionEnable();
return XST_SUCCESS;
}
/******************************************************************************/
/**
*
* This function is the handler which performs processing for the SPI driver. It
* is called from an interrupt context such that the amount of processing to be
* performed should be minimized. This handler provides an example of how to
* handle SPI interrupts but is application specific.
*
* @param CallBackRef is a reference passed to the handler.
* @param StatusEvent is the status of the SPI.
* @param ByteCount is the number of bytes transferred.
*
* @return None.
*
* @note None.
*
******************************************************************************/
static void SpiHandler(void *CallBackRef, u32 StatusEvent,
unsigned int ByteCount)
{
if (StatusEvent == XST_SPI_TRANSFER_DONE) {
/*
* Indicate the transfer on the SPI bus is no longer in
* progress.
*/
TransferInProgress = FALSE;
}
}

View file

@ -0,0 +1,242 @@
/******************************************************************************
*
* Copyright (C) 2008 - 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 xspi_slave_polled_example.c
*
* This file contains a design example using the Spi driver (XSpi) and the SPI
* device as a Slave, in polled mode.
*
* This example fills the Spi Tx buffer with the number of data bytes it expects
* to receive from the master and then Spi device waits for an external master to
* initiate the transfer. When the master initiates the transfer, the Spi device
* receives data from the master and simultaneously sends the data in Tx buffer
* to the master. Once the transfer is complete, this example prints the data
* received from the master. The number of bytes to be received by the Spi slave
* is defined by the constant BUFFER_SIZE in this file.
*
* The external SPI devices that are present on the Xilinx boards don't support
* the Master functionality. This example has been tested with an off board
* external SPI Master device and the Xilinx SPI device configured as a Slave.
* This example has been tested for byte-wide SPI transfers.
*
* @note
*
* This example assumes that there is a STDIO device in the system.
*
*<pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- -------- ---------------------------------------------------------
* 1.00a psk 09/05/08 First Release
* 3.00a ktn 10/28/09 Converted all register accesses to 32 bit access.
* Updated to use the HAL APIs/macros. Replaced call to
* XSpi_Initialize API with XSpi_LookupConfig and
* XSpi_CfgInitialize.
*
*</pre>
******************************************************************************/
/***************************** Include Files *********************************/
#include "xparameters.h" /* XPAR parameters */
#include "xspi.h" /* SPI device driver */
#include "stdio.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 SPI_DEVICE_ID XPAR_SPI_0_DEVICE_ID
/*
* This is the size of the buffer to be transmitted/received in this example.
*/
#define BUFFER_SIZE 16
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
static int SpiSlavePolledExample(XSpi *SpiInstancePtr, u16 SpiDeviceId);
/************************** Variable Definitions *****************************/
/*
* The instances to support the device drivers are global such that they are
* initialized to zero each time the program runs. They could be local but
* should at least be static so that they are zeroed.
*/
static XSpi SpiInstance; /* The instance of the SPI device */
/*
* The following variables are used to read from the Spi device, these are
* global to avoid having large buffers on the stack.
*/
u8 ReadBuffer[BUFFER_SIZE];
u8 WriteBuffer[BUFFER_SIZE];
/*
* The following variable allows a test value to be added to the values that
* are sent in reflection to the Master transmission such that unique values can
* be generated to guarantee the transfer from Slave to Master is successful.
*/
int Test;
/*****************************************************************************/
/**
*
* Main function to call the Spi Slave example in polled mode.
*
* @param None
*
* @return XST_SUCCESS if successful, otherwise XST_FAILURE.
*
* @note None
*
******************************************************************************/
int main(void)
{
int Status;
/*
* Run the Spi Slave polled example.
*/
Status = SpiSlavePolledExample(&SpiInstance, SPI_DEVICE_ID);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function does a minimal test on the Spi device and driver as a design
* example. The purpose of this function is to illustrate the device slave
* functionality in polled mode. This function receives data from a master and
* prints the received data.
*
* @param SpiInstancePtr is a pointer to the instance of Spi component.
*
* @param SpiDeviceId is the Device ID of the Spi Device and is the
* XPAR_<SPI_instance>_DEVICE_ID value from xparameters.h.
*
* @return XST_SUCCESS if successful, otherwise XST_FAILURE.
*
* @note This function contains an infinite loop such that if the Spi
* device doesn't receive any data, it may never return.
*
******************************************************************************/
int SpiSlavePolledExample(XSpi *SpiInstancePtr, u16 SpiDeviceId)
{
XSpi_Config *ConfigPtr;
int Status;
u32 Count;
xil_printf("\r\nEntering the Spi Slave Polled Example.\r\n");
xil_printf("Waiting for data from SPI master\r\n");
/*
* Initialize the SPI driver so that it's ready to use, specify the
* device ID that is generated in xparameters.h.
*/
ConfigPtr = XSpi_LookupConfig(SpiDeviceId);
if (ConfigPtr == NULL) {
return XST_FAILURE;
}
Status = XSpi_CfgInitialize(SpiInstancePtr, ConfigPtr,
ConfigPtr->BaseAddress);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* The SPI device is a slave by default and the clock phase and polarity
* have to be set according to its master. In this example, CPOL is set
* to active low and CPHA is set to 1.
*/
Status = XSpi_SetOptions(SpiInstancePtr, XSP_CLK_PHASE_1_OPTION |
XSP_CLK_ACTIVE_LOW_OPTION);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Start the SPI driver so that the device is enabled.
*/
XSpi_Start(SpiInstancePtr);
/*
* Disable Global interrupt to use polled mode operation.
*/
XSpi_IntrGlobalDisable(SpiInstancePtr);
/*
* Initialize the write buffer with pattern to write, initialize the
* read buffer to zero so that it can be verified after the read.
*/
Test = 0xF0;
for (Count = 0; Count < BUFFER_SIZE; Count++) {
WriteBuffer[Count] = (u8)(Count + Test);
ReadBuffer[Count] = 0;
}
/*
* Prepare the data buffers for transmission and to send/receive data
* when the SPI device is selected by a master.
*/
XSpi_Transfer(SpiInstancePtr, WriteBuffer, ReadBuffer, BUFFER_SIZE);
/*
* Print all the data received from the master so that it can be
* compared with the data sent by the master.
*/
xil_printf("\r\nReceived data is:\r\n");
for (Count = 0; Count < BUFFER_SIZE; Count++) {
xil_printf("0x%x \r\n", ReadBuffer[Count]);
}
xil_printf("\r\nExiting the Spi Slave Polled Example.\r\n");
return XST_SUCCESS;
}

View file

@ -0,0 +1,822 @@
/******************************************************************************
*
* Copyright (C) 2008 - 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 xspi_stm_flash_example.c
*
* This file contains a design example using the SPI driver (XSpi) and hardware
* device with an STM serial Flash device (M25P series) in the interrupt mode.
* This example erases a Sector, writes to a Page within the Sector, reads back
* from that Page and compares the data.
*
* This example has been tested with an M25P16 device. The bytes per page
* (STM_PAGE_SIZE) in M25P16 is 256.
*
* This example assumes that the underlying processor is MicroBlaze.
*
* @note
*
* None.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- -------- -----------------------------------------------
* 1.00a sd 02/26/08 First release
* 3.00a ktn 10/28/09 Converted all register accesses to 32 bit access.
* Updated to use the HAL APIs/macros. Replaced call to
* XSpi_Initialize API with XSpi_LookupConfig and
* XSpi_CfgInitialize.
*
* </pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "xparameters.h" /* EDK generated parameters */
#include "xintc.h" /* Interrupt controller device driver */
#include "xspi.h" /* SPI device driver */
#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 SPI_DEVICE_ID XPAR_SPI_0_DEVICE_ID
#define INTC_DEVICE_ID XPAR_INTC_0_DEVICE_ID
#define SPI_INTR_ID XPAR_INTC_0_SPI_0_VEC_ID
/*
* The following constant defines the slave select signal that is used to
* to select the Flash device on the SPI bus, this signal is typically
* connected to the chip select of the device.
*/
#define STM_SPI_SELECT 0x01
/*
* Definitions of the commands shown in this example.
*/
#define STM_COMMAND_RANDOM_READ 0x03 /* Random read command */
#define STM_COMMAND_PAGEPROGRAM_WRITE 0x02 /* Page Program command */
#define STM_COMMAND_WRITE_ENABLE 0x06 /* Write Enable command */
#define STM_COMMAND_SECTOR_ERASE 0xD8 /* Sector Erase command */
#define STM_COMMAND_BULK_ERASE 0xC7 /* Bulk Erase command */
#define STM_COMMAND_STATUSREG_READ 0x05 /* Status read command */
/**
* This definitions specify the EXTRA bytes in each of the command
* transactions. This count includes Command byte, address bytes and any
* don't care bytes needed.
*/
#define STM_READ_WRITE_EXTRA_BYTES 4 /* Read/Write extra bytes */
#define STM_WRITE_ENABLE_BYTES 1 /* Write Enable bytes */
#define STM_SECTOR_ERASE_BYTES 4 /* Sector erase extra bytes */
#define STM_BULK_ERASE_BYTES 1 /* Bulk erase extra bytes */
#define STM_STATUS_READ_BYTES 2 /* Status read bytes count */
#define STM_STATUS_WRITE_BYTES 2 /* Status write bytes count */
/*
* Flash not busy mask in the status register of the flash device.
*/
#define STM_FLASH_SR_IS_READY_MASK 0x01 /* Ready mask */
/*
* Number of bytes per page in the flash device.
*/
#define STM_PAGE_SIZE 256
/*
* Address of the page to perform Erase, Write and Read operations.
*/
#define STM_FLASH_TEST_ADDRESS 0x00
/*
* Byte offset value written to Flash. This needs to redefined for writing
* different patterns of data to the Flash device.
*/
#define STM_FLASH_TEST_BYTE 0x20
/*
* Byte Positions.
*/
#define BYTE1 0 /* Byte 1 position */
#define BYTE2 1 /* Byte 2 position */
#define BYTE3 2 /* Byte 3 position */
#define BYTE4 3 /* Byte 4 position */
#define BYTE5 4 /* Byte 5 position */
#define STM_DUMMYBYTE 0xFF /* Dummy byte */
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
int SpiStmFlashWriteEnable(XSpi *SpiPtr);
int SpiStmFlashWrite(XSpi *SpiPtr, u32 Addr, u32 ByteCount);
int SpiStmFlashRead(XSpi *SpiPtr, u32 Addr, u32 ByteCount);
int SpiStmFlashBulkErase(XSpi *SpiPtr);
int SpiStmFlashSectorErase(XSpi *SpiPtr, u32 Addr);
int SpiStmFlashGetStatus(XSpi *SpiPtr);
static int SpiStmFlashWaitForFlashNotBusy(void);
void SpiHandler(void *CallBackRef, u32 StatusEvent, unsigned int ByteCount);
static int SetupInterruptSystem(XSpi *SpiPtr);
/************************** Variable Definitions *****************************/
/*
* The instances to support the device drivers are global such that they
* are initialized to zero each time the program runs. They could be local
* but should at least be static so they are zeroed.
*/
static XIntc InterruptController;
static XSpi Spi;
/*
* The following variables are shared between non-interrupt processing and
* interrupt processing such that they must be global.
*/
volatile static int TransferInProgress;
/*
* The following variable tracks any errors that occur during interrupt
* processing.
*/
int ErrorCount;
/*
* Buffers used during read and write transactions.
*/
u8 ReadBuffer[STM_PAGE_SIZE + STM_READ_WRITE_EXTRA_BYTES];
u8 WriteBuffer[STM_PAGE_SIZE + STM_READ_WRITE_EXTRA_BYTES];
/************************** Function Definitions ******************************/
/*****************************************************************************/
/**
*
* Main function to execute the Flash example.
*
* @param None
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note None
*
******************************************************************************/
int main()
{
int Status;
u32 Index;
u32 Address;
XSpi_Config *ConfigPtr; /* Pointer to Configuration data */
/*
* Initialize the SPI driver so that it's ready to use,
* specify the device ID that is generated in xparameters.h.
*/
ConfigPtr = XSpi_LookupConfig(SPI_DEVICE_ID);
if (ConfigPtr == NULL) {
return XST_DEVICE_NOT_FOUND;
}
Status = XSpi_CfgInitialize(&Spi, ConfigPtr,
ConfigPtr->BaseAddress);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Connect the SPI driver to the interrupt subsystem such that
* interrupts can occur. This function is application specific.
*/
Status = SetupInterruptSystem(&Spi);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Setup the handler for the SPI that will be called from the interrupt
* context when an SPI status occurs, specify a pointer to the SPI
* driver instance as the callback reference so the handler is able to
* access the instance data.
*/
XSpi_SetStatusHandler(&Spi, &Spi, (XSpi_StatusHandler)SpiHandler);
/*
* Set the SPI device as a master and in manual slave select mode such
* that the slave select signal does not toggle for every byte of a
* transfer, this must be done before the slave select is set.
*/
Status = XSpi_SetOptions(&Spi, XSP_MASTER_OPTION |
XSP_MANUAL_SSELECT_OPTION);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Select the STM flash device on the SPI bus, so that it can be
* read and written using the SPI bus.
*/
Status = XSpi_SetSlaveSelect(&Spi, STM_SPI_SELECT);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Start the SPI driver so that interrupts and the device are enabled.
*/
XSpi_Start(&Spi);
/*
* Specify the address in the STM Serial Flash for the Erase/Write/Read
* operations.
*/
Address = STM_FLASH_TEST_ADDRESS;
/*
* Perform the Write Enable operation.
*/
Status = SpiStmFlashWriteEnable(&Spi);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = SpiStmFlashWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Perform the Sector Erase operation.
*/
Status = SpiStmFlashSectorErase(&Spi, Address);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = SpiStmFlashWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Perform the Write Enable operation.
*/
Status = SpiStmFlashWriteEnable(&Spi);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = SpiStmFlashWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Write the data to the Page.
* Perform the Write operation.
*/
Status = SpiStmFlashWrite(&Spi, Address, STM_PAGE_SIZE);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = SpiStmFlashWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Clear the read Buffer.
*/
for(Index = 0; Index < STM_PAGE_SIZE + STM_READ_WRITE_EXTRA_BYTES;
Index++) {
ReadBuffer[Index] = 0x0;
}
/*
* Read the data from the Page.
*/
Status = SpiStmFlashRead(&Spi, Address, STM_PAGE_SIZE);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Compare the data read against the data Written.
*/
for(Index = 0; Index < STM_PAGE_SIZE; Index++) {
if(ReadBuffer[Index + STM_READ_WRITE_EXTRA_BYTES] !=
(u8)(Index + STM_FLASH_TEST_BYTE)) {
return XST_FAILURE;
}
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function enables writes to the STM Serial Flash memory.
*
* @param SpiPtr is a pointer to the instance of the Spi device.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note None
*
******************************************************************************/
int SpiStmFlashWriteEnable(XSpi *SpiPtr)
{
int Status;
/*
* Prepare the WriteBuffer.
*/
WriteBuffer[BYTE1] = STM_COMMAND_WRITE_ENABLE;
/*
* Initiate the Transfer.
*/
TransferInProgress = TRUE;
Status = XSpi_Transfer(SpiPtr, WriteBuffer, NULL,
STM_WRITE_ENABLE_BYTES);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check if there are any errors
* in the transaction..
*/
while(TransferInProgress);
if(ErrorCount != 0) {
ErrorCount = 0;
return XST_FAILURE;
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function writes the data to the specified locations in the STM Serial
* Flash memory.
*
* @param SpiPtr is a pointer to the instance of the Spi device.
* @param Addr is the address in the Buffer, where to write the data.
* @param ByteCount is the number of bytes to be written.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note None
*
******************************************************************************/
int SpiStmFlashWrite(XSpi *SpiPtr, u32 Addr, u32 ByteCount)
{
u32 Index;
int Status;
/*
* Prepare the WriteBuffer.
*/
WriteBuffer[BYTE1] = STM_COMMAND_PAGEPROGRAM_WRITE;
WriteBuffer[BYTE2] = (u8) (Addr >> 16);
WriteBuffer[BYTE3] = (u8) (Addr >> 8);
WriteBuffer[BYTE4] = (u8) Addr;
/*
* Fill in the TEST data that is to be written into the STM Serial Flash
* device.
*/
for(Index = 4; Index < ByteCount + STM_READ_WRITE_EXTRA_BYTES;
Index++) {
WriteBuffer[Index] = (u8)((Index - 4) + STM_FLASH_TEST_BYTE);
}
/*
* Initiate the Transfer.
*/
TransferInProgress = TRUE;
Status = XSpi_Transfer(SpiPtr, WriteBuffer, NULL,
(ByteCount + STM_READ_WRITE_EXTRA_BYTES));
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check if there are any errors
* in the transaction..
*/
while(TransferInProgress);
if(ErrorCount != 0) {
ErrorCount = 0;
return XST_FAILURE;
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function reads the data from the STM Serial Flash Memory
*
* @param SpiPtr is a pointer to the instance of the Spi device.
* @param Addr is the starting address in the Flash Memory from which the
* data is to be read.
* @param ByteCount is the number of bytes to be read.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note None
*
******************************************************************************/
int SpiStmFlashRead(XSpi *SpiPtr, u32 Addr, u32 ByteCount)
{
int Status;
/*
* Prepare the WriteBuffer.
*/
WriteBuffer[BYTE1] = STM_COMMAND_RANDOM_READ;
WriteBuffer[BYTE2] = (u8) (Addr >> 16);
WriteBuffer[BYTE3] = (u8) (Addr >> 8);
WriteBuffer[BYTE4] = (u8) Addr;
/*
* Initiate the Transfer.
*/
TransferInProgress = TRUE;
Status = XSpi_Transfer( SpiPtr, WriteBuffer, ReadBuffer,
(ByteCount + STM_READ_WRITE_EXTRA_BYTES));
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check if there are any errors
* in the transaction.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
ErrorCount = 0;
return XST_FAILURE;
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function erases the entire contents of the STM Serial Flash device.
*
* @param SpiPtr is a pointer to the instance of the Spi device.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note The erased bytes will read as 0xFF.
*
******************************************************************************/
int SpiStmFlashBulkErase(XSpi *SpiPtr)
{
int Status;
/*
* Prepare the WriteBuffer.
*/
WriteBuffer[BYTE1] = STM_COMMAND_BULK_ERASE;
/*
* Initiate the Transfer.
*/
TransferInProgress = TRUE;
Status = XSpi_Transfer(SpiPtr, WriteBuffer, NULL,
STM_BULK_ERASE_BYTES);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check if there are any errors
* in the transaction..
*/
while(TransferInProgress);
if(ErrorCount != 0) {
ErrorCount = 0;
return XST_FAILURE;
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function erases the contents of the specified Sector in the STM Serial
* Flash device.
*
* @param SpiPtr is a pointer to the instance of the Spi device.
* @param Addr is the address within a sector of the Buffer, which is to
* be erased.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note The erased bytes will be read back as 0xFF.
*
******************************************************************************/
int SpiStmFlashSectorErase(XSpi *SpiPtr, u32 Addr)
{
int Status;
/*
* Prepare the WriteBuffer.
*/
WriteBuffer[BYTE1] = STM_COMMAND_SECTOR_ERASE;
WriteBuffer[BYTE2] = (u8) (Addr >> 16);
WriteBuffer[BYTE3] = (u8) (Addr >> 8);
WriteBuffer[BYTE4] = (u8) (Addr);
/*
* Initiate the Transfer.
*/
TransferInProgress = TRUE;
Status = XSpi_Transfer(SpiPtr, WriteBuffer, NULL,
STM_SECTOR_ERASE_BYTES);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check if there are any errors
* in the transaction..
*/
while(TransferInProgress);
if(ErrorCount != 0) {
ErrorCount = 0;
return XST_FAILURE;
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function reads the Status register of the STM Flash.
*
* @param SpiPtr is a pointer to the instance of the Spi device.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note The status register content is stored at the second byte pointed
* by the ReadBuffer.
*
******************************************************************************/
int SpiStmFlashGetStatus(XSpi *SpiPtr)
{
int Status;
/*
* Prepare the Write Buffer.
*/
WriteBuffer[BYTE1] = STM_COMMAND_STATUSREG_READ;
/*
* Initiate the Transfer.
*/
TransferInProgress = TRUE;
Status = XSpi_Transfer(SpiPtr, WriteBuffer, ReadBuffer,
STM_STATUS_READ_BYTES);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check if there are any errors
* in the transaction..
*/
while(TransferInProgress);
if(ErrorCount != 0) {
ErrorCount = 0;
return XST_FAILURE;
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function waits till the STM serial Flash is ready to accept next command.
*
* @param None
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note This function reads the status register of the Buffer and waits
*. till the WIP bit of the status register becomes 0.
*
******************************************************************************/
int SpiStmFlashWaitForFlashNotBusy(void)
{
int Status;
u8 StatusReg;
while(1) {
/*
* Get the Status Register.
*/
Status = SpiStmFlashGetStatus(&Spi);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Check if the flash is ready to accept the next command.
* If so break.
*/
StatusReg = ReadBuffer[1];
if((StatusReg & STM_FLASH_SR_IS_READY_MASK) == 0) {
break;
}
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function is the handler which performs processing for the SPI driver.
* It is called from an interrupt context such that the amount of processing
* performed should be minimized. It is called when a transfer of SPI data
* completes or an error occurs.
*
* This handler provides an example of how to handle SPI interrupts and
* is application specific.
*
* @param CallBackRef is the upper layer callback reference passed back
* when the callback function is invoked.
* @param StatusEvent is the event that just occurred.
* @param ByteCount is the number of bytes transferred up until the event
* occurred.
*
* @return None.
*
* @note None.
*
******************************************************************************/
void SpiHandler(void *CallBackRef, u32 StatusEvent, unsigned int ByteCount)
{
/*
* Indicate the transfer on the SPI bus is no longer in progress
* regardless of the status event.
*/
TransferInProgress = FALSE;
/*
* If the event was not transfer done, then track it as an error.
*/
if (StatusEvent != XST_SPI_TRANSFER_DONE) {
ErrorCount++;
}
}
/*****************************************************************************/
/**
*
* This function setups the interrupt system such that interrupts can occur
* for the Spi device. This function is application specific since the actual
* system may or may not have an interrupt controller. The Spi device could be
* directly connected to a processor without an interrupt controller. The
* user should modify this function to fit the application.
*
* @param SpiPtr is a pointer to the instance of the Spi device.
*
* @return XST_SUCCESS if successful, otherwise XST_FAILURE.
*
* @note None
*
******************************************************************************/
static int SetupInterruptSystem(XSpi *SpiPtr)
{
int Status;
/*
* Initialize the interrupt controller driver so that
* it's ready to use, specify the device ID that is generated in
* xparameters.h
*/
Status = XIntc_Initialize(&InterruptController, INTC_DEVICE_ID);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* 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(&InterruptController,
SPI_INTR_ID,
(XInterruptHandler)XSpi_InterruptHandler,
(void *)SpiPtr);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Start the interrupt controller such that interrupts are enabled for
* all devices that cause interrupts, specific real mode so that
* the SPI can cause interrupts thru the interrupt controller.
*/
Status = XIntc_Start(&InterruptController, XIN_REAL_MODE);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Enable the interrupt for the SPI.
*/
XIntc_Enable(&InterruptController, SPI_INTR_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,
&InterruptController);
/*
* Enable non-critical exceptions.
*/
Xil_ExceptionEnable();
return XST_SUCCESS;
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,164 @@
/******************************************************************************
*
* 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.
*
******************************************************************************/
/*****************************************************************************/
/**
* @file xspi_polled_example.c
*
*
* This file contains a design example using the Spi driver (XSpi) and the Spi
* device configured in XIP Mode. This example reads data from the Flash Memory
* in the way RAM is accessed.
*
* @note
*
* None.
*
*<pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- -------- ---------------------------------------------------------
* 3.04a bss 03/21/12 First Release
*
*</pre>
******************************************************************************/
/***************************** Include Files *********************************/
#include "xparameters.h" /* XPAR parameters */
#include "xspi.h" /* SPI device driver */
/************************** 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 SPI_DEVICE_ID XPAR_SPI_0_DEVICE_ID
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
int SpiXipExample(XSpi *SpiInstancePtr, u16 SpiDeviceId);
/************************** Variable Definitions *****************************/
/*
* The instances to support the device drivers are global such that the
* are initialized to zero each time the program runs.
*/
static XSpi SpiInstance; /* The instance of the SPI device */
/*****************************************************************************/
/**
*
* Main function to call the Spi XIP example.
*
* @param None
*
* @return XST_SUCCESS if successful, otherwise XST_FAILURE.
*
* @note None
*
******************************************************************************/
int main(void)
{
int Status;
/*
* Run the Spi XIP example.
*/
Status = SpiXipExample(&SpiInstance, SPI_DEVICE_ID);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function reads data from Flash memory in the way any memory is accessed.
* The purpose of this function is to illustrate how to use SPI device in XIP
* Mode.
*
* This function reads data from Flash in the same way any other memory is
* accessed
*
*
* @param SpiInstancePtr is a pointer to the instance of Spi component.
* @param SpiDeviceId is the Device ID of the Spi Device and is the
* XPAR_<SPI_instance>_DEVICE_ID value from xparameters.h.
*
* @return XST_SUCCESS if successful, otherwise XST_FAILURE.
*
* @note None
*
******************************************************************************/
int SpiXipExample(XSpi *SpiInstancePtr, u16 SpiDeviceId)
{
u32 Flashdata;
int Status;
XSpi_Config *ConfigPtr; /* Pointer to Configuration data */
/*
* Initialize the SPI driver so that it is ready to use.
*/
ConfigPtr = XSpi_LookupConfig(SpiDeviceId);
if (ConfigPtr == NULL) {
return XST_DEVICE_NOT_FOUND;
}
Status = XSpi_CfgInitialize(SpiInstancePtr, ConfigPtr,
ConfigPtr->BaseAddress);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/* Read data from flash in the way any memory is accessed using
Flash Memory Base Address in InstancePtr */
Flashdata = Xil_In32(SpiInstancePtr->FlashBaseAddr);
return XST_SUCCESS;
}

View file

@ -0,0 +1,28 @@
COMPILER=
ARCHIVER=
CP=cp
COMPILER_FLAGS=
EXTRA_COMPILER_FLAGS=
LIB=libxil.a
RELEASEDIR=../../../lib
INCLUDEDIR=../../../include
INCLUDES=-I./. -I${INCLUDEDIR}
INCLUDEFILES=xspi_l.h xspi.h
LIBSOURCES=*.c
OUTS = *.o
libs:
echo "Compiling spi"
$(COMPILER) $(COMPILER_FLAGS) $(EXTRA_COMPILER_FLAGS) $(INCLUDES) $(LIBSOURCES)
$(ARCHIVER) -r ${RELEASEDIR}/${LIB} $(OUTS)
make clean
include:
${CP} ${INCLUDEFILES} ${INCLUDEDIR}
clean:
rm -rf ${OUTS}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,835 @@
/******************************************************************************
*
* Copyright (C) 2001 - 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 xspi.h
*
* This component contains the implementation of the XSpi component. It is the
* driver for an SPI master or slave device. It supports 8-bit, 16-bit and 32-bit
* wide data transfers.
*
* SPI is a 4-wire serial interface. It is a full-duplex, synchronous bus that
* facilitates communication between one master and one slave. The device is
* always full-duplex, which means that for every byte sent, one is received, and
* vice-versa. The master controls the clock, so it can regulate when it wants
* to send or receive data. The slave is under control of the master, it must
* respond quickly since it has no control of the clock and must send/receive
* data as fast or as slow as the master does.
*
* The application software between master and slave must implement a higher
* layer protocol so that slaves know what to transmit to the master and when.
*
* <b>Initialization & Configuration</b>
*
* The XSpi_Config structure is used by the driver to configure itself. This
* configuration structure is typically created by the tool-chain based on HW
* build properties.
*
* To support multiple runtime loading and initialization strategies employed
* by various operating systems, the driver instance can be initialized in one
* of the following ways:
*
* - XSpi_Initialize(InstancePtr, DeviceId) - The driver looks up its own
* configuration structure created by the tool-chain based on an ID provided
* by the tool-chain.
*
* - XSpi_CfgInitialize(InstancePtr, CfgPtr, EffectiveAddr) - Uses a
* configuration structure provided by the caller. If running in a system
* with address translation, the provided virtual memory base address
* replaces the physical address present in the configuration structure.
*
* <b>Multiple Masters</b>
*
* More than one master can exist, but arbitration is the responsibility of the
* higher layer software. The device driver does not perform any type of
* arbitration.
*
* <b>Multiple Slaves</b>
*
* Multiple slaves are supported by adding additional slave select (SS) signals
* to each device, one for each slave on the bus. The driver ensures that only
* one slave can be selected at any one time.
*
* <b>FIFOs</b>
*
* The SPI hardware is parameterized such that it can be built with or without
* FIFOs. When using FIFOs, both send and receive must have FIFOs. The driver
* will not function correctly if one direction has a FIFO but the other
* direction does not. The frequency of the interrupts which occur is
* proportional to the data rate such that high data rates without the FIFOs
* could cause the software to consume large amounts of processing time. The
* driver is designed to work with or without the FIFOs.
*
* <b>Interrupts</b>
*
* The user must connect the interrupt handler of the driver,
* XSpi_InterruptHandler to an interrupt system such that it will be called when
* an interrupt occurs. This function does not save and restore the processor
* context such that the user must provide this processing.
*
* The driver handles the following interrupts:
* - Data Transmit Register/FIFO Empty
* - Data Transmit FIFO Half Empty
* - Data Transmit Register/FIFO Underrun
* - Data Receive Register/FIFO Overrun
* - Mode Fault Error
* - Slave Mode Fault Error
* - Slave Mode Select
* - Data Receive FIFO not Empty
*
* The Data Transmit Register/FIFO Empty interrupt indicates that the SPI device
* has transmitted all the data available to transmit, and now its data register
* (or FIFO) is empty. The driver uses this interrupt to indicate progress while
* sending data. The driver may have more data to send, in which case the data
* transmit register (or FIFO) is filled for subsequent transmission. When this
* interrupt arrives and all the data has been sent, the driver invokes the
* status callback with a value of XST_SPI_TRANSFER_DONE to inform the upper
* layer software that all data has been sent.
*
* The Data Transmit FIFO Half Empty interrupt indicates that the SPI device has
* transmitted half of the data available, in the FIFO, to transmit. The driver
* uses this interrupt to indicate progress while sending data. The driver may
* have more data to send, in which case the data transmit FIFO is filled for
* subsequent transmission. This interrupt is particualrly useful in slave mode,
* while transfering more than FIFO_DEPTH number of bytes. In this case, the
* driver ensures that the FIFO is never empty during a transfer and avoids
* master receiving invalid data.
*
* The Data Transmit Register/FIFO Underrun interrupt indicates that, as slave,
* the SPI device was required to transmit but there was no data available to
* transmit in the transmit register (or FIFO). This may not be an error if the
* master is not expecting data, but in the case where the master is expecting
* data this serves as a notification of such a condition. The driver reports
* this condition to the upper layer software through the status handler.
*
* The Data Receive Register/FIFO Overrun interrupt indicates that the SPI device
* received data and subsequently dropped the data because the data receive
* register (or FIFO) was full. The interrupt applies to both master and slave
* operation. The driver reports this condition to the upper layer software
* through the status handler. This likely indicates a problem with the higher
* layer protocol, or a problem with the slave performance.
*
* The Mode Fault Error interrupt indicates that while configured as a master,
* the device was selected as a slave by another master. This can be used by the
* application for arbitration in a multimaster environment or to indicate a
* problem with arbitration. When this interrupt occurs, the driver invokes the
* status callback with a status value of XST_SPI_MODE_FAULT. It is up to the
* application to resolve the conflict.
*
* The Slave Mode Fault Error interrupt indicates that a slave device was
* selected as a slave by a master, but the slave device was disabled. This can
* be used during system debugging or by the slave application to learn when the
* slave application has not prepared for a master operation in a timely fashion.
* This likely indicates a problem with the higher layer protocol, or a problem
* with the slave performance.
*
* The Slave Mode Select interrupt indicates that the SPI device was selected as
* a slave by a master. The driver reports this condition to the upper layer
* software through the status handler.
*
* Data Receive FIFO not Empty interrupt indicates that the SPI device, in slave
* mode, has received a data byte in the Data Receive FIFO, after the master has
* started a transfer. The driver reports this condition to the upper layer
* software through the status handler.
*
* <b>Polled Operation</b>
*
* This driver operates in polled mode operation too. To put the driver in polled
* mode the Global Interrupt must be disabled after the Spi is Initialized and
* Spi driver is started.
*
* Statistics are not updated in this mode of operation.
*
* <b>Device Busy</b>
*
* Some operations are disallowed when the device is busy. The driver tracks
* whether a device is busy. The device is considered busy when a data transfer
* request is outstanding, and is considered not busy only when that transfer
* completes (or is aborted with a mode fault error). This applies to both
* master and slave devices.
*
* <b>Device Configuration</b>
*
* The device can be configured in various ways during the FPGA implementation
* process. Configuration parameters are stored in the xspi_g.c file or passed
* in via _CfgInitialize(). A table is defined where each entry contains
* configuration information for an SPI device. This information includes such
* things as the base address of the memory-mapped device, the number of slave
* select bits in the device, and whether the device has FIFOs and is configured
* as slave-only.
*
* <b>RTOS Independence</b>
*
* 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.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- -------- -----------------------------------------------
* 1.00a rpm 10/11/01 First release
* 1.00b jhl 03/14/02 Repartitioned driver for smaller files.
* 1.01a jvb 12/14/05 I separated dependency on the static config table and
* xparameters.h from the driver initialization by moving
* _Initialize and _LookupConfig to _sinit.c. I also added
* the new _CfgInitialize routine.
* 1.11a wgr 03/22/07 Converted to new coding style.
* 1.11a sv 02/22/08 Added the definition of LSB-MSB first option in xspi_l.h.
* 1.12a sdm 03/22/08 Updated the code to support 16/32 bit transfer width and
* polled mode of operation, removed the macros in xspi_l.h,
* added macros in xspi.h file, moved the interrupt
* register/bit definitions from xspi_i.h to xpsi_l.h.
* Even for the polled mode of operation the Interrupt Logic
* in the core should be included. The driver can be put in
* polled mode of operation by disabling the Global Interrupt
* after the Spi Initialization is completed and Spi is
* started.
* 2.00a sdm 07/30/08 Updated the code to support 16/32 bit transfer width and
* polled mode of operation, removed the macros in xspi_l.h,
* added macros in xspi.h file, moved the interrupt
* register/bit definitions from xspi_i.h to xpsi_l.h.
* Even for the polled mode of operation the Interrupt Logic
* in the core should be included. The driver can be put in
* polled mode of operation by disabling the Global Interrupt
* after the Spi Initialization is completed and Spi is
* started.
* 2.01a sdm 08/22/08 Removed support for static interrupt handlers from the MDD
* file
* 2.01b sdm 04/08/09 Fixed an issue in the XSpi_Transfer function where the
* Global Interrupt is being enabled in polled mode when a
* slave is not selected.
* 3.00a ktn 10/22/09 Converted all register accesses to 32 bit access.
* Updated driver to use the HAL APIs/macros.
* Removed the macro XSpi_mReset, XSpi_Reset API should be
* used in its place.
* The macros have been renamed to remove _m from the name
* XSpi_mIntrGlobalEnable is renamed XSpi_IntrGlobalEnable,
* XSpi_mIntrGlobalDisable is now XSpi_IntrGlobalDisable,
* XSpi_mIsIntrGlobalEnabled is now XSpi_IsIntrGlobalEnabled,
* XSpi_mIntrGetStatus is now XSpi_IntrGetStatus,
* XSpi_mIntrClear is now XSpi_IntrClear,
* XSpi_mIntrEnable is now XSpi_IntrEnable,
* XSpi_mIntrDisable is now XSpi_IntrDisable,
* XSpi_mIntrGetEnabled is now XSpi_IntrGetEnabled,
* XSpi_mSetControlReg is now XSpi_SetControlReg,
* XSpi_mGetControlReg is now XSpi_GetControlReg,
* XSpi_mGetStatusReg is now XSpi_GetStatusReg,
* XSpi_mSetSlaveSelectReg is now XSpi_SetSlaveSelectReg,
* XSpi_mGetSlaveSelectReg is now XSpi_GetSlaveSelectReg,
* XSpi_mEnable is now XSpi_Enable,
* XSpi_mDisable is now XSpi_Disable.
* 3.01a sdm 04/23/10 Updated the driver to handle new slave mode interrupts
* and the DTR Half Empty interrupt.
* 3.02a sdm 03/30/11 Updated to support axi_qspi.
* 3.03a sdm 08/09/11 Updated the selftest to check for a correct default value
* in the case of axi_qspi - CR 620502
* Updated tcl to generate a config parameter for C_SPI_MODE
* 3.04a bss 03/21/12 Updated XSpi_Config and XSpi instance structure to support
* XIP Mode.
* Updated XSpi_CfgInitialize to support XIP Mode
* Added XIP Mode Register masks in xspi_l.h
* Tcl Script changes:
* Added C_TYPE_OF_AXI4_INTERFACE, C_AXI4_BASEADDR and
* C_XIP_MODE to config structure.
* Modified such that based on C_XIP_MODE and
* C_TYPE_OF_AXI4_INTERFACE parameters C_BASEADDR will
* be updated with C_AXI4_BASEADDR.
* Modified such that C_FIFO_EXIST will be updated based
* on C_FIFO_DEPTH for compatability of the driver with
* Axi Spi.
* 3.05a adk 18/04/13 Updated the code to avoid unused variable
* warnings when compiling with the -Wextra -Wall flags
* In the file xspi.c. CR:705005.
* 3.06a adk 07/08/13 Added a dummy read in the CfgInitialize(), if startup
* block is used in the h/w design (CR 721229).
* 3.07a adk 11/10/13 Fixed CR:732962 Changes are made in the xspi.c file
* 4.0 adk 19/12/13 Updated as per the New Tcl API's
*
*
* </pre>
*
******************************************************************************/
#ifndef XSPI_H /* prevent circular inclusions */
#define XSPI_H /* by using protection macros */
#ifdef __cplusplus
extern "C" {
#endif
/***************************** Include Files *********************************/
#include "xil_types.h"
#include "xil_assert.h"
#include "xstatus.h"
#include "xspi_l.h"
/************************** Constant Definitions *****************************/
/** @name Configuration options
*
* The following options may be specified or retrieved for the device and
* enable/disable additional features of the SPI. Each of the options
* are bit fields, so more than one may be specified.
*
* @{
*/
/**
* <pre>
* The Master option configures the SPI device as a master. By default, the
* device is a slave.
*
* The Active Low Clock option configures the device's clock polarity. Setting
* this option means the clock is active low and the SCK signal idles high. By
* default, the clock is active high and SCK idles low.
*
* The Clock Phase option configures the SPI device for one of two transfer
* formats. A clock phase of 0, the default, means data if valid on the first
* SCK edge (rising or falling) after the slave select (SS) signal has been
* asserted. A clock phase of 1 means data is valid on the second SCK edge
* (rising or falling) after SS has been asserted.
*
* The Loopback option configures the SPI device for loopback mode. Data is
* looped back from the transmitter to the receiver.
*
* The Manual Slave Select option, which is default, causes the device not
* to automatically drive the slave select. The driver selects the device
* at the start of a transfer and deselects it at the end of a transfer.
* If this option is off, then the device automatically toggles the slave
* select signal between bytes in a transfer.
* </pre>
*/
#define XSP_MASTER_OPTION 0x1
#define XSP_CLK_ACTIVE_LOW_OPTION 0x2
#define XSP_CLK_PHASE_1_OPTION 0x4
#define XSP_LOOPBACK_OPTION 0x8
#define XSP_MANUAL_SSELECT_OPTION 0x10
/*@}*/
/**************************** Type Definitions *******************************/
/******************************************************************************/
/**
* The handler data type allows the user to define a callback function to
* handle the asynchronous processing of the SPI driver. The application using
* this driver is expected to define a handler of this type to support interrupt
* driven mode. The handler executes in an interrupt context such that minimal
* processing should be performed.
*
* @param CallBackRef A callback reference passed in by the upper layer when
* setting the callback functions, and passed back to the
* upper layer when the callback is invoked. Its type is
* unimportant to the driver component, so it is a void
* pointer.
* @param StatusEvent Indicates one or more status events that occurred. See
* the XSpi_SetStatusHandler() for details on the status
* events that can be passed in the callback.
* @param ByteCount Indicates how many bytes of data were successfully
* transferred. This may be less than the number of bytes
* requested if the status event indicates an error.
*
*******************************************************************************/
typedef void (*XSpi_StatusHandler) (void *CallBackRef, u32 StatusEvent,
unsigned int ByteCount);
/**
* XSpi statistics
*/
typedef struct {
u32 ModeFaults; /**< Number of mode fault errors */
u32 XmitUnderruns; /**< Number of transmit underruns */
u32 RecvOverruns; /**< Number of receive overruns */
u32 SlaveModeFaults; /**< Num of selects as slave while disabled */
u32 BytesTransferred; /**< Number of bytes transferred */
u32 NumInterrupts; /**< Number of transmit/receive interrupts */
} XSpi_Stats;
/**
* This typedef contains configuration information for the device.
*/
typedef struct {
u16 DeviceId; /**< Unique ID of device */
u32 BaseAddress; /**< Base address of the device */
int HasFifos; /**< Does device have FIFOs? */
u32 SlaveOnly; /**< Is the device slave only? */
u8 NumSlaveBits; /**< Num of slave select bits on the device */
u8 DataWidth; /**< Data transfer Width */
u8 SpiMode; /**< Standard/Dual/Quad mode */
u8 AxiInterface; /**< AXI-Lite/AXI Full Interface */
u32 AxiFullBaseAddress; /**< AXI Full Interface Base address of
the device */
u8 XipMode; /**< 0 if Non-XIP, 1 if XIP Mode */
u8 Use_Startup; /**< 1 if Starup block is used in h/w */
} XSpi_Config;
/**
* The XSpi driver instance data. The user is required to allocate a
* variable of this type for every SPI device in the system. A pointer
* to a variable of this type is then passed to the driver API functions.
*/
typedef struct {
XSpi_Stats Stats; /**< Statistics */
u32 BaseAddr; /**< Base address of device (IPIF) */
int IsReady; /**< Device is initialized and ready */
int IsStarted; /**< Device has been started */
int HasFifos; /**< Device is configured with FIFOs or not */
u32 SlaveOnly; /**< Device is configured to be slave only */
u8 NumSlaveBits; /**< Number of slave selects for this device */
u8 DataWidth; /**< Data Transfer Width 8 or 16 or 32 */
u8 SpiMode; /**< Standard/Dual/Quad mode */
u32 SlaveSelectMask; /**< Mask that matches the number of SS bits */
u32 SlaveSelectReg; /**< Slave select register */
u8 *SendBufferPtr; /**< Buffer to send */
u8 *RecvBufferPtr; /**< Buffer to receive */
unsigned int RequestedBytes; /**< Total bytes to transfer (state) */
unsigned int RemainingBytes; /**< Bytes left to transfer (state) */
int IsBusy; /**< A transfer is in progress (state) */
XSpi_StatusHandler StatusHandler; /**< Status Handler */
void *StatusRef; /**< Callback reference for status handler */
u32 FlashBaseAddr; /**< Used in XIP Mode */
u8 XipMode; /**< 0 if Non-XIP, 1 if XIP Mode */
} XSpi;
/***************** Macros (Inline Functions) Definitions *********************/
/******************************************************************************/
/**
*
* This macro writes to the global interrupt enable register to enable
* interrupts from the device.
*
* Interrupts enabled using XSpi_IntrEnable() will not occur until the global
* interrupt enable bit is set by using this function.
*
* @param InstancePtr is a pointer to the XSpi instance to be worked on.
*
* @return None.
*
* @note C-Style signature:
* void XSpi_IntrGlobalEnable(XSpi *InstancePtr);
*
******************************************************************************/
#define XSpi_IntrGlobalEnable(InstancePtr) \
XSpi_WriteReg(((InstancePtr)->BaseAddr), XSP_DGIER_OFFSET, \
XSP_GINTR_ENABLE_MASK)
/******************************************************************************/
/**
*
* This macro disables all interrupts for the device by writing to the Global
* interrupt enable register.
*
* @param InstancePtr is a pointer to the XSpi instance to be worked on.
*
* @return None.
*
* @note C-Style signature:
* void XSpi_IntrGlobalDisable(XSpi *InstancePtr);
*
******************************************************************************/
#define XSpi_IntrGlobalDisable(InstancePtr) \
XSpi_WriteReg(((InstancePtr)->BaseAddr), XSP_DGIER_OFFSET, 0)
/*****************************************************************************/
/**
*
* This function determines if interrupts are enabled at the global level by
* reading the global interrupt register.
*
* @param InstancePtr is a pointer to the XSpi instance to be worked on.
*
* @return
* - TRUE if global interrupts are enabled.
* - FALSE if global interrupts are disabled.
*
* @note C-Style signature:
* int XSpi_IsIntrGlobalEnabled(XSpi *InstancePtr);
*
******************************************************************************/
#define XSpi_IsIntrGlobalEnabled(InstancePtr) \
(XSpi_ReadReg(((InstancePtr)->BaseAddr), XSP_DGIER_OFFSET) == \
XSP_GINTR_ENABLE_MASK)
/*****************************************************************************/
/**
*
* This function gets the contents of the Interrupt Status Register.
* This register indicates the status of interrupt sources for the device.
* The status is independent of whether interrupts are enabled such
* that the status register may also be polled when interrupts are not enabled.
*
* @param InstancePtr is a pointer to the XSpi instance to be worked on.
*
* @return A status which contains the value read from the Interrupt
* Status Register.
*
* @note C-Style signature:
* u32 XSpi_IntrGetStatus(XSpi *InstancePtr);
*
******************************************************************************/
#define XSpi_IntrGetStatus(InstancePtr) \
XSpi_ReadReg(((InstancePtr)->BaseAddr), XSP_IISR_OFFSET)
/*****************************************************************************/
/**
*
* This function clears the specified interrupts in the Interrupt status
* Register. The interrupt is cleared by writing to this register with the bits
* to be cleared set to a one and all others bits to zero. Setting a bit which
* is zero within this register causes an interrupt to be generated.
*
* This function writes only the specified value to the register such that
* some status bits may be set and others cleared. It is the caller's
* responsibility to get the value of the register prior to setting the value
* to prevent an destructive behavior.
*
* @param InstancePtr is a pointer to the XSpi instance to be worked on.
* @param ClearMask is the Bitmask for interrupts to be cleared.
* Bit positions of "1" clears the interrupt. Bit positions of 0
* will keep the previous setting. This mask is formed by OR'ing
* XSP_INTR_* bits defined in xspi_l.h.
*
* @return None.
*
* @note C-Style signature:
* void XSpi_IntrClear(XSpi *InstancePtr, u32 ClearMask);
*
******************************************************************************/
#define XSpi_IntrClear(InstancePtr, ClearMask) \
XSpi_WriteReg(((InstancePtr)->BaseAddr), XSP_IISR_OFFSET, \
XSpi_IntrGetStatus(InstancePtr) | (ClearMask))
/******************************************************************************/
/**
*
* This function sets the contents of the Interrupt Enable Register.
*
* @param InstancePtr is a pointer to the XSpi instance to be worked on.
* @param EnableMask is the bitmask of the interrupts to be enabled.
* Bit positions of 1 will be enabled. Bit positions of 0 will
* keep the previous setting. This mask is formed by OR'ing
* XSP_INTR_* bits defined in xspi_l.h.
*
* @return None.
*
* @note C-Style signature:
* void XSpi_IntrEnable(XSpi *InstancePtr, u32 EnableMask);
*
******************************************************************************/
#define XSpi_IntrEnable(InstancePtr, EnableMask) \
XSpi_WriteReg(((InstancePtr)->BaseAddr), XSP_IIER_OFFSET, \
(XSpi_ReadReg(((InstancePtr)->BaseAddr), \
XSP_IIER_OFFSET)) | (((EnableMask) & XSP_INTR_ALL )))
/****************************************************************************/
/**
*
* Disable the specified Interrupts in the Interrupt Enable Register.
*
* @param InstancePtr is a pointer to the XSpi instance to be worked on.
* @param DisableMask is the bitmask of the interrupts to be disabled.
* Bit positions of 1 will be disabled. Bit positions of 0 will
* keep the previous setting. This mask is formed by OR'ing
* XSP_INTR_* bits defined in xspi_l.h.
*
* @return None.
*
* @note C-Style signature:
* void XSpi_IntrDisable(XSpi *InstancePtr, u32 DisableMask);
*
******************************************************************************/
#define XSpi_IntrDisable(InstancePtr, DisableMask) \
XSpi_WriteReg(((InstancePtr)->BaseAddr), XSP_IIER_OFFSET, \
XSpi_ReadReg(((InstancePtr)->BaseAddr), \
XSP_IIER_OFFSET) & (~ ((DisableMask) & XSP_INTR_ALL )))
/*****************************************************************************/
/**
*
* This function gets the contents of the Interrupt Enable Register.
*
* @param InstancePtr is a pointer to the XSpi instance to be worked on.
*
* @return The contents read from the Interrupt Enable Register.
*
* @note C-Style signature:
* u32 XSpi_IntrGetEnabled(XSpi *InstancePtr)
*
******************************************************************************/
#define XSpi_IntrGetEnabled(InstancePtr) \
XSpi_ReadReg(((InstancePtr)->BaseAddr), XSP_IIER_OFFSET)
/****************************************************************************/
/**
*
* Set the contents of the control register. Use the XSP_CR_* constants defined
* above to create the bit-mask to be written to the register.
*
* @param InstancePtr is a pointer to the XSpi instance to be worked on.
* @param Mask is the 32-bit value to write to the control register.
*
* @return None.
*
* @note C-Style signature:
* void XSpi_SetControlReg(XSpi *InstancePtr, u32 Mask);
*
*****************************************************************************/
#define XSpi_SetControlReg(InstancePtr, Mask) \
XSpi_WriteReg(((InstancePtr)->BaseAddr), XSP_CR_OFFSET, (Mask))
/****************************************************************************/
/**
*
* Get the contents of the control register. Use the XSP_CR_* constants defined
* above to interpret the bit-mask returned.
*
* @param InstancePtr is a pointer to the XSpi instance to be worked on.
*
* @return A 32-bit value representing the contents of the control
* register.
*
* @note C-Style signature:
* u32 XSpi_GetControlReg(XSpi *InstancePtr);
*
*****************************************************************************/
#define XSpi_GetControlReg(InstancePtr) \
XSpi_ReadReg(((InstancePtr)->BaseAddr), XSP_CR_OFFSET)
/***************************************************************************/
/**
*
* Get the contents of the status register. Use the XSP_SR_* constants defined
* above to interpret the bit-mask returned.
*
* @param InstancePtr is a pointer to the XSpi instance to be worked on.
*
* @return An 32-bit value representing the contents of the status
* register.
*
* @note C-Style signature:
* u8 XSpi_GetStatusReg(XSpi *InstancePtr);
*
*****************************************************************************/
#define XSpi_GetStatusReg(InstancePtr) \
XSpi_ReadReg(((InstancePtr)->BaseAddr), XSP_SR_OFFSET)
/****************************************************************************/
/**
*
* Set the contents of the XIP control register. Use the XSP_CR_XIP_* constants
* defined above to create the bit-mask to be written to the register.
*
* @param InstancePtr is a pointer to the XSpi instance to be worked on.
* @param Mask is the 32-bit value to write to the control register.
*
* @return None.
*
* @note C-Style signature:
* void XSpi_SetXipControlReg(XSpi *InstancePtr, u32 Mask);
*
*****************************************************************************/
#define XSpi_SetXipControlReg(InstancePtr, Mask) \
XSpi_WriteReg(((InstancePtr)->BaseAddr), XSP_CR_OFFSET, (Mask))
/****************************************************************************/
/**
*
* Get the contents of the XIP control register. Use the XSP_CR_XIP_* constants
* defined above to interpret the bit-mask returned.
*
* @param InstancePtr is a pointer to the XSpi instance to be worked on.
*
* @return A 32-bit value representing the contents of the control
* register.
*
* @note C-Style signature:
* u32 XSpi_GetXipControlReg(XSpi *InstancePtr);
*
*****************************************************************************/
#define XSpi_GetXipControlReg(InstancePtr) \
XSpi_ReadReg(((InstancePtr)->BaseAddr), XSP_CR_OFFSET)
/****************************************************************************/
/**
*
* Get the contents of the status register. Use the XSP_SR_XIP_* constants
* defined above to interpret the bit-mask returned.
*
* @param InstancePtr is a pointer to the XSpi instance to be worked on.
*
* @return An 32-bit value representing the contents of the status
* register.
*
* @note C-Style signature:
* u8 XSpi_GetXipStatusReg(XSpi *InstancePtr);
*
*****************************************************************************/
#define XSpi_GetXipStatusReg(InstancePtr) \
XSpi_ReadReg(((InstancePtr)->BaseAddr), XSP_SR_OFFSET)
/****************************************************************************/
/**
*
* Set the contents of the slave select register. Each bit in the mask
* corresponds to a slave select line. Only one slave should be selected at
* any one time.
*
* @param InstancePtr is a pointer to the XSpi instance to be worked on.
* @param Mask is the 32-bit value to write to the slave select register.
*
* @return None.
*
* @note C-Style signature:
* void XSpi_SetSlaveSelectReg(XSpi *InstancePtr, u32 Mask);
*
*****************************************************************************/
#define XSpi_SetSlaveSelectReg(InstancePtr, Mask) \
XSpi_WriteReg(((InstancePtr)->BaseAddr), XSP_SSR_OFFSET, (Mask))
/****************************************************************************/
/**
*
* Get the contents of the slave select register. Each bit in the mask
* corresponds to a slave select line. Only one slave should be selected at
* any one time.
*
* @param InstancePtr is a pointer to the XSpi instance to be worked on.
*
* @return The 32-bit value in the slave select register.
*
* @note C-Style signature:
* u32 XSpi_GetSlaveSelectReg(XSpi *InstancePtr);
*
*****************************************************************************/
#define XSpi_GetSlaveSelectReg(InstancePtr) \
XSpi_ReadReg((InstancePtr)->BaseAddr, XSP_SSR_OFFSET)
/****************************************************************************/
/**
*
* Enable the device and uninhibit master transactions. Preserves the current
* contents of the control register.
*
* @param InstancePtr is a pointer to the XSpi instance to be worked on.
*
* @return None.
*
* @note C-Style signature:
* void XSpi_Enable(XSpi *InstancePtr);
*
*****************************************************************************/
#define XSpi_Enable(InstancePtr) \
{ \
u16 Control; \
Control = XSpi_GetControlReg((InstancePtr)); \
Control |= XSP_CR_ENABLE_MASK; \
Control &= ~XSP_CR_TRANS_INHIBIT_MASK; \
XSpi_SetControlReg((InstancePtr), Control); \
}
/****************************************************************************/
/**
*
* Disable the device. Preserves the current contents of the control register.
*
* @param InstancePtr is a pointer to the XSpi instance to be worked on.
*
* @return None.
*
* @note C-Style signature:
* void XSpi_Disable(XSpi *InstancePtr);
*
*****************************************************************************/
#define XSpi_Disable(InstancePtr) \
XSpi_SetControlReg((InstancePtr), \
XSpi_GetControlReg((InstancePtr)) & ~XSP_CR_ENABLE_MASK)
/************************** Function Prototypes ******************************/
/*
* Initialization functions in xspi_sinit.c
*/
int XSpi_Initialize(XSpi *InstancePtr, u16 DeviceId);
XSpi_Config *XSpi_LookupConfig(u16 DeviceId);
/*
* Functions, in xspi.c
*/
int XSpi_CfgInitialize(XSpi *InstancePtr, XSpi_Config * Config,
u32 EffectiveAddr);
int XSpi_Start(XSpi *InstancePtr);
int XSpi_Stop(XSpi *InstancePtr);
void XSpi_Reset(XSpi *InstancePtr);
int XSpi_SetSlaveSelect(XSpi *InstancePtr, u32 SlaveMask);
u32 XSpi_GetSlaveSelect(XSpi *InstancePtr);
int XSpi_Transfer(XSpi *InstancePtr, u8 *SendBufPtr, u8 *RecvBufPtr,
unsigned int ByteCount);
void XSpi_SetStatusHandler(XSpi *InstancePtr, void *CallBackRef,
XSpi_StatusHandler FuncPtr);
void XSpi_InterruptHandler(void *InstancePtr);
/*
* Functions for selftest, in xspi_selftest.c
*/
int XSpi_SelfTest(XSpi *InstancePtr);
/*
* Functions for statistics, in xspi_stats.c
*/
void XSpi_GetStats(XSpi *InstancePtr, XSpi_Stats *StatsPtr);
void XSpi_ClearStats(XSpi *InstancePtr);
/*
* Functions for options, in xspi_options.c
*/
int XSpi_SetOptions(XSpi *InstancePtr, u32 Options);
u32 XSpi_GetOptions(XSpi *InstancePtr);
#ifdef __cplusplus
}
#endif
#endif /* end of protection macro */

View file

@ -0,0 +1,104 @@
/******************************************************************************
*
* Copyright (C) 2001 - 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 xspi_g.c
*
* This file contains a configuration table that specifies the configuration of
* SPI devices in the system.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- -------- -----------------------------------------------
* 1.00a rpm 10/11/01 First release
* 1.00b jhl 03/14/02 Repartitioned driver for smaller files.
* 1.00b rpm 04/24/02 Condensed config typedef - got rid of versions and
* multiple base addresses.
* 1.11a wgr 03/22/07 Converted to new coding style.
* 1.12a sv 03/17/08 Updated the code to support 16/32 bit transfer width.
* 2.00a sv 07/30/08 Updated the code to support 16/32 bit transfer width.
* 3.02a sdm 05/04/11 Added a new parameter for the mode in which SPI device
* operates.
* 3.06a adk 07/08/13 Added a new parmeter for the startup block
*
* </pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "xspi.h"
#include "xparameters.h"
/************************** Constant Definitions *****************************/
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
/************************** Variable Prototypes ******************************/
/**
* This table contains configuration information for each SPI device
* in the system.
*/
XSpi_Config XSpi_ConfigTable[XPAR_XSPI_NUM_INSTANCES] = {
{
XPAR_SPI_0_DEVICE_ID, /* Device ID for instance */
XPAR_SPI_0_BASEADDR, /* Device base address */
XPAR_SPI_0_FIFO_EXIST, /* Does device have FIFOs? */
XPAR_SPI_0_SLAVE_ONLY, /* Is the device slave only? */
XPAR_SPI_0_NUM_SS_BITS, /* Number of slave select bits */
XPAR_SPI_0_NUM_TRANSFER_BITS /* Transfer Data width */
XPAR_SPI_0_SPI_MODE /* standard/dual/quad mode */
XPAR_SPI_0_USE_STARTUP /* Startup Parameter */
}
,
{
XPAR_SPI_1_DEVICE_ID, /* Device ID for instance */
XPAR_SPI_1_BASEADDR, /* Device base address */
XPAR_SPI_1_FIFO_EXIST, /* Does device have FIFOs? */
XPAR_SPI_1_SLAVE_ONLY, /* Is the device slave only? */
XPAR_SPI_1_NUM_SS_BITS, /* Number of slave select bits */
XPAR_SPI_1_NUM_TRANSFER_BITS /* Transfer Data width */
XPAR_SPI_1_SPI_MODE /* standard/dual/quad mode */
XPAR_SPI_0_USE_STARTUP /* Startup Parameter */
}
};

View file

@ -0,0 +1,88 @@
/******************************************************************************
*
* Copyright (C) 2001 - 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 xspi_i.h
*
* This header file contains internal identifiers. It is intended for internal
* use only.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- -------- -----------------------------------------------
* 1.00a rpm 10/11/01 First release
* 1.00b jhl 03/14/02 Repartitioned driver for smaller files.
* 1.00b rpm 04/24/02 Moved register definitions to xspi_l.h
* 1.11a wgr 03/22/07 Converted to new coding style.
* 1.12a sv 03/28/08 Removed the Macro for statistics, moved the interrupt
* register definitions and bit definitions to _l.h.
* 2.00a sv 07/30/08 Removed the Macro for statistics, moved the interrupt
* register definitions and bit definitions to _l.h.
* </pre>
*
******************************************************************************/
#ifndef XSPI_I_H /* prevent circular inclusions */
#define XSPI_I_H /* by using protection macros */
#ifdef __cplusplus
extern "C" {
#endif
/***************************** Include Files *********************************/
#include "xil_types.h"
#include "xil_assert.h"
#include "xspi_l.h"
/************************** Constant Definitions *****************************/
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
void XSpi_Abort(XSpi *InstancePtr);
/************************** Variable Definitions *****************************/
extern XSpi_Config XSpi_ConfigTable[];
#ifdef __cplusplus
}
#endif
#endif /* end of protection macro */

View file

@ -0,0 +1,363 @@
/******************************************************************************
*
* Copyright (C) 2001 - 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 xspi_l.h
*
* This header file contains identifiers, Register Definitions and basic driver
* functions (or macros) that can be used to access the device.
* Refer xspi.h for information about the driver.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- -------- -----------------------------------------------
* 1.00b rpm 04/24/02 First release
* 1.11a wgr 03/22/07 Converted to new coding style.
* 1.11a sv 02/22/08 Added the definition of LSB-MSB first option.
* 1.12a sv 03/28/08 Removed macros in _l.h file, moved the
* interrupt register definitions from _i.h to _l.h.
* 2.00a sv 07/30/08 Removed macros in _l.h file, moved the
* interrupt register definitions from _i.h to _l.h.
* 3.00a ktn 10/28/09 Updated all the register accesses as 32 bit access.
* Added XSpi_ReadReg and XSpi_WriteReg macros.
* 3.01a sdm 04/23/10 Added definitions for the new slave mode interrupts.
* 3.02a sdm 03/30/11 Added definitions for the new register bits in axi_qspi.
* 3.04a bss 03/21/12 Added XIP Mode Register masks
*
* </pre>
*
******************************************************************************/
#ifndef XSPI_L_H /* prevent circular inclusions */
#define XSPI_L_H /* by using protection macros */
#ifdef __cplusplus
extern "C" {
#endif
/***************************** Include Files *********************************/
#include "xil_types.h"
#include "xil_assert.h"
#include "xil_io.h"
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
#define XSpi_In32 Xil_In32
#define XSpi_Out32 Xil_Out32
/****************************************************************************/
/**
*
* Read from the specified Spi device register.
*
* @param BaseAddress contains the base address of the device.
* @param RegOffset contains the offset from the 1st register of the
* device to select the specific register.
*
* @return The value read from the register.
*
* @note C-Style signature:
* u32 XSpi_ReadReg(u32 BaseAddress, u32 RegOffset);
*
******************************************************************************/
#define XSpi_ReadReg(BaseAddress, RegOffset) \
XSpi_In32((BaseAddress) + (RegOffset))
/***************************************************************************/
/**
*
* Write to the specified Spi device register.
*
* @param BaseAddress contains the base address of the device.
* @param RegOffset contains the offset from the 1st register of the
* device to select the specific register.
* @param RegisterValue is the value to be written to the register.
*
* @return None.
*
* @note C-Style signature:
* void XSpi_WriteReg(u32 BaseAddress, u32 RegOffset,
* u32 RegisterValue);
******************************************************************************/
#define XSpi_WriteReg(BaseAddress, RegOffset, RegisterValue) \
XSpi_Out32((BaseAddress) + (RegOffset), (RegisterValue))
/************************** Function Prototypes ******************************/
/************************** Constant Definitions *****************************/
/**
* XSPI register offsets
*/
/** @name Register Map
*
* Register offsets for the XSpi device.
* @{
*/
#define XSP_DGIER_OFFSET 0x1C /**< Global Intr Enable Reg */
#define XSP_IISR_OFFSET 0x20 /**< Interrupt status Reg */
#define XSP_IIER_OFFSET 0x28 /**< Interrupt Enable Reg */
#define XSP_SRR_OFFSET 0x40 /**< Software Reset register */
#define XSP_CR_OFFSET 0x60 /**< Control register */
#define XSP_SR_OFFSET 0x64 /**< Status Register */
#define XSP_DTR_OFFSET 0x68 /**< Data transmit */
#define XSP_DRR_OFFSET 0x6C /**< Data receive */
#define XSP_SSR_OFFSET 0x70 /**< 32-bit slave select */
#define XSP_TFO_OFFSET 0x74 /**< Tx FIFO occupancy */
#define XSP_RFO_OFFSET 0x78 /**< Rx FIFO occupancy */
/* @} */
/**
* @name Global Interrupt Enable Register (GIER) mask(s)
* @{
*/
#define XSP_GINTR_ENABLE_MASK 0x80000000 /**< Global interrupt enable */
/* @} */
/** @name SPI Device Interrupt Status/Enable Registers
*
* <b> Interrupt Status Register (IPISR) </b>
*
* This register holds the interrupt status flags for the Spi device.
*
* <b> Interrupt Enable Register (IPIER) </b>
*
* This register is used to enable interrupt sources for the Spi device.
* Writing a '1' to a bit in this register enables the corresponding Interrupt.
* Writing a '0' to a bit in this register disables the corresponding Interrupt.
*
* ISR/IER registers have the same bit definitions and are only defined once.
* @{
*/
#define XSP_INTR_MODE_FAULT_MASK 0x00000001 /**< Mode fault error */
#define XSP_INTR_SLAVE_MODE_FAULT_MASK 0x00000002 /**< Selected as slave while
* disabled */
#define XSP_INTR_TX_EMPTY_MASK 0x00000004 /**< DTR/TxFIFO is empty */
#define XSP_INTR_TX_UNDERRUN_MASK 0x00000008 /**< DTR/TxFIFO underrun */
#define XSP_INTR_RX_FULL_MASK 0x00000010 /**< DRR/RxFIFO is full */
#define XSP_INTR_RX_OVERRUN_MASK 0x00000020 /**< DRR/RxFIFO overrun */
#define XSP_INTR_TX_HALF_EMPTY_MASK 0x00000040 /**< TxFIFO is half empty */
#define XSP_INTR_SLAVE_MODE_MASK 0x00000080 /**< Slave select mode */
#define XSP_INTR_RX_NOT_EMPTY_MASK 0x00000100 /**< RxFIFO not empty */
/**
* The following bits are available only in axi_qspi Interrupt Status and
* Interrupt Enable registers.
*/
#define XSP_INTR_CPOL_CPHA_ERR_MASK 0x00000200 /**< CPOL/CPHA error */
#define XSP_INTR_SLAVE_MODE_ERR_MASK 0x00000400 /**< Slave mode error */
#define XSP_INTR_MSB_ERR_MASK 0x00000800 /**< MSB Error */
#define XSP_INTR_LOOP_BACK_ERR_MASK 0x00001000 /**< Loop back error */
#define XSP_INTR_CMD_ERR_MASK 0x00002000 /**< 'Invalid cmd' error */
/**
* Mask for all the interrupts in the IP Interrupt Registers.
*/
#define XSP_INTR_ALL (XSP_INTR_MODE_FAULT_MASK | \
XSP_INTR_SLAVE_MODE_FAULT_MASK | \
XSP_INTR_TX_EMPTY_MASK | \
XSP_INTR_TX_UNDERRUN_MASK | \
XSP_INTR_RX_FULL_MASK | \
XSP_INTR_TX_HALF_EMPTY_MASK | \
XSP_INTR_RX_OVERRUN_MASK | \
XSP_INTR_SLAVE_MODE_MASK | \
XSP_INTR_RX_NOT_EMPTY_MASK | \
XSP_INTR_CMD_ERR_MASK | \
XSP_INTR_LOOP_BACK_ERR_MASK | \
XSP_INTR_MSB_ERR_MASK | \
XSP_INTR_SLAVE_MODE_ERR_MASK | \
XSP_INTR_CPOL_CPHA_ERR_MASK)
/**
* The interrupts we want at startup. We add the TX_EMPTY interrupt in later
* when we're getting ready to transfer data. The others we don't care
* about for now.
*/
#define XSP_INTR_DFT_MASK (XSP_INTR_MODE_FAULT_MASK | \
XSP_INTR_TX_UNDERRUN_MASK | \
XSP_INTR_RX_OVERRUN_MASK | \
XSP_INTR_SLAVE_MODE_FAULT_MASK | \
XSP_INTR_CMD_ERR_MASK)
/* @} */
/**
* SPI Software Reset Register (SRR) mask.
*/
#define XSP_SRR_RESET_MASK 0x0000000A
/** @name SPI Control Register (CR) masks
*
* @{
*/
#define XSP_CR_LOOPBACK_MASK 0x00000001 /**< Local loopback mode */
#define XSP_CR_ENABLE_MASK 0x00000002 /**< System enable */
#define XSP_CR_MASTER_MODE_MASK 0x00000004 /**< Enable master mode */
#define XSP_CR_CLK_POLARITY_MASK 0x00000008 /**< Clock polarity high
or low */
#define XSP_CR_CLK_PHASE_MASK 0x00000010 /**< Clock phase 0 or 1 */
#define XSP_CR_TXFIFO_RESET_MASK 0x00000020 /**< Reset transmit FIFO */
#define XSP_CR_RXFIFO_RESET_MASK 0x00000040 /**< Reset receive FIFO */
#define XSP_CR_MANUAL_SS_MASK 0x00000080 /**< Manual slave select
assert */
#define XSP_CR_TRANS_INHIBIT_MASK 0x00000100 /**< Master transaction
inhibit */
/**
* LSB/MSB first data format select. The default data format is MSB first.
* The LSB first data format is not available in all versions of the Xilinx Spi
* Device whereas the MSB first data format is supported by all the versions of
* the Xilinx Spi Devices. Please check the HW specification to see if this
* feature is supported or not.
*/
#define XSP_CR_LSB_MSB_FIRST_MASK 0x00000200
/* @} */
/** @name SPI Control Register (CR) masks for XIP Mode
*
* @{
*/
#define XSP_CR_XIP_CLK_PHASE_MASK 0x00000001 /**< Clock phase 0 or 1 */
#define XSP_CR_XIP_CLK_POLARITY_MASK 0x00000002 /**< Clock polarity
high or low */
/* @} */
/** @name Status Register (SR) masks
*
* @{
*/
#define XSP_SR_RX_EMPTY_MASK 0x00000001 /**< Receive Reg/FIFO is empty */
#define XSP_SR_RX_FULL_MASK 0x00000002 /**< Receive Reg/FIFO is full */
#define XSP_SR_TX_EMPTY_MASK 0x00000004 /**< Transmit Reg/FIFO is
empty */
#define XSP_SR_TX_FULL_MASK 0x00000008 /**< Transmit Reg/FIFO is full */
#define XSP_SR_MODE_FAULT_MASK 0x00000010 /**< Mode fault error */
#define XSP_SR_SLAVE_MODE_MASK 0x00000020 /**< Slave mode select */
/*
* The following bits are available only in axi_qspi Status register.
*/
#define XSP_SR_CPOL_CPHA_ERR_MASK 0x00000040 /**< CPOL/CPHA error */
#define XSP_SR_SLAVE_MODE_ERR_MASK 0x00000080 /**< Slave mode error */
#define XSP_SR_MSB_ERR_MASK 0x00000100 /**< MSB Error */
#define XSP_SR_LOOP_BACK_ERR_MASK 0x00000200 /**< Loop back error */
#define XSP_SR_CMD_ERR_MASK 0x00000400 /**< 'Invalid cmd' error */
/* @} */
/** @name Status Register (SR) masks for XIP Mode
*
* @{
*/
#define XSP_SR_XIP_RX_EMPTY_MASK 0x00000001 /**< Receive Reg/FIFO
is empty */
#define XSP_SR_XIP_RX_FULL_MASK 0x00000002 /**< Receive Reg/FIFO
is full */
#define XSP_SR_XIP_MASTER_MODF_MASK 0x00000004 /**< Receive Reg/FIFO
is full */
#define XSP_SR_XIP_CPHPL_ERROR_MASK 0x00000008 /**< Clock Phase,Clock
Polarity Error */
#define XSP_SR_XIP_AXI_ERROR_MASK 0x00000010 /**< AXI Transaction
Error */
/* @} */
/** @name SPI Transmit FIFO Occupancy (TFO) mask
*
* @{
*/
/* The binary value plus one yields the occupancy.*/
#define XSP_TFO_MASK 0x0000001F
/* @} */
/** @name SPI Receive FIFO Occupancy (RFO) mask
*
* @{
*/
/* The binary value plus one yields the occupancy.*/
#define XSP_RFO_MASK 0x0000001F
/* @} */
/** @name Data Width Definitions
*
* @{
*/
#define XSP_DATAWIDTH_BYTE 8 /**< Tx/Rx Reg is Byte Wide */
#define XSP_DATAWIDTH_HALF_WORD 16 /**< Tx/Rx Reg is Half Word (16 bit)
Wide */
#define XSP_DATAWIDTH_WORD 32 /**< Tx/Rx Reg is Word (32 bit) Wide */
/* @} */
/** @name SPI Modes
*
* The following constants define the modes in which qxi_qspi operates.
*
* @{
*/
#define XSP_STANDARD_MODE 0
#define XSP_DUAL_MODE 1
#define XSP_QUAD_MODE 2
/*@}*/
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
/************************** Variable Definitions *****************************/
#ifdef __cplusplus
}
#endif
#endif /* end of protection macro */

View file

@ -0,0 +1,222 @@
/******************************************************************************
*
* Copyright (C) 2001 - 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 xspi_options.c
*
* Contains functions for the configuration of the XSpi driver component.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- -------- -----------------------------------------------
* 1.00b jhl 2/27/02 First release
* 1.00b rpm 04/25/02 Collapsed IPIF and reg base addresses into one
* 1.11a wgr 03/22/07 Converted to new coding style.
* 3.00a ktn 10/28/09 Updated all the register accesses as 32 bit access.
* Updated driver to use the HAL APIs/macros.
*
* </pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "xspi.h"
#include "xspi_i.h"
/************************** Constant Definitions *****************************/
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
/************************** Variable Definitions *****************************/
/*
* Create the table of options which are processed to get/set the device
* options. These options are table driven to allow easy maintenance and
* expansion of the options.
*/
typedef struct {
u32 Option;
u32 Mask;
} OptionsMap;
static OptionsMap OptionsTable[] = {
{XSP_LOOPBACK_OPTION, XSP_CR_LOOPBACK_MASK},
{XSP_CLK_ACTIVE_LOW_OPTION, XSP_CR_CLK_POLARITY_MASK},
{XSP_CLK_PHASE_1_OPTION, XSP_CR_CLK_PHASE_MASK},
{XSP_MASTER_OPTION, XSP_CR_MASTER_MODE_MASK},
{XSP_MANUAL_SSELECT_OPTION, XSP_CR_MANUAL_SS_MASK}
};
#define XSP_NUM_OPTIONS (sizeof(OptionsTable) / sizeof(OptionsMap))
/*****************************************************************************/
/**
*
* This function sets the options for the SPI device driver. The options control
* how the device behaves relative to the SPI bus. The device must be idle
* rather than busy transferring data before setting these device options.
*
* @param InstancePtr is a pointer to the XSpi instance to be worked on.
* @param Options contains the specified options to be set. This is a bit
* mask where a 1 means to turn the option on, and a 0 means to
* turn the option off. One or more bit values may be contained in
* the mask.
* See the bit definitions named XSP_*_OPTIONS in the file xspi.h.
*
* @return
* -XST_SUCCESS if options are successfully set.
* - XST_DEVICE_BUSY if the device is currently transferring data.
* The transfer must complete or be aborted before setting options.
* - XST_SPI_SLAVE_ONLY if the caller attempted to configure a
* slave-only device as a master.
*
* @note
*
* This function makes use of internal resources that are shared between the
* XSpi_Stop() and XSpi_SetOptions() functions. So if one task might be setting
* device options while another is trying to stop the device, the user is
* required to provide protection of this shared data (typically using a
* semaphore).
*
******************************************************************************/
int XSpi_SetOptions(XSpi *InstancePtr, u32 Options)
{
u32 ControlReg;
u32 Index;
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
/*
* Do not allow the slave select to change while a transfer is in
* progress.
* No need to worry about a critical section here since even if the Isr
* changes the busy flag just after we read it, the function will return
* busy and the caller can retry when notified that their current
* transfer is done.
*/
if (InstancePtr->IsBusy) {
return XST_DEVICE_BUSY;
}
/*
* Do not allow master option to be set if the device is slave only.
*/
if ((Options & XSP_MASTER_OPTION) && (InstancePtr->SlaveOnly)) {
return XST_SPI_SLAVE_ONLY;
}
ControlReg = XSpi_GetControlReg(InstancePtr);
/*
* Loop through the options table, turning the option on or off
* depending on whether the bit is set in the incoming options flag.
*/
for (Index = 0; Index < XSP_NUM_OPTIONS; Index++) {
if (Options & OptionsTable[Index].Option) {
/*
*Turn it ON.
*/
ControlReg |= OptionsTable[Index].Mask;
}
else {
/*
*Turn it OFF.
*/
ControlReg &= ~OptionsTable[Index].Mask;
}
}
/*
* Now write the control register. Leave it to the upper layers
* to restart the device.
*/
XSpi_SetControlReg(InstancePtr, ControlReg);
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function gets the options for the SPI device. The options control how
* the device behaves relative to the SPI bus.
*
* @param InstancePtr is a pointer to the XSpi instance to be worked on.
*
* @return
*
* Options contains the specified options to be set. This is a bit mask where a
* 1 means to turn the option on, and a 0 means to turn the option off. One or
* more bit values may be contained in the mask. See the bit definitions named
* XSP_*_OPTIONS in the file xspi.h.
*
* @note None.
*
******************************************************************************/
u32 XSpi_GetOptions(XSpi *InstancePtr)
{
u32 OptionsFlag = 0;
u32 ControlReg;
u32 Index;
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
/*
* Get the control register to determine which options are currently
* set.
*/
ControlReg = XSpi_GetControlReg(InstancePtr);
/*
* Loop through the options table to determine which options are set.
*/
for (Index = 0; Index < XSP_NUM_OPTIONS; Index++) {
if (ControlReg & OptionsTable[Index].Mask) {
OptionsFlag |= OptionsTable[Index].Option;
}
}
return OptionsFlag;
}

View file

@ -0,0 +1,357 @@
/******************************************************************************
*
* Copyright (C) 2001 - 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 xspi_selftest.c
*
* This component contains the implementation of selftest functions for the
* XSpi driver component.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- -------- -----------------------------------------------
* 1.00b jhl 2/27/02 First release
* 1.00b rpm 04/25/02 Collapsed IPIF and reg base addresses into one
* 1.11a wgr 03/22/07 Converted to new coding style.
* 1.12a sv 03/17/08 Updated the code to support 16/32 bit transfer width.
* 2.00a sv 07/30/08 Updated the code to support 16/32 bit transfer width.
* 3.00a sdm 10/28/09 Updated all the register accesses as 32 bit access.
* 3.02a sdm 05/04/11 Updated to run the loopback test only in standard spi
* mode.
* 3.03a sdm 08/09/11 Updated the selftest to check for a correct default value
* in the case of axi_qspi - CR 620502
* 3.04a bss 03/21/12 Updated Selftest to check for XIP mode and return if XIP
* mode is true
* </pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "xspi.h"
#include "xspi_i.h"
/************************** Constant Definitions *****************************/
#define XSP_SR_RESET_STATE 0x5 /* Default to Tx/Rx reg empty */
#define XSP_CR_RESET_STATE 0x180
#define XSP_HALF_WORD_TESTBYTE 0x2200 /* Test Byte for Half Word */
#define XSP_WORD_TESTBYTE 0xAA005500 /* Test Byte for Word */
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
static int LoopbackTest(XSpi *InstancePtr);
/************************** Variable Definitions *****************************/
/*****************************************************************************/
/**
*
* Runs a self-test on the driver/device. The self-test is destructive in that
* a reset of the device is performed in order to check the reset values of
* the registers and to get the device into a known state. A simple loopback
* test is also performed to verify that transmit and receive are working
* properly. The device is changed to master mode for the loopback test, since
* only a master can initiate a data transfer.
*
* Upon successful return from the self-test, the device is reset.
*
* @param InstancePtr is a pointer to the XSpi instance to be worked on.
*
* @return
* - XST_SUCCESS if successful.
* - XST_REGISTER_ERROR indicates a register did not read or write
* correctly.
* - XST_LOOPBACK_ERROR if a loopback error occurred.
*
* @note None.
*
******************************************************************************/
int XSpi_SelfTest(XSpi *InstancePtr)
{
int Result;
u32 Register;
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
/* Return Success if XIP Mode */
if((InstancePtr->XipMode) == 1) {
return XST_SUCCESS;
}
/*
* Reset the SPI device to leave it in a known good state.
*/
XSpi_Reset(InstancePtr);
if(InstancePtr->XipMode)
{
Register = XSpi_GetControlReg(InstancePtr);
if (Register != XSP_CR_RESET_STATE) {
return XST_REGISTER_ERROR;
}
Register = XSpi_GetStatusReg(InstancePtr);
if ((Register & XSP_SR_RESET_STATE) != XSP_SR_RESET_STATE) {
return XST_REGISTER_ERROR;
}
}
/*
* All the SPI registers should be in their default state right now.
*/
Register = XSpi_GetControlReg(InstancePtr);
if (Register != XSP_CR_RESET_STATE) {
return XST_REGISTER_ERROR;
}
Register = XSpi_GetStatusReg(InstancePtr);
if ((Register & XSP_SR_RESET_STATE) != XSP_SR_RESET_STATE) {
return XST_REGISTER_ERROR;
}
/*
* Each supported slave select bit should be set to 1.
*/
Register = XSpi_GetSlaveSelectReg(InstancePtr);
if (Register != InstancePtr->SlaveSelectMask) {
return XST_REGISTER_ERROR;
}
/*
* If configured with FIFOs, the occupancy values should be 0.
*/
if (InstancePtr->HasFifos) {
Register = XSpi_ReadReg(InstancePtr->BaseAddr,
XSP_TFO_OFFSET);
if (Register != 0) {
return XST_REGISTER_ERROR;
}
Register = XSpi_ReadReg(InstancePtr->BaseAddr,
XSP_RFO_OFFSET);
if (Register != 0) {
return XST_REGISTER_ERROR;
}
}
/*
* Run loopback test only in case of standard SPI mode.
*/
if (InstancePtr->SpiMode != XSP_STANDARD_MODE) {
return XST_SUCCESS;
}
/*
* Run an internal loopback test on the SPI.
*/
Result = LoopbackTest(InstancePtr);
if (Result != XST_SUCCESS) {
return Result;
}
/*
* Reset the SPI device to leave it in a known good state.
*/
XSpi_Reset(InstancePtr);
return XST_SUCCESS;
}
/*****************************************************************************/
/*
*
* Runs an internal loopback test on the SPI device. This is done as a master
* with a enough data to fill the FIFOs if FIFOs are present. If the device is
* configured as a slave-only, this function returns successfully even though
* no loopback test is performed.
*
* This function does not restore the device context after performing the test
* as it assumes the device will be reset after the call.
*
* @param InstancePtr is a pointer to the XSpi instance to be worked on.
*
* @return
* - XST_SUCCESS if loopback was performed successfully or not
* performed at all if device is slave-only.
* - XST_LOOPBACK_ERROR if loopback failed.
*
* @note None.
*
******************************************************************************/
static int LoopbackTest(XSpi *InstancePtr)
{
u32 StatusReg;
u32 ControlReg;
u32 Index;
u32 Data;
u32 RxData;
u32 NumSent = 0;
u32 NumRecvd = 0;
u8 DataWidth;
/*
* Cannot run as a slave-only because we need to be master in order to
* initiate a transfer. Still return success, though.
*/
if (InstancePtr->SlaveOnly) {
return XST_SUCCESS;
}
/*
* Setup the control register to enable master mode and the loopback so
* that data can be sent and received.
*/
ControlReg = XSpi_GetControlReg(InstancePtr);
XSpi_SetControlReg(InstancePtr, ControlReg |
XSP_CR_LOOPBACK_MASK | XSP_CR_MASTER_MODE_MASK);
/*
* We do not need interrupts for this loopback test.
*/
XSpi_IntrGlobalDisable(InstancePtr);
DataWidth = InstancePtr->DataWidth;
/*
* Send data up to the maximum size of the transmit register, which is
* one byte without FIFOs. We send data 4 times just to exercise the
* device through more than one iteration.
*/
for (Index = 0; Index < 4; Index++) {
Data = 0;
/*
* Fill the transmit register.
*/
StatusReg = XSpi_GetStatusReg(InstancePtr);
while ((StatusReg & XSP_SR_TX_FULL_MASK) == 0) {
if (DataWidth == XSP_DATAWIDTH_BYTE) {
/*
* Data Transfer Width is Byte (8 bit).
*/
Data = 0;
} else if (DataWidth == XSP_DATAWIDTH_HALF_WORD) {
/*
* Data Transfer Width is Half Word (16 bit).
*/
Data = XSP_HALF_WORD_TESTBYTE;
} else if (DataWidth == XSP_DATAWIDTH_WORD){
/*
* Data Transfer Width is Word (32 bit).
*/
Data = XSP_WORD_TESTBYTE;
}
XSpi_WriteReg(InstancePtr->BaseAddr, XSP_DTR_OFFSET,
Data + Index);
NumSent += (DataWidth >> 3);
StatusReg = XSpi_GetStatusReg(InstancePtr);
}
/*
* Start the transfer by not inhibiting the transmitter and
* enabling the device.
*/
ControlReg = XSpi_GetControlReg(InstancePtr) &
(~XSP_CR_TRANS_INHIBIT_MASK);
XSpi_SetControlReg(InstancePtr, ControlReg |
XSP_CR_ENABLE_MASK);
/*
* Wait for the transfer to be done by polling the transmit
* empty status bit.
*/
do {
StatusReg = XSpi_GetStatusReg(InstancePtr);
} while ((StatusReg & XSP_SR_TX_EMPTY_MASK) == 0);
/*
* Receive and verify the data just transmitted.
*/
while ((StatusReg & XSP_SR_RX_EMPTY_MASK) == 0) {
RxData = XSpi_ReadReg(InstancePtr->BaseAddr,
XSP_DRR_OFFSET);
if (DataWidth == XSP_DATAWIDTH_BYTE) {
if((u8)RxData != Index) {
return XST_LOOPBACK_ERROR;
}
} else if (DataWidth ==
XSP_DATAWIDTH_HALF_WORD) {
if((u16)RxData != (u16)(Index +
XSP_HALF_WORD_TESTBYTE)) {
return XST_LOOPBACK_ERROR;
}
} else if (DataWidth == XSP_DATAWIDTH_WORD) {
if(RxData != (u32)(Index + XSP_WORD_TESTBYTE)) {
return XST_LOOPBACK_ERROR;
}
}
NumRecvd += (DataWidth >> 3);
StatusReg = XSpi_GetStatusReg(InstancePtr);
}
/*
* Stop the transfer (hold off automatic sending) by inhibiting
* the transmitter and disabling the device.
*/
ControlReg |= XSP_CR_TRANS_INHIBIT_MASK;
XSpi_SetControlReg(InstancePtr ,
ControlReg & ~ XSP_CR_ENABLE_MASK);
}
/*
* One final check to make sure the total number of bytes sent equals
* the total number of bytes received.
*/
if (NumSent != NumRecvd) {
return XST_LOOPBACK_ERROR;
}
return XST_SUCCESS;
}

View file

@ -0,0 +1,150 @@
/******************************************************************************
*
* 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.
*
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xspi_sinit.c
*
* The implementation of the XSpi component's static initialization
* functionality.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- -------- -----------------------------------------------
* 1.01a jvb 10/13/05 First release
* 1.11a wgr 03/22/07 Converted to new coding style.
*
* </pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "xparameters.h"
#include "xspi.h"
/************************** Constant Definitions *****************************/
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
/************************** Variable Definitions *****************************/
extern XSpi_Config XSpi_ConfigTable[];
/*****************************************************************************/
/**
*
* 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 contains the ID of the device to look up the
* configuration for.
*
* @return
*
* A pointer to the configuration found or NULL if the specified device ID was
* not found. See xspi.h for the definition of XSpi_Config.
*
* @note None.
*
******************************************************************************/
XSpi_Config *XSpi_LookupConfig(u16 DeviceId)
{
XSpi_Config *CfgPtr = NULL;
u32 Index;
for (Index = 0; Index < XPAR_XSPI_NUM_INSTANCES; Index++) {
if (XSpi_ConfigTable[Index].DeviceId == DeviceId) {
CfgPtr = &XSpi_ConfigTable[Index];
break;
}
}
return CfgPtr;
}
/*****************************************************************************/
/**
*
* Initializes a specific XSpi instance such that the driver is ready to use.
*
* The state of the device after initialization is:
* - Device is disabled
* - Slave mode
* - Active high clock polarity
* - Clock phase 0
*
* @param InstancePtr is a pointer to the XSpi instance to be worked on.
* @param DeviceId is the unique id of the device controlled by this XSpi
* instance. Passing in a device id associates the generic XSpi
* instance to a specific device, as chosen by the caller or
* application developer.
*
* @return
*
* - XST_SUCCESS if successful.
* - XST_DEVICE_IS_STARTED if the device is started. It must be
* stopped to re-initialize.
* - XST_DEVICE_NOT_FOUND if the device was not found in the
* configuration such that initialization could not be
* accomplished.
*
* @note None.
*
******************************************************************************/
int XSpi_Initialize(XSpi *InstancePtr, u16 DeviceId)
{
XSpi_Config *ConfigPtr; /* Pointer to Configuration ROM data */
Xil_AssertNonvoid(InstancePtr != NULL);
/*
* Lookup the device configuration in the temporary CROM table. Use this
* configuration info down below when initializing this component.
*/
ConfigPtr = XSpi_LookupConfig(DeviceId);
if (ConfigPtr == NULL) {
return XST_DEVICE_NOT_FOUND;
}
return XSpi_CfgInitialize(InstancePtr, ConfigPtr,
ConfigPtr->BaseAddress);
}

View file

@ -0,0 +1,128 @@
/******************************************************************************
*
* 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 xspi_stats.c
*
* This component contains the implementation of statistics functions for the
* XSpi driver component.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- -------- -----------------------------------------------
* 1.00b jhl 03/14/02 First release
* 1.00b rpm 04/25/02 Changed macro naming convention
* 1.11a wgr 03/22/07 Converted to new coding style.
* 1.12a sv 03/28/08 Removed the call to the Macro for clearing statistics.
* 2.00a sv 07/30/08 Removed the call to the Macro for clearing statistics.
* 3.00a ktn 10/28/09 Updated all the register accesses as 32 bit access.
* Updated driver to use the HAL APIs/macros.
* </pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "xspi.h"
#include "xspi_i.h"
/************************** Constant Definitions *****************************/
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
/************************** Variable Definitions *****************************/
/*****************************************************************************/
/**
*
* Gets a copy of the statistics for an SPI device.
*
* @param InstancePtr is a pointer to the XSpi instance to be worked on.
* @param StatsPtr is a pointer to a XSpi_Stats structure which will get a
* copy of current statistics.
*
* @return None.
*
* @note Statistics are not updated in polled mode of operation.
*
******************************************************************************/
void XSpi_GetStats(XSpi *InstancePtr, XSpi_Stats *StatsPtr)
{
Xil_AssertVoid(InstancePtr != NULL);
Xil_AssertVoid(StatsPtr != NULL);
Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
StatsPtr->ModeFaults = InstancePtr->Stats.ModeFaults;
StatsPtr->XmitUnderruns = InstancePtr->Stats.XmitUnderruns;
StatsPtr->RecvOverruns = InstancePtr->Stats.RecvOverruns;
StatsPtr->SlaveModeFaults = InstancePtr->Stats.SlaveModeFaults;
StatsPtr->BytesTransferred = InstancePtr->Stats.BytesTransferred;
StatsPtr->NumInterrupts = InstancePtr->Stats.NumInterrupts;
}
/*****************************************************************************/
/**
*
* Clears the statistics for the SPI device.
*
* @param InstancePtr is a pointer to the XSpi instance to be worked on.
*
* @return None.
*
* @note Statistics are not updated in polled mode of operation.
*
******************************************************************************/
void XSpi_ClearStats(XSpi *InstancePtr)
{
Xil_AssertVoid(InstancePtr != NULL);
Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
InstancePtr->Stats.ModeFaults = 0;
InstancePtr->Stats.XmitUnderruns = 0;
InstancePtr->Stats.RecvOverruns = 0;
InstancePtr->Stats.SlaveModeFaults = 0;
InstancePtr->Stats.BytesTransferred = 0;
InstancePtr->Stats.NumInterrupts = 0;
}