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:
parent
ecd70612c1
commit
10d10f8c2e
29 changed files with 11675 additions and 0 deletions
60
XilinxProcessorIPLib/drivers/spi/data/spi.mdd
Executable file
60
XilinxProcessorIPLib/drivers/spi/data/spi.mdd
Executable 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
|
348
XilinxProcessorIPLib/drivers/spi/data/spi.tcl
Executable file
348
XilinxProcessorIPLib/drivers/spi/data/spi.tcl
Executable 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"
|
||||
}
|
||||
|
42
XilinxProcessorIPLib/drivers/spi/data/spi_header.h
Executable file
42
XilinxProcessorIPLib/drivers/spi/data/spi_header.h
Executable 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
|
||||
|
53
XilinxProcessorIPLib/drivers/spi/data/spi_intr_header.h
Executable file
53
XilinxProcessorIPLib/drivers/spi/data/spi_intr_header.h
Executable 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
|
||||
|
236
XilinxProcessorIPLib/drivers/spi/data/spi_tapp.tcl
Executable file
236
XilinxProcessorIPLib/drivers/spi/data/spi_tapp.tcl
Executable 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
|
||||
}
|
27
XilinxProcessorIPLib/drivers/spi/examples/index.html
Executable file
27
XilinxProcessorIPLib/drivers/spi/examples/index.html
Executable 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>
|
692
XilinxProcessorIPLib/drivers/spi/examples/xspi_atmel_flash_example.c
Executable file
692
XilinxProcessorIPLib/drivers/spi/examples/xspi_atmel_flash_example.c
Executable 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;
|
||||
}
|
589
XilinxProcessorIPLib/drivers/spi/examples/xspi_eeprom_example.c
Executable file
589
XilinxProcessorIPLib/drivers/spi/examples/xspi_eeprom_example.c
Executable 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;
|
||||
}
|
||||
|
911
XilinxProcessorIPLib/drivers/spi/examples/xspi_intel_flash_example.c
Executable file
911
XilinxProcessorIPLib/drivers/spi/examples/xspi_intel_flash_example.c
Executable 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;
|
||||
}
|
||||
|
522
XilinxProcessorIPLib/drivers/spi/examples/xspi_intr_example.c
Executable file
522
XilinxProcessorIPLib/drivers/spi/examples/xspi_intr_example.c
Executable 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
|
||||
|
||||
|
||||
}
|
222
XilinxProcessorIPLib/drivers/spi/examples/xspi_low_level_example.c
Executable file
222
XilinxProcessorIPLib/drivers/spi/examples/xspi_low_level_example.c
Executable 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;
|
||||
}
|
1085
XilinxProcessorIPLib/drivers/spi/examples/xspi_numonyx_flash_quad_example.c
Executable file
1085
XilinxProcessorIPLib/drivers/spi/examples/xspi_numonyx_flash_quad_example.c
Executable file
File diff suppressed because it is too large
Load diff
250
XilinxProcessorIPLib/drivers/spi/examples/xspi_polled_example.c
Executable file
250
XilinxProcessorIPLib/drivers/spi/examples/xspi_polled_example.c
Executable 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;
|
||||
}
|
164
XilinxProcessorIPLib/drivers/spi/examples/xspi_selftest_example.c
Executable file
164
XilinxProcessorIPLib/drivers/spi/examples/xspi_selftest_example.c
Executable 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;
|
||||
}
|
||||
|
399
XilinxProcessorIPLib/drivers/spi/examples/xspi_slave_intr_example.c
Executable file
399
XilinxProcessorIPLib/drivers/spi/examples/xspi_slave_intr_example.c
Executable 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;
|
||||
}
|
||||
}
|
242
XilinxProcessorIPLib/drivers/spi/examples/xspi_slave_polled_example.c
Executable file
242
XilinxProcessorIPLib/drivers/spi/examples/xspi_slave_polled_example.c
Executable 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;
|
||||
}
|
822
XilinxProcessorIPLib/drivers/spi/examples/xspi_stm_flash_example.c
Executable file
822
XilinxProcessorIPLib/drivers/spi/examples/xspi_stm_flash_example.c
Executable 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;
|
||||
}
|
1189
XilinxProcessorIPLib/drivers/spi/examples/xspi_winbond_flash_quad_example.c
Executable file
1189
XilinxProcessorIPLib/drivers/spi/examples/xspi_winbond_flash_quad_example.c
Executable file
File diff suppressed because it is too large
Load diff
164
XilinxProcessorIPLib/drivers/spi/examples/xspi_winbond_flash_xip_example.c
Executable file
164
XilinxProcessorIPLib/drivers/spi/examples/xspi_winbond_flash_xip_example.c
Executable 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;
|
||||
}
|
28
XilinxProcessorIPLib/drivers/spi/src/Makefile
Executable file
28
XilinxProcessorIPLib/drivers/spi/src/Makefile
Executable 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}
|
1383
XilinxProcessorIPLib/drivers/spi/src/xspi.c
Executable file
1383
XilinxProcessorIPLib/drivers/spi/src/xspi.c
Executable file
File diff suppressed because it is too large
Load diff
835
XilinxProcessorIPLib/drivers/spi/src/xspi.h
Executable file
835
XilinxProcessorIPLib/drivers/spi/src/xspi.h
Executable 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 */
|
104
XilinxProcessorIPLib/drivers/spi/src/xspi_g.c
Executable file
104
XilinxProcessorIPLib/drivers/spi/src/xspi_g.c
Executable 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 */
|
||||
}
|
||||
};
|
88
XilinxProcessorIPLib/drivers/spi/src/xspi_i.h
Executable file
88
XilinxProcessorIPLib/drivers/spi/src/xspi_i.h
Executable 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 */
|
363
XilinxProcessorIPLib/drivers/spi/src/xspi_l.h
Executable file
363
XilinxProcessorIPLib/drivers/spi/src/xspi_l.h
Executable 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 */
|
222
XilinxProcessorIPLib/drivers/spi/src/xspi_options.c
Executable file
222
XilinxProcessorIPLib/drivers/spi/src/xspi_options.c
Executable 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;
|
||||
}
|
357
XilinxProcessorIPLib/drivers/spi/src/xspi_selftest.c
Executable file
357
XilinxProcessorIPLib/drivers/spi/src/xspi_selftest.c
Executable 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;
|
||||
}
|
150
XilinxProcessorIPLib/drivers/spi/src/xspi_sinit.c
Executable file
150
XilinxProcessorIPLib/drivers/spi/src/xspi_sinit.c
Executable 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);
|
||||
|
||||
}
|
128
XilinxProcessorIPLib/drivers/spi/src/xspi_stats.c
Executable file
128
XilinxProcessorIPLib/drivers/spi/src/xspi_stats.c
Executable 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;
|
||||
|
||||
}
|
Loading…
Add table
Reference in a new issue